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