LCOV - code coverage report
Current view: top level - src/compiler/x64 - code-generator-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1177 1320 89.2 %
Date: 2017-10-20 Functions: 42 105 40.0 %

          Line data    Source code
       1             : // Copyright 2013 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             : #include "src/compiler/code-generator.h"
       6             : 
       7             : #include <limits>
       8             : 
       9             : #include "src/compilation-info.h"
      10             : #include "src/compiler/code-generator-impl.h"
      11             : #include "src/compiler/gap-resolver.h"
      12             : #include "src/compiler/node-matchers.h"
      13             : #include "src/compiler/osr.h"
      14             : #include "src/heap/heap-inl.h"
      15             : #include "src/x64/assembler-x64.h"
      16             : #include "src/x64/macro-assembler-x64.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22             : #define __ tasm()->
      23             : 
      24             : // Adds X64 specific methods for decoding operands.
      25             : class X64OperandConverter : public InstructionOperandConverter {
      26             :  public:
      27             :   X64OperandConverter(CodeGenerator* gen, Instruction* instr)
      28             :       : InstructionOperandConverter(gen, instr) {}
      29             : 
      30             :   Immediate InputImmediate(size_t index) {
      31     2806631 :     return ToImmediate(instr_->InputAt(index));
      32             :   }
      33             : 
      34      635483 :   Operand InputOperand(size_t index, int extra = 0) {
      35     1906449 :     return ToOperand(instr_->InputAt(index), extra);
      36             :   }
      37             : 
      38           0 :   Operand OutputOperand() { return ToOperand(instr_->Output()); }
      39             : 
      40     2459051 :   Immediate ToImmediate(InstructionOperand* operand) {
      41     2459051 :     Constant constant = ToConstant(operand);
      42     2459071 :     if (constant.type() == Constant::kFloat64) {
      43             :       DCHECK_EQ(0, constant.ToFloat64().AsUint64());
      44       81262 :       return Immediate(0);
      45             :     }
      46     2377809 :     if (RelocInfo::IsWasmReference(constant.rmode())) {
      47        3251 :       return Immediate(constant.ToInt32(), constant.rmode());
      48             :     }
      49     2374558 :     return Immediate(constant.ToInt32());
      50             :   }
      51             : 
      52             :   Operand ToOperand(InstructionOperand* op, int extra = 0) {
      53             :     DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
      54    10675407 :     return SlotToOperand(AllocatedOperand::cast(op)->index(), extra);
      55             :   }
      56             : 
      57    10685925 :   Operand SlotToOperand(int slot_index, int extra = 0) {
      58    21371850 :     FrameOffset offset = frame_access_state()->GetFrameOffset(slot_index);
      59             :     return Operand(offset.from_stack_pointer() ? rsp : rbp,
      60    21371960 :                    offset.offset() + extra);
      61             :   }
      62             : 
      63             :   static size_t NextOffset(size_t* offset) {
      64     7977413 :     size_t i = *offset;
      65    14628428 :     (*offset)++;
      66             :     return i;
      67             :   }
      68             : 
      69             :   static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) {
      70             :     STATIC_ASSERT(0 == static_cast<int>(times_1));
      71             :     STATIC_ASSERT(1 == static_cast<int>(times_2));
      72             :     STATIC_ASSERT(2 == static_cast<int>(times_4));
      73             :     STATIC_ASSERT(3 == static_cast<int>(times_8));
      74      640545 :     int scale = static_cast<int>(mode - one);
      75             :     DCHECK(scale >= 0 && scale < 4);
      76      640545 :     return static_cast<ScaleFactor>(scale);
      77             :   }
      78             : 
      79     7977413 :   Operand MemoryOperand(size_t* offset) {
      80     7977413 :     AddressingMode mode = AddressingModeField::decode(instr_->opcode());
      81     7977413 :     switch (mode) {
      82             :       case kMode_MR: {
      83     7801679 :         Register base = InputRegister(NextOffset(offset));
      84             :         int32_t disp = 0;
      85      438247 :         return Operand(base, disp);
      86             :       }
      87             :       case kMode_MRI: {
      88     5706978 :         Register base = InputRegister(NextOffset(offset));
      89     5706978 :         int32_t disp = InputInt32(NextOffset(offset));
      90     5706981 :         return Operand(base, disp);
      91             :       }
      92             :       case kMode_MR1:
      93             :       case kMode_MR2:
      94             :       case kMode_MR4:
      95             :       case kMode_MR8: {
      96      272395 :         Register base = InputRegister(NextOffset(offset));
      97      272395 :         Register index = InputRegister(NextOffset(offset));
      98             :         ScaleFactor scale = ScaleFor(kMode_MR1, mode);
      99             :         int32_t disp = 0;
     100      272395 :         return Operand(base, index, scale, disp);
     101             :       }
     102             :       case kMode_MR1I:
     103             :       case kMode_MR2I:
     104             :       case kMode_MR4I:
     105             :       case kMode_MR8I: {
     106      305267 :         Register base = InputRegister(NextOffset(offset));
     107      305267 :         Register index = InputRegister(NextOffset(offset));
     108             :         ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
     109      305267 :         int32_t disp = InputInt32(NextOffset(offset));
     110      305267 :         return Operand(base, index, scale, disp);
     111             :       }
     112             :       case kMode_M1: {
     113           0 :         Register base = InputRegister(NextOffset(offset));
     114             :         int32_t disp = 0;
     115           0 :         return Operand(base, disp);
     116             :       }
     117             :       case kMode_M2:
     118           0 :         UNREACHABLE();  // Should use kModeMR with more compact encoding instead
     119             :         return Operand(no_reg, 0);
     120             :       case kMode_M4:
     121             :       case kMode_M8: {
     122        1775 :         Register index = InputRegister(NextOffset(offset));
     123             :         ScaleFactor scale = ScaleFor(kMode_M1, mode);
     124             :         int32_t disp = 0;
     125        1775 :         return Operand(index, scale, disp);
     126             :       }
     127             :       case kMode_M1I:
     128             :       case kMode_M2I:
     129             :       case kMode_M4I:
     130             :       case kMode_M8I: {
     131       61108 :         Register index = InputRegister(NextOffset(offset));
     132             :         ScaleFactor scale = ScaleFor(kMode_M1I, mode);
     133       61108 :         int32_t disp = InputInt32(NextOffset(offset));
     134       61109 :         return Operand(index, scale, disp);
     135             :       }
     136             :       case kMode_Root: {
     137     1191643 :         Register base = kRootRegister;
     138     1191643 :         int32_t disp = InputInt32(NextOffset(offset));
     139     1191645 :         return Operand(base, disp);
     140             :       }
     141             :       case kMode_None:
     142           0 :         UNREACHABLE();
     143             :     }
     144           0 :     UNREACHABLE();
     145             :   }
     146             : 
     147             :   Operand MemoryOperand(size_t first_input = 0) {
     148     4325518 :     return MemoryOperand(&first_input);
     149             :   }
     150             : };
     151             : 
     152             : 
     153             : namespace {
     154             : 
     155             : bool HasImmediateInput(Instruction* instr, size_t index) {
     156    14437261 :   return instr->InputAt(index)->IsImmediate();
     157             : }
     158             : 
     159             : 
     160           0 : class OutOfLineLoadZero final : public OutOfLineCode {
     161             :  public:
     162             :   OutOfLineLoadZero(CodeGenerator* gen, Register result)
     163       67341 :       : OutOfLineCode(gen), result_(result) {}
     164             : 
     165      134682 :   void Generate() final { __ xorl(result_, result_); }
     166             : 
     167             :  private:
     168             :   Register const result_;
     169             : };
     170             : 
     171           0 : class OutOfLineLoadFloat32NaN final : public OutOfLineCode {
     172             :  public:
     173             :   OutOfLineLoadFloat32NaN(CodeGenerator* gen, XMMRegister result)
     174        7734 :       : OutOfLineCode(gen), result_(result) {}
     175             : 
     176        7734 :   void Generate() final {
     177        7734 :     __ Xorps(result_, result_);
     178        7734 :     __ Divss(result_, result_);
     179        7734 :   }
     180             : 
     181             :  private:
     182             :   XMMRegister const result_;
     183             : };
     184             : 
     185           0 : class OutOfLineLoadFloat64NaN final : public OutOfLineCode {
     186             :  public:
     187             :   OutOfLineLoadFloat64NaN(CodeGenerator* gen, XMMRegister result)
     188        1476 :       : OutOfLineCode(gen), result_(result) {}
     189             : 
     190        1475 :   void Generate() final {
     191        1475 :     __ Xorpd(result_, result_);
     192        1475 :     __ Divsd(result_, result_);
     193        1476 :   }
     194             : 
     195             :  private:
     196             :   XMMRegister const result_;
     197             : };
     198             : 
     199           0 : class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
     200             :  public:
     201       45401 :   OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result,
     202             :                              XMMRegister input,
     203             :                              UnwindingInfoWriter* unwinding_info_writer)
     204             :       : OutOfLineCode(gen),
     205             :         result_(result),
     206             :         input_(input),
     207             :         unwinding_info_writer_(unwinding_info_writer),
     208       90806 :         zone_(gen->zone()) {}
     209             : 
     210       45404 :   void Generate() final {
     211      227047 :     __ subp(rsp, Immediate(kDoubleSize));
     212             :     unwinding_info_writer_->MaybeIncreaseBaseOffsetAt(__ pc_offset(),
     213       90814 :                                                       kDoubleSize);
     214       90815 :     __ Movsd(MemOperand(rsp, 0), input_);
     215       90816 :     __ SlowTruncateToIDelayed(zone_, result_);
     216       45412 :     __ addp(rsp, Immediate(kDoubleSize));
     217             :     unwinding_info_writer_->MaybeIncreaseBaseOffsetAt(__ pc_offset(),
     218       90828 :                                                       -kDoubleSize);
     219       45414 :   }
     220             : 
     221             :  private:
     222             :   Register const result_;
     223             :   XMMRegister const input_;
     224             :   UnwindingInfoWriter* const unwinding_info_writer_;
     225             :   Zone* zone_;
     226             : };
     227             : 
     228             : 
     229           0 : class OutOfLineRecordWrite final : public OutOfLineCode {
     230             :  public:
     231      320882 :   OutOfLineRecordWrite(CodeGenerator* gen, Register object, Operand operand,
     232             :                        Register value, Register scratch0, Register scratch1,
     233             :                        RecordWriteMode mode)
     234             :       : OutOfLineCode(gen),
     235             :         object_(object),
     236             :         operand_(operand),
     237             :         value_(value),
     238             :         scratch0_(scratch0),
     239             :         scratch1_(scratch1),
     240             :         mode_(mode),
     241      641764 :         zone_(gen->zone()) {}
     242             : 
     243      320882 :   void Generate() final {
     244      320882 :     if (mode_ > RecordWriteMode::kValueIsPointer) {
     245     1555508 :       __ JumpIfSmi(value_, exit());
     246             :     }
     247             :     __ CheckPageFlag(value_, scratch0_,
     248             :                      MemoryChunk::kPointersToHereAreInterestingMask, zero,
     249      641764 :                      exit());
     250      320882 :     __ leap(scratch1_, operand_);
     251             : 
     252             :     RememberedSetAction const remembered_set_action =
     253             :         mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
     254      320882 :                                              : OMIT_REMEMBERED_SET;
     255             :     SaveFPRegsMode const save_fp_mode =
     256      641764 :         frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
     257             : 
     258             : #ifdef V8_CSA_WRITE_BARRIER
     259             :     __ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
     260      320882 :                            save_fp_mode);
     261             : #else
     262             :     __ CallStubDelayed(
     263             :         new (zone_) RecordWriteStub(nullptr, object_, scratch0_, scratch1_,
     264             :                                     remembered_set_action, save_fp_mode));
     265             : #endif
     266      320882 :   }
     267             : 
     268             :  private:
     269             :   Register const object_;
     270             :   Operand const operand_;
     271             :   Register const value_;
     272             :   Register const scratch0_;
     273             :   Register const scratch1_;
     274             :   RecordWriteMode const mode_;
     275             :   Zone* zone_;
     276             : };
     277             : 
     278           0 : class WasmOutOfLineTrap final : public OutOfLineCode {
     279             :  public:
     280             :   WasmOutOfLineTrap(CodeGenerator* gen, int pc, bool frame_elided,
     281             :                     Instruction* instr)
     282             :       : OutOfLineCode(gen),
     283             :         gen_(gen),
     284             :         pc_(pc),
     285             :         frame_elided_(frame_elided),
     286        5292 :         instr_(instr) {}
     287             : 
     288             :   // TODO(eholk): Refactor this method to take the code generator as a
     289             :   // parameter.
     290        5287 :   void Generate() final {
     291       22024 :     __ RecordProtectedInstructionLanding(pc_);
     292             : 
     293        5292 :     if (frame_elided_) {
     294         865 :       __ EnterFrame(StackFrame::WASM_COMPILED);
     295             :     }
     296             : 
     297       10578 :     gen_->AssembleSourcePosition(instr_);
     298             :     __ Call(__ isolate()->builtins()->builtin_handle(
     299             :                 Builtins::kThrowWasmTrapMemOutOfBounds),
     300       10580 :             RelocInfo::CODE_TARGET);
     301        5289 :     ReferenceMap* reference_map = new (gen_->zone()) ReferenceMap(gen_->zone());
     302             :     gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
     303        5285 :                           Safepoint::kNoLazyDeopt);
     304        5292 :     __ AssertUnreachable(kUnexpectedReturnFromWasmTrap);
     305        5291 :   }
     306             : 
     307             :  private:
     308             :   CodeGenerator* gen_;
     309             :   int pc_;
     310             :   bool frame_elided_;
     311             :   Instruction* instr_;
     312             : };
     313             : 
     314     5483671 : void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
     315             :                          InstructionCode opcode, Instruction* instr,
     316             :                          X64OperandConverter& i, int pc) {
     317             :   const X64MemoryProtection protection =
     318     5478379 :       static_cast<X64MemoryProtection>(MiscField::decode(opcode));
     319     5478379 :   if (protection == X64MemoryProtection::kProtected) {
     320        5292 :     const bool frame_elided = !codegen->frame_access_state()->has_frame();
     321             :     new (zone) WasmOutOfLineTrap(codegen, pc, frame_elided, instr);
     322             :   }
     323     5478372 : }
     324             : }  // namespace
     325             : 
     326             : 
     327             : #define ASSEMBLE_UNOP(asm_instr)         \
     328             :   do {                                   \
     329             :     if (instr->Output()->IsRegister()) { \
     330             :       __ asm_instr(i.OutputRegister());  \
     331             :     } else {                             \
     332             :       __ asm_instr(i.OutputOperand());   \
     333             :     }                                    \
     334             :   } while (0)
     335             : 
     336             : #define ASSEMBLE_BINOP(asm_instr)                                     \
     337             :   do {                                                                \
     338             :     if (AddressingModeField::decode(instr->opcode()) != kMode_None) { \
     339             :       size_t index = 1;                                               \
     340             :       Operand right = i.MemoryOperand(&index);                        \
     341             :       __ asm_instr(i.InputRegister(0), right);                        \
     342             :     } else {                                                          \
     343             :       if (HasImmediateInput(instr, 1)) {                              \
     344             :         if (instr->InputAt(0)->IsRegister()) {                        \
     345             :           __ asm_instr(i.InputRegister(0), i.InputImmediate(1));      \
     346             :         } else {                                                      \
     347             :           __ asm_instr(i.InputOperand(0), i.InputImmediate(1));       \
     348             :         }                                                             \
     349             :       } else {                                                        \
     350             :         if (instr->InputAt(1)->IsRegister()) {                        \
     351             :           __ asm_instr(i.InputRegister(0), i.InputRegister(1));       \
     352             :         } else {                                                      \
     353             :           __ asm_instr(i.InputRegister(0), i.InputOperand(1));        \
     354             :         }                                                             \
     355             :       }                                                               \
     356             :     }                                                                 \
     357             :   } while (0)
     358             : 
     359             : #define ASSEMBLE_COMPARE(asm_instr)                                   \
     360             :   do {                                                                \
     361             :     if (AddressingModeField::decode(instr->opcode()) != kMode_None) { \
     362             :       size_t index = 0;                                               \
     363             :       Operand left = i.MemoryOperand(&index);                         \
     364             :       if (HasImmediateInput(instr, index)) {                          \
     365             :         __ asm_instr(left, i.InputImmediate(index));                  \
     366             :       } else {                                                        \
     367             :         __ asm_instr(left, i.InputRegister(index));                   \
     368             :       }                                                               \
     369             :     } else {                                                          \
     370             :       if (HasImmediateInput(instr, 1)) {                              \
     371             :         if (instr->InputAt(0)->IsRegister()) {                        \
     372             :           __ asm_instr(i.InputRegister(0), i.InputImmediate(1));      \
     373             :         } else {                                                      \
     374             :           __ asm_instr(i.InputOperand(0), i.InputImmediate(1));       \
     375             :         }                                                             \
     376             :       } else {                                                        \
     377             :         if (instr->InputAt(1)->IsRegister()) {                        \
     378             :           __ asm_instr(i.InputRegister(0), i.InputRegister(1));       \
     379             :         } else {                                                      \
     380             :           __ asm_instr(i.InputRegister(0), i.InputOperand(1));        \
     381             :         }                                                             \
     382             :       }                                                               \
     383             :     }                                                                 \
     384             :   } while (0)
     385             : 
     386             : #define ASSEMBLE_MULT(asm_instr)                              \
     387             :   do {                                                        \
     388             :     if (HasImmediateInput(instr, 1)) {                        \
     389             :       if (instr->InputAt(0)->IsRegister()) {                  \
     390             :         __ asm_instr(i.OutputRegister(), i.InputRegister(0),  \
     391             :                      i.InputImmediate(1));                    \
     392             :       } else {                                                \
     393             :         __ asm_instr(i.OutputRegister(), i.InputOperand(0),   \
     394             :                      i.InputImmediate(1));                    \
     395             :       }                                                       \
     396             :     } else {                                                  \
     397             :       if (instr->InputAt(1)->IsRegister()) {                  \
     398             :         __ asm_instr(i.OutputRegister(), i.InputRegister(1)); \
     399             :       } else {                                                \
     400             :         __ asm_instr(i.OutputRegister(), i.InputOperand(1));  \
     401             :       }                                                       \
     402             :     }                                                         \
     403             :   } while (0)
     404             : 
     405             : 
     406             : #define ASSEMBLE_SHIFT(asm_instr, width)                                   \
     407             :   do {                                                                     \
     408             :     if (HasImmediateInput(instr, 1)) {                                     \
     409             :       if (instr->Output()->IsRegister()) {                                 \
     410             :         __ asm_instr(i.OutputRegister(), Immediate(i.InputInt##width(1))); \
     411             :       } else {                                                             \
     412             :         __ asm_instr(i.OutputOperand(), Immediate(i.InputInt##width(1)));  \
     413             :       }                                                                    \
     414             :     } else {                                                               \
     415             :       if (instr->Output()->IsRegister()) {                                 \
     416             :         __ asm_instr##_cl(i.OutputRegister());                             \
     417             :       } else {                                                             \
     418             :         __ asm_instr##_cl(i.OutputOperand());                              \
     419             :       }                                                                    \
     420             :     }                                                                      \
     421             :   } while (0)
     422             : 
     423             : 
     424             : #define ASSEMBLE_MOVX(asm_instr)                            \
     425             :   do {                                                      \
     426             :     if (instr->addressing_mode() != kMode_None) {           \
     427             :       __ asm_instr(i.OutputRegister(), i.MemoryOperand());  \
     428             :     } else if (instr->InputAt(0)->IsRegister()) {           \
     429             :       __ asm_instr(i.OutputRegister(), i.InputRegister(0)); \
     430             :     } else {                                                \
     431             :       __ asm_instr(i.OutputRegister(), i.InputOperand(0));  \
     432             :     }                                                       \
     433             :   } while (0)
     434             : 
     435             : #define ASSEMBLE_SSE_BINOP(asm_instr)                                   \
     436             :   do {                                                                  \
     437             :     if (instr->InputAt(1)->IsFPRegister()) {                            \
     438             :       __ asm_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
     439             :     } else {                                                            \
     440             :       __ asm_instr(i.InputDoubleRegister(0), i.InputOperand(1));        \
     441             :     }                                                                   \
     442             :   } while (0)
     443             : 
     444             : #define ASSEMBLE_SSE_UNOP(asm_instr)                                    \
     445             :   do {                                                                  \
     446             :     if (instr->InputAt(0)->IsFPRegister()) {                            \
     447             :       __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
     448             :     } else {                                                            \
     449             :       __ asm_instr(i.OutputDoubleRegister(), i.InputOperand(0));        \
     450             :     }                                                                   \
     451             :   } while (0)
     452             : 
     453             : #define ASSEMBLE_AVX_BINOP(asm_instr)                                  \
     454             :   do {                                                                 \
     455             :     CpuFeatureScope avx_scope(tasm(), AVX);                            \
     456             :     if (instr->InputAt(1)->IsFPRegister()) {                           \
     457             :       __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
     458             :                    i.InputDoubleRegister(1));                          \
     459             :     } else {                                                           \
     460             :       __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
     461             :                    i.InputOperand(1));                                 \
     462             :     }                                                                  \
     463             :   } while (0)
     464             : 
     465             : #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, OutOfLineLoadNaN)             \
     466             :   do {                                                                       \
     467             :     auto result = i.OutputDoubleRegister();                                  \
     468             :     auto buffer = i.InputRegister(0);                                        \
     469             :     auto index1 = i.InputRegister(1);                                        \
     470             :     auto index2 = i.InputUint32(2);                                          \
     471             :     OutOfLineCode* ool;                                                      \
     472             :     if (instr->InputAt(3)->IsRegister()) {                                   \
     473             :       auto length = i.InputRegister(3);                                      \
     474             :       DCHECK_EQ(0u, index2);                                                 \
     475             :       __ cmpl(index1, length);                                               \
     476             :       ool = new (zone()) OutOfLineLoadNaN(this, result);                     \
     477             :     } else {                                                                 \
     478             :       auto length = i.InputUint32(3);                                        \
     479             :       RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();       \
     480             :       DCHECK_LE(index2, length);                                             \
     481             :       __ cmpl(index1, Immediate(length - index2, rmode));                    \
     482             :       class OutOfLineLoadFloat final : public OutOfLineCode {                \
     483             :        public:                                                               \
     484             :         OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result,           \
     485             :                            Register buffer, Register index1, int32_t index2, \
     486             :                            int32_t length, RelocInfo::Mode rmode)            \
     487             :             : OutOfLineCode(gen),                                            \
     488             :               result_(result),                                               \
     489             :               buffer_(buffer),                                               \
     490             :               index1_(index1),                                               \
     491             :               index2_(index2),                                               \
     492             :               length_(length),                                               \
     493             :               rmode_(rmode) {}                                               \
     494             :                                                                              \
     495             :         void Generate() final {                                              \
     496             :           __ leal(kScratchRegister, Operand(index1_, index2_));              \
     497             :           __ Pcmpeqd(result_, result_);                                      \
     498             :           __ cmpl(kScratchRegister, Immediate(length_, rmode_));             \
     499             :           __ j(above_equal, exit());                                         \
     500             :           __ asm_instr(result_,                                              \
     501             :                        Operand(buffer_, kScratchRegister, times_1, 0));      \
     502             :         }                                                                    \
     503             :                                                                              \
     504             :        private:                                                              \
     505             :         XMMRegister const result_;                                           \
     506             :         Register const buffer_;                                              \
     507             :         Register const index1_;                                              \
     508             :         int32_t const index2_;                                               \
     509             :         int32_t const length_;                                               \
     510             :         RelocInfo::Mode rmode_;                                              \
     511             :       };                                                                     \
     512             :       ool = new (zone()) OutOfLineLoadFloat(this, result, buffer, index1,    \
     513             :                                             index2, length, rmode);          \
     514             :     }                                                                        \
     515             :     __ j(above_equal, ool->entry());                                         \
     516             :     __ asm_instr(result, Operand(buffer, index1, times_1, index2));          \
     517             :     __ bind(ool->exit());                                                    \
     518             :   } while (false)
     519             : 
     520             : #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                               \
     521             :   do {                                                                         \
     522             :     auto result = i.OutputRegister();                                          \
     523             :     auto buffer = i.InputRegister(0);                                          \
     524             :     auto index1 = i.InputRegister(1);                                          \
     525             :     auto index2 = i.InputUint32(2);                                            \
     526             :     OutOfLineCode* ool;                                                        \
     527             :     if (instr->InputAt(3)->IsRegister()) {                                     \
     528             :       auto length = i.InputRegister(3);                                        \
     529             :       DCHECK_EQ(0u, index2);                                                   \
     530             :       __ cmpl(index1, length);                                                 \
     531             :       ool = new (zone()) OutOfLineLoadZero(this, result);                      \
     532             :     } else {                                                                   \
     533             :       auto length = i.InputUint32(3);                                          \
     534             :       RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();         \
     535             :       DCHECK_LE(index2, length);                                               \
     536             :       __ cmpl(index1, Immediate(length - index2, rmode));                      \
     537             :       class OutOfLineLoadInteger final : public OutOfLineCode {                \
     538             :        public:                                                                 \
     539             :         OutOfLineLoadInteger(CodeGenerator* gen, Register result,              \
     540             :                              Register buffer, Register index1, int32_t index2, \
     541             :                              int32_t length, RelocInfo::Mode rmode)            \
     542             :             : OutOfLineCode(gen),                                              \
     543             :               result_(result),                                                 \
     544             :               buffer_(buffer),                                                 \
     545             :               index1_(index1),                                                 \
     546             :               index2_(index2),                                                 \
     547             :               length_(length),                                                 \
     548             :               rmode_(rmode) {}                                                 \
     549             :                                                                                \
     550             :         void Generate() final {                                                \
     551             :           Label oob;                                                           \
     552             :           __ leal(kScratchRegister, Operand(index1_, index2_));                \
     553             :           __ cmpl(kScratchRegister, Immediate(length_, rmode_));               \
     554             :           __ j(above_equal, &oob, Label::kNear);                               \
     555             :           __ asm_instr(result_,                                                \
     556             :                        Operand(buffer_, kScratchRegister, times_1, 0));        \
     557             :           __ jmp(exit());                                                      \
     558             :           __ bind(&oob);                                                       \
     559             :           __ xorl(result_, result_);                                           \
     560             :         }                                                                      \
     561             :                                                                                \
     562             :        private:                                                                \
     563             :         Register const result_;                                                \
     564             :         Register const buffer_;                                                \
     565             :         Register const index1_;                                                \
     566             :         int32_t const index2_;                                                 \
     567             :         int32_t const length_;                                                 \
     568             :         RelocInfo::Mode const rmode_;                                          \
     569             :       };                                                                       \
     570             :       ool = new (zone()) OutOfLineLoadInteger(this, result, buffer, index1,    \
     571             :                                               index2, length, rmode);          \
     572             :     }                                                                          \
     573             :     __ j(above_equal, ool->entry());                                           \
     574             :     __ asm_instr(result, Operand(buffer, index1, times_1, index2));            \
     575             :     __ bind(ool->exit());                                                      \
     576             :   } while (false)
     577             : 
     578             : #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr)                              \
     579             :   do {                                                                       \
     580             :     auto buffer = i.InputRegister(0);                                        \
     581             :     auto index1 = i.InputRegister(1);                                        \
     582             :     auto index2 = i.InputUint32(2);                                          \
     583             :     auto value = i.InputDoubleRegister(4);                                   \
     584             :     if (instr->InputAt(3)->IsRegister()) {                                   \
     585             :       auto length = i.InputRegister(3);                                      \
     586             :       DCHECK_EQ(0u, index2);                                                 \
     587             :       Label done;                                                            \
     588             :       __ cmpl(index1, length);                                               \
     589             :       __ j(above_equal, &done, Label::kNear);                                \
     590             :       __ asm_instr(Operand(buffer, index1, times_1, index2), value);         \
     591             :       __ bind(&done);                                                        \
     592             :     } else {                                                                 \
     593             :       auto length = i.InputUint32(3);                                        \
     594             :       RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();       \
     595             :       DCHECK_LE(index2, length);                                             \
     596             :       __ cmpl(index1, Immediate(length - index2, rmode));                    \
     597             :       class OutOfLineStoreFloat final : public OutOfLineCode {               \
     598             :        public:                                                               \
     599             :         OutOfLineStoreFloat(CodeGenerator* gen, Register buffer,             \
     600             :                             Register index1, int32_t index2, int32_t length, \
     601             :                             XMMRegister value, RelocInfo::Mode rmode)        \
     602             :             : OutOfLineCode(gen),                                            \
     603             :               buffer_(buffer),                                               \
     604             :               index1_(index1),                                               \
     605             :               index2_(index2),                                               \
     606             :               length_(length),                                               \
     607             :               value_(value),                                                 \
     608             :               rmode_(rmode) {}                                               \
     609             :                                                                              \
     610             :         void Generate() final {                                              \
     611             :           __ leal(kScratchRegister, Operand(index1_, index2_));              \
     612             :           __ cmpl(kScratchRegister, Immediate(length_, rmode_));             \
     613             :           __ j(above_equal, exit());                                         \
     614             :           __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0),       \
     615             :                        value_);                                              \
     616             :         }                                                                    \
     617             :                                                                              \
     618             :        private:                                                              \
     619             :         Register const buffer_;                                              \
     620             :         Register const index1_;                                              \
     621             :         int32_t const index2_;                                               \
     622             :         int32_t const length_;                                               \
     623             :         XMMRegister const value_;                                            \
     624             :         RelocInfo::Mode rmode_;                                              \
     625             :       };                                                                     \
     626             :       auto ool = new (zone()) OutOfLineStoreFloat(                           \
     627             :           this, buffer, index1, index2, length, value, rmode);               \
     628             :       __ j(above_equal, ool->entry());                                       \
     629             :       __ asm_instr(Operand(buffer, index1, times_1, index2), value);         \
     630             :       __ bind(ool->exit());                                                  \
     631             :     }                                                                        \
     632             :   } while (false)
     633             : 
     634             : #define ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Value)                  \
     635             :   do {                                                                         \
     636             :     auto buffer = i.InputRegister(0);                                          \
     637             :     auto index1 = i.InputRegister(1);                                          \
     638             :     auto index2 = i.InputUint32(2);                                            \
     639             :     if (instr->InputAt(3)->IsRegister()) {                                     \
     640             :       auto length = i.InputRegister(3);                                        \
     641             :       DCHECK_EQ(0u, index2);                                                   \
     642             :       Label done;                                                              \
     643             :       __ cmpl(index1, length);                                                 \
     644             :       __ j(above_equal, &done, Label::kNear);                                  \
     645             :       __ asm_instr(Operand(buffer, index1, times_1, index2), value);           \
     646             :       __ bind(&done);                                                          \
     647             :     } else {                                                                   \
     648             :       auto length = i.InputUint32(3);                                          \
     649             :       RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();         \
     650             :       DCHECK_LE(index2, length);                                               \
     651             :       __ cmpl(index1, Immediate(length - index2, rmode));                      \
     652             :       class OutOfLineStoreInteger final : public OutOfLineCode {               \
     653             :        public:                                                                 \
     654             :         OutOfLineStoreInteger(CodeGenerator* gen, Register buffer,             \
     655             :                               Register index1, int32_t index2, int32_t length, \
     656             :                               Value value, RelocInfo::Mode rmode)              \
     657             :             : OutOfLineCode(gen),                                              \
     658             :               buffer_(buffer),                                                 \
     659             :               index1_(index1),                                                 \
     660             :               index2_(index2),                                                 \
     661             :               length_(length),                                                 \
     662             :               value_(value),                                                   \
     663             :               rmode_(rmode) {}                                                 \
     664             :                                                                                \
     665             :         void Generate() final {                                                \
     666             :           __ leal(kScratchRegister, Operand(index1_, index2_));                \
     667             :           __ cmpl(kScratchRegister, Immediate(length_, rmode_));               \
     668             :           __ j(above_equal, exit());                                           \
     669             :           __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0),         \
     670             :                        value_);                                                \
     671             :         }                                                                      \
     672             :                                                                                \
     673             :        private:                                                                \
     674             :         Register const buffer_;                                                \
     675             :         Register const index1_;                                                \
     676             :         int32_t const index2_;                                                 \
     677             :         int32_t const length_;                                                 \
     678             :         Value const value_;                                                    \
     679             :         RelocInfo::Mode rmode_;                                                \
     680             :       };                                                                       \
     681             :       auto ool = new (zone()) OutOfLineStoreInteger(                           \
     682             :           this, buffer, index1, index2, length, value, rmode);                 \
     683             :       __ j(above_equal, ool->entry());                                         \
     684             :       __ asm_instr(Operand(buffer, index1, times_1, index2), value);           \
     685             :       __ bind(ool->exit());                                                    \
     686             :     }                                                                          \
     687             :   } while (false)
     688             : 
     689             : #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)                \
     690             :   do {                                                           \
     691             :     if (instr->InputAt(4)->IsRegister()) {                       \
     692             :       Register value = i.InputRegister(4);                       \
     693             :       ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Register);  \
     694             :     } else {                                                     \
     695             :       Immediate value = i.InputImmediate(4);                     \
     696             :       ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \
     697             :     }                                                            \
     698             :   } while (false)
     699             : 
     700             : #define ASSEMBLE_IEEE754_BINOP(name)                                    \
     701             :   do {                                                                  \
     702             :     __ PrepareCallCFunction(2);                                         \
     703             :     __ CallCFunction(                                                   \
     704             :         ExternalReference::ieee754_##name##_function(__ isolate()), 2); \
     705             :   } while (false)
     706             : 
     707             : #define ASSEMBLE_IEEE754_UNOP(name)                                     \
     708             :   do {                                                                  \
     709             :     __ PrepareCallCFunction(1);                                         \
     710             :     __ CallCFunction(                                                   \
     711             :         ExternalReference::ieee754_##name##_function(__ isolate()), 1); \
     712             :   } while (false)
     713             : 
     714             : #define ASSEMBLE_ATOMIC_BINOP(bin_inst, mov_inst, cmpxchg_inst) \
     715             :   do {                                                          \
     716             :     Label binop;                                                \
     717             :     __ bind(&binop);                                            \
     718             :     __ mov_inst(rax, i.MemoryOperand(1));                       \
     719             :     __ movl(i.TempRegister(0), rax);                            \
     720             :     __ bin_inst(i.TempRegister(0), i.InputRegister(0));         \
     721             :     __ lock();                                                  \
     722             :     __ cmpxchg_inst(i.MemoryOperand(1), i.TempRegister(0));     \
     723             :     __ j(not_equal, &binop);                                    \
     724             :   } while (false)
     725             : 
     726     1077568 : void CodeGenerator::AssembleDeconstructFrame() {
     727     2155136 :   unwinding_info_writer_.MarkFrameDeconstructed(__ pc_offset());
     728     1077589 :   __ movq(rsp, rbp);
     729     1077596 :   __ popq(rbp);
     730     1077592 : }
     731             : 
     732      373178 : void CodeGenerator::AssemblePrepareTailCall() {
     733      186589 :   if (frame_access_state()->has_frame()) {
     734       46994 :     __ movq(rbp, MemOperand(rbp, 0));
     735             :   }
     736             :   frame_access_state()->SetFrameAccessToSP();
     737      186589 : }
     738             : 
     739         930 : void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
     740             :                                                      Register scratch1,
     741             :                                                      Register scratch2,
     742             :                                                      Register scratch3) {
     743             :   DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
     744             :   Label done;
     745             : 
     746             :   // Check if current frame is an arguments adaptor frame.
     747             :   __ cmpp(Operand(rbp, CommonFrameConstants::kContextOrFrameTypeOffset),
     748        1860 :           Immediate(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
     749         930 :   __ j(not_equal, &done, Label::kNear);
     750             : 
     751             :   // Load arguments count from current arguments adaptor frame (note, it
     752             :   // does not include receiver).
     753         930 :   Register caller_args_count_reg = scratch1;
     754             :   __ SmiToInteger32(
     755             :       caller_args_count_reg,
     756         930 :       Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
     757             : 
     758             :   ParameterCount callee_args_count(args_reg);
     759             :   __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
     760         930 :                         scratch3);
     761         930 :   __ bind(&done);
     762         930 : }
     763             : 
     764             : namespace {
     765             : 
     766      413304 : void AdjustStackPointerForTailCall(Assembler* assembler,
     767             :                                    FrameAccessState* state,
     768             :                                    int new_slot_above_sp,
     769             :                                    bool allow_shrinkage = true) {
     770             :   int current_sp_offset = state->GetSPToFPSlotCount() +
     771      413304 :                           StandardFrameConstants::kFixedSlotCountAboveFp;
     772      413304 :   int stack_slot_delta = new_slot_above_sp - current_sp_offset;
     773      413304 :   if (stack_slot_delta > 0) {
     774         260 :     assembler->subq(rsp, Immediate(stack_slot_delta * kPointerSize));
     775             :     state->IncreaseSPDelta(stack_slot_delta);
     776      413174 :   } else if (allow_shrinkage && stack_slot_delta < 0) {
     777       46038 :     assembler->addq(rsp, Immediate(-stack_slot_delta * kPointerSize));
     778             :     state->IncreaseSPDelta(stack_slot_delta);
     779             :   }
     780      413304 : }
     781             : 
     782             : }  // namespace
     783             : 
     784      186607 : void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
     785      453394 :                                               int first_unused_stack_slot) {
     786             :   CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush);
     787             :   ZoneVector<MoveOperands*> pushes(zone());
     788      186607 :   GetPushCompatibleMoves(instr, flags, &pushes);
     789             : 
     790      197175 :   if (!pushes.empty() &&
     791       21136 :       (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
     792             :        first_unused_stack_slot)) {
     793             :     X64OperandConverter g(this, instr);
     794       61226 :     for (auto move : pushes) {
     795             :       LocationOperand destination_location(
     796             :           LocationOperand::cast(move->destination()));
     797       40090 :       InstructionOperand source(move->source());
     798       40090 :       AdjustStackPointerForTailCall(tasm(), frame_access_state(),
     799       40090 :                                     destination_location.index());
     800       40090 :       if (source.IsStackSlot()) {
     801             :         LocationOperand source_location(LocationOperand::cast(source));
     802       10586 :         __ Push(g.SlotToOperand(source_location.index()));
     803       29504 :       } else if (source.IsRegister()) {
     804             :         LocationOperand source_location(LocationOperand::cast(source));
     805       29504 :         __ Push(source_location.GetRegister());
     806           0 :       } else if (source.IsImmediate()) {
     807           0 :         __ Push(Immediate(ImmediateOperand::cast(source).inline_value()));
     808             :       } else {
     809             :         // Pushes of non-scalar data types is not supported.
     810           0 :         UNIMPLEMENTED();
     811             :       }
     812             :       frame_access_state()->IncreaseSPDelta(1);
     813             :       move->Eliminate();
     814             :     }
     815             :   }
     816      186607 :   AdjustStackPointerForTailCall(tasm(), frame_access_state(),
     817      186607 :                                 first_unused_stack_slot, false);
     818      186607 : }
     819             : 
     820      186607 : void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
     821      186607 :                                              int first_unused_stack_slot) {
     822      186607 :   AdjustStackPointerForTailCall(tasm(), frame_access_state(),
     823      186607 :                                 first_unused_stack_slot);
     824      186607 : }
     825             : 
     826             : // Check if the code object is marked for deoptimization. If it is, then it
     827             : // jumps to CompileLazyDeoptimizedCode builtin. In order to do this we need to:
     828             : //    1. load the address of the current instruction;
     829             : //    2. read from memory the word that contains that bit, which can be found in
     830             : //       the first set of flags ({kKindSpecificFlags1Offset});
     831             : //    3. test kMarkedForDeoptimizationBit in those flags; and
     832             : //    4. if it is not zero then it jumps to the builtin.
     833      443344 : void CodeGenerator::BailoutIfDeoptimized() {
     834             :   Label current;
     835             :   // Load effective address to get the address of the current instruction into
     836             :   // rcx.
     837      886693 :   __ leaq(rcx, Operand(&current));
     838      443349 :   __ bind(&current);
     839      443346 :   int pc = __ pc_offset();
     840      443346 :   int offset = Code::kKindSpecificFlags1Offset - (Code::kHeaderSize + pc);
     841             :   __ testl(Operand(rcx, offset),
     842      886695 :            Immediate(1 << Code::kMarkedForDeoptimizationBit));
     843             :   Handle<Code> code = isolate()->builtins()->builtin_handle(
     844      443349 :       Builtins::kCompileLazyDeoptimizedCode);
     845      443345 :   __ j(not_zero, code, RelocInfo::CODE_TARGET);
     846      443347 : }
     847             : 
     848             : // Assembles an instruction after register allocation, producing machine code.
     849    44716154 : CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
     850    59445190 :     Instruction* instr) {
     851             :   X64OperandConverter i(this, instr);
     852             :   InstructionCode opcode = instr->opcode();
     853    44716154 :   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
     854    44716154 :   switch (arch_opcode) {
     855             :     case kArchCallCodeObject: {
     856     4389782 :       if (HasImmediateInput(instr, 0)) {
     857     4385516 :         Handle<Code> code = i.InputCode(0);
     858     4385516 :         __ Call(code, RelocInfo::CODE_TARGET);
     859             :       } else {
     860        4299 :         Register reg = i.InputRegister(0);
     861        4299 :         __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
     862        4299 :         __ call(reg);
     863             :       }
     864     4389826 :       RecordCallPosition(instr);
     865             :       frame_access_state()->ClearSPDelta();
     866             :       break;
     867             :     }
     868             :     case kArchTailCallCodeObjectFromJSFunction:
     869             :     case kArchTailCallCodeObject: {
     870      156302 :       if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
     871             :         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
     872             :                                          i.TempRegister(0), i.TempRegister(1),
     873         930 :                                          i.TempRegister(2));
     874             :       }
     875      156302 :       if (HasImmediateInput(instr, 0)) {
     876      155398 :         Handle<Code> code = i.InputCode(0);
     877      155398 :         __ jmp(code, RelocInfo::CODE_TARGET);
     878             :       } else {
     879        1808 :         Register reg = i.InputRegister(0);
     880         904 :         __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
     881         904 :         __ jmp(reg);
     882             :       }
     883             :       unwinding_info_writer_.MarkBlockWillExit();
     884             :       frame_access_state()->ClearSPDelta();
     885      156302 :       frame_access_state()->SetFrameAccessToDefault();
     886      156302 :       break;
     887             :     }
     888             :     case kArchTailCallAddress: {
     889       30287 :       CHECK(!HasImmediateInput(instr, 0));
     890       30287 :       Register reg = i.InputRegister(0);
     891       30287 :       __ jmp(reg);
     892             :       unwinding_info_writer_.MarkBlockWillExit();
     893             :       frame_access_state()->ClearSPDelta();
     894       30287 :       frame_access_state()->SetFrameAccessToDefault();
     895             :       break;
     896             :     }
     897             :     case kArchCallJSFunction: {
     898             :       Register func = i.InputRegister(0);
     899      152973 :       if (FLAG_debug_code) {
     900             :         // Check the function's context matches the context argument.
     901           8 :         __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset));
     902           8 :         __ Assert(equal, kWrongFunctionContext);
     903             :       }
     904      152973 :       __ movp(rcx, FieldOperand(func, JSFunction::kCodeOffset));
     905      152973 :       __ addp(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag));
     906      152973 :       __ call(rcx);
     907             :       frame_access_state()->ClearSPDelta();
     908      152973 :       RecordCallPosition(instr);
     909             :       break;
     910             :     }
     911             :     case kArchPrepareCallCFunction: {
     912             :       // Frame alignment requires using FP-relative frame addressing.
     913             :       frame_access_state()->SetFrameAccessToFP();
     914       41300 :       int const num_parameters = MiscField::decode(instr->opcode());
     915       41300 :       __ PrepareCallCFunction(num_parameters);
     916       41300 :       break;
     917             :     }
     918             :     case kArchSaveCallerRegisters: {
     919             :       fp_mode_ =
     920         378 :           static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode()));
     921             :       DCHECK(fp_mode_ == kDontSaveFPRegs || fp_mode_ == kSaveFPRegs);
     922             :       // kReturnRegister0 should have been saved before entering the stub.
     923         378 :       int bytes = __ PushCallerSaved(fp_mode_, kReturnRegister0);
     924             :       DCHECK_EQ(0, bytes % kPointerSize);
     925             :       DCHECK_EQ(0, frame_access_state()->sp_delta());
     926         378 :       frame_access_state()->IncreaseSPDelta(bytes / kPointerSize);
     927             :       DCHECK(!caller_registers_saved_);
     928         378 :       caller_registers_saved_ = true;
     929         378 :       break;
     930             :     }
     931             :     case kArchRestoreCallerRegisters: {
     932             :       DCHECK(fp_mode_ ==
     933             :              static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode())));
     934             :       DCHECK(fp_mode_ == kDontSaveFPRegs || fp_mode_ == kSaveFPRegs);
     935             :       // Don't overwrite the returned value.
     936         378 :       int bytes = __ PopCallerSaved(fp_mode_, kReturnRegister0);
     937         378 :       frame_access_state()->IncreaseSPDelta(-(bytes / kPointerSize));
     938             :       DCHECK_EQ(0, frame_access_state()->sp_delta());
     939             :       DCHECK(caller_registers_saved_);
     940         378 :       caller_registers_saved_ = false;
     941         378 :       break;
     942             :     }
     943             :     case kArchPrepareTailCall:
     944      186589 :       AssemblePrepareTailCall();
     945      186589 :       break;
     946             :     case kArchCallCFunction: {
     947             :       int const num_parameters = MiscField::decode(instr->opcode());
     948       41300 :       if (HasImmediateInput(instr, 0)) {
     949       40655 :         ExternalReference ref = i.InputExternalReference(0);
     950       40655 :         __ CallCFunction(ref, num_parameters);
     951             :       } else {
     952         645 :         Register func = i.InputRegister(0);
     953         645 :         __ CallCFunction(func, num_parameters);
     954             :       }
     955       41300 :       frame_access_state()->SetFrameAccessToDefault();
     956             :       // Ideally, we should decrement SP delta to match the change of stack
     957             :       // pointer in CallCFunction. However, for certain architectures (e.g.
     958             :       // ARM), there may be more strict alignment requirement, causing old SP
     959             :       // to be saved on the stack. In those cases, we can not calculate the SP
     960             :       // delta statically.
     961             :       frame_access_state()->ClearSPDelta();
     962       41300 :       if (caller_registers_saved_) {
     963             :         // Need to re-sync SP delta introduced in kArchSaveCallerRegisters.
     964             :         // Here, we assume the sequence to be:
     965             :         //   kArchSaveCallerRegisters;
     966             :         //   kArchCallCFunction;
     967             :         //   kArchRestoreCallerRegisters;
     968             :         int bytes =
     969         378 :             __ RequiredStackSizeForCallerSaved(fp_mode_, kReturnRegister0);
     970         378 :         frame_access_state()->IncreaseSPDelta(bytes / kPointerSize);
     971             :       }
     972             :       break;
     973             :     }
     974             :     case kArchJmp:
     975     3391140 :       AssembleArchJump(i.InputRpo(0));
     976     3391130 :       break;
     977             :     case kArchLookupSwitch:
     978       20780 :       AssembleArchLookupSwitch(instr);
     979       20780 :       break;
     980             :     case kArchTableSwitch:
     981        7807 :       AssembleArchTableSwitch(instr);
     982        7807 :       break;
     983             :     case kArchComment: {
     984             :       Address comment_string = i.InputExternalReference(0).address();
     985           0 :       __ RecordComment(reinterpret_cast<const char*>(comment_string));
     986           0 :       break;
     987             :     }
     988             :     case kArchDebugAbort:
     989             :       DCHECK(i.InputRegister(0) == rdx);
     990           0 :       if (!frame_access_state()->has_frame()) {
     991             :         // We don't actually want to generate a pile of code for this, so just
     992             :         // claim there is a stack frame, without generating one.
     993           0 :         FrameScope scope(tasm(), StackFrame::NONE);
     994             :         __ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
     995           0 :                 RelocInfo::CODE_TARGET);
     996             :       } else {
     997             :         __ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
     998           0 :                 RelocInfo::CODE_TARGET);
     999             :       }
    1000           0 :       __ int3();
    1001           0 :       break;
    1002             :     case kArchDebugBreak:
    1003       22395 :       __ int3();
    1004       22395 :       break;
    1005             :     case kArchNop:
    1006             :     case kArchThrowTerminator:
    1007             :       // don't emit code for nops.
    1008             :       break;
    1009             :     case kArchDeoptimize: {
    1010             :       int deopt_state_id =
    1011       51672 :           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
    1012             :       CodeGenResult result =
    1013       51672 :           AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
    1014       51672 :       if (result != kSuccess) return result;
    1015             :       break;
    1016             :     }
    1017             :     case kArchRet:
    1018     1510596 :       AssembleReturn(instr->InputAt(0));
    1019     1510605 :       break;
    1020             :     case kArchStackPointer:
    1021          62 :       __ movq(i.OutputRegister(), rsp);
    1022             :       break;
    1023             :     case kArchFramePointer:
    1024       19989 :       __ movq(i.OutputRegister(), rbp);
    1025             :       break;
    1026             :     case kArchParentFramePointer:
    1027       24681 :       if (frame_access_state()->has_frame()) {
    1028       33960 :         __ movq(i.OutputRegister(), Operand(rbp, 0));
    1029             :       } else {
    1030       13361 :         __ movq(i.OutputRegister(), rbp);
    1031             :       }
    1032             :       break;
    1033             :     case kArchTruncateDoubleToI: {
    1034             :       auto result = i.OutputRegister();
    1035             :       auto input = i.InputDoubleRegister(0);
    1036             :       auto ool = new (zone()) OutOfLineTruncateDoubleToI(
    1037       45405 :           this, result, input, &unwinding_info_writer_);
    1038             :       // We use Cvttsd2siq instead of Cvttsd2si due to performance reasons. The
    1039             :       // use of Cvttsd2siq requires the movl below to avoid sign extension.
    1040       45401 :       __ Cvttsd2siq(result, input);
    1041       45408 :       __ cmpq(result, Immediate(1));
    1042       45408 :       __ j(overflow, ool->entry());
    1043       45406 :       __ bind(ool->exit());
    1044             :       __ movl(result, result);
    1045             :       break;
    1046             :     }
    1047             :     case kArchStoreWithWriteBarrier: {
    1048             :       RecordWriteMode mode =
    1049             :           static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
    1050             :       Register object = i.InputRegister(0);
    1051      320882 :       size_t index = 0;
    1052      320882 :       Operand operand = i.MemoryOperand(&index);
    1053      320882 :       Register value = i.InputRegister(index);
    1054             :       Register scratch0 = i.TempRegister(0);
    1055             :       Register scratch1 = i.TempRegister(1);
    1056             :       auto ool = new (zone()) OutOfLineRecordWrite(this, object, operand, value,
    1057      641764 :                                                    scratch0, scratch1, mode);
    1058      320882 :       __ movp(operand, value);
    1059             :       __ CheckPageFlag(object, scratch0,
    1060             :                        MemoryChunk::kPointersFromHereAreInterestingMask,
    1061      320882 :                        not_zero, ool->entry());
    1062      320882 :       __ bind(ool->exit());
    1063             :       break;
    1064             :     }
    1065             :     case kArchStackSlot: {
    1066             :       FrameOffset offset =
    1067        2354 :           frame_access_state()->GetFrameOffset(i.InputInt32(0));
    1068        1177 :       Register base = offset.from_stack_pointer() ? rsp : rbp;
    1069        3531 :       __ leaq(i.OutputRegister(), Operand(base, offset.offset()));
    1070             :       break;
    1071             :     }
    1072             :     case kIeee754Float64Acos:
    1073          68 :       ASSEMBLE_IEEE754_UNOP(acos);
    1074          68 :       break;
    1075             :     case kIeee754Float64Acosh:
    1076          67 :       ASSEMBLE_IEEE754_UNOP(acosh);
    1077          67 :       break;
    1078             :     case kIeee754Float64Asin:
    1079          68 :       ASSEMBLE_IEEE754_UNOP(asin);
    1080          68 :       break;
    1081             :     case kIeee754Float64Asinh:
    1082          67 :       ASSEMBLE_IEEE754_UNOP(asinh);
    1083          67 :       break;
    1084             :     case kIeee754Float64Atan:
    1085          81 :       ASSEMBLE_IEEE754_UNOP(atan);
    1086          81 :       break;
    1087             :     case kIeee754Float64Atanh:
    1088          67 :       ASSEMBLE_IEEE754_UNOP(atanh);
    1089          67 :       break;
    1090             :     case kIeee754Float64Atan2:
    1091          91 :       ASSEMBLE_IEEE754_BINOP(atan2);
    1092          91 :       break;
    1093             :     case kIeee754Float64Cbrt:
    1094          67 :       ASSEMBLE_IEEE754_UNOP(cbrt);
    1095          67 :       break;
    1096             :     case kIeee754Float64Cos:
    1097         256 :       ASSEMBLE_IEEE754_UNOP(cos);
    1098         256 :       break;
    1099             :     case kIeee754Float64Cosh:
    1100          75 :       ASSEMBLE_IEEE754_UNOP(cosh);
    1101          75 :       break;
    1102             :     case kIeee754Float64Exp:
    1103          81 :       ASSEMBLE_IEEE754_UNOP(exp);
    1104          81 :       break;
    1105             :     case kIeee754Float64Expm1:
    1106          67 :       ASSEMBLE_IEEE754_UNOP(expm1);
    1107          67 :       break;
    1108             :     case kIeee754Float64Log:
    1109         232 :       ASSEMBLE_IEEE754_UNOP(log);
    1110         232 :       break;
    1111             :     case kIeee754Float64Log1p:
    1112          67 :       ASSEMBLE_IEEE754_UNOP(log1p);
    1113          67 :       break;
    1114             :     case kIeee754Float64Log2:
    1115          67 :       ASSEMBLE_IEEE754_UNOP(log2);
    1116          67 :       break;
    1117             :     case kIeee754Float64Log10:
    1118          67 :       ASSEMBLE_IEEE754_UNOP(log10);
    1119          67 :       break;
    1120             :     case kIeee754Float64Pow: {
    1121             :       // TODO(bmeurer): Improve integration of the stub.
    1122         140 :       __ Movsd(xmm2, xmm0);
    1123             :       __ CallStubDelayed(new (zone())
    1124         140 :                              MathPowStub(nullptr, MathPowStub::DOUBLE));
    1125         140 :       __ Movsd(xmm0, xmm3);
    1126         140 :       break;
    1127             :     }
    1128             :     case kIeee754Float64Sin:
    1129         256 :       ASSEMBLE_IEEE754_UNOP(sin);
    1130         256 :       break;
    1131             :     case kIeee754Float64Sinh:
    1132          75 :       ASSEMBLE_IEEE754_UNOP(sinh);
    1133          75 :       break;
    1134             :     case kIeee754Float64Tan:
    1135          81 :       ASSEMBLE_IEEE754_UNOP(tan);
    1136          81 :       break;
    1137             :     case kIeee754Float64Tanh:
    1138          75 :       ASSEMBLE_IEEE754_UNOP(tanh);
    1139          75 :       break;
    1140             :     case kX64Add32:
    1141      289938 :       ASSEMBLE_BINOP(addl);
    1142             :       break;
    1143             :     case kX64Add:
    1144      187232 :       ASSEMBLE_BINOP(addq);
    1145             :       break;
    1146             :     case kX64Sub32:
    1147      347690 :       ASSEMBLE_BINOP(subl);
    1148             :       break;
    1149             :     case kX64Sub:
    1150      194412 :       ASSEMBLE_BINOP(subq);
    1151             :       break;
    1152             :     case kX64And32:
    1153      540291 :       ASSEMBLE_BINOP(andl);
    1154             :       break;
    1155             :     case kX64And:
    1156      868395 :       ASSEMBLE_BINOP(andq);
    1157             :       break;
    1158             :     case kX64Cmp8:
    1159      750757 :       ASSEMBLE_COMPARE(cmpb);
    1160             :       break;
    1161             :     case kX64Cmp16:
    1162       17496 :       ASSEMBLE_COMPARE(cmpw);
    1163             :       break;
    1164             :     case kX64Cmp32:
    1165     4257283 :       ASSEMBLE_COMPARE(cmpl);
    1166             :       break;
    1167             :     case kX64Cmp:
    1168     6588705 :       ASSEMBLE_COMPARE(cmpq);
    1169             :       break;
    1170             :     case kX64Test8:
    1171      312536 :       ASSEMBLE_COMPARE(testb);
    1172             :       break;
    1173             :     case kX64Test16:
    1174        7152 :       ASSEMBLE_COMPARE(testw);
    1175             :       break;
    1176             :     case kX64Test32:
    1177      187799 :       ASSEMBLE_COMPARE(testl);
    1178             :       break;
    1179             :     case kX64Test:
    1180     1998878 :       ASSEMBLE_COMPARE(testq);
    1181             :       break;
    1182             :     case kX64Imul32:
    1183      182313 :       ASSEMBLE_MULT(imull);
    1184             :       break;
    1185             :     case kX64Imul:
    1186        9243 :       ASSEMBLE_MULT(imulq);
    1187             :       break;
    1188             :     case kX64ImulHigh32:
    1189        9698 :       if (instr->InputAt(1)->IsRegister()) {
    1190        4849 :         __ imull(i.InputRegister(1));
    1191             :       } else {
    1192           0 :         __ imull(i.InputOperand(1));
    1193             :       }
    1194             :       break;
    1195             :     case kX64UmulHigh32:
    1196        1258 :       if (instr->InputAt(1)->IsRegister()) {
    1197         629 :         __ mull(i.InputRegister(1));
    1198             :       } else {
    1199           0 :         __ mull(i.InputOperand(1));
    1200             :       }
    1201             :       break;
    1202             :     case kX64Idiv32:
    1203        5486 :       __ cdq();
    1204        5486 :       __ idivl(i.InputRegister(1));
    1205             :       break;
    1206             :     case kX64Idiv:
    1207        1028 :       __ cqo();
    1208        1028 :       __ idivq(i.InputRegister(1));
    1209             :       break;
    1210             :     case kX64Udiv32:
    1211        1164 :       __ xorl(rdx, rdx);
    1212        1164 :       __ divl(i.InputRegister(1));
    1213             :       break;
    1214             :     case kX64Udiv:
    1215         866 :       __ xorq(rdx, rdx);
    1216         866 :       __ divq(i.InputRegister(1));
    1217             :       break;
    1218             :     case kX64Not:
    1219         110 :       ASSEMBLE_UNOP(notq);
    1220             :       break;
    1221             :     case kX64Not32:
    1222        6938 :       ASSEMBLE_UNOP(notl);
    1223             :       break;
    1224             :     case kX64Neg:
    1225        9340 :       ASSEMBLE_UNOP(negq);
    1226             :       break;
    1227             :     case kX64Neg32:
    1228       10336 :       ASSEMBLE_UNOP(negl);
    1229             :       break;
    1230             :     case kX64Or32:
    1231       80518 :       ASSEMBLE_BINOP(orl);
    1232             :       break;
    1233             :     case kX64Or:
    1234      147880 :       ASSEMBLE_BINOP(orq);
    1235             :       break;
    1236             :     case kX64Xor32:
    1237       39512 :       ASSEMBLE_BINOP(xorl);
    1238             :       break;
    1239             :     case kX64Xor:
    1240        1647 :       ASSEMBLE_BINOP(xorq);
    1241             :       break;
    1242             :     case kX64Shl32:
    1243       41342 :       ASSEMBLE_SHIFT(shll, 5);
    1244             :       break;
    1245             :     case kX64Shl:
    1246     1080654 :       ASSEMBLE_SHIFT(shlq, 6);
    1247             :       break;
    1248             :     case kX64Shr32:
    1249      169721 :       ASSEMBLE_SHIFT(shrl, 5);
    1250             :       break;
    1251             :     case kX64Shr:
    1252     1175984 :       ASSEMBLE_SHIFT(shrq, 6);
    1253             :       break;
    1254             :     case kX64Sar32:
    1255       46519 :       ASSEMBLE_SHIFT(sarl, 5);
    1256             :       break;
    1257             :     case kX64Sar:
    1258      127634 :       ASSEMBLE_SHIFT(sarq, 6);
    1259             :       break;
    1260             :     case kX64Ror32:
    1261        3741 :       ASSEMBLE_SHIFT(rorl, 5);
    1262             :       break;
    1263             :     case kX64Ror:
    1264         468 :       ASSEMBLE_SHIFT(rorq, 6);
    1265             :       break;
    1266             :     case kX64Lzcnt:
    1267          74 :       if (instr->InputAt(0)->IsRegister()) {
    1268          37 :         __ Lzcntq(i.OutputRegister(), i.InputRegister(0));
    1269             :       } else {
    1270           0 :         __ Lzcntq(i.OutputRegister(), i.InputOperand(0));
    1271             :       }
    1272             :       break;
    1273             :     case kX64Lzcnt32:
    1274        3710 :       if (instr->InputAt(0)->IsRegister()) {
    1275        1695 :         __ Lzcntl(i.OutputRegister(), i.InputRegister(0));
    1276             :       } else {
    1277         320 :         __ Lzcntl(i.OutputRegister(), i.InputOperand(0));
    1278             :       }
    1279             :       break;
    1280             :     case kX64Tzcnt:
    1281          54 :       if (instr->InputAt(0)->IsRegister()) {
    1282          27 :         __ Tzcntq(i.OutputRegister(), i.InputRegister(0));
    1283             :       } else {
    1284           0 :         __ Tzcntq(i.OutputRegister(), i.InputOperand(0));
    1285             :       }
    1286             :       break;
    1287             :     case kX64Tzcnt32:
    1288        1714 :       if (instr->InputAt(0)->IsRegister()) {
    1289         857 :         __ Tzcntl(i.OutputRegister(), i.InputRegister(0));
    1290             :       } else {
    1291           0 :         __ Tzcntl(i.OutputRegister(), i.InputOperand(0));
    1292             :       }
    1293             :       break;
    1294             :     case kX64Popcnt:
    1295          98 :       if (instr->InputAt(0)->IsRegister()) {
    1296          49 :         __ Popcntq(i.OutputRegister(), i.InputRegister(0));
    1297             :       } else {
    1298           0 :         __ Popcntq(i.OutputRegister(), i.InputOperand(0));
    1299             :       }
    1300             :       break;
    1301             :     case kX64Popcnt32:
    1302         314 :       if (instr->InputAt(0)->IsRegister()) {
    1303         157 :         __ Popcntl(i.OutputRegister(), i.InputRegister(0));
    1304             :       } else {
    1305           0 :         __ Popcntl(i.OutputRegister(), i.InputOperand(0));
    1306             :       }
    1307             :       break;
    1308             :     case kSSEFloat32Cmp:
    1309           0 :       ASSEMBLE_SSE_BINOP(Ucomiss);
    1310             :       break;
    1311             :     case kSSEFloat32Add:
    1312           0 :       ASSEMBLE_SSE_BINOP(addss);
    1313             :       break;
    1314             :     case kSSEFloat32Sub:
    1315           0 :       ASSEMBLE_SSE_BINOP(subss);
    1316             :       break;
    1317             :     case kSSEFloat32Mul:
    1318           0 :       ASSEMBLE_SSE_BINOP(mulss);
    1319             :       break;
    1320             :     case kSSEFloat32Div:
    1321           0 :       ASSEMBLE_SSE_BINOP(divss);
    1322             :       // Don't delete this mov. It may improve performance on some CPUs,
    1323             :       // when there is a (v)mulss depending on the result.
    1324           0 :       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    1325           0 :       break;
    1326             :     case kSSEFloat32Abs: {
    1327             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1328           0 :       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    1329           0 :       __ psrlq(kScratchDoubleReg, 33);
    1330           0 :       __ andps(i.OutputDoubleRegister(), kScratchDoubleReg);
    1331           0 :       break;
    1332             :     }
    1333             :     case kSSEFloat32Neg: {
    1334             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1335           0 :       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    1336           0 :       __ psllq(kScratchDoubleReg, 31);
    1337           0 :       __ xorps(i.OutputDoubleRegister(), kScratchDoubleReg);
    1338           0 :       break;
    1339             :     }
    1340             :     case kSSEFloat32Sqrt:
    1341         588 :       ASSEMBLE_SSE_UNOP(sqrtss);
    1342             :       break;
    1343             :     case kSSEFloat32ToFloat64:
    1344       73524 :       ASSEMBLE_SSE_UNOP(Cvtss2sd);
    1345             :       break;
    1346             :     case kSSEFloat32Round: {
    1347             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    1348             :       RoundingMode const mode =
    1349             :           static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
    1350         512 :       __ Roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
    1351             :       break;
    1352             :     }
    1353             :     case kSSEFloat32ToInt32:
    1354         542 :       if (instr->InputAt(0)->IsFPRegister()) {
    1355         271 :         __ Cvttss2si(i.OutputRegister(), i.InputDoubleRegister(0));
    1356             :       } else {
    1357           0 :         __ Cvttss2si(i.OutputRegister(), i.InputOperand(0));
    1358             :       }
    1359             :       break;
    1360             :     case kSSEFloat32ToUint32: {
    1361         134 :       if (instr->InputAt(0)->IsFPRegister()) {
    1362          67 :         __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
    1363             :       } else {
    1364           0 :         __ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
    1365             :       }
    1366             :       break;
    1367             :     }
    1368             :     case kSSEFloat64Cmp:
    1369        4074 :       ASSEMBLE_SSE_BINOP(Ucomisd);
    1370             :       break;
    1371             :     case kSSEFloat64Add:
    1372         768 :       ASSEMBLE_SSE_BINOP(addsd);
    1373             :       break;
    1374             :     case kSSEFloat64Sub:
    1375        1158 :       ASSEMBLE_SSE_BINOP(subsd);
    1376             :       break;
    1377             :     case kSSEFloat64Mul:
    1378         108 :       ASSEMBLE_SSE_BINOP(mulsd);
    1379             :       break;
    1380             :     case kSSEFloat64Div:
    1381          78 :       ASSEMBLE_SSE_BINOP(divsd);
    1382             :       // Don't delete this mov. It may improve performance on some CPUs,
    1383             :       // when there is a (v)mulsd depending on the result.
    1384          52 :       __ Movapd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    1385          26 :       break;
    1386             :     case kSSEFloat64Mod: {
    1387        1365 :       __ subq(rsp, Immediate(kDoubleSize));
    1388             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    1389        2730 :                                                        kDoubleSize);
    1390             :       // Move values to st(0) and st(1).
    1391        2730 :       __ Movsd(Operand(rsp, 0), i.InputDoubleRegister(1));
    1392        1365 :       __ fld_d(Operand(rsp, 0));
    1393        2730 :       __ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
    1394        1365 :       __ fld_d(Operand(rsp, 0));
    1395             :       // Loop while fprem isn't done.
    1396             :       Label mod_loop;
    1397        1365 :       __ bind(&mod_loop);
    1398             :       // This instructions traps on all kinds inputs, but we are assuming the
    1399             :       // floating point control word is set to ignore them all.
    1400        1365 :       __ fprem();
    1401             :       // The following 2 instruction implicitly use rax.
    1402        1365 :       __ fnstsw_ax();
    1403        1365 :       if (CpuFeatures::IsSupported(SAHF)) {
    1404             :         CpuFeatureScope sahf_scope(tasm(), SAHF);
    1405        1341 :         __ sahf();
    1406             :       } else {
    1407             :         __ shrl(rax, Immediate(8));
    1408          24 :         __ andl(rax, Immediate(0xFF));
    1409          24 :         __ pushq(rax);
    1410             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    1411          48 :                                                          kPointerSize);
    1412          24 :         __ popfq();
    1413             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    1414          48 :                                                          -kPointerSize);
    1415             :       }
    1416        1365 :       __ j(parity_even, &mod_loop);
    1417             :       // Move output to stack and clean up.
    1418        1365 :       __ fstp(1);
    1419        1365 :       __ fstp_d(Operand(rsp, 0));
    1420        2730 :       __ Movsd(i.OutputDoubleRegister(), Operand(rsp, 0));
    1421        1365 :       __ addq(rsp, Immediate(kDoubleSize));
    1422             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    1423        2730 :                                                        -kDoubleSize);
    1424             :       break;
    1425             :     }
    1426             :     case kSSEFloat32Max: {
    1427             :       Label compare_nan, compare_swap, done_compare;
    1428         122 :       if (instr->InputAt(1)->IsFPRegister()) {
    1429          61 :         __ Ucomiss(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1430             :       } else {
    1431           0 :         __ Ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
    1432             :       }
    1433             :       auto ool =
    1434          61 :           new (zone()) OutOfLineLoadFloat32NaN(this, i.OutputDoubleRegister());
    1435          61 :       __ j(parity_even, ool->entry());
    1436          61 :       __ j(above, &done_compare, Label::kNear);
    1437          61 :       __ j(below, &compare_swap, Label::kNear);
    1438         122 :       __ Movmskps(kScratchRegister, i.InputDoubleRegister(0));
    1439             :       __ testl(kScratchRegister, Immediate(1));
    1440          61 :       __ j(zero, &done_compare, Label::kNear);
    1441          61 :       __ bind(&compare_swap);
    1442         122 :       if (instr->InputAt(1)->IsFPRegister()) {
    1443         122 :         __ Movss(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1444             :       } else {
    1445           0 :         __ Movss(i.InputDoubleRegister(0), i.InputOperand(1));
    1446             :       }
    1447          61 :       __ bind(&done_compare);
    1448          61 :       __ bind(ool->exit());
    1449             :       break;
    1450             :     }
    1451             :     case kSSEFloat32Min: {
    1452             :       Label compare_swap, done_compare;
    1453         122 :       if (instr->InputAt(1)->IsFPRegister()) {
    1454          61 :         __ Ucomiss(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1455             :       } else {
    1456           0 :         __ Ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
    1457             :       }
    1458             :       auto ool =
    1459          61 :           new (zone()) OutOfLineLoadFloat32NaN(this, i.OutputDoubleRegister());
    1460          61 :       __ j(parity_even, ool->entry());
    1461          61 :       __ j(below, &done_compare, Label::kNear);
    1462          61 :       __ j(above, &compare_swap, Label::kNear);
    1463         122 :       if (instr->InputAt(1)->IsFPRegister()) {
    1464         122 :         __ Movmskps(kScratchRegister, i.InputDoubleRegister(1));
    1465             :       } else {
    1466           0 :         __ Movss(kScratchDoubleReg, i.InputOperand(1));
    1467           0 :         __ Movmskps(kScratchRegister, kScratchDoubleReg);
    1468             :       }
    1469             :       __ testl(kScratchRegister, Immediate(1));
    1470          61 :       __ j(zero, &done_compare, Label::kNear);
    1471          61 :       __ bind(&compare_swap);
    1472         122 :       if (instr->InputAt(1)->IsFPRegister()) {
    1473         122 :         __ Movss(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1474             :       } else {
    1475           0 :         __ Movss(i.InputDoubleRegister(0), i.InputOperand(1));
    1476             :       }
    1477          61 :       __ bind(&done_compare);
    1478          61 :       __ bind(ool->exit());
    1479             :       break;
    1480             :     }
    1481             :     case kSSEFloat64Max: {
    1482             :       Label compare_nan, compare_swap, done_compare;
    1483         284 :       if (instr->InputAt(1)->IsFPRegister()) {
    1484         142 :         __ Ucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1485             :       } else {
    1486           0 :         __ Ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
    1487             :       }
    1488             :       auto ool =
    1489         142 :           new (zone()) OutOfLineLoadFloat64NaN(this, i.OutputDoubleRegister());
    1490         142 :       __ j(parity_even, ool->entry());
    1491         142 :       __ j(above, &done_compare, Label::kNear);
    1492         142 :       __ j(below, &compare_swap, Label::kNear);
    1493         284 :       __ Movmskpd(kScratchRegister, i.InputDoubleRegister(0));
    1494             :       __ testl(kScratchRegister, Immediate(1));
    1495         142 :       __ j(zero, &done_compare, Label::kNear);
    1496         142 :       __ bind(&compare_swap);
    1497         284 :       if (instr->InputAt(1)->IsFPRegister()) {
    1498         284 :         __ Movsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1499             :       } else {
    1500           0 :         __ Movsd(i.InputDoubleRegister(0), i.InputOperand(1));
    1501             :       }
    1502         142 :       __ bind(&done_compare);
    1503         142 :       __ bind(ool->exit());
    1504             :       break;
    1505             :     }
    1506             :     case kSSEFloat64Min: {
    1507             :       Label compare_swap, done_compare;
    1508         602 :       if (instr->InputAt(1)->IsFPRegister()) {
    1509         293 :         __ Ucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1510             :       } else {
    1511          16 :         __ Ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
    1512             :       }
    1513             :       auto ool =
    1514         301 :           new (zone()) OutOfLineLoadFloat64NaN(this, i.OutputDoubleRegister());
    1515         301 :       __ j(parity_even, ool->entry());
    1516         301 :       __ j(below, &done_compare, Label::kNear);
    1517         301 :       __ j(above, &compare_swap, Label::kNear);
    1518         602 :       if (instr->InputAt(1)->IsFPRegister()) {
    1519         586 :         __ Movmskpd(kScratchRegister, i.InputDoubleRegister(1));
    1520             :       } else {
    1521           8 :         __ Movsd(kScratchDoubleReg, i.InputOperand(1));
    1522           8 :         __ Movmskpd(kScratchRegister, kScratchDoubleReg);
    1523             :       }
    1524             :       __ testl(kScratchRegister, Immediate(1));
    1525         301 :       __ j(zero, &done_compare, Label::kNear);
    1526         301 :       __ bind(&compare_swap);
    1527         602 :       if (instr->InputAt(1)->IsFPRegister()) {
    1528         586 :         __ Movsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1529             :       } else {
    1530          16 :         __ Movsd(i.InputDoubleRegister(0), i.InputOperand(1));
    1531             :       }
    1532         301 :       __ bind(&done_compare);
    1533         301 :       __ bind(ool->exit());
    1534             :       break;
    1535             :     }
    1536             :     case kSSEFloat64Abs: {
    1537             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1538           6 :       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    1539           6 :       __ psrlq(kScratchDoubleReg, 1);
    1540          12 :       __ andpd(i.OutputDoubleRegister(), kScratchDoubleReg);
    1541           6 :       break;
    1542             :     }
    1543             :     case kSSEFloat64Neg: {
    1544             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1545         182 :       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    1546         182 :       __ psllq(kScratchDoubleReg, 63);
    1547         364 :       __ xorpd(i.OutputDoubleRegister(), kScratchDoubleReg);
    1548         182 :       break;
    1549             :     }
    1550             :     case kSSEFloat64Sqrt:
    1551        1263 :       ASSEMBLE_SSE_UNOP(Sqrtsd);
    1552             :       break;
    1553             :     case kSSEFloat64Round: {
    1554             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    1555             :       RoundingMode const mode =
    1556             :           static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
    1557       18797 :       __ Roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
    1558             :       break;
    1559             :     }
    1560             :     case kSSEFloat64ToFloat32:
    1561       61902 :       ASSEMBLE_SSE_UNOP(Cvtsd2ss);
    1562             :       break;
    1563             :     case kSSEFloat64ToInt32:
    1564      217294 :       if (instr->InputAt(0)->IsFPRegister()) {
    1565       86211 :         __ Cvttsd2si(i.OutputRegister(), i.InputDoubleRegister(0));
    1566             :       } else {
    1567       44872 :         __ Cvttsd2si(i.OutputRegister(), i.InputOperand(0));
    1568             :       }
    1569             :       break;
    1570             :     case kSSEFloat64ToUint32: {
    1571         638 :       if (instr->InputAt(0)->IsFPRegister()) {
    1572         319 :         __ Cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
    1573             :       } else {
    1574           0 :         __ Cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
    1575             :       }
    1576         638 :       if (MiscField::decode(instr->opcode())) {
    1577         534 :         __ AssertZeroExtended(i.OutputRegister());
    1578             :       }
    1579             :       break;
    1580             :     }
    1581             :     case kSSEFloat32ToInt64:
    1582         148 :       if (instr->InputAt(0)->IsFPRegister()) {
    1583          74 :         __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
    1584             :       } else {
    1585           0 :         __ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
    1586             :       }
    1587          74 :       if (instr->OutputCount() > 1) {
    1588         138 :         __ Set(i.OutputRegister(1), 1);
    1589             :         Label done;
    1590             :         Label fail;
    1591             :         __ Move(kScratchDoubleReg, static_cast<float>(INT64_MIN));
    1592         138 :         if (instr->InputAt(0)->IsFPRegister()) {
    1593         138 :           __ Ucomiss(kScratchDoubleReg, i.InputDoubleRegister(0));
    1594             :         } else {
    1595           0 :           __ Ucomiss(kScratchDoubleReg, i.InputOperand(0));
    1596             :         }
    1597             :         // If the input is NaN, then the conversion fails.
    1598          69 :         __ j(parity_even, &fail);
    1599             :         // If the input is INT64_MIN, then the conversion succeeds.
    1600          69 :         __ j(equal, &done);
    1601         138 :         __ cmpq(i.OutputRegister(0), Immediate(1));
    1602             :         // If the conversion results in INT64_MIN, but the input was not
    1603             :         // INT64_MIN, then the conversion fails.
    1604          69 :         __ j(no_overflow, &done);
    1605          69 :         __ bind(&fail);
    1606         138 :         __ Set(i.OutputRegister(1), 0);
    1607          69 :         __ bind(&done);
    1608             :       }
    1609             :       break;
    1610             :     case kSSEFloat64ToInt64:
    1611         252 :       if (instr->InputAt(0)->IsFPRegister()) {
    1612         126 :         __ Cvttsd2siq(i.OutputRegister(0), i.InputDoubleRegister(0));
    1613             :       } else {
    1614           0 :         __ Cvttsd2siq(i.OutputRegister(0), i.InputOperand(0));
    1615             :       }
    1616         126 :       if (instr->OutputCount() > 1) {
    1617         242 :         __ Set(i.OutputRegister(1), 1);
    1618             :         Label done;
    1619             :         Label fail;
    1620             :         __ Move(kScratchDoubleReg, static_cast<double>(INT64_MIN));
    1621         242 :         if (instr->InputAt(0)->IsFPRegister()) {
    1622         242 :           __ Ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
    1623             :         } else {
    1624           0 :           __ Ucomisd(kScratchDoubleReg, i.InputOperand(0));
    1625             :         }
    1626             :         // If the input is NaN, then the conversion fails.
    1627         121 :         __ j(parity_even, &fail);
    1628             :         // If the input is INT64_MIN, then the conversion succeeds.
    1629         121 :         __ j(equal, &done);
    1630         242 :         __ cmpq(i.OutputRegister(0), Immediate(1));
    1631             :         // If the conversion results in INT64_MIN, but the input was not
    1632             :         // INT64_MIN, then the conversion fails.
    1633         121 :         __ j(no_overflow, &done);
    1634         121 :         __ bind(&fail);
    1635         242 :         __ Set(i.OutputRegister(1), 0);
    1636         121 :         __ bind(&done);
    1637             :       }
    1638             :       break;
    1639             :     case kSSEFloat32ToUint64: {
    1640             :       Label done;
    1641             :       Label success;
    1642          74 :       if (instr->OutputCount() > 1) {
    1643          69 :         __ Set(i.OutputRegister(1), 0);
    1644             :       }
    1645             :       // There does not exist a Float32ToUint64 instruction, so we have to use
    1646             :       // the Float32ToInt64 instruction.
    1647         148 :       if (instr->InputAt(0)->IsFPRegister()) {
    1648         148 :         __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
    1649             :       } else {
    1650           0 :         __ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
    1651             :       }
    1652             :       // Check if the result of the Float32ToInt64 conversion is positive, we
    1653             :       // are already done.
    1654         148 :       __ testq(i.OutputRegister(), i.OutputRegister());
    1655          74 :       __ j(positive, &success);
    1656             :       // The result of the first conversion was negative, which means that the
    1657             :       // input value was not within the positive int64 range. We subtract 2^64
    1658             :       // and convert it again to see if it is within the uint64 range.
    1659          74 :       __ Move(kScratchDoubleReg, -9223372036854775808.0f);
    1660         148 :       if (instr->InputAt(0)->IsFPRegister()) {
    1661         148 :         __ addss(kScratchDoubleReg, i.InputDoubleRegister(0));
    1662             :       } else {
    1663           0 :         __ addss(kScratchDoubleReg, i.InputOperand(0));
    1664             :       }
    1665         148 :       __ Cvttss2siq(i.OutputRegister(), kScratchDoubleReg);
    1666          74 :       __ testq(i.OutputRegister(), i.OutputRegister());
    1667             :       // The only possible negative value here is 0x80000000000000000, which is
    1668             :       // used on x64 to indicate an integer overflow.
    1669          74 :       __ j(negative, &done);
    1670             :       // The input value is within uint64 range and the second conversion worked
    1671             :       // successfully, but we still have to undo the subtraction we did
    1672             :       // earlier.
    1673          74 :       __ Set(kScratchRegister, 0x8000000000000000);
    1674         148 :       __ orq(i.OutputRegister(), kScratchRegister);
    1675          74 :       __ bind(&success);
    1676          74 :       if (instr->OutputCount() > 1) {
    1677         138 :         __ Set(i.OutputRegister(1), 1);
    1678             :       }
    1679          74 :       __ bind(&done);
    1680             :       break;
    1681             :     }
    1682             :     case kSSEFloat64ToUint64: {
    1683             :       Label done;
    1684             :       Label success;
    1685         270 :       if (instr->OutputCount() > 1) {
    1686          79 :         __ Set(i.OutputRegister(1), 0);
    1687             :       }
    1688             :       // There does not exist a Float64ToUint64 instruction, so we have to use
    1689             :       // the Float64ToInt64 instruction.
    1690         540 :       if (instr->InputAt(0)->IsFPRegister()) {
    1691         540 :         __ Cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
    1692             :       } else {
    1693           0 :         __ Cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
    1694             :       }
    1695             :       // Check if the result of the Float64ToInt64 conversion is positive, we
    1696             :       // are already done.
    1697         540 :       __ testq(i.OutputRegister(), i.OutputRegister());
    1698         270 :       __ j(positive, &success);
    1699             :       // The result of the first conversion was negative, which means that the
    1700             :       // input value was not within the positive int64 range. We subtract 2^64
    1701             :       // and convert it again to see if it is within the uint64 range.
    1702         270 :       __ Move(kScratchDoubleReg, -9223372036854775808.0);
    1703         540 :       if (instr->InputAt(0)->IsFPRegister()) {
    1704         540 :         __ addsd(kScratchDoubleReg, i.InputDoubleRegister(0));
    1705             :       } else {
    1706           0 :         __ addsd(kScratchDoubleReg, i.InputOperand(0));
    1707             :       }
    1708         540 :       __ Cvttsd2siq(i.OutputRegister(), kScratchDoubleReg);
    1709         270 :       __ testq(i.OutputRegister(), i.OutputRegister());
    1710             :       // The only possible negative value here is 0x80000000000000000, which is
    1711             :       // used on x64 to indicate an integer overflow.
    1712         270 :       __ j(negative, &done);
    1713             :       // The input value is within uint64 range and the second conversion worked
    1714             :       // successfully, but we still have to undo the subtraction we did
    1715             :       // earlier.
    1716         270 :       __ Set(kScratchRegister, 0x8000000000000000);
    1717         540 :       __ orq(i.OutputRegister(), kScratchRegister);
    1718         270 :       __ bind(&success);
    1719         270 :       if (instr->OutputCount() > 1) {
    1720         158 :         __ Set(i.OutputRegister(1), 1);
    1721             :       }
    1722         270 :       __ bind(&done);
    1723             :       break;
    1724             :     }
    1725             :     case kSSEInt32ToFloat64:
    1726      598756 :       if (instr->InputAt(0)->IsRegister()) {
    1727      295316 :         __ Cvtlsi2sd(i.OutputDoubleRegister(), i.InputRegister(0));
    1728             :       } else {
    1729        8124 :         __ Cvtlsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
    1730             :       }
    1731             :       break;
    1732             :     case kSSEInt32ToFloat32:
    1733        1130 :       if (instr->InputAt(0)->IsRegister()) {
    1734         555 :         __ Cvtlsi2ss(i.OutputDoubleRegister(), i.InputRegister(0));
    1735             :       } else {
    1736          20 :         __ Cvtlsi2ss(i.OutputDoubleRegister(), i.InputOperand(0));
    1737             :       }
    1738             :       break;
    1739             :     case kSSEInt64ToFloat32:
    1740          90 :       if (instr->InputAt(0)->IsRegister()) {
    1741          45 :         __ Cvtqsi2ss(i.OutputDoubleRegister(), i.InputRegister(0));
    1742             :       } else {
    1743           0 :         __ Cvtqsi2ss(i.OutputDoubleRegister(), i.InputOperand(0));
    1744             :       }
    1745             :       break;
    1746             :     case kSSEInt64ToFloat64:
    1747        2110 :       if (instr->InputAt(0)->IsRegister()) {
    1748        1055 :         __ Cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0));
    1749             :       } else {
    1750           0 :         __ Cvtqsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
    1751             :       }
    1752             :       break;
    1753             :     case kSSEUint64ToFloat32:
    1754          94 :       if (instr->InputAt(0)->IsRegister()) {
    1755          47 :         __ movq(kScratchRegister, i.InputRegister(0));
    1756             :       } else {
    1757           0 :         __ movq(kScratchRegister, i.InputOperand(0));
    1758             :       }
    1759             :       __ Cvtqui2ss(i.OutputDoubleRegister(), kScratchRegister,
    1760          94 :                    i.TempRegister(0));
    1761          47 :       break;
    1762             :     case kSSEUint64ToFloat64:
    1763         354 :       if (instr->InputAt(0)->IsRegister()) {
    1764         177 :         __ movq(kScratchRegister, i.InputRegister(0));
    1765             :       } else {
    1766           0 :         __ movq(kScratchRegister, i.InputOperand(0));
    1767             :       }
    1768             :       __ Cvtqui2sd(i.OutputDoubleRegister(), kScratchRegister,
    1769         348 :                    i.TempRegister(0));
    1770         177 :       break;
    1771             :     case kSSEUint32ToFloat64:
    1772        5102 :       if (instr->InputAt(0)->IsRegister()) {
    1773        2071 :         __ movl(kScratchRegister, i.InputRegister(0));
    1774             :       } else {
    1775         480 :         __ movl(kScratchRegister, i.InputOperand(0));
    1776             :       }
    1777        5104 :       __ Cvtqsi2sd(i.OutputDoubleRegister(), kScratchRegister);
    1778        2552 :       break;
    1779             :     case kSSEUint32ToFloat32:
    1780         246 :       if (instr->InputAt(0)->IsRegister()) {
    1781         123 :         __ movl(kScratchRegister, i.InputRegister(0));
    1782             :       } else {
    1783           0 :         __ movl(kScratchRegister, i.InputOperand(0));
    1784             :       }
    1785         246 :       __ Cvtqsi2ss(i.OutputDoubleRegister(), kScratchRegister);
    1786         123 :       break;
    1787             :     case kSSEFloat64ExtractLowWord32:
    1788          10 :       if (instr->InputAt(0)->IsFPStackSlot()) {
    1789           0 :         __ movl(i.OutputRegister(), i.InputOperand(0));
    1790             :       } else {
    1791           5 :         __ Movd(i.OutputRegister(), i.InputDoubleRegister(0));
    1792             :       }
    1793             :       break;
    1794             :     case kSSEFloat64ExtractHighWord32:
    1795      145066 :       if (instr->InputAt(0)->IsFPStackSlot()) {
    1796       85540 :         __ movl(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
    1797             :       } else {
    1798       29763 :         __ Pextrd(i.OutputRegister(), i.InputDoubleRegister(0), 1);
    1799             :       }
    1800             :       break;
    1801             :     case kSSEFloat64InsertLowWord32:
    1802          10 :       if (instr->InputAt(1)->IsRegister()) {
    1803           5 :         __ Pinsrd(i.OutputDoubleRegister(), i.InputRegister(1), 0);
    1804             :       } else {
    1805           0 :         __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 0);
    1806             :       }
    1807             :       break;
    1808             :     case kSSEFloat64InsertHighWord32:
    1809          10 :       if (instr->InputAt(1)->IsRegister()) {
    1810           5 :         __ Pinsrd(i.OutputDoubleRegister(), i.InputRegister(1), 1);
    1811             :       } else {
    1812           0 :         __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 1);
    1813             :       }
    1814             :       break;
    1815             :     case kSSEFloat64LoadLowWord32:
    1816           0 :       if (instr->InputAt(0)->IsRegister()) {
    1817           0 :         __ Movd(i.OutputDoubleRegister(), i.InputRegister(0));
    1818             :       } else {
    1819           0 :         __ Movd(i.OutputDoubleRegister(), i.InputOperand(0));
    1820             :       }
    1821             :       break;
    1822             :     case kAVXFloat32Cmp: {
    1823             :       CpuFeatureScope avx_scope(tasm(), AVX);
    1824        3886 :       if (instr->InputAt(1)->IsFPRegister()) {
    1825        1921 :         __ vucomiss(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1826             :       } else {
    1827          44 :         __ vucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
    1828             :       }
    1829             :       break;
    1830             :     }
    1831             :     case kAVXFloat32Add:
    1832        1878 :       ASSEMBLE_AVX_BINOP(vaddss);
    1833             :       break;
    1834             :     case kAVXFloat32Sub:
    1835        4815 :       ASSEMBLE_AVX_BINOP(vsubss);
    1836             :       break;
    1837             :     case kAVXFloat32Mul:
    1838        1713 :       ASSEMBLE_AVX_BINOP(vmulss);
    1839             :       break;
    1840             :     case kAVXFloat32Div:
    1841        1509 :       ASSEMBLE_AVX_BINOP(vdivss);
    1842             :       // Don't delete this mov. It may improve performance on some CPUs,
    1843             :       // when there is a (v)mulss depending on the result.
    1844        1006 :       __ Movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    1845         503 :       break;
    1846             :     case kAVXFloat64Cmp: {
    1847             :       CpuFeatureScope avx_scope(tasm(), AVX);
    1848      422794 :       if (instr->InputAt(1)->IsFPRegister()) {
    1849      184568 :         __ vucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
    1850             :       } else {
    1851       80487 :         __ vucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
    1852             :       }
    1853             :       break;
    1854             :     }
    1855             :     case kAVXFloat64Add:
    1856      181590 :       ASSEMBLE_AVX_BINOP(vaddsd);
    1857             :       break;
    1858             :     case kAVXFloat64Sub:
    1859       66729 :       ASSEMBLE_AVX_BINOP(vsubsd);
    1860             :       break;
    1861             :     case kAVXFloat64Mul:
    1862       41472 :       ASSEMBLE_AVX_BINOP(vmulsd);
    1863             :       break;
    1864             :     case kAVXFloat64Div:
    1865       35010 :       ASSEMBLE_AVX_BINOP(vdivsd);
    1866             :       // Don't delete this mov. It may improve performance on some CPUs,
    1867             :       // when there is a (v)mulsd depending on the result.
    1868       23340 :       __ Movapd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    1869       11671 :       break;
    1870             :     case kAVXFloat32Abs: {
    1871             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1872             :       CpuFeatureScope avx_scope(tasm(), AVX);
    1873          85 :       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
    1874             :       __ vpsrlq(kScratchDoubleReg, kScratchDoubleReg, 33);
    1875         170 :       if (instr->InputAt(0)->IsFPRegister()) {
    1876             :         __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg,
    1877          85 :                   i.InputDoubleRegister(0));
    1878             :       } else {
    1879             :         __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg,
    1880           0 :                   i.InputOperand(0));
    1881             :       }
    1882             :       break;
    1883             :     }
    1884             :     case kAVXFloat32Neg: {
    1885             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1886             :       CpuFeatureScope avx_scope(tasm(), AVX);
    1887         225 :       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
    1888             :       __ vpsllq(kScratchDoubleReg, kScratchDoubleReg, 31);
    1889         456 :       if (instr->InputAt(0)->IsFPRegister()) {
    1890             :         __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg,
    1891         228 :                   i.InputDoubleRegister(0));
    1892             :       } else {
    1893             :         __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg,
    1894           0 :                   i.InputOperand(0));
    1895             :       }
    1896             :       break;
    1897             :     }
    1898             :     case kAVXFloat64Abs: {
    1899             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1900             :       CpuFeatureScope avx_scope(tasm(), AVX);
    1901         367 :       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
    1902             :       __ vpsrlq(kScratchDoubleReg, kScratchDoubleReg, 1);
    1903         734 :       if (instr->InputAt(0)->IsFPRegister()) {
    1904             :         __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg,
    1905         367 :                   i.InputDoubleRegister(0));
    1906             :       } else {
    1907             :         __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg,
    1908           0 :                   i.InputOperand(0));
    1909             :       }
    1910             :       break;
    1911             :     }
    1912             :     case kAVXFloat64Neg: {
    1913             :       // TODO(bmeurer): Use RIP relative 128-bit constants.
    1914             :       CpuFeatureScope avx_scope(tasm(), AVX);
    1915        9913 :       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
    1916             :       __ vpsllq(kScratchDoubleReg, kScratchDoubleReg, 63);
    1917       19826 :       if (instr->InputAt(0)->IsFPRegister()) {
    1918             :         __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg,
    1919        9817 :                   i.InputDoubleRegister(0));
    1920             :       } else {
    1921             :         __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg,
    1922         192 :                   i.InputOperand(0));
    1923             :       }
    1924             :       break;
    1925             :     }
    1926             :     case kSSEFloat64SilenceNaN:
    1927        1825 :       __ Xorpd(kScratchDoubleReg, kScratchDoubleReg);
    1928        3650 :       __ Subsd(i.InputDoubleRegister(0), kScratchDoubleReg);
    1929        1825 :       break;
    1930             :     case kX64Movsxbl:
    1931       13844 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1932       21733 :       ASSEMBLE_MOVX(movsxbl);
    1933       13844 :       __ AssertZeroExtended(i.OutputRegister());
    1934        6922 :       break;
    1935             :     case kX64Movzxbl:
    1936      290874 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1937      438376 :       ASSEMBLE_MOVX(movzxbl);
    1938      290874 :       __ AssertZeroExtended(i.OutputRegister());
    1939      145437 :       break;
    1940             :     case kX64Movsxbq:
    1941       12724 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1942       19086 :       ASSEMBLE_MOVX(movsxbq);
    1943             :       break;
    1944             :     case kX64Movzxbq:
    1945       13336 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1946       20004 :       ASSEMBLE_MOVX(movzxbq);
    1947       13336 :       __ AssertZeroExtended(i.OutputRegister());
    1948        6668 :       break;
    1949             :     case kX64Movb: {
    1950       24062 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1951       12031 :       size_t index = 0;
    1952       12031 :       Operand operand = i.MemoryOperand(&index);
    1953       24062 :       if (HasImmediateInput(instr, index)) {
    1954        4332 :         __ movb(operand, Immediate(i.InputInt8(index)));
    1955             :       } else {
    1956       19730 :         __ movb(operand, i.InputRegister(index));
    1957             :       }
    1958             :       break;
    1959             :     }
    1960             :     case kX64Movsxwl:
    1961        6180 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1962        9956 :       ASSEMBLE_MOVX(movsxwl);
    1963        6180 :       __ AssertZeroExtended(i.OutputRegister());
    1964        3090 :       break;
    1965             :     case kX64Movzxwl:
    1966       44088 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1967       71248 :       ASSEMBLE_MOVX(movzxwl);
    1968       44090 :       __ AssertZeroExtended(i.OutputRegister());
    1969       22045 :       break;
    1970             :     case kX64Movsxwq:
    1971        9952 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1972       14928 :       ASSEMBLE_MOVX(movsxwq);
    1973             :       break;
    1974             :     case kX64Movzxwq:
    1975           0 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1976           0 :       ASSEMBLE_MOVX(movzxwq);
    1977           0 :       __ AssertZeroExtended(i.OutputRegister());
    1978           0 :       break;
    1979             :     case kX64Movw: {
    1980       16090 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1981        8045 :       size_t index = 0;
    1982        8045 :       Operand operand = i.MemoryOperand(&index);
    1983       16090 :       if (HasImmediateInput(instr, index)) {
    1984         702 :         __ movw(operand, Immediate(i.InputInt16(index)));
    1985             :       } else {
    1986       15388 :         __ movw(operand, i.InputRegister(index));
    1987             :       }
    1988             :       break;
    1989             :     }
    1990             :     case kX64Movl:
    1991     1276930 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    1992      638466 :       if (instr->HasOutput()) {
    1993      389331 :         if (instr->addressing_mode() == kMode_None) {
    1994      156242 :           if (instr->InputAt(0)->IsRegister()) {
    1995      153346 :             __ movl(i.OutputRegister(), i.InputRegister(0));
    1996             :           } else {
    1997        2896 :             __ movl(i.OutputRegister(), i.InputOperand(0));
    1998             :           }
    1999             :         } else {
    2000      622410 :           __ movl(i.OutputRegister(), i.MemoryOperand());
    2001             :         }
    2002      778598 :         __ AssertZeroExtended(i.OutputRegister());
    2003             :       } else {
    2004      249135 :         size_t index = 0;
    2005      249135 :         Operand operand = i.MemoryOperand(&index);
    2006      498272 :         if (HasImmediateInput(instr, index)) {
    2007       68181 :           __ movl(operand, i.InputImmediate(index));
    2008             :         } else {
    2009      361910 :           __ movl(operand, i.InputRegister(index));
    2010             :         }
    2011             :       }
    2012             :       break;
    2013             :     case kX64Movsxlq:
    2014      160432 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    2015      268441 :       ASSEMBLE_MOVX(movsxlq);
    2016             :       break;
    2017             :     case kX64Movq:
    2018     8219362 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    2019     4109678 :       if (instr->HasOutput()) {
    2020     5278760 :         __ movq(i.OutputRegister(), i.MemoryOperand());
    2021             :       } else {
    2022     1470322 :         size_t index = 0;
    2023     1470322 :         Operand operand = i.MemoryOperand(&index);
    2024     2940640 :         if (HasImmediateInput(instr, index)) {
    2025       53562 :           __ movq(operand, i.InputImmediate(index));
    2026             :         } else {
    2027     2833516 :           __ movq(operand, i.InputRegister(index));
    2028             :         }
    2029             :       }
    2030             :       break;
    2031             :     case kX64Movss:
    2032       37170 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    2033       18585 :       if (instr->HasOutput()) {
    2034       22506 :         __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
    2035             :       } else {
    2036        7333 :         size_t index = 0;
    2037        7333 :         Operand operand = i.MemoryOperand(&index);
    2038       14666 :         __ movss(operand, i.InputDoubleRegister(index));
    2039             :       }
    2040             :       break;
    2041             :     case kX64Movsd:
    2042      831474 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    2043      415728 :       if (instr->HasOutput()) {
    2044      577342 :         __ Movsd(i.OutputDoubleRegister(), i.MemoryOperand());
    2045             :       } else {
    2046      127073 :         size_t index = 0;
    2047      127073 :         Operand operand = i.MemoryOperand(&index);
    2048      254150 :         __ Movsd(operand, i.InputDoubleRegister(index));
    2049             :       }
    2050             :       break;
    2051             :     case kX64Movdqu: {
    2052             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2053         240 :       EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
    2054         120 :       if (instr->HasOutput()) {
    2055         156 :         __ movdqu(i.OutputSimd128Register(), i.MemoryOperand());
    2056             :       } else {
    2057          42 :         size_t index = 0;
    2058          42 :         Operand operand = i.MemoryOperand(&index);
    2059          84 :         __ movdqu(operand, i.InputSimd128Register(index));
    2060             :       }
    2061             :       break;
    2062             :     }
    2063             :     case kX64BitcastFI:
    2064      125568 :       if (instr->InputAt(0)->IsFPStackSlot()) {
    2065           0 :         __ movl(i.OutputRegister(), i.InputOperand(0));
    2066             :       } else {
    2067       62784 :         __ Movd(i.OutputRegister(), i.InputDoubleRegister(0));
    2068             :       }
    2069             :       break;
    2070             :     case kX64BitcastDL:
    2071      124780 :       if (instr->InputAt(0)->IsFPStackSlot()) {
    2072           0 :         __ movq(i.OutputRegister(), i.InputOperand(0));
    2073             :       } else {
    2074       62390 :         __ Movq(i.OutputRegister(), i.InputDoubleRegister(0));
    2075             :       }
    2076             :       break;
    2077             :     case kX64BitcastIF:
    2078         438 :       if (instr->InputAt(0)->IsRegister()) {
    2079         219 :         __ Movd(i.OutputDoubleRegister(), i.InputRegister(0));
    2080             :       } else {
    2081           0 :         __ movss(i.OutputDoubleRegister(), i.InputOperand(0));
    2082             :       }
    2083             :       break;
    2084             :     case kX64BitcastLD:
    2085         550 :       if (instr->InputAt(0)->IsRegister()) {
    2086         275 :         __ Movq(i.OutputDoubleRegister(), i.InputRegister(0));
    2087             :       } else {
    2088           0 :         __ Movsd(i.OutputDoubleRegister(), i.InputOperand(0));
    2089             :       }
    2090             :       break;
    2091             :     case kX64Lea32: {
    2092             :       AddressingMode mode = AddressingModeField::decode(instr->opcode());
    2093             :       // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
    2094             :       // and addressing mode just happens to work out. The "addl"/"subl" forms
    2095             :       // in these cases are faster based on measurements.
    2096      223533 :       if (i.InputRegister(0) == i.OutputRegister()) {
    2097       94124 :         if (mode == kMode_MRI) {
    2098       68580 :           int32_t constant_summand = i.InputInt32(1);
    2099       68584 :           if (constant_summand > 0) {
    2100       86512 :             __ addl(i.OutputRegister(), Immediate(constant_summand));
    2101       25328 :           } else if (constant_summand < 0) {
    2102       75321 :             __ subl(i.OutputRegister(), Immediate(-constant_summand));
    2103             :           }
    2104       25544 :         } else if (mode == kMode_MR1) {
    2105       10745 :           if (i.InputRegister(1) == i.OutputRegister()) {
    2106         887 :             __ shll(i.OutputRegister(), Immediate(1));
    2107             :           } else {
    2108        9858 :             __ addl(i.OutputRegister(), i.InputRegister(1));
    2109             :           }
    2110       14799 :         } else if (mode == kMode_M2) {
    2111           0 :           __ shll(i.OutputRegister(), Immediate(1));
    2112       14799 :         } else if (mode == kMode_M4) {
    2113         265 :           __ shll(i.OutputRegister(), Immediate(2));
    2114       14534 :         } else if (mode == kMode_M8) {
    2115         117 :           __ shll(i.OutputRegister(), Immediate(3));
    2116             :         } else {
    2117       28836 :           __ leal(i.OutputRegister(), i.MemoryOperand());
    2118             :         }
    2119      150620 :       } else if (mode == kMode_MR1 &&
    2120             :                  i.InputRegister(1) == i.OutputRegister()) {
    2121       14193 :         __ addl(i.OutputRegister(), i.InputRegister(0));
    2122             :       } else {
    2123      230438 :         __ leal(i.OutputRegister(), i.MemoryOperand());
    2124             :       }
    2125      447084 :       __ AssertZeroExtended(i.OutputRegister());
    2126      223542 :       break;
    2127             :     }
    2128             :     case kX64Lea: {
    2129             :       AddressingMode mode = AddressingModeField::decode(instr->opcode());
    2130             :       // Shorten "leaq" to "addq", "subq" or "shlq" if the register allocation
    2131             :       // and addressing mode just happens to work out. The "addq"/"subq" forms
    2132             :       // in these cases are faster based on measurements.
    2133     1123591 :       if (i.InputRegister(0) == i.OutputRegister()) {
    2134      418397 :         if (mode == kMode_MRI) {
    2135      369448 :           int32_t constant_summand = i.InputInt32(1);
    2136      369475 :           if (constant_summand > 0) {
    2137      466914 :             __ addq(i.OutputRegister(), Immediate(constant_summand));
    2138      136018 :           } else if (constant_summand < 0) {
    2139      405903 :             __ subq(i.OutputRegister(), Immediate(-constant_summand));
    2140             :           }
    2141       48949 :         } else if (mode == kMode_MR1) {
    2142       21500 :           if (i.InputRegister(1) == i.OutputRegister()) {
    2143        2246 :             __ shlq(i.OutputRegister(), Immediate(1));
    2144             :           } else {
    2145       19254 :             __ addq(i.OutputRegister(), i.InputRegister(1));
    2146             :           }
    2147       27449 :         } else if (mode == kMode_M2) {
    2148           0 :           __ shlq(i.OutputRegister(), Immediate(1));
    2149       27449 :         } else if (mode == kMode_M4) {
    2150        1054 :           __ shlq(i.OutputRegister(), Immediate(2));
    2151       26395 :         } else if (mode == kMode_M8) {
    2152        6972 :           __ shlq(i.OutputRegister(), Immediate(3));
    2153             :         } else {
    2154       38846 :           __ leaq(i.OutputRegister(), i.MemoryOperand());
    2155             :         }
    2156      766407 :       } else if (mode == kMode_MR1 &&
    2157             :                  i.InputRegister(1) == i.OutputRegister()) {
    2158       23957 :         __ addq(i.OutputRegister(), i.InputRegister(0));
    2159             :       } else {
    2160     1362496 :         __ leaq(i.OutputRegister(), i.MemoryOperand());
    2161             :       }
    2162             :       break;
    2163             :     }
    2164             :     case kX64Dec32:
    2165           0 :       __ decl(i.OutputRegister());
    2166             :       break;
    2167             :     case kX64Inc32:
    2168           0 :       __ incl(i.OutputRegister());
    2169             :       break;
    2170             :     case kX64Push:
    2171     3698046 :       if (AddressingModeField::decode(instr->opcode()) != kMode_None) {
    2172      135062 :         size_t index = 0;
    2173      135062 :         Operand operand = i.MemoryOperand(&index);
    2174      135062 :         __ pushq(operand);
    2175             :         frame_access_state()->IncreaseSPDelta(1);
    2176             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    2177      270124 :                                                          kPointerSize);
    2178     3562984 :       } else if (HasImmediateInput(instr, 0)) {
    2179      194900 :         __ pushq(i.InputImmediate(0));
    2180             :         frame_access_state()->IncreaseSPDelta(1);
    2181             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    2182      389800 :                                                          kPointerSize);
    2183     3368084 :       } else if (instr->InputAt(0)->IsRegister()) {
    2184     2910131 :         __ pushq(i.InputRegister(0));
    2185             :         frame_access_state()->IncreaseSPDelta(1);
    2186             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    2187     5820266 :                                                          kPointerSize);
    2188      457953 :       } else if (instr->InputAt(0)->IsFPRegister()) {
    2189             :         // TODO(titzer): use another machine instruction?
    2190       28694 :         __ subq(rsp, Immediate(kDoubleSize));
    2191             :         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
    2192             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    2193       57388 :                                                          kDoubleSize);
    2194       57388 :         __ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
    2195             :       } else {
    2196      429259 :         __ pushq(i.InputOperand(0));
    2197             :         frame_access_state()->IncreaseSPDelta(1);
    2198             :         unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    2199      858518 :                                                          kPointerSize);
    2200             :       }
    2201             :       break;
    2202             :     case kX64Poke: {
    2203             :       int const slot = MiscField::decode(instr->opcode());
    2204        1903 :       if (HasImmediateInput(instr, 0)) {
    2205        1276 :         __ movq(Operand(rsp, slot * kPointerSize), i.InputImmediate(0));
    2206             :       } else {
    2207        2530 :         __ movq(Operand(rsp, slot * kPointerSize), i.InputRegister(0));
    2208             :       }
    2209             :       break;
    2210             :     }
    2211             :     case kX64I32x4Splat: {
    2212         354 :       XMMRegister dst = i.OutputSimd128Register();
    2213         354 :       __ movd(dst, i.InputRegister(0));
    2214         354 :       __ pshufd(dst, dst, 0x0);
    2215             :       break;
    2216             :     }
    2217             :     case kX64I32x4ExtractLane: {
    2218             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2219        1680 :       __ Pextrd(i.OutputRegister(), i.InputSimd128Register(0), i.InputInt8(1));
    2220             :       break;
    2221             :     }
    2222             :     case kX64I32x4ReplaceLane: {
    2223             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2224         156 :       if (instr->InputAt(2)->IsRegister()) {
    2225             :         __ Pinsrd(i.OutputSimd128Register(), i.InputRegister(2),
    2226         156 :                   i.InputInt8(1));
    2227             :       } else {
    2228           0 :         __ Pinsrd(i.OutputSimd128Register(), i.InputOperand(2), i.InputInt8(1));
    2229             :       }
    2230             :       break;
    2231             :     }
    2232             :     case kX64I32x4Neg: {
    2233             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2234             :       XMMRegister dst = i.OutputSimd128Register();
    2235             :       XMMRegister src = i.InputSimd128Register(0);
    2236           6 :       if (dst == src) {
    2237           6 :         __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    2238             :         __ psignd(dst, kScratchDoubleReg);
    2239             :       } else {
    2240           0 :         __ pxor(dst, dst);
    2241             :         __ psubd(dst, src);
    2242             :       }
    2243             :       break;
    2244             :     }
    2245             :     case kX64I32x4Shl: {
    2246          12 :       __ pslld(i.OutputSimd128Register(), i.InputInt8(1));
    2247           6 :       break;
    2248             :     }
    2249             :     case kX64I32x4ShrS: {
    2250          12 :       __ psrad(i.OutputSimd128Register(), i.InputInt8(1));
    2251           6 :       break;
    2252             :     }
    2253             :     case kX64I32x4Add: {
    2254          12 :       __ paddd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2255             :       break;
    2256             :     }
    2257             :     case kX64I32x4AddHoriz: {
    2258             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2259           6 :       __ phaddd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2260             :       break;
    2261             :     }
    2262             :     case kX64I32x4Sub: {
    2263           6 :       __ psubd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2264             :       break;
    2265             :     }
    2266             :     case kX64I32x4Mul: {
    2267             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2268           6 :       __ pmulld(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2269             :       break;
    2270             :     }
    2271             :     case kX64I32x4MinS: {
    2272             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2273           6 :       __ pminsd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2274             :       break;
    2275             :     }
    2276             :     case kX64I32x4MaxS: {
    2277             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2278           6 :       __ pmaxsd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2279             :       break;
    2280             :     }
    2281             :     case kX64I32x4Eq: {
    2282           6 :       __ pcmpeqd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2283             :       break;
    2284             :     }
    2285             :     case kX64I32x4Ne: {
    2286          12 :       __ pcmpeqd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2287             :       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    2288          12 :       __ pxor(i.OutputSimd128Register(), kScratchDoubleReg);
    2289             :       break;
    2290             :     }
    2291             :     case kX64I32x4GtS: {
    2292          12 :       __ pcmpgtd(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2293             :       break;
    2294             :     }
    2295             :     case kX64I32x4GeS: {
    2296             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2297             :       XMMRegister dst = i.OutputSimd128Register();
    2298             :       XMMRegister src = i.InputSimd128Register(1);
    2299          12 :       __ pminsd(dst, src);
    2300             :       __ pcmpeqd(dst, src);
    2301             :       break;
    2302             :     }
    2303             :     case kX64I32x4ShrU: {
    2304          12 :       __ psrld(i.OutputSimd128Register(), i.InputInt8(1));
    2305           6 :       break;
    2306             :     }
    2307             :     case kX64I32x4MinU: {
    2308             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2309           6 :       __ pminud(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2310             :       break;
    2311             :     }
    2312             :     case kX64I32x4MaxU: {
    2313             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2314           6 :       __ pmaxud(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2315             :       break;
    2316             :     }
    2317             :     case kX64I32x4GtU: {
    2318             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2319             :       XMMRegister dst = i.OutputSimd128Register();
    2320             :       XMMRegister src = i.InputSimd128Register(1);
    2321          12 :       __ pmaxud(dst, src);
    2322             :       __ pcmpeqd(dst, src);
    2323             :       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    2324             :       __ pxor(dst, kScratchDoubleReg);
    2325             :       break;
    2326             :     }
    2327             :     case kX64I32x4GeU: {
    2328             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2329             :       XMMRegister dst = i.OutputSimd128Register();
    2330             :       XMMRegister src = i.InputSimd128Register(1);
    2331          12 :       __ pminud(dst, src);
    2332             :       __ pcmpeqd(dst, src);
    2333             :       break;
    2334             :     }
    2335             :     case kX64S128Zero: {
    2336           0 :       XMMRegister dst = i.OutputSimd128Register();
    2337           0 :       __ xorps(dst, dst);
    2338             :       break;
    2339             :     }
    2340             :     case kX64I16x8Splat: {
    2341         324 :       XMMRegister dst = i.OutputSimd128Register();
    2342         324 :       __ movd(dst, i.InputRegister(0));
    2343         324 :       __ pshuflw(dst, dst, 0x0);
    2344         324 :       __ pshufhw(dst, dst, 0x0);
    2345         324 :       __ pshufd(dst, dst, 0x0);
    2346             :       break;
    2347             :     }
    2348             :     case kX64I16x8ExtractLane: {
    2349             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2350        1680 :       Register dst = i.OutputRegister();
    2351        3360 :       __ pextrw(dst, i.InputSimd128Register(0), i.InputInt8(1));
    2352        1680 :       __ movsxwl(dst, dst);
    2353             :       break;
    2354             :     }
    2355             :     case kX64I16x8ReplaceLane: {
    2356             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2357         144 :       if (instr->InputAt(2)->IsRegister()) {
    2358             :         __ pinsrw(i.OutputSimd128Register(), i.InputRegister(2),
    2359         144 :                   i.InputInt8(1));
    2360             :       } else {
    2361           0 :         __ pinsrw(i.OutputSimd128Register(), i.InputOperand(2), i.InputInt8(1));
    2362             :       }
    2363             :       break;
    2364             :     }
    2365             :     case kX64I16x8Neg: {
    2366             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2367             :       XMMRegister dst = i.OutputSimd128Register();
    2368             :       XMMRegister src = i.InputSimd128Register(0);
    2369           6 :       if (dst == src) {
    2370           6 :         __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    2371             :         __ psignw(dst, kScratchDoubleReg);
    2372             :       } else {
    2373           0 :         __ pxor(dst, dst);
    2374             :         __ psubw(dst, src);
    2375             :       }
    2376             :       break;
    2377             :     }
    2378             :     case kX64I16x8Shl: {
    2379          12 :       __ psllw(i.OutputSimd128Register(), i.InputInt8(1));
    2380           6 :       break;
    2381             :     }
    2382             :     case kX64I16x8ShrS: {
    2383          12 :       __ psraw(i.OutputSimd128Register(), i.InputInt8(1));
    2384           6 :       break;
    2385             :     }
    2386             :     case kX64I16x8Add: {
    2387           6 :       __ paddw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2388             :       break;
    2389             :     }
    2390             :     case kX64I16x8AddSaturateS: {
    2391           6 :       __ paddsw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2392             :       break;
    2393             :     }
    2394             :     case kX64I16x8AddHoriz: {
    2395             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2396           6 :       __ phaddw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2397             :       break;
    2398             :     }
    2399             :     case kX64I16x8Sub: {
    2400           6 :       __ psubw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2401             :       break;
    2402             :     }
    2403             :     case kX64I16x8SubSaturateS: {
    2404           6 :       __ psubsw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2405             :       break;
    2406             :     }
    2407             :     case kX64I16x8Mul: {
    2408             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2409           6 :       __ pmullw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2410             :       break;
    2411             :     }
    2412             :     case kX64I16x8MinS: {
    2413             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2414           6 :       __ pminsw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2415             :       break;
    2416             :     }
    2417             :     case kX64I16x8MaxS: {
    2418             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2419           6 :       __ pmaxsw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2420             :       break;
    2421             :     }
    2422             :     case kX64I16x8Eq: {
    2423           6 :       __ pcmpeqw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2424             :       break;
    2425             :     }
    2426             :     case kX64I16x8Ne: {
    2427          12 :       __ pcmpeqw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2428             :       __ pcmpeqw(kScratchDoubleReg, kScratchDoubleReg);
    2429          12 :       __ pxor(i.OutputSimd128Register(), kScratchDoubleReg);
    2430             :       break;
    2431             :     }
    2432             :     case kX64I16x8GtS: {
    2433          12 :       __ pcmpgtw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2434             :       break;
    2435             :     }
    2436             :     case kX64I16x8GeS: {
    2437             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2438             :       XMMRegister dst = i.OutputSimd128Register();
    2439             :       XMMRegister src = i.InputSimd128Register(1);
    2440          12 :       __ pminsw(dst, src);
    2441             :       __ pcmpeqw(dst, src);
    2442             :       break;
    2443             :     }
    2444             :     case kX64I16x8ShrU: {
    2445          12 :       __ psrlw(i.OutputSimd128Register(), i.InputInt8(1));
    2446           6 :       break;
    2447             :     }
    2448             :     case kX64I16x8AddSaturateU: {
    2449           6 :       __ paddusw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2450             :       break;
    2451             :     }
    2452             :     case kX64I16x8SubSaturateU: {
    2453           6 :       __ psubusw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2454             :       break;
    2455             :     }
    2456             :     case kX64I16x8MinU: {
    2457             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2458           6 :       __ pminuw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2459             :       break;
    2460             :     }
    2461             :     case kX64I16x8MaxU: {
    2462             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2463           6 :       __ pmaxuw(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2464             :       break;
    2465             :     }
    2466             :     case kX64I16x8GtU: {
    2467             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2468             :       XMMRegister dst = i.OutputSimd128Register();
    2469             :       XMMRegister src = i.InputSimd128Register(1);
    2470          12 :       __ pmaxuw(dst, src);
    2471             :       __ pcmpeqw(dst, src);
    2472             :       __ pcmpeqw(kScratchDoubleReg, kScratchDoubleReg);
    2473             :       __ pxor(dst, kScratchDoubleReg);
    2474             :       break;
    2475             :     }
    2476             :     case kX64I16x8GeU: {
    2477             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2478             :       XMMRegister dst = i.OutputSimd128Register();
    2479             :       XMMRegister src = i.InputSimd128Register(1);
    2480          24 :       __ pminuw(dst, src);
    2481             :       __ pcmpeqw(dst, src);
    2482             :       break;
    2483             :     }
    2484             :     case kX64I8x16Splat: {
    2485             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2486             :       XMMRegister dst = i.OutputSimd128Register();
    2487         294 :       __ movd(dst, i.InputRegister(0));
    2488         294 :       __ xorps(kScratchDoubleReg, kScratchDoubleReg);
    2489             :       __ pshufb(dst, kScratchDoubleReg);
    2490             :       break;
    2491             :     }
    2492             :     case kX64I8x16ExtractLane: {
    2493             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2494        3648 :       Register dst = i.OutputRegister();
    2495        7296 :       __ pextrb(dst, i.InputSimd128Register(0), i.InputInt8(1));
    2496        3648 :       __ movsxbl(dst, dst);
    2497             :       break;
    2498             :     }
    2499             :     case kX64I8x16ReplaceLane: {
    2500             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2501         240 :       if (instr->InputAt(2)->IsRegister()) {
    2502             :         __ pinsrb(i.OutputSimd128Register(), i.InputRegister(2),
    2503         240 :                   i.InputInt8(1));
    2504             :       } else {
    2505           0 :         __ pinsrb(i.OutputSimd128Register(), i.InputOperand(2), i.InputInt8(1));
    2506             :       }
    2507             :       break;
    2508             :     }
    2509             :     case kX64I8x16Neg: {
    2510             :       CpuFeatureScope sse_scope(tasm(), SSSE3);
    2511             :       XMMRegister dst = i.OutputSimd128Register();
    2512             :       XMMRegister src = i.InputSimd128Register(0);
    2513           6 :       if (dst == src) {
    2514           6 :         __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    2515             :         __ psignb(dst, kScratchDoubleReg);
    2516             :       } else {
    2517           0 :         __ pxor(dst, dst);
    2518             :         __ psubb(dst, src);
    2519             :       }
    2520             :       break;
    2521             :     }
    2522             :     case kX64I8x16Add: {
    2523           6 :       __ paddb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2524             :       break;
    2525             :     }
    2526             :     case kX64I8x16AddSaturateS: {
    2527           6 :       __ paddsb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2528             :       break;
    2529             :     }
    2530             :     case kX64I8x16Sub: {
    2531           6 :       __ psubb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2532             :       break;
    2533             :     }
    2534             :     case kX64I8x16SubSaturateS: {
    2535           6 :       __ psubsb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2536             :       break;
    2537             :     }
    2538             :     case kX64I8x16MinS: {
    2539             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2540           6 :       __ pminsb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2541             :       break;
    2542             :     }
    2543             :     case kX64I8x16MaxS: {
    2544             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2545           6 :       __ pmaxsb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2546             :       break;
    2547             :     }
    2548             :     case kX64I8x16Eq: {
    2549           6 :       __ pcmpeqb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2550             :       break;
    2551             :     }
    2552             :     case kX64I8x16Ne: {
    2553          12 :       __ pcmpeqb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2554             :       __ pcmpeqb(kScratchDoubleReg, kScratchDoubleReg);
    2555          12 :       __ pxor(i.OutputSimd128Register(), kScratchDoubleReg);
    2556             :       break;
    2557             :     }
    2558             :     case kX64I8x16GtS: {
    2559          12 :       __ pcmpgtb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2560             :       break;
    2561             :     }
    2562             :     case kX64I8x16GeS: {
    2563             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2564             :       XMMRegister dst = i.OutputSimd128Register();
    2565             :       XMMRegister src = i.InputSimd128Register(1);
    2566          12 :       __ pminsb(dst, src);
    2567             :       __ pcmpeqb(dst, src);
    2568             :       break;
    2569             :     }
    2570             :     case kX64I8x16AddSaturateU: {
    2571           6 :       __ paddusb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2572             :       break;
    2573             :     }
    2574             :     case kX64I8x16SubSaturateU: {
    2575           6 :       __ psubusb(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2576             :       break;
    2577             :     }
    2578             :     case kX64I8x16MinU: {
    2579             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2580           6 :       __ pminub(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2581             :       break;
    2582             :     }
    2583             :     case kX64I8x16MaxU: {
    2584             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2585           6 :       __ pmaxub(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2586             :       break;
    2587             :     }
    2588             :     case kX64I8x16GtU: {
    2589             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2590             :       XMMRegister dst = i.OutputSimd128Register();
    2591             :       XMMRegister src = i.InputSimd128Register(1);
    2592          12 :       __ pmaxub(dst, src);
    2593             :       __ pcmpeqb(dst, src);
    2594             :       __ pcmpeqb(kScratchDoubleReg, kScratchDoubleReg);
    2595             :       __ pxor(dst, kScratchDoubleReg);
    2596             :       break;
    2597             :     }
    2598             :     case kX64I8x16GeU: {
    2599             :       CpuFeatureScope sse_scope(tasm(), SSE4_1);
    2600             :       XMMRegister dst = i.OutputSimd128Register();
    2601             :       XMMRegister src = i.InputSimd128Register(1);
    2602           0 :       __ pminub(dst, src);
    2603             :       __ pcmpeqb(dst, src);
    2604             :       break;
    2605             :     }
    2606             :     case kX64S128And: {
    2607           6 :       __ pand(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2608             :       break;
    2609             :     }
    2610             :     case kX64S128Or: {
    2611           6 :       __ por(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2612             :       break;
    2613             :     }
    2614             :     case kX64S128Xor: {
    2615           6 :       __ pxor(i.OutputSimd128Register(), i.InputSimd128Register(1));
    2616             :       break;
    2617             :     }
    2618             :     case kX64S128Not: {
    2619             :       XMMRegister dst = i.OutputSimd128Register();
    2620             :       XMMRegister src = i.InputSimd128Register(0);
    2621           6 :       if (dst == src) {
    2622           6 :         __ movaps(kScratchDoubleReg, dst);
    2623             :         __ pcmpeqd(dst, dst);
    2624             :         __ pxor(dst, kScratchDoubleReg);
    2625             :       } else {
    2626           0 :         __ pcmpeqd(dst, dst);
    2627             :         __ pxor(dst, src);
    2628             :       }
    2629             : 
    2630             :       break;
    2631             :     }
    2632             :     case kX64S128Select: {
    2633             :       // Mask used here is stored in dst.
    2634          36 :       XMMRegister dst = i.OutputSimd128Register();
    2635          36 :       __ movaps(kScratchDoubleReg, i.InputSimd128Register(1));
    2636          72 :       __ xorps(kScratchDoubleReg, i.InputSimd128Register(2));
    2637          36 :       __ andps(dst, kScratchDoubleReg);
    2638          72 :       __ xorps(dst, i.InputSimd128Register(2));
    2639             :       break;
    2640             :     }
    2641             :     case kCheckedLoadInt8:
    2642       11310 :       ASSEMBLE_CHECKED_LOAD_INTEGER(movsxbl);
    2643        3770 :       break;
    2644             :     case kCheckedLoadUint8:
    2645       11344 :       ASSEMBLE_CHECKED_LOAD_INTEGER(movzxbl);
    2646        2836 :       break;
    2647             :     case kCheckedLoadInt16:
    2648        3810 :       ASSEMBLE_CHECKED_LOAD_INTEGER(movsxwl);
    2649        1270 :       break;
    2650             :     case kCheckedLoadUint16:
    2651        2868 :       ASSEMBLE_CHECKED_LOAD_INTEGER(movzxwl);
    2652         717 :       break;
    2653             :     case kCheckedLoadWord32:
    2654      236360 :       ASSEMBLE_CHECKED_LOAD_INTEGER(movl);
    2655       58862 :       break;
    2656             :     case kCheckedLoadWord64:
    2657          72 :       ASSEMBLE_CHECKED_LOAD_INTEGER(movq);
    2658           6 :       break;
    2659             :     case kCheckedLoadFloat32:
    2660       23268 :       ASSEMBLE_CHECKED_LOAD_FLOAT(Movss, OutOfLineLoadFloat32NaN);
    2661        7666 :       break;
    2662             :     case kCheckedLoadFloat64:
    2663        3531 :       ASSEMBLE_CHECKED_LOAD_FLOAT(Movsd, OutOfLineLoadFloat64NaN);
    2664        1087 :       break;
    2665             :     case kCheckedStoreWord8:
    2666       26015 :       ASSEMBLE_CHECKED_STORE_INTEGER(movb);
    2667             :       break;
    2668             :     case kCheckedStoreWord16:
    2669       11988 :       ASSEMBLE_CHECKED_STORE_INTEGER(movw);
    2670             :       break;
    2671             :     case kCheckedStoreWord32:
    2672      307337 :       ASSEMBLE_CHECKED_STORE_INTEGER(movl);
    2673             :       break;
    2674             :     case kCheckedStoreWord64:
    2675          72 :       ASSEMBLE_CHECKED_STORE_INTEGER(movq);
    2676             :       break;
    2677             :     case kCheckedStoreFloat32:
    2678       23075 :       ASSEMBLE_CHECKED_STORE_FLOAT(Movss);
    2679             :       break;
    2680             :     case kCheckedStoreFloat64:
    2681        4475 :       ASSEMBLE_CHECKED_STORE_FLOAT(Movsd);
    2682             :       break;
    2683             :     case kX64StackCheck:
    2684      666206 :       __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
    2685      666214 :       break;
    2686             :     case kAtomicExchangeInt8: {
    2687         280 :       __ xchgb(i.InputRegister(0), i.MemoryOperand(1));
    2688         280 :       __ movsxbl(i.InputRegister(0), i.InputRegister(0));
    2689         140 :       break;
    2690             :     }
    2691             :     case kAtomicExchangeUint8: {
    2692         156 :       __ xchgb(i.InputRegister(0), i.MemoryOperand(1));
    2693          78 :       __ movzxbl(i.InputRegister(0), i.InputRegister(0));
    2694             :       break;
    2695             :     }
    2696             :     case kAtomicExchangeInt16: {
    2697         280 :       __ xchgw(i.InputRegister(0), i.MemoryOperand(1));
    2698         280 :       __ movsxwl(i.InputRegister(0), i.InputRegister(0));
    2699         140 :       break;
    2700             :     }
    2701             :     case kAtomicExchangeUint16: {
    2702         156 :       __ xchgw(i.InputRegister(0), i.MemoryOperand(1));
    2703          78 :       __ movzxwl(i.InputRegister(0), i.InputRegister(0));
    2704             :       break;
    2705             :     }
    2706             :     case kAtomicExchangeWord32: {
    2707         508 :       __ xchgl(i.InputRegister(0), i.MemoryOperand(1));
    2708             :       break;
    2709             :     }
    2710             :     case kAtomicCompareExchangeInt8: {
    2711          62 :       __ lock();
    2712         124 :       __ cmpxchgb(i.MemoryOperand(2), i.InputRegister(1));
    2713          62 :       __ movsxbl(rax, rax);
    2714          62 :       break;
    2715             :     }
    2716             :     case kAtomicCompareExchangeUint8: {
    2717          78 :       __ lock();
    2718         156 :       __ cmpxchgb(i.MemoryOperand(2), i.InputRegister(1));
    2719             :       __ movzxbl(rax, rax);
    2720             :       break;
    2721             :     }
    2722             :     case kAtomicCompareExchangeInt16: {
    2723          62 :       __ lock();
    2724         124 :       __ cmpxchgw(i.MemoryOperand(2), i.InputRegister(1));
    2725          62 :       __ movsxwl(rax, rax);
    2726          62 :       break;
    2727             :     }
    2728             :     case kAtomicCompareExchangeUint16: {
    2729          78 :       __ lock();
    2730         156 :       __ cmpxchgw(i.MemoryOperand(2), i.InputRegister(1));
    2731             :       __ movzxwl(rax, rax);
    2732             :       break;
    2733             :     }
    2734             :     case kAtomicCompareExchangeWord32: {
    2735         140 :       __ lock();
    2736         140 :       __ cmpxchgl(i.MemoryOperand(2), i.InputRegister(1));
    2737             :       break;
    2738             :     }
    2739             : #define ATOMIC_BINOP_CASE(op, inst)              \
    2740             :   case kAtomic##op##Int8:                        \
    2741             :     ASSEMBLE_ATOMIC_BINOP(inst, movb, cmpxchgb); \
    2742             :     __ movsxbl(rax, rax);                        \
    2743             :     break;                                       \
    2744             :   case kAtomic##op##Uint8:                       \
    2745             :     ASSEMBLE_ATOMIC_BINOP(inst, movb, cmpxchgb); \
    2746             :     __ movzxbl(rax, rax);                        \
    2747             :     break;                                       \
    2748             :   case kAtomic##op##Int16:                       \
    2749             :     ASSEMBLE_ATOMIC_BINOP(inst, movw, cmpxchgw); \
    2750             :     __ movsxwl(rax, rax);                        \
    2751             :     break;                                       \
    2752             :   case kAtomic##op##Uint16:                      \
    2753             :     ASSEMBLE_ATOMIC_BINOP(inst, movw, cmpxchgw); \
    2754             :     __ movzxwl(rax, rax);                        \
    2755             :     break;                                       \
    2756             :   case kAtomic##op##Word32:                      \
    2757             :     ASSEMBLE_ATOMIC_BINOP(inst, movl, cmpxchgl); \
    2758             :     break;
    2759        2100 :       ATOMIC_BINOP_CASE(Add, addl)
    2760        2100 :       ATOMIC_BINOP_CASE(Sub, subl)
    2761        2100 :       ATOMIC_BINOP_CASE(And, andl)
    2762        2100 :       ATOMIC_BINOP_CASE(Or, orl)
    2763        2100 :       ATOMIC_BINOP_CASE(Xor, xorl)
    2764             : #undef ATOMIC_BINOP_CASE
    2765             :     case kAtomicLoadInt8:
    2766             :     case kAtomicLoadUint8:
    2767             :     case kAtomicLoadInt16:
    2768             :     case kAtomicLoadUint16:
    2769             :     case kAtomicLoadWord32:
    2770             :     case kAtomicStoreWord8:
    2771             :     case kAtomicStoreWord16:
    2772             :     case kAtomicStoreWord32:
    2773           0 :       UNREACHABLE();  // Won't be generated by instruction selector.
    2774             :       break;
    2775             :   }
    2776             :   return kSuccess;
    2777             : }  // NOLINT(readability/fn_size)
    2778             : 
    2779             : namespace {
    2780             : 
    2781     4309476 : Condition FlagsConditionToCondition(FlagsCondition condition) {
    2782     4309476 :   switch (condition) {
    2783             :     case kUnorderedEqual:
    2784             :     case kEqual:
    2785             :       return equal;
    2786             :     case kUnorderedNotEqual:
    2787             :     case kNotEqual:
    2788     1084299 :       return not_equal;
    2789             :     case kSignedLessThan:
    2790      103491 :       return less;
    2791             :     case kSignedGreaterThanOrEqual:
    2792       41659 :       return greater_equal;
    2793             :     case kSignedLessThanOrEqual:
    2794       31667 :       return less_equal;
    2795             :     case kSignedGreaterThan:
    2796       35909 :       return greater;
    2797             :     case kUnsignedLessThan:
    2798       67851 :       return below;
    2799             :     case kUnsignedGreaterThanOrEqual:
    2800      130522 :       return above_equal;
    2801             :     case kUnsignedLessThanOrEqual:
    2802      876306 :       return below_equal;
    2803             :     case kUnsignedGreaterThan:
    2804       40091 :       return above;
    2805             :     case kOverflow:
    2806      204408 :       return overflow;
    2807             :     case kNotOverflow:
    2808        1302 :       return no_overflow;
    2809             :     default:
    2810             :       break;
    2811             :   }
    2812           0 :   UNREACHABLE();
    2813             : }
    2814             : 
    2815             : }  // namespace
    2816             : 
    2817             : // Assembles branches after this instruction.
    2818     3609646 : void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
    2819             :   Label::Distance flabel_distance =
    2820     3609646 :       branch->fallthru ? Label::kNear : Label::kFar;
    2821     3609646 :   Label* tlabel = branch->true_label;
    2822     3609646 :   Label* flabel = branch->false_label;
    2823     3609646 :   if (branch->condition == kUnorderedEqual) {
    2824       38512 :     __ j(parity_even, flabel, flabel_distance);
    2825     3571134 :   } else if (branch->condition == kUnorderedNotEqual) {
    2826       82724 :     __ j(parity_even, tlabel);
    2827             :   }
    2828     3609646 :   __ j(FlagsConditionToCondition(branch->condition), tlabel);
    2829             : 
    2830     3609655 :   if (!branch->fallthru) __ jmp(flabel, flabel_distance);
    2831     3609655 : }
    2832             : 
    2833      302299 : void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
    2834             :                                             BranchInfo* branch) {
    2835             :   Label::Distance flabel_distance =
    2836      302299 :       branch->fallthru ? Label::kNear : Label::kFar;
    2837      302299 :   Label* tlabel = branch->true_label;
    2838      302299 :   Label* flabel = branch->false_label;
    2839             :   Label nodeopt;
    2840      302299 :   if (branch->condition == kUnorderedEqual) {
    2841           0 :     __ j(parity_even, flabel, flabel_distance);
    2842      302299 :   } else if (branch->condition == kUnorderedNotEqual) {
    2843        6434 :     __ j(parity_even, tlabel);
    2844             :   }
    2845      302299 :   __ j(FlagsConditionToCondition(branch->condition), tlabel);
    2846             : 
    2847      302306 :   if (FLAG_deopt_every_n_times > 0) {
    2848             :     ExternalReference counter =
    2849         268 :         ExternalReference::stress_deopt_count(isolate());
    2850             : 
    2851         268 :     __ pushfq();
    2852         268 :     __ pushq(rax);
    2853         268 :     __ load_rax(counter);
    2854             :     __ decl(rax);
    2855         268 :     __ j(not_zero, &nodeopt);
    2856             : 
    2857         268 :     __ Set(rax, FLAG_deopt_every_n_times);
    2858         268 :     __ store_rax(counter);
    2859         268 :     __ popq(rax);
    2860         268 :     __ popfq();
    2861         268 :     __ jmp(tlabel);
    2862             : 
    2863         268 :     __ bind(&nodeopt);
    2864         268 :     __ store_rax(counter);
    2865         268 :     __ popq(rax);
    2866         268 :     __ popfq();
    2867             :   }
    2868             : 
    2869      302306 :   if (!branch->fallthru) {
    2870           0 :     __ jmp(flabel, flabel_distance);
    2871             :   }
    2872      302306 : }
    2873             : 
    2874     5608892 : void CodeGenerator::AssembleArchJump(RpoNumber target) {
    2875     5608892 :   if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target));
    2876     3412136 : }
    2877             : 
    2878      197640 : void CodeGenerator::AssembleArchTrap(Instruction* instr,
    2879      395280 :                                      FlagsCondition condition) {
    2880           0 :   class OutOfLineTrap final : public OutOfLineCode {
    2881             :    public:
    2882             :     OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr)
    2883             :         : OutOfLineCode(gen),
    2884             :           frame_elided_(frame_elided),
    2885             :           instr_(instr),
    2886      197661 :           gen_(gen) {}
    2887             : 
    2888      197648 :     void Generate() final {
    2889      395296 :       X64OperandConverter i(gen_, instr_);
    2890             : 
    2891             :       Builtins::Name trap_id =
    2892      197648 :           static_cast<Builtins::Name>(i.InputInt32(instr_->InputCount() - 1));
    2893      238613 :       bool old_has_frame = __ has_frame();
    2894      197671 :       if (frame_elided_) {
    2895             :         __ set_has_frame(true);
    2896       20461 :         __ EnterFrame(StackFrame::WASM_COMPILED);
    2897             :       }
    2898      197660 :       GenerateCallToTrap(trap_id);
    2899      197674 :       if (frame_elided_) {
    2900             :         __ set_has_frame(old_has_frame);
    2901             :       }
    2902      197674 :     }
    2903             : 
    2904             :    private:
    2905      197650 :     void GenerateCallToTrap(Builtins::Name trap_id) {
    2906      197650 :       if (trap_id == Builtins::builtin_count) {
    2907             :         // We cannot test calls to the runtime in cctest/test-run-wasm.
    2908             :         // Therefore we emit a call to C here instead of a call to the runtime.
    2909      627970 :         __ PrepareCallCFunction(0);
    2910             :         __ CallCFunction(ExternalReference::wasm_call_trap_callback_for_testing(
    2911             :                              __ isolate()),
    2912       69856 :                          0);
    2913       34928 :         __ LeaveFrame(StackFrame::WASM_COMPILED);
    2914      232600 :         CallDescriptor* descriptor = gen_->linkage()->GetIncomingDescriptor();
    2915       34928 :         size_t pop_size = descriptor->StackParameterCount() * kPointerSize;
    2916             :         // Use rcx as a scratch register, we return anyways immediately.
    2917       69856 :         __ Ret(static_cast<int>(pop_size), rcx);
    2918             :       } else {
    2919      162722 :         gen_->AssembleSourcePosition(instr_);
    2920             :         __ Call(__ isolate()->builtins()->builtin_handle(trap_id),
    2921      325487 :                 RelocInfo::CODE_TARGET);
    2922             :         ReferenceMap* reference_map =
    2923      162744 :             new (gen_->zone()) ReferenceMap(gen_->zone());
    2924             :         gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
    2925      162738 :                               Safepoint::kNoLazyDeopt);
    2926      162771 :         __ AssertUnreachable(kUnexpectedReturnFromWasmTrap);
    2927             :       }
    2928      197672 :     }
    2929             : 
    2930             :     bool frame_elided_;
    2931             :     Instruction* instr_;
    2932             :     CodeGenerator* gen_;
    2933             :   };
    2934      197640 :   bool frame_elided = !frame_access_state()->has_frame();
    2935             :   auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr);
    2936      197617 :   Label* tlabel = ool->entry();
    2937             :   Label end;
    2938      197617 :   if (condition == kUnorderedEqual) {
    2939           0 :     __ j(parity_even, &end);
    2940      197617 :   } else if (condition == kUnorderedNotEqual) {
    2941         630 :     __ j(parity_even, tlabel);
    2942             :   }
    2943      197619 :   __ j(FlagsConditionToCondition(condition), tlabel);
    2944      197676 :   __ bind(&end);
    2945      197692 : }
    2946             : 
    2947             : // Assembles boolean materializations after this instruction.
    2948      399828 : void CodeGenerator::AssembleArchBoolean(Instruction* instr,
    2949             :                                         FlagsCondition condition) {
    2950             :   X64OperandConverter i(this, instr);
    2951             :   Label done;
    2952             : 
    2953             :   // Materialize a full 64-bit 1 or 0 value. The result register is always the
    2954             :   // last output of the instruction.
    2955             :   Label check;
    2956             :   DCHECK_NE(0u, instr->OutputCount());
    2957      199914 :   Register reg = i.OutputRegister(instr->OutputCount() - 1);
    2958      199914 :   if (condition == kUnorderedEqual) {
    2959        4148 :     __ j(parity_odd, &check, Label::kNear);
    2960             :     __ movl(reg, Immediate(0));
    2961        4147 :     __ jmp(&done, Label::kNear);
    2962      195766 :   } else if (condition == kUnorderedNotEqual) {
    2963        1148 :     __ j(parity_odd, &check, Label::kNear);
    2964             :     __ movl(reg, Immediate(1));
    2965        1148 :     __ jmp(&done, Label::kNear);
    2966             :   }
    2967      199913 :   __ bind(&check);
    2968      199916 :   __ setcc(FlagsConditionToCondition(condition), reg);
    2969             :   __ movzxbl(reg, reg);
    2970      199917 :   __ bind(&done);
    2971      199918 : }
    2972             : 
    2973             : 
    2974      152657 : void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
    2975             :   X64OperandConverter i(this, instr);
    2976       20780 :   Register input = i.InputRegister(0);
    2977      152656 :   for (size_t index = 2; index < instr->InputCount(); index += 2) {
    2978      111096 :     __ cmpl(input, Immediate(i.InputInt32(index + 0)));
    2979      111097 :     __ j(equal, GetLabel(i.InputRpo(index + 1)));
    2980             :   }
    2981       20780 :   AssembleArchJump(i.InputRpo(1));
    2982       20780 : }
    2983             : 
    2984             : 
    2985      342541 : void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
    2986             :   X64OperandConverter i(this, instr);
    2987        7807 :   Register input = i.InputRegister(0);
    2988        7807 :   int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2);
    2989        7807 :   Label** cases = zone()->NewArray<Label*>(case_count);
    2990      326927 :   for (int32_t index = 0; index < case_count; ++index) {
    2991      638240 :     cases[index] = GetLabel(i.InputRpo(index + 2));
    2992             :   }
    2993        7807 :   Label* const table = AddJumpTable(cases, case_count);
    2994        7807 :   __ cmpl(input, Immediate(case_count));
    2995       15614 :   __ j(above_equal, GetLabel(i.InputRpo(1)));
    2996       15614 :   __ leaq(kScratchRegister, Operand(table));
    2997        7807 :   __ jmp(Operand(kScratchRegister, input, times_8, 0));
    2998        7807 : }
    2999             : 
    3000             : namespace {
    3001             : 
    3002             : static const int kQuadWordSize = 16;
    3003             : 
    3004             : }  // namespace
    3005             : 
    3006     1301525 : void CodeGenerator::FinishFrame(Frame* frame) {
    3007     2603050 :   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
    3008             : 
    3009             :   const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
    3010     1301525 :   if (saves_fp != 0) {
    3011             :     frame->AlignSavedCalleeRegisterSlots();
    3012           0 :     if (saves_fp != 0) {  // Save callee-saved XMM registers.
    3013             :       const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
    3014           0 :       frame->AllocateSavedCalleeRegisterSlots(saves_fp_count *
    3015           0 :                                               (kQuadWordSize / kPointerSize));
    3016             :     }
    3017             :   }
    3018             :   const RegList saves = descriptor->CalleeSavedRegisters();
    3019     1301525 :   if (saves != 0) {  // Save callee-saved registers.
    3020             :     int count = 0;
    3021     3662512 :     for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
    3022     3662512 :       if (((1 << i) & saves)) {
    3023     1144535 :         ++count;
    3024             :       }
    3025             :     }
    3026             :     frame->AllocateSavedCalleeRegisterSlots(count);
    3027             :   }
    3028     1301525 : }
    3029             : 
    3030     5159584 : void CodeGenerator::AssembleConstructFrame() {
    3031     3224113 :   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
    3032     1074688 :   if (frame_access_state()->has_frame()) {
    3033     1074710 :     int pc_base = __ pc_offset();
    3034             : 
    3035     1074710 :     if (descriptor->IsCFunctionCall()) {
    3036      228907 :       __ pushq(rbp);
    3037             :       __ movq(rbp, rsp);
    3038      845803 :     } else if (descriptor->IsJSFunctionCall()) {
    3039      619711 :       __ Prologue();
    3040      619715 :       if (descriptor->PushArgumentCount()) {
    3041       15917 :         __ pushq(kJavaScriptCallArgCountRegister);
    3042             :       }
    3043             :     } else {
    3044      226092 :       __ StubPrologue(info()->GetOutputStackFrameType());
    3045             :     }
    3046             : 
    3047     1074698 :     unwinding_info_writer_.MarkFrameConstructed(pc_base);
    3048             :   }
    3049             :   int shrink_slots =
    3050     1074667 :       frame()->GetTotalFrameSlotCount() - descriptor->CalculateFixedFrameSize();
    3051             : 
    3052     1074702 :   if (info()->is_osr()) {
    3053             :     // TurboFan OSR-compiled functions cannot be entered directly.
    3054        5809 :     __ Abort(kShouldNotDirectlyEnterOsrFunction);
    3055             : 
    3056             :     // Unoptimized code jumps directly to this entrypoint while the unoptimized
    3057             :     // frame is still on the stack. Optimized code uses OSR values directly from
    3058             :     // the unoptimized frame. Thus, all that needs to be done is to allocate the
    3059             :     // remaining stack slots.
    3060        5809 :     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
    3061       11618 :     osr_pc_offset_ = __ pc_offset();
    3062        5809 :     shrink_slots -= static_cast<int>(osr_helper()->UnoptimizedFrameSlots());
    3063             :   }
    3064             : 
    3065             :   const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
    3066     1074702 :   if (shrink_slots > 0) {
    3067      634717 :     if (info()->IsWasm() && shrink_slots > 128) {
    3068             :       // For WebAssembly functions with big frames we have to do the stack
    3069             :       // overflow check before we construct the frame. Otherwise we may not
    3070             :       // have enough space on the stack to call the runtime for the stack
    3071             :       // overflow.
    3072             :       Label done;
    3073             : 
    3074             :       // If the frame is bigger than the stack, we throw the stack overflow
    3075             :       // exception unconditionally. Thereby we can avoid the integer overflow
    3076             :       // check in the condition code.
    3077          10 :       if (shrink_slots * kPointerSize < FLAG_stack_size * 1024) {
    3078             :         __ Move(kScratchRegister,
    3079          10 :                 ExternalReference::address_of_real_stack_limit(__ isolate()));
    3080          20 :         __ movq(kScratchRegister, Operand(kScratchRegister, 0));
    3081          10 :         __ addq(kScratchRegister, Immediate(shrink_slots * kPointerSize));
    3082          10 :         __ cmpq(rsp, kScratchRegister);
    3083          10 :         __ j(above_equal, &done);
    3084             :       }
    3085          10 :       if (!frame_access_state()->has_frame()) {
    3086             :         __ set_has_frame(true);
    3087           0 :         __ EnterFrame(StackFrame::WASM_COMPILED);
    3088             :       }
    3089          10 :       __ Move(rsi, Smi::kZero);
    3090          10 :       __ CallRuntimeDelayed(zone(), Runtime::kThrowWasmStackOverflow);
    3091             :       ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
    3092             :       RecordSafepoint(reference_map, Safepoint::kSimple, 0,
    3093          10 :                       Safepoint::kNoLazyDeopt);
    3094          10 :       __ AssertUnreachable(kUnexpectedReturnFromWasmTrap);
    3095          10 :       __ bind(&done);
    3096             :     }
    3097     1269434 :     __ subq(rsp, Immediate(shrink_slots * kPointerSize));
    3098             :   }
    3099             : 
    3100     1074701 :   if (saves_fp != 0) {  // Save callee-saved XMM registers.
    3101             :     const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
    3102           0 :     const int stack_size = saves_fp_count * kQuadWordSize;
    3103             :     // Adjust the stack pointer.
    3104           0 :     __ subp(rsp, Immediate(stack_size));
    3105             :     // Store the registers on the stack.
    3106             :     int slot_idx = 0;
    3107           0 :     for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
    3108           0 :       if (!((1 << i) & saves_fp)) continue;
    3109             :       __ movdqu(Operand(rsp, kQuadWordSize * slot_idx),
    3110           0 :                 XMMRegister::from_code(i));
    3111           0 :       slot_idx++;
    3112             :     }
    3113             :   }
    3114             : 
    3115             :   const RegList saves = descriptor->CalleeSavedRegisters();
    3116     1074701 :   if (saves != 0) {  // Save callee-saved registers.
    3117     3662512 :     for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
    3118     3662512 :       if (!((1 << i) & saves)) continue;
    3119     1144535 :       __ pushq(Register::from_code(i));
    3120             :     }
    3121             :   }
    3122     1074701 : }
    3123             : 
    3124     2779299 : void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
    3125     6042156 :   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
    3126             : 
    3127             :   // Restore registers.
    3128             :   const RegList saves = descriptor->CalleeSavedRegisters();
    3129     1510539 :   if (saves != 0) {
    3130     3868464 :     for (int i = 0; i < Register::kNumRegisters; i++) {
    3131     3868464 :       if (!((1 << i) & saves)) continue;
    3132     1208895 :       __ popq(Register::from_code(i));
    3133             :     }
    3134             :   }
    3135             :   const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
    3136     1510539 :   if (saves_fp != 0) {
    3137             :     const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
    3138           0 :     const int stack_size = saves_fp_count * kQuadWordSize;
    3139             :     // Load the registers from the stack.
    3140             :     int slot_idx = 0;
    3141           0 :     for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
    3142           0 :       if (!((1 << i) & saves_fp)) continue;
    3143             :       __ movdqu(XMMRegister::from_code(i),
    3144           0 :                 Operand(rsp, kQuadWordSize * slot_idx));
    3145           0 :       slot_idx++;
    3146             :     }
    3147             :     // Adjust the stack pointer.
    3148           0 :     __ addp(rsp, Immediate(stack_size));
    3149             :   }
    3150             : 
    3151             :   unwinding_info_writer_.MarkBlockWillExit();
    3152             : 
    3153             :   // Might need rcx for scratch if pop_size is too big or if there is a variable
    3154             :   // pop count.
    3155             :   DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rcx.bit());
    3156             :   DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rdx.bit());
    3157     1510539 :   size_t pop_size = descriptor->StackParameterCount() * kPointerSize;
    3158             :   X64OperandConverter g(this, nullptr);
    3159     1510539 :   if (descriptor->IsCFunctionCall()) {
    3160      241779 :     AssembleDeconstructFrame();
    3161     1268760 :   } else if (frame_access_state()->has_frame()) {
    3162     2168423 :     if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) {
    3163             :       // Canonicalize JSFunction return sites for now.
    3164     1077735 :       if (return_label_.is_bound()) {
    3165      298808 :         __ jmp(&return_label_);
    3166     1510638 :         return;
    3167             :       } else {
    3168      778927 :         __ bind(&return_label_);
    3169      778903 :         AssembleDeconstructFrame();
    3170             :       }
    3171             :     } else {
    3172       12970 :       AssembleDeconstructFrame();
    3173             :     }
    3174             :   }
    3175             : 
    3176     1211717 :   if (pop->IsImmediate()) {
    3177             :     DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type());
    3178     2397566 :     pop_size += g.ToConstant(pop).ToInt32() * kPointerSize;
    3179     1198813 :     CHECK_LT(pop_size, static_cast<size_t>(std::numeric_limits<int>::max()));
    3180     1198813 :     __ Ret(static_cast<int>(pop_size), rcx);
    3181             :   } else {
    3182             :     Register pop_reg = g.ToRegister(pop);
    3183       12964 :     Register scratch_reg = pop_reg == rcx ? rdx : rcx;
    3184       12964 :     __ popq(scratch_reg);
    3185       25928 :     __ leaq(rsp, Operand(rsp, pop_reg, times_8, static_cast<int>(pop_size)));
    3186       12964 :     __ jmp(scratch_reg);
    3187             :   }
    3188             : }
    3189             : 
    3190     1301268 : void CodeGenerator::FinishCode() {}
    3191             : 
    3192    27149840 : void CodeGenerator::AssembleMove(InstructionOperand* source,
    3193             :                                  InstructionOperand* destination) {
    3194             :   X64OperandConverter g(this, nullptr);
    3195             :   // Dispatch on the source and destination operand kinds.  Not all
    3196             :   // combinations are possible.
    3197    27149840 :   if (source->IsRegister()) {
    3198             :     DCHECK(destination->IsRegister() || destination->IsStackSlot());
    3199             :     Register src = g.ToRegister(source);
    3200     5691234 :     if (destination->IsRegister()) {
    3201     3381998 :       __ movq(g.ToRegister(destination), src);
    3202             :     } else {
    3203     2309251 :       __ movq(g.ToOperand(destination), src);
    3204             :     }
    3205    21458606 :   } else if (source->IsStackSlot()) {
    3206             :     DCHECK(destination->IsRegister() || destination->IsStackSlot());
    3207     6954973 :     Operand src = g.ToOperand(source);
    3208     6954973 :     if (destination->IsRegister()) {
    3209             :       Register dst = g.ToRegister(destination);
    3210     6876576 :       __ movq(dst, src);
    3211             :     } else {
    3212             :       // Spill on demand to use a temporary register for memory-to-memory
    3213             :       // moves.
    3214             :       Register tmp = kScratchRegister;
    3215       78397 :       Operand dst = g.ToOperand(destination);
    3216       78397 :       __ movq(tmp, src);
    3217             :       __ movq(dst, tmp);
    3218             :     }
    3219    14503640 :   } else if (source->IsConstant()) {
    3220             :     ConstantOperand* constant_source = ConstantOperand::cast(source);
    3221    13795034 :     Constant src = g.ToConstant(constant_source);
    3222    14409604 :     if (destination->IsRegister() || destination->IsStackSlot()) {
    3223             :       Register dst = destination->IsRegister() ? g.ToRegister(destination)
    3224    13212279 :                                                : kScratchRegister;
    3225    13212279 :       switch (src.type()) {
    3226             :         case Constant::kInt32: {
    3227     5033302 :           if (RelocInfo::IsWasmPtrReference(src.rmode())) {
    3228           0 :             __ movq(dst, src.ToInt64(), src.rmode());
    3229             :           } else {
    3230             :             // TODO(dcarney): don't need scratch in this case.
    3231     2516651 :             int32_t value = src.ToInt32();
    3232     2516651 :             if (RelocInfo::IsWasmSizeReference(src.rmode())) {
    3233           5 :               __ movl(dst, Immediate(value, src.rmode()));
    3234     2516646 :             } else if (value == 0) {
    3235      897244 :               __ xorl(dst, dst);
    3236             :             } else {
    3237     1619402 :               __ movl(dst, Immediate(value));
    3238             :             }
    3239             :           }
    3240             :           break;
    3241             :         }
    3242             :         case Constant::kInt64:
    3243     2051574 :           if (RelocInfo::IsWasmPtrReference(src.rmode())) {
    3244      183969 :             __ movq(dst, src.ToInt64(), src.rmode());
    3245             :           } else {
    3246             :             DCHECK(!RelocInfo::IsWasmSizeReference(src.rmode()));
    3247      841818 :             __ Set(dst, src.ToInt64());
    3248             :           }
    3249             :           break;
    3250             :         case Constant::kFloat32:
    3251         504 :           __ MoveNumber(dst, src.ToFloat32());
    3252         252 :           break;
    3253             :         case Constant::kFloat64:
    3254     3112847 :           __ MoveNumber(dst, src.ToFloat64().value());
    3255     3112845 :           break;
    3256             :         case Constant::kExternalReference:
    3257     1255919 :           __ Move(dst, src.ToExternalReference());
    3258             :           break;
    3259             :         case Constant::kHeapObject: {
    3260     5300832 :           Handle<HeapObject> src_object = src.ToHeapObject();
    3261             :           Heap::RootListIndex index;
    3262     5300829 :           if (IsMaterializableFromRoot(src_object, &index)) {
    3263     1741037 :             __ LoadRoot(dst, index);
    3264             :           } else {
    3265     3559793 :             __ Move(dst, src_object);
    3266             :           }
    3267             :           break;
    3268             :         }
    3269             :         case Constant::kRpoNumber:
    3270           0 :           UNREACHABLE();  // TODO(dcarney): load of labels on x64.
    3271             :           break;
    3272             :       }
    3273    13212311 :       if (destination->IsStackSlot()) {
    3274       31788 :         __ movq(g.ToOperand(destination), kScratchRegister);
    3275             :       }
    3276      582779 :     } else if (src.type() == Constant::kFloat32) {
    3277             :       // TODO(turbofan): Can we do better here?
    3278      150700 :       uint32_t src_const = bit_cast<uint32_t>(src.ToFloat32());
    3279      150700 :       if (destination->IsFPRegister()) {
    3280      150148 :         __ Move(g.ToDoubleRegister(destination), src_const);
    3281             :       } else {
    3282             :         DCHECK(destination->IsFPStackSlot());
    3283         552 :         Operand dst = g.ToOperand(destination);
    3284         552 :         __ movl(dst, Immediate(src_const));
    3285             :       }
    3286             :     } else {
    3287             :       DCHECK_EQ(Constant::kFloat64, src.type());
    3288             :       uint64_t src_const = src.ToFloat64().AsUint64();
    3289      432079 :       if (destination->IsFPRegister()) {
    3290      431056 :         __ Move(g.ToDoubleRegister(destination), src_const);
    3291             :       } else {
    3292             :         DCHECK(destination->IsFPStackSlot());
    3293        1023 :         __ movq(kScratchRegister, src_const);
    3294             :         __ movq(g.ToOperand(destination), kScratchRegister);
    3295             :       }
    3296             :     }
    3297      708606 :   } else if (source->IsFPRegister()) {
    3298      354682 :     XMMRegister src = g.ToDoubleRegister(source);
    3299      354682 :     if (destination->IsFPRegister()) {
    3300       89334 :       XMMRegister dst = g.ToDoubleRegister(destination);
    3301       89334 :       __ Movapd(dst, src);
    3302             :     } else {
    3303             :       DCHECK(destination->IsFPStackSlot());
    3304      265346 :       Operand dst = g.ToOperand(destination);
    3305             :       MachineRepresentation rep =
    3306             :           LocationOperand::cast(source)->representation();
    3307      265346 :       if (rep != MachineRepresentation::kSimd128) {
    3308      265346 :         __ Movsd(dst, src);
    3309             :       } else {
    3310           0 :         __ Movups(dst, src);
    3311             :       }
    3312             :     }
    3313      353924 :   } else if (source->IsFPStackSlot()) {
    3314             :     DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
    3315      353924 :     Operand src = g.ToOperand(source);
    3316             :     MachineRepresentation rep = LocationOperand::cast(source)->representation();
    3317      353924 :     if (destination->IsFPRegister()) {
    3318      328401 :       XMMRegister dst = g.ToDoubleRegister(destination);
    3319      328401 :       if (rep != MachineRepresentation::kSimd128) {
    3320      328401 :         __ Movsd(dst, src);
    3321             :       } else {
    3322           0 :         __ Movups(dst, src);
    3323             :       }
    3324             :     } else {
    3325       25523 :       Operand dst = g.ToOperand(destination);
    3326       25523 :       if (rep != MachineRepresentation::kSimd128) {
    3327       25523 :         __ Movsd(kScratchDoubleReg, src);
    3328       25523 :         __ Movsd(dst, kScratchDoubleReg);
    3329             :       } else {
    3330           0 :         __ Movups(kScratchDoubleReg, src);
    3331           0 :         __ Movups(dst, kScratchDoubleReg);
    3332             :       }
    3333             :     }
    3334             :   } else {
    3335           0 :     UNREACHABLE();
    3336             :   }
    3337    27149900 : }
    3338             : 
    3339             : 
    3340       41899 : void CodeGenerator::AssembleSwap(InstructionOperand* source,
    3341        3626 :                                  InstructionOperand* destination) {
    3342             :   X64OperandConverter g(this, nullptr);
    3343             :   // Dispatch on the source and destination operand kinds.  Not all
    3344             :   // combinations are possible.
    3345       72917 :   if (source->IsRegister() && destination->IsRegister()) {
    3346             :     // Register-register.
    3347             :     Register src = g.ToRegister(source);
    3348             :     Register dst = g.ToRegister(destination);
    3349       29205 :     __ movq(kScratchRegister, src);
    3350             :     __ movq(src, dst);
    3351             :     __ movq(dst, kScratchRegister);
    3352       14507 :   } else if (source->IsRegister() && destination->IsStackSlot()) {
    3353             :     Register src = g.ToRegister(source);
    3354        1813 :     __ pushq(src);
    3355             :     frame_access_state()->IncreaseSPDelta(1);
    3356             :     unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3357        3626 :                                                      kPointerSize);
    3358        1813 :     Operand dst = g.ToOperand(destination);
    3359             :     __ movq(src, dst);
    3360             :     frame_access_state()->IncreaseSPDelta(-1);
    3361        1813 :     dst = g.ToOperand(destination);
    3362        1813 :     __ popq(dst);
    3363             :     unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3364        3626 :                                                      -kPointerSize);
    3365       32643 :   } else if ((source->IsStackSlot() && destination->IsStackSlot()) ||
    3366        1774 :              (source->IsFPStackSlot() && destination->IsFPStackSlot())) {
    3367             :     // Memory-memory.
    3368        6101 :     Operand src = g.ToOperand(source);
    3369        6101 :     Operand dst = g.ToOperand(destination);
    3370             :     MachineRepresentation rep = LocationOperand::cast(source)->representation();
    3371        6101 :     if (rep != MachineRepresentation::kSimd128) {
    3372             :       Register tmp = kScratchRegister;
    3373        6101 :       __ movq(tmp, dst);
    3374        6101 :       __ pushq(src);  // Then use stack to copy src to destination.
    3375             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3376       12202 :                                                        kPointerSize);
    3377        6101 :       __ popq(dst);
    3378             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3379       12202 :                                                        -kPointerSize);
    3380             :       __ movq(src, tmp);
    3381             :     } else {
    3382             :       // Without AVX, misaligned reads and writes will trap. Move using the
    3383             :       // stack, in two parts.
    3384           0 :       __ movups(kScratchDoubleReg, dst);  // Save dst in scratch register.
    3385           0 :       __ pushq(src);  // Then use stack to copy src to destination.
    3386             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3387           0 :                                                        kPointerSize);
    3388           0 :       __ popq(dst);
    3389             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3390           0 :                                                        -kPointerSize);
    3391           0 :       __ pushq(g.ToOperand(source, kPointerSize));
    3392             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3393           0 :                                                        kPointerSize);
    3394           0 :       __ popq(g.ToOperand(destination, kPointerSize));
    3395             :       unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
    3396           0 :                                                        -kPointerSize);
    3397           0 :       __ movups(src, kScratchDoubleReg);
    3398             :     }
    3399        9560 :   } else if (source->IsFPRegister() && destination->IsFPRegister()) {
    3400             :     // XMM register-register swap.
    3401        1441 :     XMMRegister src = g.ToDoubleRegister(source);
    3402        1441 :     XMMRegister dst = g.ToDoubleRegister(destination);
    3403        1441 :     __ Movapd(kScratchDoubleReg, src);
    3404        1441 :     __ Movapd(src, dst);
    3405        1441 :     __ Movapd(dst, kScratchDoubleReg);
    3406        6678 :   } else if (source->IsFPRegister() && destination->IsFPStackSlot()) {
    3407             :     // XMM register-memory swap.
    3408        3339 :     XMMRegister src = g.ToDoubleRegister(source);
    3409        3339 :     Operand dst = g.ToOperand(destination);
    3410             :     MachineRepresentation rep = LocationOperand::cast(source)->representation();
    3411        3339 :     if (rep != MachineRepresentation::kSimd128) {
    3412        3339 :       __ Movsd(kScratchDoubleReg, src);
    3413        3339 :       __ Movsd(src, dst);
    3414        3339 :       __ Movsd(dst, kScratchDoubleReg);
    3415             :     } else {
    3416           0 :       __ Movups(kScratchDoubleReg, src);
    3417           0 :       __ Movups(src, dst);
    3418           0 :       __ Movups(dst, kScratchDoubleReg);
    3419             :     }
    3420             :   } else {
    3421             :     // No other combinations are possible.
    3422           0 :     UNREACHABLE();
    3423             :   }
    3424       41899 : }
    3425             : 
    3426             : 
    3427        7807 : void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
    3428      326927 :   for (size_t index = 0; index < target_count; ++index) {
    3429      319120 :     __ dq(targets[index]);
    3430             :   }
    3431        7807 : }
    3432             : 
    3433             : #undef __
    3434             : 
    3435             : }  // namespace compiler
    3436             : }  // namespace internal
    3437             : }  // namespace v8

Generated by: LCOV version 1.10