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