Upgrade to 3.29

Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.

Bug: 17370214

Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 96a7d3c..85977b1 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -1,29 +1,6 @@
 // Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
 
 // A Disassembler object is used to disassemble a block of code instruction by
 // instruction. The default implementation of the NameConverter object can be
@@ -47,21 +24,18 @@
 
 
 #include <assert.h>
-#include <stdio.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
-#ifndef WIN32
-#include <stdint.h>
-#endif
 
-#include "v8.h"
+#include "src/v8.h"
 
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
 
-#include "constants-arm.h"
-#include "disasm.h"
-#include "macro-assembler.h"
-#include "platform.h"
+#include "src/arm/constants-arm.h"
+#include "src/base/platform/platform.h"
+#include "src/disasm.h"
+#include "src/macro-assembler.h"
 
 
 namespace v8 {
@@ -113,6 +87,8 @@
 
   // Handle formatting of instructions and their options.
   int FormatRegister(Instruction* instr, const char* option);
+  void FormatNeonList(int Vd, int type);
+  void FormatNeonMemory(int Rn, int align, int Rm);
   int FormatOption(Instruction* instr, const char* option);
   void Format(Instruction* instr, const char* format);
   void Unknown(Instruction* instr);
@@ -133,6 +109,8 @@
   void DecodeTypeVFP(Instruction* instr);
   void DecodeType6CoprocessorIns(Instruction* instr);
 
+  void DecodeSpecialCondition(Instruction* instr);
+
   void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
   void DecodeVCMP(Instruction* instr);
   void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
@@ -187,12 +165,14 @@
   Print(converter_.NameOfCPURegister(reg));
 }
 
+
 // Print the VFP S register name according to the active name converter.
 void Decoder::PrintSRegister(int reg) {
   Print(VFPRegisters::Name(reg, false));
 }
 
-// Print the  VFP D register name according to the active name converter.
+
+// Print the VFP D register name according to the active name converter.
 void Decoder::PrintDRegister(int reg) {
   Print(VFPRegisters::Name(reg, true));
 }
@@ -227,15 +207,15 @@
     } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
       shift_amount = 32;
     }
-    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                    ", %s #%d",
-                                    shift_names[shift_index],
-                                    shift_amount);
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                ", %s #%d",
+                                shift_names[shift_index],
+                                shift_amount);
   } else {
     // by register
     int rs = instr->RsValue();
-    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                    ", %s ", shift_names[shift_index]);
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                ", %s ", shift_names[shift_index]);
     PrintRegister(rs);
   }
 }
@@ -247,8 +227,7 @@
   int rotate = instr->RotateValue() * 2;
   int immed8 = instr->Immed8Value();
   int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
-  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                  "#%d", imm);
+  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
 }
 
 
@@ -256,10 +235,10 @@
 void Decoder::PrintShiftSat(Instruction* instr) {
   int shift = instr->Bits(11, 7);
   if (shift > 0) {
-    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                    ", %s #%d",
-                                    shift_names[instr->Bit(6) * 2],
-                                    instr->Bits(11, 7));
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                ", %s #%d",
+                                shift_names[instr->Bit(6) * 2],
+                                instr->Bits(11, 7));
   }
 }
 
@@ -303,14 +282,14 @@
       return;
     default:
       if (svc >= kStopCode) {
-        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                        "%d - 0x%x",
-                                        svc & kStopCodeMask,
-                                        svc & kStopCodeMask);
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "%d - 0x%x",
+                                    svc & kStopCodeMask,
+                                    svc & kStopCodeMask);
       } else {
-        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                        "%d",
-                                        svc);
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "%d",
+                                    svc);
       }
       return;
   }
