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