disasm-arm.cc revision 3b9bc31999c9787eb726ecdbfd5796bfdec32a18
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.
4
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.
8//
9// The example below will disassemble a block of code and print it to stdout.
10//
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);
19//   }
20//
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);
24
25
26#include <assert.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <string.h>
30
31#if V8_TARGET_ARCH_ARM
32
33#include "src/arm/constants-arm.h"
34#include "src/base/bits.h"
35#include "src/base/platform/platform.h"
36#include "src/disasm.h"
37#include "src/macro-assembler.h"
38
39
40namespace v8 {
41namespace internal {
42
43
44//------------------------------------------------------------------------------
45
46// Decoder decodes and disassembles instructions into an output buffer.
47// It uses the converter to convert register names and call destinations into
48// more informative description.
49class Decoder {
50 public:
51  Decoder(const disasm::NameConverter& converter,
52          Vector<char> out_buffer)
53    : converter_(converter),
54      out_buffer_(out_buffer),
55      out_buffer_pos_(0) {
56    out_buffer_[out_buffer_pos_] = '\0';
57  }
58
59  ~Decoder() {}
60
61  // Writes one disassembled instruction into 'buffer' (0-terminated).
62  // Returns the length of the disassembled machine instruction in bytes.
63  int InstructionDecode(byte* instruction);
64
65  static bool IsConstantPoolAt(byte* instr_ptr);
66  static int ConstantPoolSizeAt(byte* instr_ptr);
67
68 private:
69  // Bottleneck functions to print into the out_buffer.
70  void PrintChar(const char ch);
71  void Print(const char* str);
72
73  // Printing of common values.
74  void PrintRegister(int reg);
75  void PrintSRegister(int reg);
76  void PrintDRegister(int reg);
77  int FormatVFPRegister(Instruction* instr, const char* format);
78  void PrintMovwMovt(Instruction* instr);
79  int FormatVFPinstruction(Instruction* instr, const char* format);
80  void PrintCondition(Instruction* instr);
81  void PrintShiftRm(Instruction* instr);
82  void PrintShiftImm(Instruction* instr);
83  void PrintShiftSat(Instruction* instr);
84  void PrintPU(Instruction* instr);
85  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
86
87  // Handle formatting of instructions and their options.
88  int FormatRegister(Instruction* instr, const char* option);
89  void FormatNeonList(int Vd, int type);
90  void FormatNeonMemory(int Rn, int align, int Rm);
91  int FormatOption(Instruction* instr, const char* option);
92  void Format(Instruction* instr, const char* format);
93  void Unknown(Instruction* instr);
94
95  // Each of these functions decodes one particular instruction type, a 3-bit
96  // field in the instruction encoding.
97  // Types 0 and 1 are combined as they are largely the same except for the way
98  // they interpret the shifter operand.
99  void DecodeType01(Instruction* instr);
100  void DecodeType2(Instruction* instr);
101  void DecodeType3(Instruction* instr);
102  void DecodeType4(Instruction* instr);
103  void DecodeType5(Instruction* instr);
104  void DecodeType6(Instruction* instr);
105  // Type 7 includes special Debugger instructions.
106  int DecodeType7(Instruction* instr);
107  // For VFP support.
108  void DecodeTypeVFP(Instruction* instr);
109  void DecodeType6CoprocessorIns(Instruction* instr);
110
111  void DecodeSpecialCondition(Instruction* instr);
112
113  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
114  void DecodeVCMP(Instruction* instr);
115  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
116  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
117
118  const disasm::NameConverter& converter_;
119  Vector<char> out_buffer_;
120  int out_buffer_pos_;
121
122  DISALLOW_COPY_AND_ASSIGN(Decoder);
123};
124
125
126// Support for assertions in the Decoder formatting functions.
127#define STRING_STARTS_WITH(string, compare_string) \
128  (strncmp(string, compare_string, strlen(compare_string)) == 0)
129
130
131// Append the ch to the output buffer.
132void Decoder::PrintChar(const char ch) {
133  out_buffer_[out_buffer_pos_++] = ch;
134}
135
136
137// Append the str to the output buffer.
138void Decoder::Print(const char* str) {
139  char cur = *str++;
140  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
141    PrintChar(cur);
142    cur = *str++;
143  }
144  out_buffer_[out_buffer_pos_] = 0;
145}
146
147
148// These condition names are defined in a way to match the native disassembler
149// formatting. See for example the command "objdump -d <binary file>".
150static const char* const cond_names[kNumberOfConditions] = {
151  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
152  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
153};
154
155
156// Print the condition guarding the instruction.
157void Decoder::PrintCondition(Instruction* instr) {
158  Print(cond_names[instr->ConditionValue()]);
159}
160
161
162// Print the register name according to the active name converter.
163void Decoder::PrintRegister(int reg) {
164  Print(converter_.NameOfCPURegister(reg));
165}
166
167
168// Print the VFP S register name according to the active name converter.
169void Decoder::PrintSRegister(int reg) {
170  Print(VFPRegisters::Name(reg, false));
171}
172
173
174// Print the VFP D register name according to the active name converter.
175void Decoder::PrintDRegister(int reg) {
176  Print(VFPRegisters::Name(reg, true));
177}
178
179
180// These shift names are defined in a way to match the native disassembler
181// formatting. See for example the command "objdump -d <binary file>".
182static const char* const shift_names[kNumberOfShifts] = {
183  "lsl", "lsr", "asr", "ror"
184};
185
186
187// Print the register shift operands for the instruction. Generally used for
188// data processing instructions.
189void Decoder::PrintShiftRm(Instruction* instr) {
190  ShiftOp shift = instr->ShiftField();
191  int shift_index = instr->ShiftValue();
192  int shift_amount = instr->ShiftAmountValue();
193  int rm = instr->RmValue();
194
195  PrintRegister(rm);
196
197  if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
198    // Special case for using rm only.
199    return;
200  }
201  if (instr->RegShiftValue() == 0) {
202    // by immediate
203    if ((shift == ROR) && (shift_amount == 0)) {
204      Print(", RRX");
205      return;
206    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
207      shift_amount = 32;
208    }
209    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
210                                ", %s #%d",
211                                shift_names[shift_index],
212                                shift_amount);
213  } else {
214    // by register
215    int rs = instr->RsValue();
216    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
217                                ", %s ", shift_names[shift_index]);
218    PrintRegister(rs);
219  }
220}
221
222
223// Print the immediate operand for the instruction. Generally used for data
224// processing instructions.
225void Decoder::PrintShiftImm(Instruction* instr) {
226  int rotate = instr->RotateValue() * 2;
227  int immed8 = instr->Immed8Value();
228  int imm = base::bits::RotateRight32(immed8, rotate);
229  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
230}
231
232
233// Print the optional shift and immediate used by saturating instructions.
234void Decoder::PrintShiftSat(Instruction* instr) {
235  int shift = instr->Bits(11, 7);
236  if (shift > 0) {
237    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
238                                ", %s #%d",
239                                shift_names[instr->Bit(6) * 2],
240                                instr->Bits(11, 7));
241  }
242}
243
244
245// Print PU formatting to reduce complexity of FormatOption.
246void Decoder::PrintPU(Instruction* instr) {
247  switch (instr->PUField()) {
248    case da_x: {
249      Print("da");
250      break;
251    }
252    case ia_x: {
253      Print("ia");
254      break;
255    }
256    case db_x: {
257      Print("db");
258      break;
259    }
260    case ib_x: {
261      Print("ib");
262      break;
263    }
264    default: {
265      UNREACHABLE();
266      break;
267    }
268  }
269}
270
271
272// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
273// the FormatOption method.
274void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
275  switch (svc) {
276    case kCallRtRedirected:
277      Print("call rt redirected");
278      return;
279    case kBreakpoint:
280      Print("breakpoint");
281      return;
282    default:
283      if (svc >= kStopCode) {
284        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
285                                    "%d - 0x%x",
286                                    svc & kStopCodeMask,
287                                    svc & kStopCodeMask);
288      } else {
289        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
290                                    "%d",
291                                    svc);
292      }
293      return;
294  }
295}
296
297
298// Handle all register based formatting in this function to reduce the
299// complexity of FormatOption.
300int Decoder::FormatRegister(Instruction* instr, const char* format) {
301  DCHECK(format[0] == 'r');
302  if (format[1] == 'n') {  // 'rn: Rn register
303    int reg = instr->RnValue();
304    PrintRegister(reg);
305    return 2;
306  } else if (format[1] == 'd') {  // 'rd: Rd register
307    int reg = instr->RdValue();
308    PrintRegister(reg);
309    return 2;
310  } else if (format[1] == 's') {  // 'rs: Rs register
311    int reg = instr->RsValue();
312    PrintRegister(reg);
313    return 2;
314  } else if (format[1] == 'm') {  // 'rm: Rm register
315    int reg = instr->RmValue();
316    PrintRegister(reg);
317    return 2;
318  } else if (format[1] == 't') {  // 'rt: Rt register
319    int reg = instr->RtValue();
320    PrintRegister(reg);
321    return 2;
322  } else if (format[1] == 'l') {
323    // 'rlist: register list for load and store multiple instructions
324    DCHECK(STRING_STARTS_WITH(format, "rlist"));
325    int rlist = instr->RlistValue();
326    int reg = 0;
327    Print("{");
328    // Print register list in ascending order, by scanning the bit mask.
329    while (rlist != 0) {
330      if ((rlist & 1) != 0) {
331        PrintRegister(reg);
332        if ((rlist >> 1) != 0) {
333          Print(", ");
334        }
335      }
336      reg++;
337      rlist >>= 1;
338    }
339    Print("}");
340    return 5;
341  }
342  UNREACHABLE();
343  return -1;
344}
345
346
347// Handle all VFP register based formatting in this function to reduce the
348// complexity of FormatOption.
349int Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
350  DCHECK((format[0] == 'S') || (format[0] == 'D'));
351
352  VFPRegPrecision precision =
353      format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
354
355  int retval = 2;
356  int reg = -1;
357  if (format[1] == 'n') {
358    reg = instr->VFPNRegValue(precision);
359  } else if (format[1] == 'm') {
360    reg = instr->VFPMRegValue(precision);
361  } else if (format[1] == 'd') {
362    if ((instr->TypeValue() == 7) &&
363        (instr->Bit(24) == 0x0) &&
364        (instr->Bits(11, 9) == 0x5) &&
365        (instr->Bit(4) == 0x1)) {
366      // vmov.32 has Vd in a different place.
367      reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
368    } else {
369      reg = instr->VFPDRegValue(precision);
370    }
371
372    if (format[2] == '+') {
373      int immed8 = instr->Immed8Value();
374      if (format[0] == 'S') reg += immed8 - 1;
375      if (format[0] == 'D') reg += (immed8 / 2 - 1);
376    }
377    if (format[2] == '+') retval = 3;
378  } else {
379    UNREACHABLE();
380  }
381
382  if (precision == kSinglePrecision) {
383    PrintSRegister(reg);
384  } else {
385    PrintDRegister(reg);
386  }
387
388  return retval;
389}
390
391
392int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
393    Print(format);
394    return 0;
395}
396
397
398void Decoder::FormatNeonList(int Vd, int type) {
399  if (type == nlt_1) {
400    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
401                                "{d%d}", Vd);
402  } else if (type == nlt_2) {
403    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
404                                "{d%d, d%d}", Vd, Vd + 1);
405  } else if (type == nlt_3) {
406    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
407                                "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
408  } else if (type == nlt_4) {
409    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
410                        "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3);
411  }
412}
413
414
415void Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
416  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
417                              "[r%d", Rn);
418  if (align != 0) {
419    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
420                                ":%d", (1 << align) << 6);
421  }
422  if (Rm == 15) {
423    Print("]");
424  } else if (Rm == 13) {
425    Print("]!");
426  } else {
427    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
428                                "], r%d", Rm);
429  }
430}
431
432
433// Print the movw or movt instruction.
434void Decoder::PrintMovwMovt(Instruction* instr) {
435  int imm = instr->ImmedMovwMovtValue();
436  int rd = instr->RdValue();
437  PrintRegister(rd);
438  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
439}
440
441
442// FormatOption takes a formatting string and interprets it based on
443// the current instructions. The format string points to the first
444// character of the option string (the option escape has already been
445// consumed by the caller.)  FormatOption returns the number of
446// characters that were consumed from the formatting string.
447int Decoder::FormatOption(Instruction* instr, const char* format) {
448  switch (format[0]) {
449    case 'a': {  // 'a: accumulate multiplies
450      if (instr->Bit(21) == 0) {
451        Print("ul");
452      } else {
453        Print("la");
454      }
455      return 1;
456    }
457    case 'b': {  // 'b: byte loads or stores
458      if (instr->HasB()) {
459        Print("b");
460      }
461      return 1;
462    }
463    case 'c': {  // 'cond: conditional execution
464      DCHECK(STRING_STARTS_WITH(format, "cond"));
465      PrintCondition(instr);
466      return 4;
467    }
468    case 'd': {  // 'd: vmov double immediate.
469      double d = instr->DoubleImmedVmov();
470      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
471      return 1;
472    }
473    case 'f': {  // 'f: bitfield instructions - v7 and above.
474      uint32_t lsbit = instr->Bits(11, 7);
475      uint32_t width = instr->Bits(20, 16) + 1;
476      if (instr->Bit(21) == 0) {
477        // BFC/BFI:
478        // Bits 20-16 represent most-significant bit. Covert to width.
479        width -= lsbit;
480        DCHECK(width > 0);
481      }
482      DCHECK((width + lsbit) <= 32);
483      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
484                                  "#%d, #%d", lsbit, width);
485      return 1;
486    }
487    case 'h': {  // 'h: halfword operation for extra loads and stores
488      if (instr->HasH()) {
489        Print("h");
490      } else {
491        Print("b");
492      }
493      return 1;
494    }
495    case 'i': {  // 'i: immediate value from adjacent bits.
496      // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
497      int width = (format[3] - '0') * 10 + (format[4] - '0');
498      int lsb   = (format[6] - '0') * 10 + (format[7] - '0');
499
500      DCHECK((width >= 1) && (width <= 32));
501      DCHECK((lsb >= 0) && (lsb <= 31));
502      DCHECK((width + lsb) <= 32);
503
504      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
505                                  "%d",
506                                  instr->Bits(width + lsb - 1, lsb));
507      return 8;
508    }
509    case 'l': {  // 'l: branch and link
510      if (instr->HasLink()) {
511        Print("l");
512      }
513      return 1;
514    }
515    case 'm': {
516      if (format[1] == 'w') {
517        // 'mw: movt/movw instructions.
518        PrintMovwMovt(instr);
519        return 2;
520      }
521      if (format[1] == 'e') {  // 'memop: load/store instructions.
522        DCHECK(STRING_STARTS_WITH(format, "memop"));
523        if (instr->HasL()) {
524          Print("ldr");
525        } else {
526          if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
527              (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
528            if (instr->Bit(5) == 1) {
529              Print("strd");
530            } else {
531              Print("ldrd");
532            }
533            return 5;
534          }
535          Print("str");
536        }
537        return 5;
538      }
539      // 'msg: for simulator break instructions
540      DCHECK(STRING_STARTS_WITH(format, "msg"));
541      byte* str =
542          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
543      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
544                                  "%s", converter_.NameInCode(str));
545      return 3;
546    }
547    case 'o': {
548      if ((format[3] == '1') && (format[4] == '2')) {
549        // 'off12: 12-bit offset for load and store instructions
550        DCHECK(STRING_STARTS_WITH(format, "off12"));
551        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
552                                    "%d", instr->Offset12Value());
553        return 5;
554      } else if (format[3] == '0') {
555        // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
556        DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19"));
557        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
558                                    "%d",
559                                    (instr->Bits(19, 8) << 4) +
560                                    instr->Bits(3, 0));
561        return 15;
562      }
563      // 'off8: 8-bit offset for extra load and store instructions
564      DCHECK(STRING_STARTS_WITH(format, "off8"));
565      int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
566      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
567      return 4;
568    }
569    case 'p': {  // 'pu: P and U bits for load and store instructions
570      DCHECK(STRING_STARTS_WITH(format, "pu"));
571      PrintPU(instr);
572      return 2;
573    }
574    case 'r': {
575      return FormatRegister(instr, format);
576    }
577    case 's': {
578      if (format[1] == 'h') {  // 'shift_op or 'shift_rm or 'shift_sat.
579        if (format[6] == 'o') {  // 'shift_op
580          DCHECK(STRING_STARTS_WITH(format, "shift_op"));
581          if (instr->TypeValue() == 0) {
582            PrintShiftRm(instr);
583          } else {
584            DCHECK(instr->TypeValue() == 1);
585            PrintShiftImm(instr);
586          }
587          return 8;
588        } else if (format[6] == 's') {  // 'shift_sat.
589          DCHECK(STRING_STARTS_WITH(format, "shift_sat"));
590          PrintShiftSat(instr);
591          return 9;
592        } else {  // 'shift_rm
593          DCHECK(STRING_STARTS_WITH(format, "shift_rm"));
594          PrintShiftRm(instr);
595          return 8;
596        }
597      } else if (format[1] == 'v') {  // 'svc
598        DCHECK(STRING_STARTS_WITH(format, "svc"));
599        PrintSoftwareInterrupt(instr->SvcValue());
600        return 3;
601      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
602        DCHECK(STRING_STARTS_WITH(format, "sign"));
603        if (instr->HasSign()) {
604          Print("s");
605        }
606        return 4;
607      } else if (format[1] == 'p') {
608        if (format[8] == '_') {  // 'spec_reg_fields
609          DCHECK(STRING_STARTS_WITH(format, "spec_reg_fields"));
610          Print("_");
611          int mask = instr->Bits(19, 16);
612          if (mask == 0) Print("(none)");
613          if ((mask & 0x8) != 0) Print("f");
614          if ((mask & 0x4) != 0) Print("s");
615          if ((mask & 0x2) != 0) Print("x");
616          if ((mask & 0x1) != 0) Print("c");
617          return 15;
618        } else {  // 'spec_reg
619          DCHECK(STRING_STARTS_WITH(format, "spec_reg"));
620          if (instr->Bit(22) == 0) {
621            Print("CPSR");
622          } else {
623            Print("SPSR");
624          }
625          return 8;
626        }
627      }
628      // 's: S field of data processing instructions
629      if (instr->HasS()) {
630        Print("s");
631      }
632      return 1;
633    }
634    case 't': {  // 'target: target of branch instructions
635      DCHECK(STRING_STARTS_WITH(format, "target"));
636      int off = (instr->SImmed24Value() << 2) + 8;
637      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
638                                  "%+d -> %s",
639                                  off,
640                                  converter_.NameOfAddress(
641                                    reinterpret_cast<byte*>(instr) + off));
642      return 6;
643    }
644    case 'u': {  // 'u: signed or unsigned multiplies
645      // The manual gets the meaning of bit 22 backwards in the multiply
646      // instruction overview on page A3.16.2.  The instructions that
647      // exist in u and s variants are the following:
648      // smull A4.1.87
649      // umull A4.1.129
650      // umlal A4.1.128
651      // smlal A4.1.76
652      // For these 0 means u and 1 means s.  As can be seen on their individual
653      // pages.  The other 18 mul instructions have the bit set or unset in
654      // arbitrary ways that are unrelated to the signedness of the instruction.
655      // None of these 18 instructions exist in both a 'u' and an 's' variant.
656
657      if (instr->Bit(22) == 0) {
658        Print("u");
659      } else {
660        Print("s");
661      }
662      return 1;
663    }
664    case 'v': {
665      return FormatVFPinstruction(instr, format);
666    }
667    case 'S':
668    case 'D': {
669      return FormatVFPRegister(instr, format);
670    }
671    case 'w': {  // 'w: W field of load and store instructions
672      if (instr->HasW()) {
673        Print("!");
674      }
675      return 1;
676    }
677    default: {
678      UNREACHABLE();
679      break;
680    }
681  }
682  UNREACHABLE();
683  return -1;
684}
685
686
687// Format takes a formatting string for a whole instruction and prints it into
688// the output buffer. All escaped options are handed to FormatOption to be
689// parsed further.
690void Decoder::Format(Instruction* instr, const char* format) {
691  char cur = *format++;
692  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
693    if (cur == '\'') {  // Single quote is used as the formatting escape.
694      format += FormatOption(instr, format);
695    } else {
696      out_buffer_[out_buffer_pos_++] = cur;
697    }
698    cur = *format++;
699  }
700  out_buffer_[out_buffer_pos_]  = '\0';
701}
702
703
704// The disassembler may end up decoding data inlined in the code. We do not want
705// it to crash if the data does not ressemble any known instruction.
706#define VERIFY(condition) \
707if(!(condition)) {        \
708  Unknown(instr);         \
709  return;                 \
710}
711
712
713// For currently unimplemented decodings the disassembler calls Unknown(instr)
714// which will just print "unknown" of the instruction bits.
715void Decoder::Unknown(Instruction* instr) {
716  Format(instr, "unknown");
717}
718
719
720void Decoder::DecodeType01(Instruction* instr) {
721  int type = instr->TypeValue();
722  if ((type == 0) && instr->IsSpecialType0()) {
723    // multiply instruction or extra loads and stores
724    if (instr->Bits(7, 4) == 9) {
725      if (instr->Bit(24) == 0) {
726        // multiply instructions
727        if (instr->Bit(23) == 0) {
728          if (instr->Bit(21) == 0) {
729            // The MUL instruction description (A 4.1.33) refers to Rd as being
730            // the destination for the operation, but it confusingly uses the
731            // Rn field to encode it.
732            Format(instr, "mul'cond's 'rn, 'rm, 'rs");
733          } else {
734            if (instr->Bit(22) == 0) {
735              // The MLA instruction description (A 4.1.28) refers to the order
736              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
737              // Rn field to encode the Rd register and the Rd field to encode
738              // the Rn register.
739              Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
740            } else {
741              // The MLS instruction description (A 4.1.29) refers to the order
742              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
743              // Rn field to encode the Rd register and the Rd field to encode
744              // the Rn register.
745              Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
746            }
747          }
748        } else {
749          // The signed/long multiply instructions use the terms RdHi and RdLo
750          // when referring to the target registers. They are mapped to the Rn
751          // and Rd fields as follows:
752          // RdLo == Rd field
753          // RdHi == Rn field
754          // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
755          Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
756        }
757      } else {
758        Unknown(instr);  // not used by V8
759      }
760    } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
761      // ldrd, strd
762      switch (instr->PUField()) {
763        case da_x: {
764          if (instr->Bit(22) == 0) {
765            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
766          } else {
767            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
768          }
769          break;
770        }
771        case ia_x: {
772          if (instr->Bit(22) == 0) {
773            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
774          } else {
775            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
776          }
777          break;
778        }
779        case db_x: {
780          if (instr->Bit(22) == 0) {
781            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
782          } else {
783            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
784          }
785          break;
786        }
787        case ib_x: {
788          if (instr->Bit(22) == 0) {
789            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
790          } else {
791            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
792          }
793          break;
794        }
795        default: {
796          // The PU field is a 2-bit field.
797          UNREACHABLE();
798          break;
799        }
800      }
801    } else {
802      // extra load/store instructions
803      switch (instr->PUField()) {
804        case da_x: {
805          if (instr->Bit(22) == 0) {
806            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
807          } else {
808            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
809          }
810          break;
811        }
812        case ia_x: {
813          if (instr->Bit(22) == 0) {
814            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
815          } else {
816            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
817          }
818          break;
819        }
820        case db_x: {
821          if (instr->Bit(22) == 0) {
822            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
823          } else {
824            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
825          }
826          break;
827        }
828        case ib_x: {
829          if (instr->Bit(22) == 0) {
830            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
831          } else {
832            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
833          }
834          break;
835        }
836        default: {
837          // The PU field is a 2-bit field.
838          UNREACHABLE();
839          break;
840        }
841      }
842      return;
843    }
844  } else if ((type == 0) && instr->IsMiscType0()) {
845    if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
846        (instr->Bits(15, 4) == 0xf00)) {
847      Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm");
848    } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
849               (instr->Bits(11, 0) == 0)) {
850      Format(instr, "mrs'cond 'rd, 'spec_reg");
851    } else if (instr->Bits(22, 21) == 1) {
852      switch (instr->BitField(7, 4)) {
853        case BX:
854          Format(instr, "bx'cond 'rm");
855          break;
856        case BLX:
857          Format(instr, "blx'cond 'rm");
858          break;
859        case BKPT:
860          Format(instr, "bkpt 'off0to3and8to19");
861          break;
862        default:
863          Unknown(instr);  // not used by V8
864          break;
865      }
866    } else if (instr->Bits(22, 21) == 3) {
867      switch (instr->BitField(7, 4)) {
868        case CLZ:
869          Format(instr, "clz'cond 'rd, 'rm");
870          break;
871        default:
872          Unknown(instr);  // not used by V8
873          break;
874      }
875    } else {
876      Unknown(instr);  // not used by V8
877    }
878  } else if ((type == 1) && instr->IsNopType1()) {
879    Format(instr, "nop'cond");
880  } else {
881    switch (instr->OpcodeField()) {
882      case AND: {
883        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
884        break;
885      }
886      case EOR: {
887        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
888        break;
889      }
890      case SUB: {
891        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
892        break;
893      }
894      case RSB: {
895        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
896        break;
897      }
898      case ADD: {
899        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
900        break;
901      }
902      case ADC: {
903        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
904        break;
905      }
906      case SBC: {
907        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
908        break;
909      }
910      case RSC: {
911        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
912        break;
913      }
914      case TST: {
915        if (instr->HasS()) {
916          Format(instr, "tst'cond 'rn, 'shift_op");
917        } else {
918          Format(instr, "movw'cond 'mw");
919        }
920        break;
921      }
922      case TEQ: {
923        if (instr->HasS()) {
924          Format(instr, "teq'cond 'rn, 'shift_op");
925        } else {
926          // Other instructions matching this pattern are handled in the
927          // miscellaneous instructions part above.
928          UNREACHABLE();
929        }
930        break;
931      }
932      case CMP: {
933        if (instr->HasS()) {
934          Format(instr, "cmp'cond 'rn, 'shift_op");
935        } else {
936          Format(instr, "movt'cond 'mw");
937        }
938        break;
939      }
940      case CMN: {
941        if (instr->HasS()) {
942          Format(instr, "cmn'cond 'rn, 'shift_op");
943        } else {
944          // Other instructions matching this pattern are handled in the
945          // miscellaneous instructions part above.
946          UNREACHABLE();
947        }
948        break;
949      }
950      case ORR: {
951        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
952        break;
953      }
954      case MOV: {
955        Format(instr, "mov'cond's 'rd, 'shift_op");
956        break;
957      }
958      case BIC: {
959        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
960        break;
961      }
962      case MVN: {
963        Format(instr, "mvn'cond's 'rd, 'shift_op");
964        break;
965      }
966      default: {
967        // The Opcode field is a 4-bit field.
968        UNREACHABLE();
969        break;
970      }
971    }
972  }
973}
974
975
976void Decoder::DecodeType2(Instruction* instr) {
977  switch (instr->PUField()) {
978    case da_x: {
979      if (instr->HasW()) {
980        Unknown(instr);  // not used in V8
981        return;
982      }
983      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
984      break;
985    }
986    case ia_x: {
987      if (instr->HasW()) {
988        Unknown(instr);  // not used in V8
989        return;
990      }
991      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
992      break;
993    }
994    case db_x: {
995      Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
996      break;
997    }
998    case ib_x: {
999      Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1000      break;
1001    }
1002    default: {
1003      // The PU field is a 2-bit field.
1004      UNREACHABLE();
1005      break;
1006    }
1007  }
1008}
1009
1010
1011void Decoder::DecodeType3(Instruction* instr) {
1012  switch (instr->PUField()) {
1013    case da_x: {
1014      VERIFY(!instr->HasW());
1015      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1016      break;
1017    }
1018    case ia_x: {
1019      if (instr->Bit(4) == 0) {
1020        Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1021      } else {
1022        if (instr->Bit(5) == 0) {
1023          switch (instr->Bits(22, 21)) {
1024            case 0:
1025              if (instr->Bit(20) == 0) {
1026                if (instr->Bit(6) == 0) {
1027                  Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1028                } else {
1029                  if (instr->Bits(11, 7) == 0) {
1030                    Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1031                  } else {
1032                    Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1033                  }
1034                }
1035              } else {
1036                UNREACHABLE();
1037              }
1038              break;
1039            case 1:
1040              UNREACHABLE();
1041              break;
1042            case 2:
1043              UNREACHABLE();
1044              break;
1045            case 3:
1046              Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1047              break;
1048          }
1049        } else {
1050          switch (instr->Bits(22, 21)) {
1051            case 0:
1052              UNREACHABLE();
1053              break;
1054            case 1:
1055              if (instr->Bits(9, 6) == 1) {
1056                if (instr->Bit(20) == 0) {
1057                  if (instr->Bits(19, 16) == 0xF) {
1058                    switch (instr->Bits(11, 10)) {
1059                      case 0:
1060                        Format(instr, "sxtb'cond 'rd, 'rm");
1061                        break;
1062                      case 1:
1063                        Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
1064                        break;
1065                      case 2:
1066                        Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
1067                        break;
1068                      case 3:
1069                        Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
1070                        break;
1071                    }
1072                  } else {
1073                    switch (instr->Bits(11, 10)) {
1074                      case 0:
1075                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
1076                        break;
1077                      case 1:
1078                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
1079                        break;
1080                      case 2:
1081                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
1082                        break;
1083                      case 3:
1084                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
1085                        break;
1086                    }
1087                  }
1088                } else {
1089                  if (instr->Bits(19, 16) == 0xF) {
1090                    switch (instr->Bits(11, 10)) {
1091                      case 0:
1092                        Format(instr, "sxth'cond 'rd, 'rm");
1093                        break;
1094                      case 1:
1095                        Format(instr, "sxth'cond 'rd, 'rm, ror #8");
1096                        break;
1097                      case 2:
1098                        Format(instr, "sxth'cond 'rd, 'rm, ror #16");
1099                        break;
1100                      case 3:
1101                        Format(instr, "sxth'cond 'rd, 'rm, ror #24");
1102                        break;
1103                    }
1104                  } else {
1105                    switch (instr->Bits(11, 10)) {
1106                      case 0:
1107                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
1108                        break;
1109                      case 1:
1110                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
1111                        break;
1112                      case 2:
1113                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
1114                        break;
1115                      case 3:
1116                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
1117                        break;
1118                    }
1119                  }
1120                }
1121              } else {
1122                UNREACHABLE();
1123              }
1124              break;
1125            case 2:
1126              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1127                if (instr->Bits(19, 16) == 0xF) {
1128                  switch (instr->Bits(11, 10)) {
1129                    case 0:
1130                      Format(instr, "uxtb16'cond 'rd, 'rm");
1131                      break;
1132                    case 1:
1133                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1134                      break;
1135                    case 2:
1136                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1137                      break;
1138                    case 3:
1139                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1140                      break;
1141                  }
1142                } else {
1143                  UNREACHABLE();
1144                }
1145              } else {
1146                UNREACHABLE();
1147              }
1148              break;
1149            case 3:
1150              if ((instr->Bits(9, 6) == 1)) {
1151                if ((instr->Bit(20) == 0)) {
1152                  if (instr->Bits(19, 16) == 0xF) {
1153                    switch (instr->Bits(11, 10)) {
1154                      case 0:
1155                        Format(instr, "uxtb'cond 'rd, 'rm");
1156                        break;
1157                      case 1:
1158                        Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1159                        break;
1160                      case 2:
1161                        Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1162                        break;
1163                      case 3:
1164                        Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1165                        break;
1166                    }
1167                  } else {
1168                    switch (instr->Bits(11, 10)) {
1169                      case 0:
1170                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1171                        break;
1172                      case 1:
1173                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1174                        break;
1175                      case 2:
1176                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1177                        break;
1178                      case 3:
1179                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1180                        break;
1181                    }
1182                  }
1183                } else {
1184                  if (instr->Bits(19, 16) == 0xF) {
1185                    switch (instr->Bits(11, 10)) {
1186                      case 0:
1187                        Format(instr, "uxth'cond 'rd, 'rm");
1188                        break;
1189                      case 1:
1190                        Format(instr, "uxth'cond 'rd, 'rm, ror #8");
1191                        break;
1192                      case 2:
1193                        Format(instr, "uxth'cond 'rd, 'rm, ror #16");
1194                        break;
1195                      case 3:
1196                        Format(instr, "uxth'cond 'rd, 'rm, ror #24");
1197                        break;
1198                    }
1199                  } else {
1200                    switch (instr->Bits(11, 10)) {
1201                      case 0:
1202                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
1203                        break;
1204                      case 1:
1205                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
1206                        break;
1207                      case 2:
1208                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
1209                        break;
1210                      case 3:
1211                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
1212                        break;
1213                    }
1214                  }
1215                }
1216              } else {
1217                // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
1218                if ((instr->Bits(20, 16) == 0x1f) &&
1219                    (instr->Bits(11, 4) == 0xf3)) {
1220                  Format(instr, "rbit'cond 'rd, 'rm");
1221                } else {
1222                  UNREACHABLE();
1223                }
1224              }
1225              break;
1226          }
1227        }
1228      }
1229      break;
1230    }
1231    case db_x: {
1232      if (instr->Bits(22, 20) == 0x5) {
1233        if (instr->Bits(7, 4) == 0x1) {
1234          if (instr->Bits(15, 12) == 0xF) {
1235            Format(instr, "smmul'cond 'rn, 'rm, 'rs");
1236          } else {
1237            // SMMLA (in V8 notation matching ARM ISA format)
1238            Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
1239          }
1240          break;
1241        }
1242      }
1243      if (FLAG_enable_sudiv) {
1244        if (instr->Bits(5, 4) == 0x1) {
1245          if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1246            if (instr->Bit(21) == 0x1) {
1247              // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1248              Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1249            } else {
1250              // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1251              Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1252            }
1253            break;
1254          }
1255        }
1256      }
1257      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1258      break;
1259    }
1260    case ib_x: {
1261      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1262        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1263        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1264        uint32_t msbit = widthminus1 + lsbit;
1265        if (msbit <= 31) {
1266          if (instr->Bit(22)) {
1267            Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1268          } else {
1269            Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1270          }
1271        } else {
1272          UNREACHABLE();
1273        }
1274      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1275        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1276        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1277        if (msbit >= lsbit) {
1278          if (instr->RmValue() == 15) {
1279            Format(instr, "bfc'cond 'rd, 'f");
1280          } else {
1281            Format(instr, "bfi'cond 'rd, 'rm, 'f");
1282          }
1283        } else {
1284          UNREACHABLE();
1285        }
1286      } else {
1287        Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1288      }
1289      break;
1290    }
1291    default: {
1292      // The PU field is a 2-bit field.
1293      UNREACHABLE();
1294      break;
1295    }
1296  }
1297}
1298
1299
1300void Decoder::DecodeType4(Instruction* instr) {
1301  if (instr->Bit(22) != 0) {
1302    // Privileged mode currently not supported.
1303    Unknown(instr);
1304  } else {
1305    if (instr->HasL()) {
1306      Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1307    } else {
1308      Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1309    }
1310  }
1311}
1312
1313
1314void Decoder::DecodeType5(Instruction* instr) {
1315  Format(instr, "b'l'cond 'target");
1316}
1317
1318
1319void Decoder::DecodeType6(Instruction* instr) {
1320  DecodeType6CoprocessorIns(instr);
1321}
1322
1323
1324int Decoder::DecodeType7(Instruction* instr) {
1325  if (instr->Bit(24) == 1) {
1326    if (instr->SvcValue() >= kStopCode) {
1327      Format(instr, "stop'cond 'svc");
1328      // Also print the stop message. Its address is encoded
1329      // in the following 4 bytes.
1330      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1331                                  "\n  %p  %08x       stop message: %s",
1332                                  reinterpret_cast<void*>(instr
1333                                                 + Instruction::kInstrSize),
1334                                  *reinterpret_cast<uint32_t*>(instr
1335                                                + Instruction::kInstrSize),
1336                                  *reinterpret_cast<char**>(instr
1337                                                + Instruction::kInstrSize));
1338      // We have decoded 2 * Instruction::kInstrSize bytes.
1339      return 2 * Instruction::kInstrSize;
1340    } else {
1341      Format(instr, "svc'cond 'svc");
1342    }
1343  } else {
1344    DecodeTypeVFP(instr);
1345  }
1346  return Instruction::kInstrSize;
1347}
1348
1349
1350// void Decoder::DecodeTypeVFP(Instruction* instr)
1351// vmov: Sn = Rt
1352// vmov: Rt = Sn
1353// vcvt: Dd = Sm
1354// vcvt: Sd = Dm
1355// vcvt.f64.s32 Dd, Dd, #<fbits>
1356// Dd = vabs(Dm)
1357// Sd = vabs(Sm)
1358// Dd = vneg(Dm)
1359// Sd = vneg(Sm)
1360// Dd = vadd(Dn, Dm)
1361// Sd = vadd(Sn, Sm)
1362// Dd = vsub(Dn, Dm)
1363// Sd = vsub(Sn, Sm)
1364// Dd = vmul(Dn, Dm)
1365// Sd = vmul(Sn, Sm)
1366// Dd = vmla(Dn, Dm)
1367// Sd = vmla(Sn, Sm)
1368// Dd = vmls(Dn, Dm)
1369// Sd = vmls(Sn, Sm)
1370// Dd = vdiv(Dn, Dm)
1371// Sd = vdiv(Sn, Sm)
1372// vcmp(Dd, Dm)
1373// vcmp(Sd, Sm)
1374// Dd = vsqrt(Dm)
1375// Sd = vsqrt(Sm)
1376// vmrs
1377// vmsr
1378void Decoder::DecodeTypeVFP(Instruction* instr) {
1379  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1380  VERIFY(instr->Bits(11, 9) == 0x5);
1381
1382  if (instr->Bit(4) == 0) {
1383    if (instr->Opc1Value() == 0x7) {
1384      // Other data processing instructions
1385      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1386        // vmov register to register.
1387        if (instr->SzValue() == 0x1) {
1388          Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1389        } else {
1390          Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1391        }
1392      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1393        // vabs
1394        if (instr->SzValue() == 0x1) {
1395          Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1396        } else {
1397          Format(instr, "vabs'cond.f32 'Sd, 'Sm");
1398        }
1399      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1400        // vneg
1401        if (instr->SzValue() == 0x1) {
1402          Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1403        } else {
1404          Format(instr, "vneg'cond.f32 'Sd, 'Sm");
1405        }
1406      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1407        DecodeVCVTBetweenDoubleAndSingle(instr);
1408      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1409        DecodeVCVTBetweenFloatingPointAndInteger(instr);
1410      } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1411                 (instr->Bit(8) == 1)) {
1412        // vcvt.f64.s32 Dd, Dd, #<fbits>
1413        int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1414        Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1415        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1416                                    ", #%d", fraction_bits);
1417      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1418                 (instr->Opc3Value() & 0x1)) {
1419        DecodeVCVTBetweenFloatingPointAndInteger(instr);
1420      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1421                 (instr->Opc3Value() & 0x1)) {
1422        DecodeVCMP(instr);
1423      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1424        if (instr->SzValue() == 0x1) {
1425          Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1426        } else {
1427          Format(instr, "vsqrt'cond.f32 'Sd, 'Sm");
1428        }
1429      } else if (instr->Opc3Value() == 0x0) {
1430        if (instr->SzValue() == 0x1) {
1431          Format(instr, "vmov'cond.f64 'Dd, 'd");
1432        } else {
1433          Format(instr, "vmov'cond.f32 'Sd, 'd");
1434        }
1435      } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
1436        // vrintz - round towards zero (truncate)
1437        if (instr->SzValue() == 0x1) {
1438          Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
1439        } else {
1440          Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm");
1441        }
1442      } else {
1443        Unknown(instr);  // Not used by V8.
1444      }
1445    } else if (instr->Opc1Value() == 0x3) {
1446      if (instr->SzValue() == 0x1) {
1447        if (instr->Opc3Value() & 0x1) {
1448          Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1449        } else {
1450          Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1451        }
1452      } else {
1453        if (instr->Opc3Value() & 0x1) {
1454          Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm");
1455        } else {
1456          Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm");
1457        }
1458      }
1459    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1460      if (instr->SzValue() == 0x1) {
1461        Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1462      } else {
1463        Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm");
1464      }
1465    } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1466      if (instr->SzValue() == 0x1) {
1467        Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1468      } else {
1469        Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm");
1470      }
1471    } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1472      if (instr->SzValue() == 0x1) {
1473        Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1474      } else {
1475        Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm");
1476      }
1477    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1478      if (instr->SzValue() == 0x1) {
1479        Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1480      } else {
1481        Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm");
1482      }
1483    } else {
1484      Unknown(instr);  // Not used by V8.
1485    }
1486  } else {
1487    if ((instr->VCValue() == 0x0) &&
1488        (instr->VAValue() == 0x0)) {
1489      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1490    } else if ((instr->VLValue() == 0x0) &&
1491               (instr->VCValue() == 0x1) &&
1492               (instr->Bit(23) == 0x0)) {
1493      if (instr->Bit(21) == 0x0) {
1494        Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1495      } else {
1496        Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1497      }
1498    } else if ((instr->VLValue() == 0x1) &&
1499               (instr->VCValue() == 0x1) &&
1500               (instr->Bit(23) == 0x0)) {
1501      if (instr->Bit(21) == 0x0) {
1502        Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1503      } else {
1504        Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1505      }
1506    } else if ((instr->VCValue() == 0x0) &&
1507               (instr->VAValue() == 0x7) &&
1508               (instr->Bits(19, 16) == 0x1)) {
1509      if (instr->VLValue() == 0) {
1510        if (instr->Bits(15, 12) == 0xF) {
1511          Format(instr, "vmsr'cond FPSCR, APSR");
1512        } else {
1513          Format(instr, "vmsr'cond FPSCR, 'rt");
1514        }
1515      } else {
1516        if (instr->Bits(15, 12) == 0xF) {
1517          Format(instr, "vmrs'cond APSR, FPSCR");
1518        } else {
1519          Format(instr, "vmrs'cond 'rt, FPSCR");
1520        }
1521      }
1522    }
1523  }
1524}
1525
1526
1527void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1528    Instruction* instr) {
1529  VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1530         (instr->VAValue() == 0x0));
1531
1532  bool to_arm_register = (instr->VLValue() == 0x1);
1533
1534  if (to_arm_register) {
1535    Format(instr, "vmov'cond 'rt, 'Sn");
1536  } else {
1537    Format(instr, "vmov'cond 'Sn, 'rt");
1538  }
1539}
1540
1541
1542void Decoder::DecodeVCMP(Instruction* instr) {
1543  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1544  VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1545         (instr->Opc3Value() & 0x1));
1546
1547  // Comparison.
1548  bool dp_operation = (instr->SzValue() == 1);
1549  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1550
1551  if (dp_operation && !raise_exception_for_qnan) {
1552    if (instr->Opc2Value() == 0x4) {
1553      Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1554    } else if (instr->Opc2Value() == 0x5) {
1555      Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1556    } else {
1557      Unknown(instr);  // invalid
1558    }
1559  } else if (!raise_exception_for_qnan) {
1560    if (instr->Opc2Value() == 0x4) {
1561      Format(instr, "vcmp'cond.f32 'Sd, 'Sm");
1562    } else if (instr->Opc2Value() == 0x5) {
1563      Format(instr, "vcmp'cond.f32 'Sd, #0.0");
1564    } else {
1565      Unknown(instr);  // invalid
1566    }
1567  } else {
1568    Unknown(instr);  // Not used by V8.
1569  }
1570}
1571
1572
1573void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1574  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1575  VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1576
1577  bool double_to_single = (instr->SzValue() == 1);
1578
1579  if (double_to_single) {
1580    Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1581  } else {
1582    Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1583  }
1584}
1585
1586
1587void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1588  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1589  VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1590         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1591
1592  bool to_integer = (instr->Bit(18) == 1);
1593  bool dp_operation = (instr->SzValue() == 1);
1594  if (to_integer) {
1595    bool unsigned_integer = (instr->Bit(16) == 0);
1596
1597    if (dp_operation) {
1598      if (unsigned_integer) {
1599        Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1600      } else {
1601        Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1602      }
1603    } else {
1604      if (unsigned_integer) {
1605        Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1606      } else {
1607        Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1608      }
1609    }
1610  } else {
1611    bool unsigned_integer = (instr->Bit(7) == 0);
1612
1613    if (dp_operation) {
1614      if (unsigned_integer) {
1615        Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1616      } else {
1617        Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1618      }
1619    } else {
1620      if (unsigned_integer) {
1621        Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1622      } else {
1623        Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1624      }
1625    }
1626  }
1627}
1628
1629
1630// Decode Type 6 coprocessor instructions.
1631// Dm = vmov(Rt, Rt2)
1632// <Rt, Rt2> = vmov(Dm)
1633// Ddst = MEM(Rbase + 4*offset).
1634// MEM(Rbase + 4*offset) = Dsrc.
1635void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1636  VERIFY(instr->TypeValue() == 6);
1637
1638  if (instr->CoprocessorValue() == 0xA) {
1639    switch (instr->OpcodeValue()) {
1640      case 0x8:
1641      case 0xA:
1642        if (instr->HasL()) {
1643          Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1644        } else {
1645          Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1646        }
1647        break;
1648      case 0xC:
1649      case 0xE:
1650        if (instr->HasL()) {
1651          Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1652        } else {
1653          Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1654        }
1655        break;
1656      case 0x4:
1657      case 0x5:
1658      case 0x6:
1659      case 0x7:
1660      case 0x9:
1661      case 0xB: {
1662        bool to_vfp_register = (instr->VLValue() == 0x1);
1663        if (to_vfp_register) {
1664          Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1665        } else {
1666          Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1667        }
1668        break;
1669      }
1670      default:
1671        Unknown(instr);  // Not used by V8.
1672    }
1673  } else if (instr->CoprocessorValue() == 0xB) {
1674    switch (instr->OpcodeValue()) {
1675      case 0x2:
1676        // Load and store double to two GP registers
1677        if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1678          Unknown(instr);  // Not used by V8.
1679        } else if (instr->HasL()) {
1680          Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1681        } else {
1682          Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1683        }
1684        break;
1685      case 0x8:
1686      case 0xA:
1687        if (instr->HasL()) {
1688          Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1689        } else {
1690          Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1691        }
1692        break;
1693      case 0xC:
1694      case 0xE:
1695        if (instr->HasL()) {
1696          Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1697        } else {
1698          Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1699        }
1700        break;
1701      case 0x4:
1702      case 0x5:
1703      case 0x6:
1704      case 0x7:
1705      case 0x9:
1706      case 0xB: {
1707        bool to_vfp_register = (instr->VLValue() == 0x1);
1708        if (to_vfp_register) {
1709          Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1710        } else {
1711          Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1712        }
1713        break;
1714      }
1715      default:
1716        Unknown(instr);  // Not used by V8.
1717    }
1718  } else {
1719    Unknown(instr);  // Not used by V8.
1720  }
1721}
1722
1723
1724static const char* const barrier_option_names[] = {
1725    "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh",
1726    "invalid", "ishld", "ishst", "ish", "invalid", "ld",    "st",    "sy",
1727};
1728
1729
1730void Decoder::DecodeSpecialCondition(Instruction* instr) {
1731  switch (instr->SpecialValue()) {
1732    case 5:
1733      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1734          (instr->Bit(4) == 1)) {
1735        // vmovl signed
1736        if ((instr->VdValue() & 1) != 0) Unknown(instr);
1737        int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1738        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1739        int imm3 = instr->Bits(21, 19);
1740        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1741                                    "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm);
1742      } else {
1743        Unknown(instr);
1744      }
1745      break;
1746    case 7:
1747      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1748          (instr->Bit(4) == 1)) {
1749        // vmovl unsigned
1750        if ((instr->VdValue() & 1) != 0) Unknown(instr);
1751        int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1752        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1753        int imm3 = instr->Bits(21, 19);
1754        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1755                                    "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm);
1756      } else {
1757        Unknown(instr);
1758      }
1759      break;
1760    case 8:
1761      if (instr->Bits(21, 20) == 0) {
1762        // vst1
1763        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1764        int Rn = instr->VnValue();
1765        int type = instr->Bits(11, 8);
1766        int size = instr->Bits(7, 6);
1767        int align = instr->Bits(5, 4);
1768        int Rm = instr->VmValue();
1769        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1770                                    "vst1.%d ", (1 << size) << 3);
1771        FormatNeonList(Vd, type);
1772        Print(", ");
1773        FormatNeonMemory(Rn, align, Rm);
1774      } else if (instr->Bits(21, 20) == 2) {
1775        // vld1
1776        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1777        int Rn = instr->VnValue();
1778        int type = instr->Bits(11, 8);
1779        int size = instr->Bits(7, 6);
1780        int align = instr->Bits(5, 4);
1781        int Rm = instr->VmValue();
1782        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1783                                    "vld1.%d ", (1 << size) << 3);
1784        FormatNeonList(Vd, type);
1785        Print(", ");
1786        FormatNeonMemory(Rn, align, Rm);
1787      } else {
1788        Unknown(instr);
1789      }
1790      break;
1791    case 0xA:
1792    case 0xB:
1793      if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
1794        int Rn = instr->Bits(19, 16);
1795        int offset = instr->Bits(11, 0);
1796        if (offset == 0) {
1797          out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1798                                      "pld [r%d]", Rn);
1799        } else if (instr->Bit(23) == 0) {
1800          out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1801                                      "pld [r%d, #-%d]", Rn, offset);
1802        } else {
1803          out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1804                                      "pld [r%d, #+%d]", Rn, offset);
1805        }
1806      } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
1807        int option = instr->Bits(3, 0);
1808        switch (instr->Bits(7, 4)) {
1809          case 4:
1810            out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1811                                        "dsb %s", barrier_option_names[option]);
1812            break;
1813          case 5:
1814            out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1815                                        "dmb %s", barrier_option_names[option]);
1816            break;
1817          case 6:
1818            out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1819                                        "isb %s", barrier_option_names[option]);
1820            break;
1821          default:
1822            Unknown(instr);
1823        }
1824      } else {
1825        Unknown(instr);
1826      }
1827      break;
1828    case 0x1D:
1829      if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 &&
1830          instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 &&
1831          instr->Bit(4) == 0x0) {
1832        // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
1833        bool dp_operation = (instr->SzValue() == 1);
1834        int rounding_mode = instr->Bits(17, 16);
1835        switch (rounding_mode) {
1836          case 0x0:
1837            if (dp_operation) {
1838              Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
1839            } else {
1840              Format(instr, "vrinta.f32.f32 'Sd, 'Sm");
1841            }
1842            break;
1843          case 0x1:
1844            if (dp_operation) {
1845              Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
1846            } else {
1847              Format(instr, "vrintn.f32.f32 'Sd, 'Sm");
1848            }
1849            break;
1850          case 0x2:
1851            if (dp_operation) {
1852              Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
1853            } else {
1854              Format(instr, "vrintp.f32.f32 'Sd, 'Sm");
1855            }
1856            break;
1857          case 0x3:
1858            if (dp_operation) {
1859              Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
1860            } else {
1861              Format(instr, "vrintm.f32.f32 'Sd, 'Sm");
1862            }
1863            break;
1864          default:
1865            UNREACHABLE();  // Case analysis is exhaustive.
1866            break;
1867        }
1868      } else {
1869        Unknown(instr);
1870      }
1871      break;
1872    default:
1873      Unknown(instr);
1874      break;
1875  }
1876}
1877
1878#undef VERIFIY
1879
1880bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
1881  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1882  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
1883}
1884
1885
1886int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
1887  if (IsConstantPoolAt(instr_ptr)) {
1888    int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1889    return DecodeConstantPoolLength(instruction_bits);
1890  } else {
1891    return -1;
1892  }
1893}
1894
1895
1896// Disassemble the instruction at *instr_ptr into the output buffer.
1897int Decoder::InstructionDecode(byte* instr_ptr) {
1898  Instruction* instr = Instruction::At(instr_ptr);
1899  // Print raw instruction bytes.
1900  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1901                              "%08x       ",
1902                              instr->InstructionBits());
1903  if (instr->ConditionField() == kSpecialCondition) {
1904    DecodeSpecialCondition(instr);
1905    return Instruction::kInstrSize;
1906  }
1907  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1908  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
1909    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1910                                "constant pool begin (length %d)",
1911                                DecodeConstantPoolLength(instruction_bits));
1912    return Instruction::kInstrSize;
1913  } else if (instruction_bits == kCodeAgeJumpInstruction) {
1914    // The code age prologue has a constant immediatly following the jump
1915    // instruction.
1916    Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize);
1917    DecodeType2(instr);
1918    SNPrintF(out_buffer_ + out_buffer_pos_,
1919             " (0x%08x)", target->InstructionBits());
1920    return 2 * Instruction::kInstrSize;
1921  }
1922  switch (instr->TypeValue()) {
1923    case 0:
1924    case 1: {
1925      DecodeType01(instr);
1926      break;
1927    }
1928    case 2: {
1929      DecodeType2(instr);
1930      break;
1931    }
1932    case 3: {
1933      DecodeType3(instr);
1934      break;
1935    }
1936    case 4: {
1937      DecodeType4(instr);
1938      break;
1939    }
1940    case 5: {
1941      DecodeType5(instr);
1942      break;
1943    }
1944    case 6: {
1945      DecodeType6(instr);
1946      break;
1947    }
1948    case 7: {
1949      return DecodeType7(instr);
1950    }
1951    default: {
1952      // The type field is 3-bits in the ARM encoding.
1953      UNREACHABLE();
1954      break;
1955    }
1956  }
1957  return Instruction::kInstrSize;
1958}
1959
1960
1961}  // namespace internal
1962}  // namespace v8
1963
1964
1965//------------------------------------------------------------------------------
1966
1967namespace disasm {
1968
1969
1970const char* NameConverter::NameOfAddress(byte* addr) const {
1971  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1972  return tmp_buffer_.start();
1973}
1974
1975
1976const char* NameConverter::NameOfConstant(byte* addr) const {
1977  return NameOfAddress(addr);
1978}
1979
1980
1981const char* NameConverter::NameOfCPURegister(int reg) const {
1982  return v8::internal::Register::from_code(reg).ToString();
1983}
1984
1985
1986const char* NameConverter::NameOfByteCPURegister(int reg) const {
1987  UNREACHABLE();  // ARM does not have the concept of a byte register
1988  return "nobytereg";
1989}
1990
1991
1992const char* NameConverter::NameOfXMMRegister(int reg) const {
1993  UNREACHABLE();  // ARM does not have any XMM registers
1994  return "noxmmreg";
1995}
1996
1997
1998const char* NameConverter::NameInCode(byte* addr) const {
1999  // The default name converter is called for unknown code. So we will not try
2000  // to access any memory.
2001  return "";
2002}
2003
2004
2005//------------------------------------------------------------------------------
2006
2007Disassembler::Disassembler(const NameConverter& converter)
2008    : converter_(converter) {}
2009
2010
2011Disassembler::~Disassembler() {}
2012
2013
2014int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2015                                    byte* instruction) {
2016  v8::internal::Decoder d(converter_, buffer);
2017  return d.InstructionDecode(instruction);
2018}
2019
2020
2021int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2022  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
2023}
2024
2025
2026void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
2027  NameConverter converter;
2028  Disassembler d(converter);
2029  for (byte* pc = begin; pc < end;) {
2030    v8::internal::EmbeddedVector<char, 128> buffer;
2031    buffer[0] = '\0';
2032    byte* prev_pc = pc;
2033    pc += d.InstructionDecode(buffer, pc);
2034    v8::internal::PrintF(
2035        f, "%p    %08x      %s\n",
2036        prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2037  }
2038}
2039
2040
2041}  // namespace disasm
2042
2043#endif  // V8_TARGET_ARCH_ARM
2044