@@ -320,7 +299,7 @@
 // Handle all register based formatting in this function to reduce the
 // complexity of FormatOption.
 int Decoder::FormatRegister(Instruction* instr, const char* format) {
-  ASSERT(format[0] == 'r');
+  DCHECK(format[0] == 'r');
   if (format[1] == 'n') {  // 'rn: Rn register
     int reg = instr->RnValue();
     PrintRegister(reg);
@@ -343,7 +322,7 @@
     return 2;
   } else if (format[1] == 'l') {
     // 'rlist: register list for load and store multiple instructions
-    ASSERT(STRING_STARTS_WITH(format, "rlist"));
+    DCHECK(STRING_STARTS_WITH(format, "rlist"));
     int rlist = instr->RlistValue();
     int reg = 0;
     Print("{");
@@ -369,7 +348,7 @@
 // Handle all VFP register based formatting in this function to reduce the
 // complexity of FormatOption.
 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
-  ASSERT((format[0] == 'S') || (format[0] == 'D'));
+  DCHECK((format[0] == 'S') || (format[0] == 'D'));
 
   VFPRegPrecision precision =
       format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
@@ -381,7 +360,16 @@
   } else if (format[1] == 'm') {
     reg = instr->VFPMRegValue(precision);
   } else if (format[1] == 'd') {
-    reg = instr->VFPDRegValue(precision);
+    if ((instr->TypeValue() == 7) &&
+        (instr->Bit(24) == 0x0) &&
+        (instr->Bits(11, 9) == 0x5) &&
+        (instr->Bit(4) == 0x1)) {
+      // vmov.32 has Vd in a different place.
+      reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
+    } else {
+      reg = instr->VFPDRegValue(precision);
+    }
+
     if (format[2] == '+') {
       int immed8 = instr->Immed8Value();
       if (format[0] == 'S') reg += immed8 - 1;
@@ -408,13 +396,47 @@
 }
 
 
+void Decoder::FormatNeonList(int Vd, int type) {
+  if (type == nlt_1) {
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                "{d%d}", Vd);
+  } else if (type == nlt_2) {
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                "{d%d, d%d}", Vd, Vd + 1);
+  } else if (type == nlt_3) {
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
+  } else if (type == nlt_4) {
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                        "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3);
+  }
+}
+
+
+void Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
+  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                              "[r%d", Rn);
+  if (align != 0) {
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                ":%d", (1 << align) << 6);
+  }
+  if (Rm == 15) {
+    Print("]");
+  } else if (Rm == 13) {
+    Print("]!");
+  } else {
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                "], r%d", Rm);
+  }
+}
+
+
 // Print the movw or movt instruction.
 void Decoder::PrintMovwMovt(Instruction* instr) {
   int imm = instr->ImmedMovwMovtValue();
   int rd = instr->RdValue();
   PrintRegister(rd);
-  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                  ", #%d", imm);
+  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
 }
 
 
@@ -440,14 +462,13 @@
       return 1;
     }
     case 'c': {  // 'cond: conditional execution
-      ASSERT(STRING_STARTS_WITH(format, "cond"));
+      DCHECK(STRING_STARTS_WITH(format, "cond"));
       PrintCondition(instr);
       return 4;
     }
     case 'd': {  // 'd: vmov double immediate.
       double d = instr->DoubleImmedVmov();
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "#%g", d);
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
       return 1;
     }
     case 'f': {  // 'f: bitfield instructions - v7 and above.
@@ -457,11 +478,11 @@
         // BFC/BFI:
         // Bits 20-16 represent most-significant bit. Covert to width.
         width -= lsbit;
-        ASSERT(width > 0);
+        DCHECK(width > 0);
       }
