| Index: src/x64/disasm-x64.cc | 
| diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc | 
| index 837da27941d33666b527f29a77632b7ee7dc84cc..bb8f5430ccb0d3e03ad565f9e38290ae81f26b6c 100644 | 
| --- a/src/x64/disasm-x64.cc | 
| +++ b/src/x64/disasm-x64.cc | 
| @@ -148,6 +148,8 @@ enum Prefixes { | 
| ESCAPE_PREFIX = 0x0F, | 
| OPERAND_SIZE_OVERRIDE_PREFIX = 0x66, | 
| ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67, | 
| +  VEX3_PREFIX = 0xC4, | 
| +  VEX2_PREFIX = 0xC5, | 
| REPNE_PREFIX = 0xF2, | 
| REP_PREFIX = 0xF3, | 
| REPEQ_PREFIX = REP_PREFIX | 
| @@ -290,11 +292,14 @@ class DisassemblerX64 { | 
| ABORT_ON_UNIMPLEMENTED_OPCODE) | 
| : converter_(converter), | 
| tmp_buffer_pos_(0), | 
| -        abort_on_unimplemented_( | 
| -            unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE), | 
| +        abort_on_unimplemented_(unimplemented_action == | 
| +                                ABORT_ON_UNIMPLEMENTED_OPCODE), | 
| rex_(0), | 
| operand_size_(0), | 
| group_1_prefix_(0), | 
| +        vex_byte0_(0), | 
| +        vex_byte1_(0), | 
| +        vex_byte2_(0), | 
| byte_size_operand_(false), | 
| instruction_table_(instruction_table.Pointer()) { | 
| tmp_buffer_[0] = '\0'; | 
| @@ -323,6 +328,9 @@ class DisassemblerX64 { | 
| byte rex_; | 
| byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0. | 
| byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. | 
| +  byte vex_byte0_;       // 0xc4 or 0xc5 | 
| +  byte vex_byte1_; | 
| +  byte vex_byte2_;  // only for 3 bytes vex prefix | 
| // Byte size operand override. | 
| bool byte_size_operand_; | 
| const InstructionTable* const instruction_table_; | 
| @@ -345,6 +353,51 @@ class DisassemblerX64 { | 
|  | 
| bool rex_w() { return (rex_ & 0x08) != 0; } | 
|  | 
| +  bool vex_128() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 
| +    byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 
| +    return (checked & 4) != 1; | 
| +  } | 
| + | 
| +  bool vex_66() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 
| +    byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 
| +    return (checked & 3) == 1; | 
| +  } | 
| + | 
| +  bool vex_f3() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 
| +    byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 
| +    return (checked & 3) == 2; | 
| +  } | 
| + | 
| +  bool vex_f2() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 
| +    byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 
| +    return (checked & 3) == 3; | 
| +  } | 
| + | 
| +  bool vex_0f() { | 
| +    if (vex_byte0_ == VEX2_PREFIX) return true; | 
| +    return (vex_byte1_ & 3) == 1; | 
| +  } | 
| + | 
| +  bool vex_0f38() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX); | 
| +    return (vex_byte1_ & 3) == 2; | 
| +  } | 
| + | 
| +  bool vex_0f3a() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX); | 
| +    return (vex_byte1_ & 3) == 3; | 
| +  } | 
| + | 
| +  int vex_vreg() { | 
| +    DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 
| +    byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 
| +    return ~(checked >> 3) & 0xf; | 
| +  } | 
| + | 
| OperandSize operand_size() { | 
| if (byte_size_operand_) return OPERAND_BYTE_SIZE; | 
| if (rex_w()) return OPERAND_QUADWORD_SIZE; | 
| @@ -356,6 +409,8 @@ class DisassemblerX64 { | 
| return "bwlq"[operand_size()]; | 
| } | 
|  | 
| +  char float_size_code() { return "sd"[rex_w()]; } | 
| + | 
| const char* NameOfCPURegister(int reg) const { | 
| return converter_.NameOfCPURegister(reg); | 
| } | 
| @@ -414,6 +469,7 @@ class DisassemblerX64 { | 
| int FPUInstruction(byte* data); | 
| int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); | 
| int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); | 
| +  int AVXInstruction(byte* data); | 
| void AppendToBuffer(const char* format, ...); | 
|  | 
| void UnimplementedInstruction() { | 
| @@ -811,6 +867,92 @@ int DisassemblerX64::SetCC(byte* data) { | 
| } | 
|  | 
|  | 
| +int DisassemblerX64::AVXInstruction(byte* data) { | 
| +  byte opcode = *data; | 
| +  byte* current = data + 1; | 
| +  if (vex_byte0_ == VEX3_PREFIX) { | 
| +    if (vex_128()) { | 
| +      if (vex_66() && vex_0f38()) { | 
| +        int mod, regop, rm, vvvv = vex_vreg(); | 
| +        get_modrm(*current, &mod, ®op, &rm); | 
| +        switch (opcode) { | 
| +          case 0x99: | 
| +            AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xa9: | 
| +            AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xb9: | 
| +            AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0x9b: | 
| +            AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xab: | 
| +            AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xbb: | 
| +            AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0x9d: | 
| +            AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xad: | 
| +            AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xbd: | 
| +            AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0x9f: | 
| +            AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xaf: | 
| +            AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          case 0xbf: | 
| +            AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(), | 
| +                           NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 
| +            current += PrintRightXMMOperand(current); | 
| +            break; | 
| +          default: | 
| +            UnimplementedInstruction(); | 
| +        } | 
| +      } | 
| +    } else { | 
| +      UnimplementedInstruction(); | 
| +    } | 
| +  } else if (vex_byte0_ == VEX2_PREFIX) { | 
| +    UnimplementedInstruction(); | 
| +  } else { | 
| +    UNREACHABLE(); | 
| +  } | 
| + | 
| +  return static_cast<int>(current - data); | 
| +} | 
| + | 
| + | 
| // Returns number of bytes used, including *data. | 
| int DisassemblerX64::FPUInstruction(byte* data) { | 
| byte escape_opcode = *data; | 
| @@ -1189,6 +1331,16 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { | 
| AppendToBuffer("cvttss2si%c %s,", | 
| operand_size_code(), NameOfCPURegister(regop)); | 
| current += PrintRightXMMOperand(current); | 
| +    } else if (opcode == 0x58) { | 
| +      int mod, regop, rm; | 
| +      get_modrm(*current, &mod, ®op, &rm); | 
| +      AppendToBuffer("addss %s,", NameOfXMMRegister(regop)); | 
| +      current += PrintRightXMMOperand(current); | 
| +    } else if (opcode == 0x59) { | 
| +      int mod, regop, rm; | 
| +      get_modrm(*current, &mod, ®op, &rm); | 
| +      AppendToBuffer("mulss %s,", NameOfXMMRegister(regop)); | 
| +      current += PrintRightXMMOperand(current); | 
| } else if (opcode == 0x5A) { | 
| // CVTSS2SD: | 
| // Convert scalar single-precision FP to scalar double-precision FP. | 
| @@ -1196,6 +1348,16 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { | 
| get_modrm(*current, &mod, ®op, &rm); | 
| AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); | 
| current += PrintRightXMMOperand(current); | 
| +    } else if (opcode == 0x5c) { | 
| +      int mod, regop, rm; | 
| +      get_modrm(*current, &mod, ®op, &rm); | 
| +      AppendToBuffer("subss %s,", NameOfXMMRegister(regop)); | 
| +      current += PrintRightXMMOperand(current); | 
| +    } else if (opcode == 0x5e) { | 
| +      int mod, regop, rm; | 
| +      get_modrm(*current, &mod, ®op, &rm); | 
| +      AppendToBuffer("divss %s,", NameOfXMMRegister(regop)); | 
| +      current += PrintRightXMMOperand(current); | 
| } else if (opcode == 0x7E) { | 
| int mod, regop, rm; | 
| get_modrm(*current, &mod, ®op, &rm); | 
| @@ -1234,6 +1396,11 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { | 
| current += PrintRightXMMOperand(current); | 
| AppendToBuffer(",%s", NameOfXMMRegister(regop)); | 
|  | 
| +  } else if (opcode == 0x2e) { | 
| +    int mod, regop, rm; | 
| +    get_modrm(*current, &mod, ®op, &rm); | 
| +    AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop)); | 
| +    current += PrintRightXMMOperand(current); | 
| } else if (opcode == 0xA2) { | 
| // CPUID | 
| AppendToBuffer("%s", mnemonic); | 
| @@ -1387,99 +1554,114 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer, | 
| if (rex_w()) AppendToBuffer("REX.W "); | 
| } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3). | 
| group_1_prefix_ = current; | 
| +    } else if (current == VEX3_PREFIX) { | 
| +      vex_byte0_ = current; | 
| +      vex_byte1_ = *(data + 1); | 
| +      vex_byte2_ = *(data + 2); | 
| +      setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8)); | 
| +      data += 2; | 
| +    } else if (current == VEX2_PREFIX) { | 
| +      vex_byte0_ = current; | 
| +      vex_byte1_ = *(data + 1); | 
| +      setRex(0x40 | (~(vex_byte1_ >> 5) & 4)); | 
| +      data++; | 
| } else {  // Not a prefix - an opcode. | 
| break; | 
| } | 
| data++; | 
| } | 
|  | 
| -  const InstructionDesc& idesc = instruction_table_->Get(current); | 
| -  byte_size_operand_ = idesc.byte_size_operation; | 
| -  switch (idesc.type) { | 
| -    case ZERO_OPERANDS_INSTR: | 
| -      if (current >= 0xA4 && current <= 0xA7) { | 
| -        // String move or compare operations. | 
| -        if (group_1_prefix_ == REP_PREFIX) { | 
| -          // REP. | 
| -          AppendToBuffer("rep "); | 
| +  // Decode AVX instructions. | 
| +  if (vex_byte0_ != 0) { | 
| +    processed = true; | 
| +    data += AVXInstruction(data); | 
| +  } else { | 
| +    const InstructionDesc& idesc = instruction_table_->Get(current); | 
| +    byte_size_operand_ = idesc.byte_size_operation; | 
| +    switch (idesc.type) { | 
| +      case ZERO_OPERANDS_INSTR: | 
| +        if (current >= 0xA4 && current <= 0xA7) { | 
| +          // String move or compare operations. | 
| +          if (group_1_prefix_ == REP_PREFIX) { | 
| +            // REP. | 
| +            AppendToBuffer("rep "); | 
| +          } | 
| +          if (rex_w()) AppendToBuffer("REX.W "); | 
| +          AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); | 
| +        } else { | 
| +          AppendToBuffer("%s", idesc.mnem, operand_size_code()); | 
| } | 
| -        if (rex_w()) AppendToBuffer("REX.W "); | 
| -        AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); | 
| -      } else { | 
| -        AppendToBuffer("%s", idesc.mnem, operand_size_code()); | 
| -      } | 
| -      data++; | 
| -      break; | 
| +        data++; | 
| +        break; | 
|  | 
| -    case TWO_OPERANDS_INSTR: | 
| -      data++; | 
| -      data += PrintOperands(idesc.mnem, idesc.op_order_, data); | 
| -      break; | 
| +      case TWO_OPERANDS_INSTR: | 
| +        data++; | 
| +        data += PrintOperands(idesc.mnem, idesc.op_order_, data); | 
| +        break; | 
|  | 
| -    case JUMP_CONDITIONAL_SHORT_INSTR: | 
| -      data += JumpConditionalShort(data); | 
| -      break; | 
| +      case JUMP_CONDITIONAL_SHORT_INSTR: | 
| +        data += JumpConditionalShort(data); | 
| +        break; | 
|  | 
| -    case REGISTER_INSTR: | 
| -      AppendToBuffer("%s%c %s", | 
| -                     idesc.mnem, | 
| -                     operand_size_code(), | 
| -                     NameOfCPURegister(base_reg(current & 0x07))); | 
| -      data++; | 
| -      break; | 
| -    case PUSHPOP_INSTR: | 
| -      AppendToBuffer("%s %s", | 
| -                     idesc.mnem, | 
| -                     NameOfCPURegister(base_reg(current & 0x07))); | 
| -      data++; | 
| -      break; | 
| -    case MOVE_REG_INSTR: { | 
| -      byte* addr = NULL; | 
| -      switch (operand_size()) { | 
| -        case OPERAND_WORD_SIZE: | 
| -          addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); | 
| -          data += 3; | 
| -          break; | 
| -        case OPERAND_DOUBLEWORD_SIZE: | 
| -          addr = | 
| -              reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1)); | 
| -          data += 5; | 
| -          break; | 
| -        case OPERAND_QUADWORD_SIZE: | 
| -          addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); | 
| -          data += 9; | 
| -          break; | 
| -        default: | 
| -          UNREACHABLE(); | 
| +      case REGISTER_INSTR: | 
| +        AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(), | 
| +                       NameOfCPURegister(base_reg(current & 0x07))); | 
| +        data++; | 
| +        break; | 
| +      case PUSHPOP_INSTR: | 
| +        AppendToBuffer("%s %s", idesc.mnem, | 
| +                       NameOfCPURegister(base_reg(current & 0x07))); | 
| +        data++; | 
| +        break; | 
| +      case MOVE_REG_INSTR: { | 
| +        byte* addr = NULL; | 
| +        switch (operand_size()) { | 
| +          case OPERAND_WORD_SIZE: | 
| +            addr = | 
| +                reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); | 
| +            data += 3; | 
| +            break; | 
| +          case OPERAND_DOUBLEWORD_SIZE: | 
| +            addr = | 
| +                reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1)); | 
| +            data += 5; | 
| +            break; | 
| +          case OPERAND_QUADWORD_SIZE: | 
| +            addr = | 
| +                reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); | 
| +            data += 9; | 
| +            break; | 
| +          default: | 
| +            UNREACHABLE(); | 
| +        } | 
| +        AppendToBuffer("mov%c %s,%s", operand_size_code(), | 
| +                       NameOfCPURegister(base_reg(current & 0x07)), | 
| +                       NameOfAddress(addr)); | 
| +        break; | 
| } | 
| -      AppendToBuffer("mov%c %s,%s", | 
| -                     operand_size_code(), | 
| -                     NameOfCPURegister(base_reg(current & 0x07)), | 
| -                     NameOfAddress(addr)); | 
| -      break; | 
| -    } | 
|  | 
| -    case CALL_JUMP_INSTR: { | 
| -      byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5; | 
| -      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); | 
| -      data += 5; | 
| -      break; | 
| -    } | 
| +      case CALL_JUMP_INSTR: { | 
| +        byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5; | 
| +        AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); | 
| +        data += 5; | 
| +        break; | 
| +      } | 
|  | 
| -    case SHORT_IMMEDIATE_INSTR: { | 
| -      byte* addr = | 
| -          reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); | 
| -      AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr)); | 
| -      data += 5; | 
| -      break; | 
| -    } | 
| +      case SHORT_IMMEDIATE_INSTR: { | 
| +        byte* addr = | 
| +            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); | 
| +        AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr)); | 
| +        data += 5; | 
| +        break; | 
| +      } | 
|  | 
| -    case NO_INSTR: | 
| -      processed = false; | 
| -      break; | 
| +      case NO_INSTR: | 
| +        processed = false; | 
| +        break; | 
|  | 
| -    default: | 
| -      UNIMPLEMENTED();  // This type is not implemented. | 
| +      default: | 
| +        UNIMPLEMENTED();  // This type is not implemented. | 
| +    } | 
| } | 
|  | 
| // The first byte didn't match any of the simple opcodes, so we | 
|  |