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