-      ASSERT((width + lsbit) <= 32);
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "#%d, #%d", lsbit, width);
+      DCHECK((width + lsbit) <= 32);
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                  "#%d, #%d", lsbit, width);
       return 1;
     }
     case 'h': {  // 'h: halfword operation for extra loads and stores
@@ -477,13 +498,13 @@
       int width = (format[3] - '0') * 10 + (format[4] - '0');
       int lsb   = (format[6] - '0') * 10 + (format[7] - '0');
 
-      ASSERT((width >= 1) && (width <= 32));
-      ASSERT((lsb >= 0) && (lsb <= 31));
-      ASSERT((width + lsb) <= 32);
+      DCHECK((width >= 1) && (width <= 32));
+      DCHECK((lsb >= 0) && (lsb <= 31));
+      DCHECK((width + lsb) <= 32);
 
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "%d",
-                                      instr->Bits(width + lsb - 1, lsb));
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                  "%d",
+                                  instr->Bits(width + lsb - 1, lsb));
       return 8;
     }
     case 'l': {  // 'l: branch and link
@@ -499,7 +520,7 @@
         return 2;
       }
       if (format[1] == 'e') {  // 'memop: load/store instructions.
-        ASSERT(STRING_STARTS_WITH(format, "memop"));
+        DCHECK(STRING_STARTS_WITH(format, "memop"));
         if (instr->HasL()) {
           Print("ldr");
         } else {
@@ -517,38 +538,37 @@
         return 5;
       }
       // 'msg: for simulator break instructions
-      ASSERT(STRING_STARTS_WITH(format, "msg"));
+      DCHECK(STRING_STARTS_WITH(format, "msg"));
       byte* str =
           reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "%s", converter_.NameInCode(str));
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                  "%s", converter_.NameInCode(str));
       return 3;
     }
     case 'o': {
       if ((format[3] == '1') && (format[4] == '2')) {
         // 'off12: 12-bit offset for load and store instructions
-        ASSERT(STRING_STARTS_WITH(format, "off12"));
-        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                        "%d", instr->Offset12Value());
+        DCHECK(STRING_STARTS_WITH(format, "off12"));
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "%d", instr->Offset12Value());
         return 5;
       } else if (format[3] == '0') {
         // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
-        ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19"));
-        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                        "%d",
-                                        (instr->Bits(19, 8) << 4) +
-                                        instr->Bits(3, 0));
+        DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19"));
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "%d",
+                                    (instr->Bits(19, 8) << 4) +
+                                    instr->Bits(3, 0));
         return 15;
       }
       // 'off8: 8-bit offset for extra load and store instructions
-      ASSERT(STRING_STARTS_WITH(format, "off8"));
+      DCHECK(STRING_STARTS_WITH(format, "off8"));
       int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "%d", offs8);
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
       return 4;
     }
     case 'p': {  // 'pu: P and U bits for load and store instructions
-      ASSERT(STRING_STARTS_WITH(format, "pu"));
+      DCHECK(STRING_STARTS_WITH(format, "pu"));
       PrintPU(instr);
       return 2;
     }
@@ -558,29 +578,29 @@
     case 's': {
       if (format[1] == 'h') {  // 'shift_op or 'shift_rm or 'shift_sat.
         if (format[6] == 'o') {  // 'shift_op
-          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
+          DCHECK(STRING_STARTS_WITH(format, "shift_op"));
           if (instr->TypeValue() == 0) {
             PrintShiftRm(instr);
           } else {
-            ASSERT(instr->TypeValue() == 1);
+            DCHECK(instr->TypeValue() == 1);
             PrintShiftImm(instr);
           }
           return 8;
         } else if (format[6] == 's') {  // 'shift_sat.
-          ASSERT(STRING_STARTS_WITH(format, "shift_sat"));
+          DCHECK(STRING_STARTS_WITH(format, "shift_sat"));
           PrintShiftSat(instr);
           return 9;
         } else {  // 'shift_rm
-          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
+          DCHECK(STRING_STARTS_WITH(format, "shift_rm"));
           PrintShiftRm(instr);
           return 8;
         }
       } else if (format[1] == 'v') {  // 'svc
-        ASSERT(STRING_STARTS_WITH(format, "svc"));
+        DCHECK(STRING_STARTS_WITH(format, "svc"));
         PrintSoftwareInterrupt(instr->SvcValue());
         return 3;
       } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
-        ASSERT(STRING_STARTS_WITH(format, "sign"));
+        DCHECK(STRING_STARTS_WITH(format, "sign"));
         if (instr->HasSign()) {
           Print("s");
         }
@@ -593,13 +613,13 @@
       return 1;
     }
     case 't': {  // 'target: target of branch instructions
-      ASSERT(STRING_STARTS_WITH(format, "target"));
+      DCHECK(STRING_STARTS_WITH(format, "target"));
       int off = (instr->SImmed24Value() << 2) + 8;
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "%+d -> %s",
-                                      off,
-                                      converter_.NameOfAddress(
-                                        reinterpret_cast<byte*>(instr) + off));
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                  "%+d -> %s",
+                                  off,
+                                  converter_.NameOfAddress(
+                                    reinterpret_cast<byte*>(instr) + off));
       return 6;
     }
     case 'u': {  // 'u: signed or unsigned multiplies
@@ -692,11 +712,19 @@
             // Rn field to encode it.
             Format(instr, "mul'cond's 'rn, 'rm, 'rs");
           } else {
-            // The MLA instruction description (A 4.1.28) refers to the order
-            // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
-            // Rn field to encode the Rd register and the Rd field to encode
-            // the Rn register.
-            Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
+            if (instr->Bit(22) == 0) {
+              // The MLA instruction description (A 4.1.28) refers to the order
+              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
+              // Rn field to encode the Rd register and the Rd field to encode
+              // the Rn register.
+              Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
+            } else {
+              // The MLS instruction description (A 4.1.29) refers to the order
+              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
+              // Rn field to encode the Rd register and the Rd field to encode
+              // the Rn register.
+              Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
+            }
           }
         } else {
           // The signed/long multiply instructions use the terms RdHi and RdLo
@@ -822,6 +850,8 @@
     } else {
       Unknown(instr);  // not used by V8
     }
