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* const 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, i.e. 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 {
506          if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
507              (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
508            if (instr->Bit(5) == 1) {
509              Print("strd");
510            } else {
511              Print("ldrd");
512            }
513            return 5;
514          }
515          Print("str");
516        }
517        return 5;
518      }
519      // 'msg: for simulator break instructions
520      ASSERT(STRING_STARTS_WITH(format, "msg"));
521      byte* str =
522          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
523      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
524                                      "%s", converter_.NameInCode(str));
525      return 3;
526    }
527    case 'o': {
528      if ((format[3] == '1') && (format[4] == '2')) {
529        // 'off12: 12-bit offset for load and store instructions
530        ASSERT(STRING_STARTS_WITH(format, "off12"));
531        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
532                                        "%d", instr->Offset12Value());
533        return 5;
534      } else if (format[3] == '0') {
535        // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
536        ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19"));
537        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
538                                        "%d",
539                                        (instr->Bits(19, 8) << 4) +
540                                        instr->Bits(3, 0));
541        return 15;
542      }
543      // 'off8: 8-bit offset for extra load and store instructions
544      ASSERT(STRING_STARTS_WITH(format, "off8"));
545      int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
546      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
547                                      "%d", offs8);
548      return 4;
549    }
550    case 'p': {  // 'pu: P and U bits for load and store instructions
551      ASSERT(STRING_STARTS_WITH(format, "pu"));
552      PrintPU(instr);
553      return 2;
554    }
555    case 'r': {
556      return FormatRegister(instr, format);
557    }
558    case 's': {
559      if (format[1] == 'h') {  // 'shift_op or 'shift_rm or 'shift_sat.
560        if (format[6] == 'o') {  // 'shift_op
561          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
562          if (instr->TypeValue() == 0) {
563            PrintShiftRm(instr);
564          } else {
565            ASSERT(instr->TypeValue() == 1);
566            PrintShiftImm(instr);
567          }
568          return 8;
569        } else if (format[6] == 's') {  // 'shift_sat.
570          ASSERT(STRING_STARTS_WITH(format, "shift_sat"));
571          PrintShiftSat(instr);
572          return 9;
573        } else {  // 'shift_rm
574          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
575          PrintShiftRm(instr);
576          return 8;
577        }
578      } else if (format[1] == 'v') {  // 'svc
579        ASSERT(STRING_STARTS_WITH(format, "svc"));
580        PrintSoftwareInterrupt(instr->SvcValue());
581        return 3;
582      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
583        ASSERT(STRING_STARTS_WITH(format, "sign"));
584        if (instr->HasSign()) {
585          Print("s");
586        }
587        return 4;
588      }
589      // 's: S field of data processing instructions
590      if (instr->HasS()) {
591        Print("s");
592      }
593      return 1;
594    }
595    case 't': {  // 'target: target of branch instructions
596      ASSERT(STRING_STARTS_WITH(format, "target"));
597      int off = (instr->SImmed24Value() << 2) + 8;
598      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
599                                      "%+d -> %s",
600                                      off,
601                                      converter_.NameOfAddress(
602                                        reinterpret_cast<byte*>(instr) + off));
603      return 6;
604    }
605    case 'u': {  // 'u: signed or unsigned multiplies
606      // The manual gets the meaning of bit 22 backwards in the multiply
607      // instruction overview on page A3.16.2.  The instructions that
608      // exist in u and s variants are the following:
609      // smull A4.1.87
610      // umull A4.1.129
611      // umlal A4.1.128
612      // smlal A4.1.76
613      // For these 0 means u and 1 means s.  As can be seen on their individual
614      // pages.  The other 18 mul instructions have the bit set or unset in
615      // arbitrary ways that are unrelated to the signedness of the instruction.
616      // None of these 18 instructions exist in both a 'u' and an 's' variant.
617
618      if (instr->Bit(22) == 0) {
619        Print("u");
620      } else {
621        Print("s");
622      }
623      return 1;
624    }
625    case 'v': {
626      return FormatVFPinstruction(instr, format);
627    }
628    case 'S':
629    case 'D': {
630      return FormatVFPRegister(instr, format);
631    }
632    case 'w': {  // 'w: W field of load and store instructions
633      if (instr->HasW()) {
634        Print("!");
635      }
636      return 1;
637    }
638    default: {
639      UNREACHABLE();
640      break;
641    }
642  }
643  UNREACHABLE();
644  return -1;
645}
646
647
648// Format takes a formatting string for a whole instruction and prints it into
649// the output buffer. All escaped options are handed to FormatOption to be
650// parsed further.
651void Decoder::Format(Instruction* instr, const char* format) {
652  char cur = *format++;
653  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
654    if (cur == '\'') {  // Single quote is used as the formatting escape.
655      format += FormatOption(instr, format);
656    } else {
657      out_buffer_[out_buffer_pos_++] = cur;
658    }
659    cur = *format++;
660  }
661  out_buffer_[out_buffer_pos_]  = '\0';
662}
663
664
665// The disassembler may end up decoding data inlined in the code. We do not want
666// it to crash if the data does not ressemble any known instruction.
667#define VERIFY(condition) \
668if(!(condition)) {        \
669  Unknown(instr);         \
670  return;                 \
671}
672
673
674// For currently unimplemented decodings the disassembler calls Unknown(instr)
675// which will just print "unknown" of the instruction bits.
676void Decoder::Unknown(Instruction* instr) {
677  Format(instr, "unknown");
678}
679
680
681void Decoder::DecodeType01(Instruction* instr) {
682  int type = instr->TypeValue();
683  if ((type == 0) && instr->IsSpecialType0()) {
684    // multiply instruction or extra loads and stores
685    if (instr->Bits(7, 4) == 9) {
686      if (instr->Bit(24) == 0) {
687        // multiply instructions
688        if (instr->Bit(23) == 0) {
689          if (instr->Bit(21) == 0) {
690            // The MUL instruction description (A 4.1.33) refers to Rd as being
691            // the destination for the operation, but it confusingly uses the
692            // Rn field to encode it.
693            Format(instr, "mul'cond's 'rn, 'rm, 'rs");
694          } else {
695            // The MLA instruction description (A 4.1.28) refers to the order
696            // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
697            // Rn field to encode the Rd register and the Rd field to encode
698            // the Rn register.
699            Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
700          }
701        } else {
702          // The signed/long multiply instructions use the terms RdHi and RdLo
703          // when referring to the target registers. They are mapped to the Rn
704          // and Rd fields as follows:
705          // RdLo == Rd field
706          // RdHi == Rn field
707          // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
708          Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
709        }
710      } else {
711        Unknown(instr);  // not used by V8
712      }
713    } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
714      // ldrd, strd
715      switch (instr->PUField()) {
716        case da_x: {
717          if (instr->Bit(22) == 0) {
718            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
719          } else {
720            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
721          }
722          break;
723        }
724        case ia_x: {
725          if (instr->Bit(22) == 0) {
726            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
727          } else {
728            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
729          }
730          break;
731        }
732        case db_x: {
733          if (instr->Bit(22) == 0) {
734            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
735          } else {
736            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
737          }
738          break;
739        }
740        case ib_x: {
741          if (instr->Bit(22) == 0) {
742            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
743          } else {
744            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
745          }
746          break;
747        }
748        default: {
749          // The PU field is a 2-bit field.
750          UNREACHABLE();
751          break;
752        }
753      }
754    } else {
755      // extra load/store instructions
756      switch (instr->PUField()) {
757        case da_x: {
758          if (instr->Bit(22) == 0) {
759            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
760          } else {
761            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
762          }
763          break;
764        }
765        case ia_x: {
766          if (instr->Bit(22) == 0) {
767            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
768          } else {
769            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
770          }
771          break;
772        }
773        case db_x: {
774          if (instr->Bit(22) == 0) {
775            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
776          } else {
777            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
778          }
779          break;
780        }
781        case ib_x: {
782          if (instr->Bit(22) == 0) {
783            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
784          } else {
785            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
786          }
787          break;
788        }
789        default: {
790          // The PU field is a 2-bit field.
791          UNREACHABLE();
792          break;
793        }
794      }
795      return;
796    }
797  } else if ((type == 0) && instr->IsMiscType0()) {
798    if (instr->Bits(22, 21) == 1) {
799      switch (instr->BitField(7, 4)) {
800        case BX:
801          Format(instr, "bx'cond 'rm");
802          break;
803        case BLX:
804          Format(instr, "blx'cond 'rm");
805          break;
806        case BKPT:
807          Format(instr, "bkpt 'off0to3and8to19");
808          break;
809        default:
810          Unknown(instr);  // not used by V8
811          break;
812      }
813    } else if (instr->Bits(22, 21) == 3) {
814      switch (instr->BitField(7, 4)) {
815        case CLZ:
816          Format(instr, "clz'cond 'rd, 'rm");
817          break;
818        default:
819          Unknown(instr);  // not used by V8
820          break;
821      }
822    } else {
823      Unknown(instr);  // not used by V8
824    }
825  } else {
826    switch (instr->OpcodeField()) {
827      case AND: {
828        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
829        break;
830      }
831      case EOR: {
832        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
833        break;
834      }
835      case SUB: {
836        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
837        break;
838      }
839      case RSB: {
840        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
841        break;
842      }
843      case ADD: {
844        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
845        break;
846      }
847      case ADC: {
848        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
849        break;
850      }
851      case SBC: {
852        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
853        break;
854      }
855      case RSC: {
856        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
857        break;
858      }
859      case TST: {
860        if (instr->HasS()) {
861          Format(instr, "tst'cond 'rn, 'shift_op");
862        } else {
863          Format(instr, "movw'cond 'mw");
864        }
865        break;
866      }
867      case TEQ: {
868        if (instr->HasS()) {
869          Format(instr, "teq'cond 'rn, 'shift_op");
870        } else {
871          // Other instructions matching this pattern are handled in the
872          // miscellaneous instructions part above.
873          UNREACHABLE();
874        }
875        break;
876      }
877      case CMP: {
878        if (instr->HasS()) {
879          Format(instr, "cmp'cond 'rn, 'shift_op");
880        } else {
881          Format(instr, "movt'cond 'mw");
882        }
883        break;
884      }
885      case CMN: {
886        if (instr->HasS()) {
887          Format(instr, "cmn'cond 'rn, 'shift_op");
888        } else {
889          // Other instructions matching this pattern are handled in the
890          // miscellaneous instructions part above.
891          UNREACHABLE();
892        }
893        break;
894      }
895      case ORR: {
896        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
897        break;
898      }
899      case MOV: {
900        Format(instr, "mov'cond's 'rd, 'shift_op");
901        break;
902      }
903      case BIC: {
904        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
905        break;
906      }
907      case MVN: {
908        Format(instr, "mvn'cond's 'rd, 'shift_op");
909        break;
910      }
911      default: {
912        // The Opcode field is a 4-bit field.
913        UNREACHABLE();
914        break;
915      }
916    }
917  }
918}
919
920
921void Decoder::DecodeType2(Instruction* instr) {
922  switch (instr->PUField()) {
923    case da_x: {
924      if (instr->HasW()) {
925        Unknown(instr);  // not used in V8
926        return;
927      }
928      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
929      break;
930    }
931    case ia_x: {
932      if (instr->HasW()) {
933        Unknown(instr);  // not used in V8
934        return;
935      }
936      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
937      break;
938    }
939    case db_x: {
940      Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
941      break;
942    }
943    case ib_x: {
944      Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
945      break;
946    }
947    default: {
948      // The PU field is a 2-bit field.
949      UNREACHABLE();
950      break;
951    }
952  }
953}
954
955
956void Decoder::DecodeType3(Instruction* instr) {
957  switch (instr->PUField()) {
958    case da_x: {
959      VERIFY(!instr->HasW());
960      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
961      break;
962    }
963    case ia_x: {
964      if (instr->HasW()) {
965        VERIFY(instr->Bits(5, 4) == 0x1);
966        if (instr->Bit(22) == 0x1) {
967          Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
968        } else {
969          UNREACHABLE();  // SSAT.
970        }
971      } else {
972        Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
973      }
974      break;
975    }
976    case db_x: {
977      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
978      break;
979    }
980    case ib_x: {
981      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
982        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
983        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
984        uint32_t msbit = widthminus1 + lsbit;
985        if (msbit <= 31) {
986          if (instr->Bit(22)) {
987            Format(instr, "ubfx'cond 'rd, 'rm, 'f");
988          } else {
989            Format(instr, "sbfx'cond 'rd, 'rm, 'f");
990          }
991        } else {
992          UNREACHABLE();
993        }
994      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
995        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
996        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
997        if (msbit >= lsbit) {
998          if (instr->RmValue() == 15) {
999            Format(instr, "bfc'cond 'rd, 'f");
1000          } else {
1001            Format(instr, "bfi'cond 'rd, 'rm, 'f");
1002          }
1003        } else {
1004          UNREACHABLE();
1005        }
1006      } else {
1007        Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1008      }
1009      break;
1010    }
1011    default: {
1012      // The PU field is a 2-bit field.
1013      UNREACHABLE();
1014      break;
1015    }
1016  }
1017}
1018
1019
1020void Decoder::DecodeType4(Instruction* instr) {
1021  if (instr->Bit(22) != 0) {
1022    // Privileged mode currently not supported.
1023    Unknown(instr);
1024  } else {
1025    if (instr->HasL()) {
1026      Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1027    } else {
1028      Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1029    }
1030  }
1031}
1032
1033
1034void Decoder::DecodeType5(Instruction* instr) {
1035  Format(instr, "b'l'cond 'target");
1036}
1037
1038
1039void Decoder::DecodeType6(Instruction* instr) {
1040  DecodeType6CoprocessorIns(instr);
1041}
1042
1043
1044int Decoder::DecodeType7(Instruction* instr) {
1045  if (instr->Bit(24) == 1) {
1046    if (instr->SvcValue() >= kStopCode) {
1047      Format(instr, "stop'cond 'svc");
1048      // Also print the stop message. Its address is encoded
1049      // in the following 4 bytes.
1050      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1051                                      "\n  %p  %08x       stop message: %s",
1052                                      reinterpret_cast<int32_t*>(instr
1053                                                     + Instruction::kInstrSize),
1054                                      *reinterpret_cast<char**>(instr
1055                                                    + Instruction::kInstrSize),
1056                                      *reinterpret_cast<char**>(instr
1057                                                    + Instruction::kInstrSize));
1058      // We have decoded 2 * Instruction::kInstrSize bytes.
1059      return 2 * Instruction::kInstrSize;
1060    } else {
1061      Format(instr, "svc'cond 'svc");
1062    }
1063  } else {
1064    DecodeTypeVFP(instr);
1065  }
1066  return Instruction::kInstrSize;
1067}
1068
1069
1070// void Decoder::DecodeTypeVFP(Instruction* instr)
1071// vmov: Sn = Rt
1072// vmov: Rt = Sn
1073// vcvt: Dd = Sm
1074// vcvt: Sd = Dm
1075// Dd = vabs(Dm)
1076// Dd = vneg(Dm)
1077// Dd = vadd(Dn, Dm)
1078// Dd = vsub(Dn, Dm)
1079// Dd = vmul(Dn, Dm)
1080// Dd = vdiv(Dn, Dm)
1081// vcmp(Dd, Dm)
1082// vmrs
1083// vmsr
1084// Dd = vsqrt(Dm)
1085void Decoder::DecodeTypeVFP(Instruction* instr) {
1086  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1087  VERIFY(instr->Bits(11, 9) == 0x5);
1088
1089  if (instr->Bit(4) == 0) {
1090    if (instr->Opc1Value() == 0x7) {
1091      // Other data processing instructions
1092      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1093        // vmov register to register.
1094        if (instr->SzValue() == 0x1) {
1095          Format(instr, "vmov.f64'cond 'Dd, 'Dm");
1096        } else {
1097          Format(instr, "vmov.f32'cond 'Sd, 'Sm");
1098        }
1099      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1100        // vabs
1101        Format(instr, "vabs.f64'cond 'Dd, 'Dm");
1102      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1103        // vneg
1104        Format(instr, "vneg.f64'cond 'Dd, 'Dm");
1105      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1106        DecodeVCVTBetweenDoubleAndSingle(instr);
1107      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1108        DecodeVCVTBetweenFloatingPointAndInteger(instr);
1109      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1110                 (instr->Opc3Value() & 0x1)) {
1111        DecodeVCVTBetweenFloatingPointAndInteger(instr);
1112      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1113                 (instr->Opc3Value() & 0x1)) {
1114        DecodeVCMP(instr);
1115      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1116        Format(instr, "vsqrt.f64'cond 'Dd, 'Dm");
1117      } else if (instr->Opc3Value() == 0x0) {
1118        if (instr->SzValue() == 0x1) {
1119          Format(instr, "vmov.f64'cond 'Dd, 'd");
1120        } else {
1121          Unknown(instr);  // Not used by V8.
1122        }
1123      } else {
1124        Unknown(instr);  // Not used by V8.
1125      }
1126    } else if (instr->Opc1Value() == 0x3) {
1127      if (instr->SzValue() == 0x1) {
1128        if (instr->Opc3Value() & 0x1) {
1129          Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
1130        } else {
1131          Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
1132        }
1133      } else {
1134        Unknown(instr);  // Not used by V8.
1135      }
1136    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1137      if (instr->SzValue() == 0x1) {
1138        Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
1139      } else {
1140        Unknown(instr);  // Not used by V8.
1141      }
1142    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1143      if (instr->SzValue() == 0x1) {
1144        Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
1145      } else {
1146        Unknown(instr);  // Not used by V8.
1147      }
1148    } else {
1149      Unknown(instr);  // Not used by V8.
1150    }
1151  } else {
1152    if ((instr->VCValue() == 0x0) &&
1153        (instr->VAValue() == 0x0)) {
1154      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1155    } else if ((instr->VCValue() == 0x0) &&
1156               (instr->VAValue() == 0x7) &&
1157               (instr->Bits(19, 16) == 0x1)) {
1158      if (instr->VLValue() == 0) {
1159        if (instr->Bits(15, 12) == 0xF) {
1160          Format(instr, "vmsr'cond FPSCR, APSR");
1161        } else {
1162          Format(instr, "vmsr'cond FPSCR, 'rt");
1163        }
1164      } else {
1165        if (instr->Bits(15, 12) == 0xF) {
1166          Format(instr, "vmrs'cond APSR, FPSCR");
1167        } else {
1168          Format(instr, "vmrs'cond 'rt, FPSCR");
1169        }
1170      }
1171    }
1172  }
1173}
1174
1175
1176void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1177    Instruction* instr) {
1178  VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1179         (instr->VAValue() == 0x0));
1180
1181  bool to_arm_register = (instr->VLValue() == 0x1);
1182
1183  if (to_arm_register) {
1184    Format(instr, "vmov'cond 'rt, 'Sn");
1185  } else {
1186    Format(instr, "vmov'cond 'Sn, 'rt");
1187  }
1188}
1189
1190
1191void Decoder::DecodeVCMP(Instruction* instr) {
1192  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1193  VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1194         (instr->Opc3Value() & 0x1));
1195
1196  // Comparison.
1197  bool dp_operation = (instr->SzValue() == 1);
1198  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1199
1200  if (dp_operation && !raise_exception_for_qnan) {
1201    if (instr->Opc2Value() == 0x4) {
1202      Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
1203    } else if (instr->Opc2Value() == 0x5) {
1204      Format(instr, "vcmp.f64'cond 'Dd, #0.0");
1205    } else {
1206      Unknown(instr);  // invalid
1207    }
1208  } else {
1209    Unknown(instr);  // Not used by V8.
1210  }
1211}
1212
1213
1214void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1215  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1216  VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1217
1218  bool double_to_single = (instr->SzValue() == 1);
1219
1220  if (double_to_single) {
1221    Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm");
1222  } else {
1223    Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm");
1224  }
1225}
1226
1227
1228void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1229  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1230  VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1231         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1232
1233  bool to_integer = (instr->Bit(18) == 1);
1234  bool dp_operation = (instr->SzValue() == 1);
1235  if (to_integer) {
1236    bool unsigned_integer = (instr->Bit(16) == 0);
1237
1238    if (dp_operation) {
1239      if (unsigned_integer) {
1240        Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm");
1241      } else {
1242        Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
1243      }
1244    } else {
1245      if (unsigned_integer) {
1246        Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm");
1247      } else {
1248        Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm");
1249      }
1250    }
1251  } else {
1252    bool unsigned_integer = (instr->Bit(7) == 0);
1253
1254    if (dp_operation) {
1255      if (unsigned_integer) {
1256        Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm");
1257      } else {
1258        Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
1259      }
1260    } else {
1261      if (unsigned_integer) {
1262        Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm");
1263      } else {
1264        Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm");
1265      }
1266    }
1267  }
1268}
1269
1270
1271// Decode Type 6 coprocessor instructions.
1272// Dm = vmov(Rt, Rt2)
1273// <Rt, Rt2> = vmov(Dm)
1274// Ddst = MEM(Rbase + 4*offset).
1275// MEM(Rbase + 4*offset) = Dsrc.
1276void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1277  VERIFY(instr->TypeValue() == 6);
1278
1279  if (instr->CoprocessorValue() == 0xA) {
1280    switch (instr->OpcodeValue()) {
1281      case 0x8:
1282      case 0xA:
1283        if (instr->HasL()) {
1284          Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1285        } else {
1286          Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1287        }
1288        break;
1289      case 0xC:
1290      case 0xE:
1291        if (instr->HasL()) {
1292          Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1293        } else {
1294          Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1295        }
1296        break;
1297      case 0x4:
1298      case 0x5:
1299      case 0x6:
1300      case 0x7:
1301      case 0x9:
1302      case 0xB: {
1303        bool to_vfp_register = (instr->VLValue() == 0x1);
1304        if (to_vfp_register) {
1305          Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1306        } else {
1307          Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1308        }
1309        break;
1310      }
1311      default:
1312        Unknown(instr);  // Not used by V8.
1313    }
1314  } else if (instr->CoprocessorValue() == 0xB) {
1315    switch (instr->OpcodeValue()) {
1316      case 0x2:
1317        // Load and store double to two GP registers
1318        if (instr->Bits(7, 4) != 0x1) {
1319          Unknown(instr);  // Not used by V8.
1320        } else if (instr->HasL()) {
1321          Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1322        } else {
1323          Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1324        }
1325        break;
1326      case 0x8:
1327        if (instr->HasL()) {
1328          Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1329        } else {
1330          Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1331        }
1332        break;
1333      case 0xC:
1334        if (instr->HasL()) {
1335          Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1336        } else {
1337          Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1338        }
1339        break;
1340      case 0x4:
1341      case 0x5:
1342      case 0x9: {
1343        bool to_vfp_register = (instr->VLValue() == 0x1);
1344        if (to_vfp_register) {
1345          Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1346        } else {
1347          Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1348        }
1349        break;
1350      }
1351      default:
1352        Unknown(instr);  // Not used by V8.
1353    }
1354  } else {
1355    Unknown(instr);  // Not used by V8.
1356  }
1357}
1358
1359#undef VERIFIY
1360
1361bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
1362  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1363  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
1364}
1365
1366
1367int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
1368  if (IsConstantPoolAt(instr_ptr)) {
1369    int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1370    return instruction_bits & kConstantPoolLengthMask;
1371  } else {
1372    return -1;
1373  }
1374}
1375
1376
1377// Disassemble the instruction at *instr_ptr into the output buffer.
1378int Decoder::InstructionDecode(byte* instr_ptr) {
1379  Instruction* instr = Instruction::At(instr_ptr);
1380  // Print raw instruction bytes.
1381  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1382                                  "%08x       ",
1383                                  instr->InstructionBits());
1384  if (instr->ConditionField() == kSpecialCondition) {
1385    Unknown(instr);
1386    return Instruction::kInstrSize;
1387  }
1388  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1389  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
1390    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1391                                    "constant pool begin (length %d)",
1392                                    instruction_bits &
1393                                    kConstantPoolLengthMask);
1394    return Instruction::kInstrSize;
1395  }
1396  switch (instr->TypeValue()) {
1397    case 0:
1398    case 1: {
1399      DecodeType01(instr);
1400      break;
1401    }
1402    case 2: {
1403      DecodeType2(instr);
1404      break;
1405    }
1406    case 3: {
1407      DecodeType3(instr);
1408      break;
1409    }
1410    case 4: {
1411      DecodeType4(instr);
1412      break;
1413    }
1414    case 5: {
1415      DecodeType5(instr);
1416      break;
1417    }
1418    case 6: {
1419      DecodeType6(instr);
1420      break;
1421    }
1422    case 7: {
1423      return DecodeType7(instr);
1424    }
1425    default: {
1426      // The type field is 3-bits in the ARM encoding.
1427      UNREACHABLE();
1428      break;
1429    }
1430  }
1431  return Instruction::kInstrSize;
1432}
1433
1434
1435} }  // namespace v8::internal
1436
1437
1438
1439//------------------------------------------------------------------------------
1440
1441namespace disasm {
1442
1443
1444const char* NameConverter::NameOfAddress(byte* addr) const {
1445  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
1446  return tmp_buffer_.start();
1447}
1448
1449
1450const char* NameConverter::NameOfConstant(byte* addr) const {
1451  return NameOfAddress(addr);
1452}
1453
1454
1455const char* NameConverter::NameOfCPURegister(int reg) const {
1456  return v8::internal::Registers::Name(reg);
1457}
1458
1459
1460const char* NameConverter::NameOfByteCPURegister(int reg) const {
1461  UNREACHABLE();  // ARM does not have the concept of a byte register
1462  return "nobytereg";
1463}
1464
1465
1466const char* NameConverter::NameOfXMMRegister(int reg) const {
1467  UNREACHABLE();  // ARM does not have any XMM registers
1468  return "noxmmreg";
1469}
1470
1471
1472const char* NameConverter::NameInCode(byte* addr) const {
1473  // The default name converter is called for unknown code. So we will not try
1474  // to access any memory.
1475  return "";
1476}
1477
1478
1479//------------------------------------------------------------------------------
1480
1481Disassembler::Disassembler(const NameConverter& converter)
1482    : converter_(converter) {}
1483
1484
1485Disassembler::~Disassembler() {}
1486
1487
1488int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1489                                    byte* instruction) {
1490  v8::internal::Decoder d(converter_, buffer);
1491  return d.InstructionDecode(instruction);
1492}
1493
1494
1495int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1496  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
1497}
1498
1499
1500void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1501  NameConverter converter;
1502  Disassembler d(converter);
1503  for (byte* pc = begin; pc < end;) {
1504    v8::internal::EmbeddedVector<char, 128> buffer;
1505    buffer[0] = '\0';
1506    byte* prev_pc = pc;
1507    pc += d.InstructionDecode(buffer, pc);
1508    fprintf(f, "%p    %08x      %s\n",
1509            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1510  }
1511}
1512
1513
1514}  // namespace disasm
1515
1516#endif  // V8_TARGET_ARCH_ARM
1517