disasm-arm.cc revision 80d68eab642096c1a48b6474d6ec33064b0ad1f5
1// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// A Disassembler object is used to disassemble a block of code instruction by
29// instruction. The default implementation of the NameConverter object can be
30// overriden to modify register names or to do symbol lookup on addresses.
31//
32// The example below will disassemble a block of code and print it to stdout.
33//
34//   NameConverter converter;
35//   Disassembler d(converter);
36//   for (byte* pc = begin; pc < end;) {
37//     v8::internal::EmbeddedVector<char, 256> buffer;
38//     byte* prev_pc = pc;
39//     pc += d.InstructionDecode(buffer, pc);
40//     printf("%p    %08x      %s\n",
41//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
42//   }
43//
44// The Disassembler class also has a convenience method to disassemble a block
45// of code into a FILE*, meaning that the above functionality could also be
46// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
47
48
49#include <assert.h>
50#include <stdio.h>
51#include <stdarg.h>
52#include <string.h>
53#ifndef WIN32
54#include <stdint.h>
55#endif
56
57#include "v8.h"
58
59#if defined(V8_TARGET_ARCH_ARM)
60
61#include "constants-arm.h"
62#include "disasm.h"
63#include "macro-assembler.h"
64#include "platform.h"
65
66
67namespace assembler {
68namespace arm {
69
70namespace v8i = v8::internal;
71
72
73//------------------------------------------------------------------------------
74
75// Decoder decodes and disassembles instructions into an output buffer.
76// It uses the converter to convert register names and call destinations into
77// more informative description.
78class Decoder {
79 public:
80  Decoder(const disasm::NameConverter& converter,
81          v8::internal::Vector<char> out_buffer)
82    : converter_(converter),
83      out_buffer_(out_buffer),
84      out_buffer_pos_(0) {
85    out_buffer_[out_buffer_pos_] = '\0';
86  }
87
88  ~Decoder() {}
89
90  // Writes one disassembled instruction into 'buffer' (0-terminated).
91  // Returns the length of the disassembled machine instruction in bytes.
92  int InstructionDecode(byte* instruction);
93
94 private:
95  // Bottleneck functions to print into the out_buffer.
96  void PrintChar(const char ch);
97  void Print(const char* str);
98
99  // Printing of common values.
100  void PrintRegister(int reg);
101  void PrintSRegister(int reg);
102  void PrintDRegister(int reg);
103  int FormatVFPRegister(Instr* instr, const char* format);
104  void PrintMovwMovt(Instr* instr);
105  int FormatVFPinstruction(Instr* instr, const char* format);
106  void PrintCondition(Instr* instr);
107  void PrintShiftRm(Instr* instr);
108  void PrintShiftImm(Instr* instr);
109  void PrintShiftSat(Instr* instr);
110  void PrintPU(Instr* instr);
111  void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
112
113  // Handle formatting of instructions and their options.
114  int FormatRegister(Instr* instr, const char* option);
115  int FormatOption(Instr* instr, const char* option);
116  void Format(Instr* instr, const char* format);
117  void Unknown(Instr* instr);
118
119  // Each of these functions decodes one particular instruction type, a 3-bit
120  // field in the instruction encoding.
121  // Types 0 and 1 are combined as they are largely the same except for the way
122  // they interpret the shifter operand.
123  void DecodeType01(Instr* instr);
124  void DecodeType2(Instr* instr);
125  void DecodeType3(Instr* instr);
126  void DecodeType4(Instr* instr);
127  void DecodeType5(Instr* instr);
128  void DecodeType6(Instr* instr);
129  void DecodeType7(Instr* instr);
130  void DecodeUnconditional(Instr* instr);
131  // For VFP support.
132  void DecodeTypeVFP(Instr* instr);
133  void DecodeType6CoprocessorIns(Instr* instr);
134
135  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr);
136  void DecodeVCMP(Instr* instr);
137  void DecodeVCVTBetweenDoubleAndSingle(Instr* instr);
138  void DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr);
139
140  const disasm::NameConverter& converter_;
141  v8::internal::Vector<char> out_buffer_;
142  int out_buffer_pos_;
143
144  DISALLOW_COPY_AND_ASSIGN(Decoder);
145};
146
147
148// Support for assertions in the Decoder formatting functions.
149#define STRING_STARTS_WITH(string, compare_string) \
150  (strncmp(string, compare_string, strlen(compare_string)) == 0)
151
152
153// Append the ch to the output buffer.
154void Decoder::PrintChar(const char ch) {
155  out_buffer_[out_buffer_pos_++] = ch;
156}
157
158
159// Append the str to the output buffer.
160void Decoder::Print(const char* str) {
161  char cur = *str++;
162  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
163    PrintChar(cur);
164    cur = *str++;
165  }
166  out_buffer_[out_buffer_pos_] = 0;
167}
168
169
170// These condition names are defined in a way to match the native disassembler
171// formatting. See for example the command "objdump -d <binary file>".
172static const char* cond_names[max_condition] = {
173  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
174  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
175};
176
177
178// Print the condition guarding the instruction.
179void Decoder::PrintCondition(Instr* instr) {
180  Print(cond_names[instr->ConditionField()]);
181}
182
183
184// Print the register name according to the active name converter.
185void Decoder::PrintRegister(int reg) {
186  Print(converter_.NameOfCPURegister(reg));
187}
188
189// Print the VFP S register name according to the active name converter.
190void Decoder::PrintSRegister(int reg) {
191  Print(assembler::arm::VFPRegisters::Name(reg, false));
192}
193
194// Print the  VFP D register name according to the active name converter.
195void Decoder::PrintDRegister(int reg) {
196  Print(assembler::arm::VFPRegisters::Name(reg, true));
197}
198
199
200// These shift names are defined in a way to match the native disassembler
201// formatting. See for example the command "objdump -d <binary file>".
202static const char* shift_names[max_shift] = {
203  "lsl", "lsr", "asr", "ror"
204};
205
206
207// Print the register shift operands for the instruction. Generally used for
208// data processing instructions.
209void Decoder::PrintShiftRm(Instr* instr) {
210  Shift shift = instr->ShiftField();
211  int shift_amount = instr->ShiftAmountField();
212  int rm = instr->RmField();
213
214  PrintRegister(rm);
215
216  if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
217    // Special case for using rm only.
218    return;
219  }
220  if (instr->RegShiftField() == 0) {
221    // by immediate
222    if ((shift == ROR) && (shift_amount == 0)) {
223      Print(", RRX");
224      return;
225    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
226      shift_amount = 32;
227    }
228    out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
229                                         ", %s #%d",
230                                         shift_names[shift], shift_amount);
231  } else {
232    // by register
233    int rs = instr->RsField();
234    out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
235                                         ", %s ", shift_names[shift]);
236    PrintRegister(rs);
237  }
238}
239
240
241// Print the immediate operand for the instruction. Generally used for data
242// processing instructions.
243void Decoder::PrintShiftImm(Instr* instr) {
244  int rotate = instr->RotateField() * 2;
245  int immed8 = instr->Immed8Field();
246  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
247  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
248                                       "#%d", imm);
249}
250
251
252// Print the optional shift and immediate used by saturating instructions.
253void Decoder::PrintShiftSat(Instr* instr) {
254  int shift = instr->Bits(11, 7);
255  if (shift > 0) {
256    out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
257                                         ", %s #%d",
258                                         shift_names[instr->Bit(6) * 2],
259                                         instr->Bits(11, 7));
260  }
261}
262
263
264// Print PU formatting to reduce complexity of FormatOption.
265void Decoder::PrintPU(Instr* instr) {
266  switch (instr->PUField()) {
267    case 0: {
268      Print("da");
269      break;
270    }
271    case 1: {
272      Print("ia");
273      break;
274    }
275    case 2: {
276      Print("db");
277      break;
278    }
279    case 3: {
280      Print("ib");
281      break;
282    }
283    default: {
284      UNREACHABLE();
285      break;
286    }
287  }
288}
289
290
291// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
292// the FormatOption method.
293void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
294  switch (swi) {
295    case call_rt_redirected:
296      Print("call_rt_redirected");
297      return;
298    case break_point:
299      Print("break_point");
300      return;
301    default:
302      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
303                                           "%d",
304                                           swi);
305      return;
306  }
307}
308
309
310// Handle all register based formatting in this function to reduce the
311// complexity of FormatOption.
312int Decoder::FormatRegister(Instr* instr, const char* format) {
313  ASSERT(format[0] == 'r');
314  if (format[1] == 'n') {  // 'rn: Rn register
315    int reg = instr->RnField();
316    PrintRegister(reg);
317    return 2;
318  } else if (format[1] == 'd') {  // 'rd: Rd register
319    int reg = instr->RdField();
320    PrintRegister(reg);
321    return 2;
322  } else if (format[1] == 's') {  // 'rs: Rs register
323    int reg = instr->RsField();
324    PrintRegister(reg);
325    return 2;
326  } else if (format[1] == 'm') {  // 'rm: Rm register
327    int reg = instr->RmField();
328    PrintRegister(reg);
329    return 2;
330  } else if (format[1] == 't') {  // 'rt: Rt register
331    int reg = instr->RtField();
332    PrintRegister(reg);
333    return 2;
334  } else if (format[1] == 'l') {
335    // 'rlist: register list for load and store multiple instructions
336    ASSERT(STRING_STARTS_WITH(format, "rlist"));
337    int rlist = instr->RlistField();
338    int reg = 0;
339    Print("{");
340    // Print register list in ascending order, by scanning the bit mask.
341    while (rlist != 0) {
342      if ((rlist & 1) != 0) {
343        PrintRegister(reg);
344        if ((rlist >> 1) != 0) {
345          Print(", ");
346        }
347      }
348      reg++;
349      rlist >>= 1;
350    }
351    Print("}");
352    return 5;
353  }
354  UNREACHABLE();
355  return -1;
356}
357
358
359// Handle all VFP register based formatting in this function to reduce the
360// complexity of FormatOption.
361int Decoder::FormatVFPRegister(Instr* instr, const char* format) {
362  ASSERT((format[0] == 'S') || (format[0] == 'D'));
363
364  if (format[1] == 'n') {
365    int reg = instr->VnField();
366    if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField()));
367    if (format[0] == 'D') PrintDRegister(reg);
368    return 2;
369  } else if (format[1] == 'm') {
370    int reg = instr->VmField();
371    if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->MField()));
372    if (format[0] == 'D') PrintDRegister(reg);
373    return 2;
374  } else if (format[1] == 'd') {
375    int reg = instr->VdField();
376    if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->DField()));
377    if (format[0] == 'D') PrintDRegister(reg);
378    return 2;
379  }
380
381  UNREACHABLE();
382  return -1;
383}
384
385
386int Decoder::FormatVFPinstruction(Instr* instr, const char* format) {
387    Print(format);
388    return 0;
389}
390
391
392// Print the movw or movt instruction.
393void Decoder::PrintMovwMovt(Instr* instr) {
394  int imm = instr->ImmedMovwMovtField();
395  int rd = instr->RdField();
396  PrintRegister(rd);
397  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
398                                       ", #%d", imm);
399}
400
401
402// FormatOption takes a formatting string and interprets it based on
403// the current instructions. The format string points to the first
404// character of the option string (the option escape has already been
405// consumed by the caller.)  FormatOption returns the number of
406// characters that were consumed from the formatting string.
407int Decoder::FormatOption(Instr* instr, const char* format) {
408  switch (format[0]) {
409    case 'a': {  // 'a: accumulate multiplies
410      if (instr->Bit(21) == 0) {
411        Print("ul");
412      } else {
413        Print("la");
414      }
415      return 1;
416    }
417    case 'b': {  // 'b: byte loads or stores
418      if (instr->HasB()) {
419        Print("b");
420      }
421      return 1;
422    }
423    case 'c': {  // 'cond: conditional execution
424      ASSERT(STRING_STARTS_WITH(format, "cond"));
425      PrintCondition(instr);
426      return 4;
427    }
428    case 'd': {  // 'd: vmov double immediate.
429      double d = instr->DoubleImmedVmov();
430      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
431                                           "#%g", d);
432      return 1;
433    }
434    case 'f': {  // 'f: bitfield instructions - v7 and above.
435      uint32_t lsbit = instr->Bits(11, 7);
436      uint32_t width = instr->Bits(20, 16) + 1;
437      if (instr->Bit(21) == 0) {
438        // BFC/BFI:
439        // Bits 20-16 represent most-significant bit. Covert to width.
440        width -= lsbit;
441        ASSERT(width > 0);
442      }
443      ASSERT((width + lsbit) <= 32);
444      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
445                                           "#%d, #%d", lsbit, width);
446      return 1;
447    }
448    case 'h': {  // 'h: halfword operation for extra loads and stores
449      if (instr->HasH()) {
450        Print("h");
451      } else {
452        Print("b");
453      }
454      return 1;
455    }
456    case 'i': {  // 'i: immediate value from adjacent bits.
457      // Expects tokens in the form imm%02d@%02d, ie. imm05@07, imm10@16
458      int width = (format[3] - '0') * 10 + (format[4] - '0');
459      int lsb   = (format[6] - '0') * 10 + (format[7] - '0');
460
461      ASSERT((width >= 1) && (width <= 32));
462      ASSERT((lsb >= 0) && (lsb <= 31));
463      ASSERT((width + lsb) <= 32);
464
465      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
466                                           "%d",
467                                           instr->Bits(width + lsb - 1, lsb));
468      return 8;
469    }
470    case 'l': {  // 'l: branch and link
471      if (instr->HasLink()) {
472        Print("l");
473      }
474      return 1;
475    }
476    case 'm': {
477      if (format[1] == 'w') {
478        // 'mw: movt/movw instructions.
479        PrintMovwMovt(instr);
480        return 2;
481      }
482      if (format[1] == 'e') {  // 'memop: load/store instructions.
483        ASSERT(STRING_STARTS_WITH(format, "memop"));
484        if (instr->HasL()) {
485          Print("ldr");
486        } else if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0)) {
487          if (instr->Bits(7, 4) == 0xf) {
488            Print("strd");
489          } else {
490            Print("ldrd");
491          }
492        } else {
493          Print("str");
494        }
495        return 5;
496      }
497      // 'msg: for simulator break instructions
498      ASSERT(STRING_STARTS_WITH(format, "msg"));
499      byte* str =
500          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
501      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
502                                           "%s", converter_.NameInCode(str));
503      return 3;
504    }
505    case 'o': {
506      if ((format[3] == '1') && (format[4] == '2')) {
507        // 'off12: 12-bit offset for load and store instructions
508        ASSERT(STRING_STARTS_WITH(format, "off12"));
509        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
510                                             "%d", instr->Offset12Field());
511        return 5;
512      } else if (format[3] == '0') {
513        // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
514        ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19"));
515        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
516                                            "%d",
517                                            (instr->Bits(19, 8) << 4) +
518                                                instr->Bits(3, 0));
519        return 15;
520      }
521      // 'off8: 8-bit offset for extra load and store instructions
522      ASSERT(STRING_STARTS_WITH(format, "off8"));
523      int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
524      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
525                                           "%d", offs8);
526      return 4;
527    }
528    case 'p': {  // 'pu: P and U bits for load and store instructions
529      ASSERT(STRING_STARTS_WITH(format, "pu"));
530      PrintPU(instr);
531      return 2;
532    }
533    case 'r': {
534      return FormatRegister(instr, format);
535    }
536    case 's': {
537      if (format[1] == 'h') {  // 'shift_op or 'shift_rm or 'shift_sat.
538        if (format[6] == 'o') {  // 'shift_op
539          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
540          if (instr->TypeField() == 0) {
541            PrintShiftRm(instr);
542          } else {
543            ASSERT(instr->TypeField() == 1);
544            PrintShiftImm(instr);
545          }
546          return 8;
547        } else if (format[6] == 's') {  // 'shift_sat.
548          ASSERT(STRING_STARTS_WITH(format, "shift_sat"));
549          PrintShiftSat(instr);
550          return 9;
551        } else {  // 'shift_rm
552          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
553          PrintShiftRm(instr);
554          return 8;
555        }
556      } else if (format[1] == 'w') {  // 'swi
557        ASSERT(STRING_STARTS_WITH(format, "swi"));
558        PrintSoftwareInterrupt(instr->SwiField());
559        return 3;
560      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
561        ASSERT(STRING_STARTS_WITH(format, "sign"));
562        if (instr->HasSign()) {
563          Print("s");
564        }
565        return 4;
566      }
567      // 's: S field of data processing instructions
568      if (instr->HasS()) {
569        Print("s");
570      }
571      return 1;
572    }
573    case 't': {  // 'target: target of branch instructions
574      ASSERT(STRING_STARTS_WITH(format, "target"));
575      int off = (instr->SImmed24Field() << 2) + 8;
576      out_buffer_pos_ += v8i::OS::SNPrintF(
577          out_buffer_ + out_buffer_pos_,
578          "%+d -> %s",
579          off,
580          converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
581      return 6;
582    }
583    case 'u': {  // 'u: signed or unsigned multiplies
584      // The manual gets the meaning of bit 22 backwards in the multiply
585      // instruction overview on page A3.16.2.  The instructions that
586      // exist in u and s variants are the following:
587      // smull A4.1.87
588      // umull A4.1.129
589      // umlal A4.1.128
590      // smlal A4.1.76
591      // For these 0 means u and 1 means s.  As can be seen on their individual
592      // pages.  The other 18 mul instructions have the bit set or unset in
593      // arbitrary ways that are unrelated to the signedness of the instruction.
594      // None of these 18 instructions exist in both a 'u' and an 's' variant.
595
596      if (instr->Bit(22) == 0) {
597        Print("u");
598      } else {
599        Print("s");
600      }
601      return 1;
602    }
603    case 'v': {
604      return FormatVFPinstruction(instr, format);
605    }
606    case 'S':
607    case 'D': {
608      return FormatVFPRegister(instr, format);
609    }
610    case 'w': {  // 'w: W field of load and store instructions
611      if (instr->HasW()) {
612        Print("!");
613      }
614      return 1;
615    }
616    default: {
617      UNREACHABLE();
618      break;
619    }
620  }
621  UNREACHABLE();
622  return -1;
623}
624
625
626// Format takes a formatting string for a whole instruction and prints it into
627// the output buffer. All escaped options are handed to FormatOption to be
628// parsed further.
629void Decoder::Format(Instr* instr, const char* format) {
630  char cur = *format++;
631  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
632    if (cur == '\'') {  // Single quote is used as the formatting escape.
633      format += FormatOption(instr, format);
634    } else {
635      out_buffer_[out_buffer_pos_++] = cur;
636    }
637    cur = *format++;
638  }
639  out_buffer_[out_buffer_pos_]  = '\0';
640}
641
642
643// For currently unimplemented decodings the disassembler calls Unknown(instr)
644// which will just print "unknown" of the instruction bits.
645void Decoder::Unknown(Instr* instr) {
646  Format(instr, "unknown");
647}
648
649
650void Decoder::DecodeType01(Instr* instr) {
651  int type = instr->TypeField();
652  if ((type == 0) && instr->IsSpecialType0()) {
653    // multiply instruction or extra loads and stores
654    if (instr->Bits(7, 4) == 9) {
655      if (instr->Bit(24) == 0) {
656        // multiply instructions
657        if (instr->Bit(23) == 0) {
658          if (instr->Bit(21) == 0) {
659            // The MUL instruction description (A 4.1.33) refers to Rd as being
660            // the destination for the operation, but it confusingly uses the
661            // Rn field to encode it.
662            Format(instr, "mul'cond's 'rn, 'rm, 'rs");
663          } else {
664            // The MLA instruction description (A 4.1.28) refers to the order
665            // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
666            // Rn field to encode the Rd register and the Rd field to encode
667            // the Rn register.
668            Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
669          }
670        } else {
671          // The signed/long multiply instructions use the terms RdHi and RdLo
672          // when referring to the target registers. They are mapped to the Rn
673          // and Rd fields as follows:
674          // RdLo == Rd field
675          // RdHi == Rn field
676          // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
677          Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
678        }
679      } else {
680        Unknown(instr);  // not used by V8
681      }
682    } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
683      // ldrd, strd
684      switch (instr->PUField()) {
685        case 0: {
686          if (instr->Bit(22) == 0) {
687            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
688          } else {
689            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
690          }
691          break;
692        }
693        case 1: {
694          if (instr->Bit(22) == 0) {
695            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
696          } else {
697            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
698          }
699          break;
700        }
701        case 2: {
702          if (instr->Bit(22) == 0) {
703            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
704          } else {
705            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
706          }
707          break;
708        }
709        case 3: {
710          if (instr->Bit(22) == 0) {
711            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
712          } else {
713            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
714          }
715          break;
716        }
717        default: {
718          // The PU field is a 2-bit field.
719          UNREACHABLE();
720          break;
721        }
722      }
723    } else {
724      // extra load/store instructions
725      switch (instr->PUField()) {
726        case 0: {
727          if (instr->Bit(22) == 0) {
728            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
729          } else {
730            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
731          }
732          break;
733        }
734        case 1: {
735          if (instr->Bit(22) == 0) {
736            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
737          } else {
738            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
739          }
740          break;
741        }
742        case 2: {
743          if (instr->Bit(22) == 0) {
744            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
745          } else {
746            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
747          }
748          break;
749        }
750        case 3: {
751          if (instr->Bit(22) == 0) {
752            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
753          } else {
754            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
755          }
756          break;
757        }
758        default: {
759          // The PU field is a 2-bit field.
760          UNREACHABLE();
761          break;
762        }
763      }
764      return;
765    }
766  } else if ((type == 0) && instr->IsMiscType0()) {
767    if (instr->Bits(22, 21) == 1) {
768      switch (instr->Bits(7, 4)) {
769        case BX:
770          Format(instr, "bx'cond 'rm");
771          break;
772        case BLX:
773          Format(instr, "blx'cond 'rm");
774          break;
775        case BKPT:
776          Format(instr, "bkpt 'off0to3and8to19");
777          break;
778        default:
779          Unknown(instr);  // not used by V8
780          break;
781      }
782    } else if (instr->Bits(22, 21) == 3) {
783      switch (instr->Bits(7, 4)) {
784        case CLZ:
785          Format(instr, "clz'cond 'rd, 'rm");
786          break;
787        default:
788          Unknown(instr);  // not used by V8
789          break;
790      }
791    } else {
792      Unknown(instr);  // not used by V8
793    }
794  } else {
795    switch (instr->OpcodeField()) {
796      case AND: {
797        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
798        break;
799      }
800      case EOR: {
801        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
802        break;
803      }
804      case SUB: {
805        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
806        break;
807      }
808      case RSB: {
809        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
810        break;
811      }
812      case ADD: {
813        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
814        break;
815      }
816      case ADC: {
817        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
818        break;
819      }
820      case SBC: {
821        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
822        break;
823      }
824      case RSC: {
825        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
826        break;
827      }
828      case TST: {
829        if (instr->HasS()) {
830          Format(instr, "tst'cond 'rn, 'shift_op");
831        } else {
832          Format(instr, "movw'cond 'mw");
833        }
834        break;
835      }
836      case TEQ: {
837        if (instr->HasS()) {
838          Format(instr, "teq'cond 'rn, 'shift_op");
839        } else {
840          // Other instructions matching this pattern are handled in the
841          // miscellaneous instructions part above.
842          UNREACHABLE();
843        }
844        break;
845      }
846      case CMP: {
847        if (instr->HasS()) {
848          Format(instr, "cmp'cond 'rn, 'shift_op");
849        } else {
850          Format(instr, "movt'cond 'mw");
851        }
852        break;
853      }
854      case CMN: {
855        if (instr->HasS()) {
856          Format(instr, "cmn'cond 'rn, 'shift_op");
857        } else {
858          // Other instructions matching this pattern are handled in the
859          // miscellaneous instructions part above.
860          UNREACHABLE();
861        }
862        break;
863      }
864      case ORR: {
865        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
866        break;
867      }
868      case MOV: {
869        Format(instr, "mov'cond's 'rd, 'shift_op");
870        break;
871      }
872      case BIC: {
873        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
874        break;
875      }
876      case MVN: {
877        Format(instr, "mvn'cond's 'rd, 'shift_op");
878        break;
879      }
880      default: {
881        // The Opcode field is a 4-bit field.
882        UNREACHABLE();
883        break;
884      }
885    }
886  }
887}
888
889
890void Decoder::DecodeType2(Instr* instr) {
891  switch (instr->PUField()) {
892    case 0: {
893      if (instr->HasW()) {
894        Unknown(instr);  // not used in V8
895      }
896      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
897      break;
898    }
899    case 1: {
900      if (instr->HasW()) {
901        Unknown(instr);  // not used in V8
902      }
903      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
904      break;
905    }
906    case 2: {
907      Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
908      break;
909    }
910    case 3: {
911      Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
912      break;
913    }
914    default: {
915      // The PU field is a 2-bit field.
916      UNREACHABLE();
917      break;
918    }
919  }
920}
921
922
923void Decoder::DecodeType3(Instr* instr) {
924  switch (instr->PUField()) {
925    case 0: {
926      ASSERT(!instr->HasW());
927      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
928      break;
929    }
930    case 1: {
931      if (instr->HasW()) {
932        ASSERT(instr->Bits(5, 4) == 0x1);
933        if (instr->Bit(22) == 0x1) {
934          Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
935        } else {
936          UNREACHABLE();  // SSAT.
937        }
938      } else {
939        Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
940      }
941      break;
942    }
943    case 2: {
944      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
945      break;
946    }
947    case 3: {
948      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
949        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
950        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
951        uint32_t msbit = widthminus1 + lsbit;
952        if (msbit <= 31) {
953          if (instr->Bit(22)) {
954            Format(instr, "ubfx'cond 'rd, 'rm, 'f");
955          } else {
956            Format(instr, "sbfx'cond 'rd, 'rm, 'f");
957          }
958        } else {
959          UNREACHABLE();
960        }
961      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
962        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
963        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
964        if (msbit >= lsbit) {
965          if (instr->RmField() == 15) {
966            Format(instr, "bfc'cond 'rd, 'f");
967          } else {
968            Format(instr, "bfi'cond 'rd, 'rm, 'f");
969          }
970        } else {
971          UNREACHABLE();
972        }
973      } else {
974        Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
975      }
976      break;
977    }
978    default: {
979      // The PU field is a 2-bit field.
980      UNREACHABLE();
981      break;
982    }
983  }
984}
985
986
987void Decoder::DecodeType4(Instr* instr) {
988  ASSERT(instr->Bit(22) == 0);  // Privileged mode currently not supported.
989  if (instr->HasL()) {
990    Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
991  } else {
992    Format(instr, "stm'cond'pu 'rn'w, 'rlist");
993  }
994}
995
996
997void Decoder::DecodeType5(Instr* instr) {
998  Format(instr, "b'l'cond 'target");
999}
1000
1001
1002void Decoder::DecodeType6(Instr* instr) {
1003  DecodeType6CoprocessorIns(instr);
1004}
1005
1006
1007void Decoder::DecodeType7(Instr* instr) {
1008  if (instr->Bit(24) == 1) {
1009    Format(instr, "swi'cond 'swi");
1010  } else {
1011    DecodeTypeVFP(instr);
1012  }
1013}
1014
1015void Decoder::DecodeUnconditional(Instr* instr) {
1016  if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
1017    Format(instr, "'memop'h'pu 'rd, ");
1018    bool immediate = instr->HasB();
1019    switch (instr->PUField()) {
1020      case 0: {
1021        // Post index, negative.
1022        if (instr->HasW()) {
1023          Unknown(instr);
1024          break;
1025        }
1026        if (immediate) {
1027          Format(instr, "['rn], #-'imm12");
1028        } else {
1029          Format(instr, "['rn], -'rm");
1030        }
1031        break;
1032      }
1033      case 1: {
1034        // Post index, positive.
1035        if (instr->HasW()) {
1036          Unknown(instr);
1037          break;
1038        }
1039        if (immediate) {
1040          Format(instr, "['rn], #+'imm12");
1041        } else {
1042          Format(instr, "['rn], +'rm");
1043        }
1044        break;
1045      }
1046      case 2: {
1047        // Pre index or offset, negative.
1048        if (immediate) {
1049          Format(instr, "['rn, #-'imm12]'w");
1050        } else {
1051          Format(instr, "['rn, -'rm]'w");
1052        }
1053        break;
1054      }
1055      case 3: {
1056        // Pre index or offset, positive.
1057        if (immediate) {
1058          Format(instr, "['rn, #+'imm12]'w");
1059        } else {
1060          Format(instr, "['rn, +'rm]'w");
1061        }
1062        break;
1063      }
1064      default: {
1065        // The PU field is a 2-bit field.
1066        UNREACHABLE();
1067        break;
1068      }
1069    }
1070    return;
1071  }
1072  Format(instr, "break 'msg");
1073}
1074
1075
1076// void Decoder::DecodeTypeVFP(Instr* instr)
1077// vmov: Sn = Rt
1078// vmov: Rt = Sn
1079// vcvt: Dd = Sm
1080// vcvt: Sd = Dm
1081// Dd = vadd(Dn, Dm)
1082// Dd = vsub(Dn, Dm)
1083// Dd = vmul(Dn, Dm)
1084// Dd = vdiv(Dn, Dm)
1085// vcmp(Dd, Dm)
1086// vmrs
1087// Dd = vsqrt(Dm)
1088void Decoder::DecodeTypeVFP(Instr* instr) {
1089  ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
1090  ASSERT(instr->Bits(11, 9) == 0x5);
1091
1092  if (instr->Bit(4) == 0) {
1093    if (instr->Opc1Field() == 0x7) {
1094      // Other data processing instructions
1095      if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) {
1096        // vmov register to register.
1097        if (instr->SzField() == 0x1) {
1098          Format(instr, "vmov.f64'cond 'Dd, 'Dm");
1099        } else {
1100          Format(instr, "vmov.f32'cond 'Sd, 'Sm");
1101        }
1102      } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) {
1103        DecodeVCVTBetweenDoubleAndSingle(instr);
1104      } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) {
1105        DecodeVCVTBetweenFloatingPointAndInteger(instr);
1106      } else if (((instr->Opc2Field() >> 1) == 0x6) &&
1107                 (instr->Opc3Field() & 0x1)) {
1108        DecodeVCVTBetweenFloatingPointAndInteger(instr);
1109      } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
1110                 (instr->Opc3Field() & 0x1)) {
1111        DecodeVCMP(instr);
1112      } else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) {
1113        Format(instr, "vsqrt.f64'cond 'Dd, 'Dm");
1114      } else if (instr->Opc3Field() == 0x0) {
1115        if (instr->SzField() == 0x1) {
1116          Format(instr, "vmov.f64'cond 'Dd, 'd");
1117        } else {
1118          Unknown(instr);  // Not used by V8.
1119        }
1120      } else {
1121        Unknown(instr);  // Not used by V8.
1122      }
1123    } else if (instr->Opc1Field() == 0x3) {
1124      if (instr->SzField() == 0x1) {
1125        if (instr->Opc3Field() & 0x1) {
1126          Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
1127        } else {
1128          Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
1129        }
1130      } else {
1131        Unknown(instr);  // Not used by V8.
1132      }
1133    } else if ((instr->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) {
1134      if (instr->SzField() == 0x1) {
1135        Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
1136      } else {
1137        Unknown(instr);  // Not used by V8.
1138      }
1139    } else if ((instr->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) {
1140      if (instr->SzField() == 0x1) {
1141        Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
1142      } else {
1143        Unknown(instr);  // Not used by V8.
1144      }
1145    } else {
1146      Unknown(instr);  // Not used by V8.
1147    }
1148  } else {
1149    if ((instr->VCField() == 0x0) &&
1150        (instr->VAField() == 0x0)) {
1151      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1152    } else if ((instr->VLField() == 0x1) &&
1153               (instr->VCField() == 0x0) &&
1154               (instr->VAField() == 0x7) &&
1155               (instr->Bits(19, 16) == 0x1)) {
1156      if (instr->Bits(15, 12) == 0xF)
1157        Format(instr, "vmrs'cond APSR, FPSCR");
1158      else
1159        Unknown(instr);  // Not used by V8.
1160    } else {
1161      Unknown(instr);  // Not used by V8.
1162    }
1163  }
1164}
1165
1166
1167void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) {
1168  ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) &&
1169         (instr->VAField() == 0x0));
1170
1171  bool to_arm_register = (instr->VLField() == 0x1);
1172
1173  if (to_arm_register) {
1174    Format(instr, "vmov'cond 'rt, 'Sn");
1175  } else {
1176    Format(instr, "vmov'cond 'Sn, 'rt");
1177  }
1178}
1179
1180
1181void Decoder::DecodeVCMP(Instr* instr) {
1182  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
1183  ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
1184         (instr->Opc3Field() & 0x1));
1185
1186  // Comparison.
1187  bool dp_operation = (instr->SzField() == 1);
1188  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1189
1190  if (dp_operation && !raise_exception_for_qnan) {
1191    if (instr->Opc2Field() == 0x4) {
1192      Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
1193    } else if (instr->Opc2Field() == 0x5) {
1194      Format(instr, "vcmp.f64'cond 'Dd, #0.0");
1195    } else {
1196      Unknown(instr);  // invalid
1197    }
1198  } else {
1199    Unknown(instr);  // Not used by V8.
1200  }
1201}
1202
1203
1204void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) {
1205  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
1206  ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3));
1207
1208  bool double_to_single = (instr->SzField() == 1);
1209
1210  if (double_to_single) {
1211    Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm");
1212  } else {
1213    Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm");
1214  }
1215}
1216
1217
1218void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
1219  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
1220  ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) ||
1221         (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1)));
1222
1223  bool to_integer = (instr->Bit(18) == 1);
1224  bool dp_operation = (instr->SzField() == 1);
1225  if (to_integer) {
1226    bool unsigned_integer = (instr->Bit(16) == 0);
1227
1228    if (dp_operation) {
1229      if (unsigned_integer) {
1230        Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm");
1231      } else {
1232        Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
1233      }
1234    } else {
1235      if (unsigned_integer) {
1236        Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm");
1237      } else {
1238        Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm");
1239      }
1240    }
1241  } else {
1242    bool unsigned_integer = (instr->Bit(7) == 0);
1243
1244    if (dp_operation) {
1245      if (unsigned_integer) {
1246        Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm");
1247      } else {
1248        Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
1249      }
1250    } else {
1251      if (unsigned_integer) {
1252        Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm");
1253      } else {
1254        Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm");
1255      }
1256    }
1257  }
1258}
1259
1260
1261// Decode Type 6 coprocessor instructions.
1262// Dm = vmov(Rt, Rt2)
1263// <Rt, Rt2> = vmov(Dm)
1264// Ddst = MEM(Rbase + 4*offset).
1265// MEM(Rbase + 4*offset) = Dsrc.
1266void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
1267  ASSERT((instr->TypeField() == 6));
1268
1269  if (instr->CoprocessorField() == 0xA) {
1270    switch (instr->OpcodeField()) {
1271      case 0x8:
1272      case 0xA:
1273        if (instr->HasL()) {
1274          Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1275        } else {
1276          Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1277        }
1278        break;
1279      case 0xC:
1280      case 0xE:
1281        if (instr->HasL()) {
1282          Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1283        } else {
1284          Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1285        }
1286        break;
1287      default:
1288        Unknown(instr);  // Not used by V8.
1289        break;
1290    }
1291  } else if (instr->CoprocessorField() == 0xB) {
1292    switch (instr->OpcodeField()) {
1293      case 0x2:
1294        // Load and store double to two GP registers
1295        if (instr->Bits(7, 4) != 0x1) {
1296          Unknown(instr);  // Not used by V8.
1297        } else if (instr->HasL()) {
1298          Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1299        } else {
1300          Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1301        }
1302        break;
1303      case 0x8:
1304        if (instr->HasL()) {
1305          Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1306        } else {
1307          Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1308        }
1309        break;
1310      case 0xC:
1311        if (instr->HasL()) {
1312          Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1313        } else {
1314          Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1315        }
1316        break;
1317      default:
1318        Unknown(instr);  // Not used by V8.
1319        break;
1320    }
1321  } else {
1322    UNIMPLEMENTED();  // Not used by V8.
1323  }
1324}
1325
1326
1327// Disassemble the instruction at *instr_ptr into the output buffer.
1328int Decoder::InstructionDecode(byte* instr_ptr) {
1329  Instr* instr = Instr::At(instr_ptr);
1330  // Print raw instruction bytes.
1331  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1332                                       "%08x       ",
1333                                       instr->InstructionBits());
1334  if (instr->ConditionField() == special_condition) {
1335    DecodeUnconditional(instr);
1336    return Instr::kInstrSize;
1337  }
1338  switch (instr->TypeField()) {
1339    case 0:
1340    case 1: {
1341      DecodeType01(instr);
1342      break;
1343    }
1344    case 2: {
1345      DecodeType2(instr);
1346      break;
1347    }
1348    case 3: {
1349      DecodeType3(instr);
1350      break;
1351    }
1352    case 4: {
1353      DecodeType4(instr);
1354      break;
1355    }
1356    case 5: {
1357      DecodeType5(instr);
1358      break;
1359    }
1360    case 6: {
1361      DecodeType6(instr);
1362      break;
1363    }
1364    case 7: {
1365      DecodeType7(instr);
1366      break;
1367    }
1368    default: {
1369      // The type field is 3-bits in the ARM encoding.
1370      UNREACHABLE();
1371      break;
1372    }
1373  }
1374  return Instr::kInstrSize;
1375}
1376
1377
1378} }  // namespace assembler::arm
1379
1380
1381
1382//------------------------------------------------------------------------------
1383
1384namespace disasm {
1385
1386namespace v8i = v8::internal;
1387
1388
1389const char* NameConverter::NameOfAddress(byte* addr) const {
1390  static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
1391  v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
1392  return tmp_buffer.start();
1393}
1394
1395
1396const char* NameConverter::NameOfConstant(byte* addr) const {
1397  return NameOfAddress(addr);
1398}
1399
1400
1401const char* NameConverter::NameOfCPURegister(int reg) const {
1402  return assembler::arm::Registers::Name(reg);
1403}
1404
1405
1406const char* NameConverter::NameOfByteCPURegister(int reg) const {
1407  UNREACHABLE();  // ARM does not have the concept of a byte register
1408  return "nobytereg";
1409}
1410
1411
1412const char* NameConverter::NameOfXMMRegister(int reg) const {
1413  UNREACHABLE();  // ARM does not have any XMM registers
1414  return "noxmmreg";
1415}
1416
1417
1418const char* NameConverter::NameInCode(byte* addr) const {
1419  // The default name converter is called for unknown code. So we will not try
1420  // to access any memory.
1421  return "";
1422}
1423
1424
1425//------------------------------------------------------------------------------
1426
1427Disassembler::Disassembler(const NameConverter& converter)
1428    : converter_(converter) {}
1429
1430
1431Disassembler::~Disassembler() {}
1432
1433
1434int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1435                                    byte* instruction) {
1436  assembler::arm::Decoder d(converter_, buffer);
1437  return d.InstructionDecode(instruction);
1438}
1439
1440
1441int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1442  int instruction_bits = *(reinterpret_cast<int*>(instruction));
1443  if ((instruction_bits & 0xfff00000) == 0x03000000) {
1444    return instruction_bits & 0x0000ffff;
1445  } else {
1446    return -1;
1447  }
1448}
1449
1450
1451void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1452  NameConverter converter;
1453  Disassembler d(converter);
1454  for (byte* pc = begin; pc < end;) {
1455    v8::internal::EmbeddedVector<char, 128> buffer;
1456    buffer[0] = '\0';
1457    byte* prev_pc = pc;
1458    pc += d.InstructionDecode(buffer, pc);
1459    fprintf(f, "%p    %08x      %s\n",
1460            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1461  }
1462}
1463
1464
1465}  // namespace disasm
1466
1467#endif  // V8_TARGET_ARCH_ARM
1468