+  } else if ((type == 1) && instr->IsNopType1()) {
+    Format(instr, "nop'cond");
   } else {
     switch (instr->OpcodeField()) {
       case AND: {
@@ -961,19 +991,125 @@
       break;
     }
     case ia_x: {
-      if (instr->HasW()) {
-        VERIFY(instr->Bits(5, 4) == 0x1);
-        if (instr->Bit(22) == 0x1) {
-          Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
-        } else {
-          UNREACHABLE();  // SSAT.
-        }
-      } else {
+      if (instr->Bit(4) == 0) {
         Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
+      } else {
+        if (instr->Bit(5) == 0) {
+          switch (instr->Bits(22, 21)) {
+            case 0:
+              if (instr->Bit(20) == 0) {
+                if (instr->Bit(6) == 0) {
+                  Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
+                } else {
+                  if (instr->Bits(11, 7) == 0) {
+                    Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
+                  } else {
+                    Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
+                  }
+                }
+              } else {
+                UNREACHABLE();
+              }
+              break;
+            case 1:
+              UNREACHABLE();
+              break;
+            case 2:
+              UNREACHABLE();
+              break;
+            case 3:
+              Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
+              break;
+          }
+        } else {
+          switch (instr->Bits(22, 21)) {
+            case 0:
+              UNREACHABLE();
+              break;
+            case 1:
+              UNREACHABLE();
+              break;
+            case 2:
+              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
+                if (instr->Bits(19, 16) == 0xF) {
+                  switch (instr->Bits(11, 10)) {
+                    case 0:
+                      Format(instr, "uxtb16'cond 'rd, 'rm");
+                      break;
+                    case 1:
+                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
+                      break;
+                    case 2:
+                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
+                      break;
+                    case 3:
+                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
+                      break;
+                  }
+                } else {
+                  UNREACHABLE();
+                }
+              } else {
+                UNREACHABLE();
+              }
+              break;
+            case 3:
+              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
+                if (instr->Bits(19, 16) == 0xF) {
+                  switch (instr->Bits(11, 10)) {
+                    case 0:
+                      Format(instr, "uxtb'cond 'rd, 'rm");
+                      break;
+                    case 1:
+                      Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
+                      break;
+                    case 2:
+                      Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
+                      break;
+                    case 3:
+                      Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
+                      break;
+                  }
+                } else {
+                  switch (instr->Bits(11, 10)) {
+                    case 0:
+                      Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
+                      break;
+                    case 1:
+                      Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
+                      break;
+                    case 2:
+                      Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
+                      break;
+                    case 3:
+                      Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
+                      break;
+                  }
+                }
+              } else {
+                UNREACHABLE();
+              }
+              break;
+          }
+        }
       }
       break;
     }
     case db_x: {
+      if (FLAG_enable_sudiv) {
+        if (instr->Bits(5, 4) == 0x1) {
+          if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
+            if (instr->Bit(21) == 0x1) {
+              // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
+              Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
+            } else {
+              // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
+              Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
+            }
+            break;
+          }
+        }
+      }
       Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
       break;
     }
