1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/code-generator.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/code-generator-impl.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/gap-resolver.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-matchers.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-properties-inl.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/x64/assembler-x64.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/x64/macro-assembler-x64.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm()->
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(turbofan): Cleanup these hacks.
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum Immediate64Type { kImm64Value, kImm64Handle, kImm64Reference };
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct Immediate64 {
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint64_t value;
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> handle;
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference reference;
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Immediate64Type type;
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum RegisterOrOperandType { kRegister, kDoubleRegister, kOperand };
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct RegisterOrOperand {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterOrOperand() : operand(no_reg, 0) {}
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg;
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_reg;
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand;
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterOrOperandType type;
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Adds X64 specific methods for decoding operands.
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass X64OperandConverter : public InstructionOperandConverter {
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X64OperandConverter(CodeGenerator* gen, Instruction* instr)
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : InstructionOperandConverter(gen, instr) {}
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterOrOperand InputRegisterOrOperand(int index) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ToRegisterOrOperand(instr_->InputAt(index));
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Immediate InputImmediate(int index) {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ToImmediate(instr_->InputAt(index));
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterOrOperand OutputRegisterOrOperand() {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ToRegisterOrOperand(instr_->Output());
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Immediate64 InputImmediate64(int index) {
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ToImmediate64(instr_->InputAt(index));
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Immediate64 ToImmediate64(InstructionOperand* operand) {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Constant constant = ToConstant(operand);
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Immediate64 immediate;
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate.value = 0xbeefdeaddeefbeed;
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate.type = kImm64Value;
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (constant.type()) {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kInt32:
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kInt64:
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.value = constant.ToInt64();
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return immediate;
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kFloat64:
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.type = kImm64Handle;
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.handle =
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED);
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return immediate;
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kExternalReference:
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.type = kImm64Reference;
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.reference = constant.ToExternalReference();
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return immediate;
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kHeapObject:
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.type = kImm64Handle;
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        immediate.handle = constant.ToHeapObject();
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return immediate;
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return immediate;
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Immediate ToImmediate(InstructionOperand* operand) {
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Constant constant = ToConstant(operand);
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (constant.type()) {
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kInt32:
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Immediate(constant.ToInt32());
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kInt64:
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kFloat64:
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kExternalReference:
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Constant::kHeapObject:
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Immediate(-1);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand ToOperand(InstructionOperand* op, int extra = 0) {
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RegisterOrOperand result = ToRegisterOrOperand(op, extra);
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(kOperand, result.type);
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return result.operand;
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterOrOperand ToRegisterOrOperand(InstructionOperand* op, int extra = 0) {
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RegisterOrOperand result;
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (op->IsRegister()) {
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(extra == 0);
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result.type = kRegister;
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result.reg = ToRegister(op);
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return result;
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (op->IsDoubleRegister()) {
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(extra == 0);
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(extra == 0);
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result.type = kDoubleRegister;
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result.double_reg = ToDoubleRegister(op);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return result;
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result.type = kOperand;
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The linkage computes where all spill slots are located.
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    result.operand =
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand(offset.from_stack_pointer() ? rsp : rbp, offset.offset());
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return result;
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand MemoryOperand(int* first_input) {
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const int offset = *first_input;
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (AddressingModeField::decode(instr_->opcode())) {
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kMode_MR1I: {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *first_input += 2;
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Register index = InputRegister(offset + 1);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Operand(InputRegister(offset + 0), index, times_1,
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       0);  // TODO(dcarney): K != 0
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kMode_MRI:
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *first_input += 2;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Operand(InputRegister(offset + 0), InputInt32(offset + 1));
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Operand(no_reg, 0);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand MemoryOperand() {
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int first_input = 0;
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MemoryOperand(&first_input);
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool HasImmediateInput(Instruction* instr, int index) {
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return instr->InputAt(index)->IsImmediate();
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ASSEMBLE_BINOP(asm_instr)                            \
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  do {                                                       \
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (HasImmediateInput(instr, 1)) {                       \
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(0); \
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kRegister) {                         \
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ asm_instr(input.reg, i.InputImmediate(1));        \
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {                                               \
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ asm_instr(input.operand, i.InputImmediate(1));    \
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }                                                      \
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {                                                 \
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(1); \
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kRegister) {                         \
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ asm_instr(i.InputRegister(0), input.reg);         \
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {                                               \
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ asm_instr(i.InputRegister(0), input.operand);     \
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }                                                      \
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }                                                        \
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } while (0)
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ASSEMBLE_SHIFT(asm_instr, width)                                 \
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  do {                                                                   \
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (HasImmediateInput(instr, 1)) {                                   \
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ asm_instr(i.OutputRegister(), Immediate(i.InputInt##width(1))); \
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {                                                             \
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ asm_instr##_cl(i.OutputRegister());                             \
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }                                                                    \
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } while (0)
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Assembles an instruction after register allocation, producing machine code.
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleArchInstruction(Instruction* instr) {
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X64OperandConverter i(this, instr);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (ArchOpcodeField::decode(instr->opcode())) {
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kArchCallCodeObject: {
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EnsureSpaceForLazyDeopt();
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HasImmediateInput(instr, 0)) {
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Call(code, RelocInfo::CODE_TARGET);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Register reg = i.InputRegister(0);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int entry = Code::kHeaderSize - kHeapObjectTag;
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Call(Operand(reg, entry));
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AddSafepointAndDeopt(instr);
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kArchCallJSFunction: {
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EnsureSpaceForLazyDeopt();
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register func = i.InputRegister(0);
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_debug_code) {
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Check the function's context matches the context argument.
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset));
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Assert(equal, kWrongFunctionContext);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset));
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AddSafepointAndDeopt(instr);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kArchJmp:
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(code_->GetLabel(i.InputBlock(0)));
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kArchNop:
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // don't emit code for nops.
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kArchRet:
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssembleReturn();
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kArchTruncateDoubleToI:
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Add32:
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(addl);
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Add:
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(addq);
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Sub32:
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(subl);
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Sub:
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(subq);
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64And32:
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(andl);
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64And:
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(andq);
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Cmp32:
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(cmpl);
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Cmp:
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(cmpq);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Test32:
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(testl);
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Test:
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(testq);
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Imul32:
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HasImmediateInput(instr, 1)) {
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RegisterOrOperand input = i.InputRegisterOrOperand(0);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (input.type == kRegister) {
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imull(i.OutputRegister(), input.reg, i.InputImmediate(1));
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movq(kScratchRegister, input.operand);
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imull(i.OutputRegister(), kScratchRegister, i.InputImmediate(1));
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RegisterOrOperand input = i.InputRegisterOrOperand(1);
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (input.type == kRegister) {
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imull(i.OutputRegister(), input.reg);
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imull(i.OutputRegister(), input.operand);
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Imul:
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HasImmediateInput(instr, 1)) {
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RegisterOrOperand input = i.InputRegisterOrOperand(0);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (input.type == kRegister) {
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imulq(i.OutputRegister(), input.reg, i.InputImmediate(1));
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movq(kScratchRegister, input.operand);
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imulq(i.OutputRegister(), kScratchRegister, i.InputImmediate(1));
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RegisterOrOperand input = i.InputRegisterOrOperand(1);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (input.type == kRegister) {
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imulq(i.OutputRegister(), input.reg);
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imulq(i.OutputRegister(), input.operand);
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Idiv32:
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cdq();
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ idivl(i.InputRegister(1));
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Idiv:
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cqo();
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ idivq(i.InputRegister(1));
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Udiv32:
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ xorl(rdx, rdx);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ divl(i.InputRegister(1));
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Udiv:
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ xorq(rdx, rdx);
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ divq(i.InputRegister(1));
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Not: {
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand output = i.OutputRegisterOrOperand();
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (output.type == kRegister) {
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ notq(output.reg);
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ notq(output.operand);
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Not32: {
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand output = i.OutputRegisterOrOperand();
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (output.type == kRegister) {
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ notl(output.reg);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ notl(output.operand);
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Neg: {
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand output = i.OutputRegisterOrOperand();
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (output.type == kRegister) {
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ negq(output.reg);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ negq(output.operand);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Neg32: {
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand output = i.OutputRegisterOrOperand();
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (output.type == kRegister) {
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ negl(output.reg);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ negl(output.operand);
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Or32:
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(orl);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Or:
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(orq);
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Xor32:
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(xorl);
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Xor:
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_BINOP(xorq);
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Shl32:
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(shll, 5);
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Shl:
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(shlq, 6);
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Shr32:
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(shrl, 5);
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Shr:
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(shrq, 6);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Sar32:
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(sarl, 5);
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Sar:
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(sarq, 6);
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Ror32:
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(rorl, 5);
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Ror:
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ASSEMBLE_SHIFT(rorq, 6);
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Cmp: {
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(1);
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kDoubleRegister) {
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ucomisd(i.InputDoubleRegister(0), input.double_reg);
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ucomisd(i.InputDoubleRegister(0), input.operand);
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Add:
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Sub:
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Mul:
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mulsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Div:
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ divsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Mod: {
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ subq(rsp, Immediate(kDoubleSize));
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Move values to st(0) and st(1).
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(Operand(rsp, 0), i.InputDoubleRegister(1));
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld_d(Operand(rsp, 0));
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld_d(Operand(rsp, 0));
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Loop while fprem isn't done.
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label mod_loop;
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&mod_loop);
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // This instructions traps on all kinds inputs, but we are assuming the
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // floating point control word is set to ignore them all.
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fprem();
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // The following 2 instruction implicitly use rax.
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fnstsw_ax();
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (CpuFeatures::IsSupported(SAHF) && masm()->IsEnabled(SAHF)) {
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sahf();
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ shrl(rax, Immediate(8));
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ andl(rax, Immediate(0xFF));
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ pushq(rax);
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ popfq();
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, &mod_loop);
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Move output to stack and clean up.
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp(1);
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp_d(Operand(rsp, 0));
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(i.OutputDoubleRegister(), Operand(rsp, 0));
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addq(rsp, Immediate(kDoubleSize));
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64Sqrt: {
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(0);
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kDoubleRegister) {
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sqrtsd(i.OutputDoubleRegister(), input.double_reg);
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sqrtsd(i.OutputDoubleRegister(), input.operand);
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64ToInt32: {
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(0);
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kDoubleRegister) {
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvttsd2si(i.OutputRegister(), input.double_reg);
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvttsd2si(i.OutputRegister(), input.operand);
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEFloat64ToUint32: {
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(0);
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kDoubleRegister) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvttsd2siq(i.OutputRegister(), input.double_reg);
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvttsd2siq(i.OutputRegister(), input.operand);
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ andl(i.OutputRegister(), i.OutputRegister());  // clear upper bits.
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(turbofan): generated code should not look at the upper 32 bits
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // of the result, but those bits could escape to the outside world.
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEInt32ToFloat64: {
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(0);
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kRegister) {
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvtlsi2sd(i.OutputDoubleRegister(), input.reg);
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvtlsi2sd(i.OutputDoubleRegister(), input.operand);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSSEUint32ToFloat64: {
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(turbofan): X64 SSE cvtqsi2sd should support operands.
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0));
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movsxbl:
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsxbl(i.OutputRegister(), i.MemoryOperand());
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movzxbl:
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movzxbl(i.OutputRegister(), i.MemoryOperand());
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movb: {
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int index = 0;
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand operand = i.MemoryOperand(&index);
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HasImmediateInput(instr, index)) {
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movb(operand, Immediate(i.InputInt8(index)));
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movb(operand, i.InputRegister(index));
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movsxwl:
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsxwl(i.OutputRegister(), i.MemoryOperand());
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movzxwl:
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movzxwl(i.OutputRegister(), i.MemoryOperand());
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movw: {
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int index = 0;
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand operand = i.MemoryOperand(&index);
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HasImmediateInput(instr, index)) {
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movw(operand, Immediate(i.InputInt16(index)));
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movw(operand, i.InputRegister(index));
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movl:
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->HasOutput()) {
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (instr->addressing_mode() == kMode_None) {
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          RegisterOrOperand input = i.InputRegisterOrOperand(0);
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (input.type == kRegister) {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movl(i.OutputRegister(), input.reg);
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ movl(i.OutputRegister(), input.operand);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movl(i.OutputRegister(), i.MemoryOperand());
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int index = 0;
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand operand = i.MemoryOperand(&index);
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (HasImmediateInput(instr, index)) {
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movl(operand, i.InputImmediate(index));
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movl(operand, i.InputRegister(index));
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movsxlq: {
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegisterOrOperand input = i.InputRegisterOrOperand(0);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (input.type == kRegister) {
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movsxlq(i.OutputRegister(), input.reg);
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movsxlq(i.OutputRegister(), input.operand);
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movq:
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->HasOutput()) {
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movq(i.OutputRegister(), i.MemoryOperand());
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int index = 0;
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand operand = i.MemoryOperand(&index);
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (HasImmediateInput(instr, index)) {
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movq(operand, i.InputImmediate(index));
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ movq(operand, i.InputRegister(index));
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movss:
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->HasOutput()) {
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int index = 0;
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand operand = i.MemoryOperand(&index);
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cvtsd2ss(xmm0, i.InputDoubleRegister(index));
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movss(operand, xmm0);
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Movsd:
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->HasOutput()) {
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int index = 0;
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand operand = i.MemoryOperand(&index);
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movsd(operand, i.InputDoubleRegister(index));
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64Push:
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HasImmediateInput(instr, 0)) {
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ pushq(i.InputImmediate(0));
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RegisterOrOperand input = i.InputRegisterOrOperand(0);
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (input.type == kRegister) {
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ pushq(input.reg);
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ pushq(input.operand);
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX64StoreWriteBarrier: {
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object = i.InputRegister(0);
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register index = i.InputRegister(1);
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register value = i.InputRegister(2);
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsxlq(index, index);
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(Operand(object, index, times_1, 0), value);
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ leaq(index, Operand(object, index, times_1, 0));
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                ? kSaveFPRegs
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                : kDontSaveFPRegs;
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWrite(object, index, value, mode);
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Assembles branches after this instruction.
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleArchBranch(Instruction* instr,
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       FlagsCondition condition) {
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X64OperandConverter i(this, instr);
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit a branch. The true and false targets are always the last two inputs
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to the instruction.
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* tblock = i.InputBlock(static_cast<int>(instr->InputCount()) - 2);
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* fblock = i.InputBlock(static_cast<int>(instr->InputCount()) - 1);
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool fallthru = IsNextInAssemblyOrder(fblock);
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* tlabel = code()->GetLabel(tblock);
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label::Distance flabel_distance = fallthru ? Label::kNear : Label::kFar;
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (condition) {
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedEqual:
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, flabel, flabel_distance);
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kEqual:
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(equal, tlabel);
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedNotEqual:
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, tlabel);
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kNotEqual:
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, tlabel);
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedLessThan:
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(less, tlabel);
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedGreaterThanOrEqual:
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(greater_equal, tlabel);
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedLessThanOrEqual:
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(less_equal, tlabel);
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedGreaterThan:
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(greater, tlabel);
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedLessThan:
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, flabel, flabel_distance);
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedLessThan:
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(below, tlabel);
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedGreaterThanOrEqual:
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, tlabel);
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedGreaterThanOrEqual:
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(above_equal, tlabel);
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedLessThanOrEqual:
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, flabel, flabel_distance);
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedLessThanOrEqual:
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(below_equal, tlabel);
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedGreaterThan:
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, tlabel);
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedGreaterThan:
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(above, tlabel);
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kOverflow:
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(overflow, tlabel);
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kNotOverflow:
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(no_overflow, tlabel);
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!fallthru) __ jmp(flabel, flabel_distance);  // no fallthru to flabel.
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Assembles boolean materializations after this instruction.
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleArchBoolean(Instruction* instr,
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        FlagsCondition condition) {
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X64OperandConverter i(this, instr);
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Materialize a full 64-bit 1 or 0 value. The result register is always the
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // last output of the instruction.
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label check;
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NE(0, instr->OutputCount());
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = i.OutputRegister(static_cast<int>(instr->OutputCount() - 1));
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cc = no_condition;
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (condition) {
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedEqual:
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &check, Label::kNear);
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(reg, Immediate(0));
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kEqual:
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = equal;
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedNotEqual:
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &check, Label::kNear);
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(reg, Immediate(1));
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kNotEqual:
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = not_equal;
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedLessThan:
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = less;
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedGreaterThanOrEqual:
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = greater_equal;
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedLessThanOrEqual:
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = less_equal;
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSignedGreaterThan:
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = greater;
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedLessThan:
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &check, Label::kNear);
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(reg, Immediate(0));
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedLessThan:
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = below;
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedGreaterThanOrEqual:
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &check, Label::kNear);
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(reg, Immediate(1));
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedGreaterThanOrEqual:
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = above_equal;
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedLessThanOrEqual:
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &check, Label::kNear);
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(reg, Immediate(0));
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedLessThanOrEqual:
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = below_equal;
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnorderedGreaterThan:
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &check, Label::kNear);
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(reg, Immediate(1));
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fall through.
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kUnsignedGreaterThan:
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = above;
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kOverflow:
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = overflow;
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kNotOverflow:
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cc = no_overflow;
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&check);
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ setcc(cc, reg);
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbl(reg, reg);
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) {
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate(), deoptimization_id, Deoptimizer::LAZY);
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssemblePrologue() {
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int stack_slots = frame()->GetSpillSlotCount();
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (descriptor->kind() == CallDescriptor::kCallAddress) {
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(rbp);
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(rbp, rsp);
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const RegList saves = descriptor->CalleeSavedRegisters();
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (saves != 0) {  // Save callee-saved registers.
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int register_save_area_size = 0;
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!((1 << i) & saves)) continue;
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ pushq(Register::from_code(i));
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        register_save_area_size += kPointerSize;
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      frame()->SetRegisterSaveAreaSize(register_save_area_size);
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (descriptor->IsJSFunctionCall()) {
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompilationInfo* info = linkage()->info();
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Prologue(info->IsCodePreAgingActive());
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    frame()->SetRegisterSaveAreaSize(
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        StandardFrameConstants::kFixedFrameSizeFromFp);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Sloppy mode functions and builtins need to replace the receiver with the
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // global proxy when called as functions (without an explicit receiver
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // object).
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (info->strict_mode() == SLOPPY && !info->is_native()) {
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label ok;
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StackArgumentsAccessor args(rbp, info->scope()->num_parameters());
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, args.GetReceiverOperand());
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, &ok, Label::kNear);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, GlobalObjectOperand());
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset));
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(args.GetReceiverOperand(), rcx);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&ok);
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ StubPrologue();
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    frame()->SetRegisterSaveAreaSize(
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        StandardFrameConstants::kFixedFrameSizeFromFp);
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (stack_slots > 0) {
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subq(rsp, Immediate(stack_slots * kPointerSize));
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleReturn() {
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (descriptor->kind() == CallDescriptor::kCallAddress) {
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (frame()->GetRegisterSaveAreaSize() > 0) {
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Remove this frame's spill slots first.
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int stack_slots = frame()->GetSpillSlotCount();
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (stack_slots > 0) {
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ addq(rsp, Immediate(stack_slots * kPointerSize));
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const RegList saves = descriptor->CalleeSavedRegisters();
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Restore registers.
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (saves != 0) {
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (int i = 0; i < Register::kNumRegisters; i++) {
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (!((1 << i) & saves)) continue;
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ popq(Register::from_code(i));
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ popq(rbp);  // Pop caller's frame pointer.
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ret(0);
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // No saved registers.
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(rsp, rbp);  // Move stack pointer back to frame pointer.
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ popq(rbp);       // Pop caller's frame pointer.
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ret(0);
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(rsp, rbp);  // Move stack pointer back to frame pointer.
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popq(rbp);       // Pop caller's frame pointer.
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int pop_count = descriptor->IsJSFunctionCall()
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        ? static_cast<int>(descriptor->JSParameterCount())
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        : 0;
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret(pop_count * kPointerSize);
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleMove(InstructionOperand* source,
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 InstructionOperand* destination) {
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X64OperandConverter g(this, NULL);
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dispatch on the source and destination operand kinds.  Not all
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // combinations are possible.
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (source->IsRegister()) {
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(destination->IsRegister() || destination->IsStackSlot());
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register src = g.ToRegister(source);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsRegister()) {
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(g.ToRegister(destination), src);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(g.ToOperand(destination), src);
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsStackSlot()) {
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(destination->IsRegister() || destination->IsStackSlot());
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand src = g.ToOperand(source);
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsRegister()) {
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register dst = g.ToRegister(destination);
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(dst, src);
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Spill on demand to use a temporary register for memory-to-memory
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // moves.
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register tmp = kScratchRegister;
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand dst = g.ToOperand(destination);
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(tmp, src);
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(dst, tmp);
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsConstant()) {
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ConstantOperand* constant_source = ConstantOperand::cast(source);
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsRegister() || destination->IsStackSlot()) {
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register dst = destination->IsRegister() ? g.ToRegister(destination)
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               : kScratchRegister;
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate64 imm = g.ToImmediate64(constant_source);
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (imm.type) {
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case kImm64Value:
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Set(dst, imm.value);
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case kImm64Reference:
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Move(dst, imm.reference);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case kImm64Handle:
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Move(dst, imm.handle);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (destination->IsStackSlot()) {
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movq(g.ToOperand(destination), kScratchRegister);
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(kScratchRegister,
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              bit_cast<uint64_t, double>(g.ToDouble(constant_source)));
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (destination->IsDoubleRegister()) {
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movq(g.ToDoubleRegister(destination), kScratchRegister);
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(destination->IsDoubleStackSlot());
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movq(g.ToOperand(destination), kScratchRegister);
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleRegister()) {
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    XMMRegister src = g.ToDoubleRegister(source);
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsDoubleRegister()) {
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      XMMRegister dst = g.ToDoubleRegister(destination);
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(dst, src);
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(destination->IsDoubleStackSlot());
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand dst = g.ToOperand(destination);
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(dst, src);
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleStackSlot()) {
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand src = g.ToOperand(source);
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination->IsDoubleRegister()) {
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      XMMRegister dst = g.ToDoubleRegister(destination);
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(dst, src);
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We rely on having xmm0 available as a fixed scratch register.
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand dst = g.ToOperand(destination);
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(xmm0, src);
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movsd(dst, xmm0);
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AssembleSwap(InstructionOperand* source,
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 InstructionOperand* destination) {
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X64OperandConverter g(this, NULL);
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dispatch on the source and destination operand kinds.  Not all
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // combinations are possible.
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (source->IsRegister() && destination->IsRegister()) {
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Register-register.
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xchgq(g.ToRegister(source), g.ToRegister(destination));
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsRegister() && destination->IsStackSlot()) {
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register src = g.ToRegister(source);
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand dst = g.ToOperand(destination);
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xchgq(src, dst);
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if ((source->IsStackSlot() && destination->IsStackSlot()) ||
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             (source->IsDoubleStackSlot() &&
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              destination->IsDoubleStackSlot())) {
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Memory-memory.
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register tmp = kScratchRegister;
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand src = g.ToOperand(source);
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand dst = g.ToOperand(destination);
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(tmp, dst);
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xchgq(tmp, src);
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(dst, tmp);
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // XMM register-register swap. We rely on having xmm0
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // available as a fixed scratch register.
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    XMMRegister src = g.ToDoubleRegister(source);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    XMMRegister dst = g.ToDoubleRegister(destination);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(xmm0, src);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(src, dst);
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(dst, xmm0);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // XMM register-memory swap.  We rely on having xmm0
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // available as a fixed scratch register.
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    XMMRegister src = g.ToDoubleRegister(source);
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand dst = g.ToOperand(destination);
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(xmm0, src);
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(src, dst);
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(dst, xmm0);
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // No other combinations are possible.
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeGenerator::EnsureSpaceForLazyDeopt() {
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int space_needed = Deoptimizer::patch_size();
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!linkage()->info()->IsStub()) {
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ensure that we have enough space after the previous lazy-bailout
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // instruction for patching the code here.
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int current_pc = masm()->pc_offset();
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Nop(padding_size);
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkLazyDeoptSite();
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
1025