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