@@ -1047,14 +1183,14 @@
       Format(instr, "stop'cond 'svc");
       // Also print the stop message. Its address is encoded
       // in the following 4 bytes.
-      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                      "\n  %p  %08x       stop message: %s",
-                                      reinterpret_cast<int32_t*>(instr
-                                                     + Instruction::kInstrSize),
-                                      *reinterpret_cast<char**>(instr
-                                                    + Instruction::kInstrSize),
-                                      *reinterpret_cast<char**>(instr
-                                                    + Instruction::kInstrSize));
+      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                  "\n  %p  %08x       stop message: %s",
+                                  reinterpret_cast<void*>(instr
+                                                 + Instruction::kInstrSize),
+                                  *reinterpret_cast<uint32_t*>(instr
+                                                + Instruction::kInstrSize),
+                                  *reinterpret_cast<char**>(instr
+                                                + Instruction::kInstrSize));
       // We have decoded 2 * Instruction::kInstrSize bytes.
       return 2 * Instruction::kInstrSize;
     } else {
@@ -1072,11 +1208,14 @@
 // vmov: Rt = Sn
 // vcvt: Dd = Sm
 // vcvt: Sd = Dm
+// vcvt.f64.s32 Dd, Dd, #<fbits>
 // Dd = vabs(Dm)
 // Dd = vneg(Dm)
 // Dd = vadd(Dn, Dm)
 // Dd = vsub(Dn, Dm)
 // Dd = vmul(Dn, Dm)
+// Dd = vmla(Dn, Dm)
+// Dd = vmls(Dn, Dm)
 // Dd = vdiv(Dn, Dm)
 // vcmp(Dd, Dm)
 // vmrs
@@ -1092,20 +1231,27 @@
       if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
         // vmov register to register.
         if (instr->SzValue() == 0x1) {
-          Format(instr, "vmov.f64'cond 'Dd, 'Dm");
+          Format(instr, "vmov'cond.f64 'Dd, 'Dm");
         } else {
-          Format(instr, "vmov.f32'cond 'Sd, 'Sm");
+          Format(instr, "vmov'cond.f32 'Sd, 'Sm");
         }
       } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
         // vabs
-        Format(instr, "vabs.f64'cond 'Dd, 'Dm");
+        Format(instr, "vabs'cond.f64 'Dd, 'Dm");
       } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
         // vneg
-        Format(instr, "vneg.f64'cond 'Dd, 'Dm");
+        Format(instr, "vneg'cond.f64 'Dd, 'Dm");
       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
         DecodeVCVTBetweenFloatingPointAndInteger(instr);
+      } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
+                 (instr->Bit(8) == 1)) {
+        // vcvt.f64.s32 Dd, Dd, #<fbits>
+        int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
+        Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    ", #%d", fraction_bits);
       } else if (((instr->Opc2Value() >> 1) == 0x6) &&
                  (instr->Opc3Value() & 0x1)) {
         DecodeVCVTBetweenFloatingPointAndInteger(instr);
@@ -1113,10 +1259,10 @@
                  (instr->Opc3Value() & 0x1)) {
         DecodeVCMP(instr);
       } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
-        Format(instr, "vsqrt.f64'cond 'Dd, 'Dm");
+        Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
       } else if (instr->Opc3Value() == 0x0) {
         if (instr->SzValue() == 0x1) {
-          Format(instr, "vmov.f64'cond 'Dd, 'd");
+          Format(instr, "vmov'cond.f64 'Dd, 'd");
         } else {
           Unknown(instr);  // Not used by V8.
         }
@@ -1126,22 +1272,34 @@
     } else if (instr->Opc1Value() == 0x3) {
       if (instr->SzValue() == 0x1) {
         if (instr->Opc3Value() & 0x1) {
-          Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
+          Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
         } else {
-          Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
+          Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
         }
       } else {
         Unknown(instr);  // Not used by V8.
       }
     } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
       if (instr->SzValue() == 0x1) {
-        Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
+        Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
+      } else {
+        Unknown(instr);  // Not used by V8.
+      }
+    } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
+      if (instr->SzValue() == 0x1) {
+        Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
+      } else {
+        Unknown(instr);  // Not used by V8.
+      }
+    } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
+      if (instr->SzValue() == 0x1) {
+        Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
       } else {
         Unknown(instr);  // Not used by V8.
       }
     } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
       if (instr->SzValue() == 0x1) {
-        Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
+        Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
       } else {
         Unknown(instr);  // Not used by V8.
       }
@@ -1152,6 +1310,22 @@
     if ((instr->VCValue() == 0x0) &&
         (instr->VAValue() == 0x0)) {
       DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
+    } else if ((instr->VLValue() == 0x0) &&
+               (instr->VCValue() == 0x1) &&
+               (instr->Bit(23) == 0x0)) {
+      if (instr->Bit(21) == 0x0) {
+        Format(instr, "vmov'cond.32 'Dd[0], 'rt");
+      } else {
+        Format(instr, "vmov'cond.32 'Dd[1], 'rt");
+      }
+    } else if ((instr->VLValue() == 0x1) &&
+               (instr->VCValue() == 0x1) &&
+               (instr->Bit(23) == 0x0)) {
+      if (instr->Bit(21) == 0x0) {
+        Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
+      } else {
+        Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
+      }
     } else if ((instr->VCValue() == 0x0) &&
                (instr->VAValue() == 0x7) &&
                (instr->Bits(19, 16) == 0x1)) {
@@ -1199,9 +1373,9 @@
 
   if (dp_operation && !raise_exception_for_qnan) {
     if (instr->Opc2Value() == 0x4) {
-      Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
+      Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
     } else if (instr->Opc2Value() == 0x5) {
-      Format(instr, "vcmp.f64'cond 'Dd, #0.0");
+      Format(instr, "vcmp'cond.f64 'Dd, #0.0");
     } else {
       Unknown(instr);  // invalid
     }
@@ -1218,9 +1392,9 @@
   bool double_to_single = (instr->SzValue() == 1);
 
   if (double_to_single) {
-    Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm");
+    Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
   } else {
-    Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm");
+    Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
   }
 }
 
@@ -1237,15 +1411,15 @@
 
     if (dp_operation) {
       if (unsigned_integer) {
-        Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm");
+        Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
       } else {
-        Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
+        Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
       }
     } else {
       if (unsigned_integer) {
-        Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm");
+        Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
       } else {
-        Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm");
+        Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
       }
     }
   } else {
@@ -1253,15 +1427,15 @@
 
     if (dp_operation) {
       if (unsigned_integer) {
-        Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm");
+        Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
       } else {
-        Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
+        Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
       }
     } else {
       if (unsigned_integer) {
-        Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm");
+        Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
       } else {
-        Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm");
+        Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
       }
     }
   }
@@ -1315,7 +1489,7 @@
     switch (instr->OpcodeValue()) {
       case 0x2:
         // Load and store double to two GP registers
-        if (instr->Bits(7, 4) != 0x1) {
+        if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
           Unknown(instr);  // Not used by V8.
         } else if (instr->HasL()) {
           Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
@@ -1324,6 +1498,7 @@
         }
         break;
       case 0x8:
+      case 0xA:
         if (instr->HasL()) {
           Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
         } else {
@@ -1331,6 +1506,7 @@
         }
         break;
       case 0xC:
+      case 0xE:
         if (instr->HasL()) {
           Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
         } else {
@@ -1339,7 +1515,10 @@
         break;
       case 0x4:
       case 0x5:
-      case 0x9: {
+      case 0x6:
+      case 0x7:
+      case 0x9:
+      case 0xB: {
         bool to_vfp_register = (instr->VLValue() == 0x1);
         if (to_vfp_register) {
           Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
@@ -1356,6 +1535,93 @@
   }
 }
 
+
+void Decoder::DecodeSpecialCondition(Instruction* instr) {
+  switch (instr->SpecialValue()) {
+    case 5:
+      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
+          (instr->Bit(4) == 1)) {
+        // vmovl signed
+        if ((instr->VdValue() & 1) != 0) Unknown(instr);
+        int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
+        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
+        int imm3 = instr->Bits(21, 19);
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm);
+      } else {
+        Unknown(instr);
+      }
+      break;
+    case 7:
+      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
+          (instr->Bit(4) == 1)) {
+        // vmovl unsigned
+        if ((instr->VdValue() & 1) != 0) Unknown(instr);
+        int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
+        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
+        int imm3 = instr->Bits(21, 19);
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm);
+      } else {
+        Unknown(instr);
+      }
+      break;
+    case 8:
+      if (instr->Bits(21, 20) == 0) {
+        // vst1
+        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
+        int Rn = instr->VnValue();
+        int type = instr->Bits(11, 8);
+        int size = instr->Bits(7, 6);
+        int align = instr->Bits(5, 4);
+        int Rm = instr->VmValue();
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "vst1.%d ", (1 << size) << 3);
+        FormatNeonList(Vd, type);
+        Print(", ");
+        FormatNeonMemory(Rn, align, Rm);
+      } else if (instr->Bits(21, 20) == 2) {
+        // vld1
+        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
+        int Rn = instr->VnValue();
+        int type = instr->Bits(11, 8);
+        int size = instr->Bits(7, 6);
+        int align = instr->Bits(5, 4);
+        int Rm = instr->VmValue();
+        out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "vld1.%d ", (1 << size) << 3);
+        FormatNeonList(Vd, type);
+        Print(", ");
+        FormatNeonMemory(Rn, align, Rm);
+      } else {
+        Unknown(instr);
+      }
+      break;
+    case 0xA:
+    case 0xB:
+      if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
+        int Rn = instr->Bits(19, 16);
+        int offset = instr->Bits(11, 0);
+        if (offset == 0) {
+          out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "pld [r%d]", Rn);
+        } else if (instr->Bit(23) == 0) {
+          out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "pld [r%d, #-%d]", Rn, offset);
+        } else {
+          out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "pld [r%d, #+%d]", Rn, offset);
+        }
+      } else {
+        Unknown(instr);
+      }
+      break;
+    default:
+      Unknown(instr);
+      break;
+  }
+}
+
 #undef VERIFIY
 
 bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
@@ -1367,7 +1633,7 @@
 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
   if (IsConstantPoolAt(instr_ptr)) {
     int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
-    return instruction_bits & kConstantPoolLengthMask;
+    return DecodeConstantPoolLength(instruction_bits);
   } else {
     return -1;
   }
@@ -1378,20 +1644,27 @@
 int Decoder::InstructionDecode(byte* instr_ptr) {
   Instruction* instr = Instruction::At(instr_ptr);
   // Print raw instruction bytes.
-  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                  "%08x       ",
-                                  instr->InstructionBits());
+  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                              "%08x       ",
+                              instr->InstructionBits());
   if (instr->ConditionField() == kSpecialCondition) {
-    Unknown(instr);
+    DecodeSpecialCondition(instr);
     return Instruction::kInstrSize;
   }
   int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
   if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
-    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                    "constant pool begin (length %d)",
-                                    instruction_bits &
-                                    kConstantPoolLengthMask);
+    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                "constant pool begin (length %d)",
+                                DecodeConstantPoolLength(instruction_bits));
     return Instruction::kInstrSize;
+  } else if (instruction_bits == kCodeAgeJumpInstruction) {
+    // The code age prologue has a constant immediatly following the jump
+    // instruction.
+    Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize);
+    DecodeType2(instr);
+    SNPrintF(out_buffer_ + out_buffer_pos_,
+             " (0x%08x)", target->InstructionBits());
+    return 2 * Instruction::kInstrSize;
   }
   switch (instr->TypeValue()) {
     case 0:
@@ -1442,7 +1715,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
   return tmp_buffer_.start();
 }
 
@@ -1505,8 +1778,9 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    fprintf(f, "%p    %08x      %s\n",
-            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+    v8::internal::PrintF(
+        f, "%p    %08x      %s\n",
+        prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   }
 }