1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 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/instruction-selector-impl.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-matchers.h" 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-properties-inl.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler { 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Adds IA32-specific methods for generating operands. 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass IA32OperandGenerator FINAL : public OperandGenerator { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit IA32OperandGenerator(InstructionSelector* selector) 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : OperandGenerator(selector) {} 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* UseByteRegister(Node* node) { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(dcarney): relax constraint. 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return UseFixed(node, edx); 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool CanBeImmediate(Node* node) { 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (node->opcode()) { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kInt32Constant: 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kNumberConstant: 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kExternalConstant: 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kHeapConstant: { 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constants in new space cannot be used as immediates in V8 because 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the GC does not scan code objects when collecting the new generation. 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !isolate()->heap()->InNewSpace(*value.handle()); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitLoad(Node* node) { 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* base = node->InputAt(0); 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* index = node->InputAt(1); 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArchOpcode opcode; 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(titzer): signed/unsigned small loads 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (rep) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepFloat32: 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movss; 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepFloat64: 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movsd; 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepBit: // Fall through. 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepWord8: 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepWord16: 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepTagged: // Fall through. 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepWord32: 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movl; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(base)) { 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Int32Matcher(index).Is(0)) { // load [#base + #0] 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MI), 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.DefineAsRegister(node), g.UseImmediate(base)); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // load [#base + %index] 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MRI), 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.DefineAsRegister(node), g.UseRegister(index), 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseImmediate(base)); 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (g.CanBeImmediate(index)) { // load [%base + #index] 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MRI), 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // load [%base + %index + K] 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MR1I), 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitStore(Node* node) { 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* base = node->InputAt(0); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* index = node->InputAt(1); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* value = node->InputAt(2); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MachineType rep = RepresentationOf(store_rep.machine_type()); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (store_rep.write_barrier_kind() == kFullWriteBarrier) { 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kRepTagged, rep); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(dcarney): refactor RecordWrite function to take temp registers 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and pass them here instead of using fixed regs 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(dcarney): handle immediate indices. 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx), 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps), 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch temps); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* val; 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(value)) { 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch val = g.UseImmediate(value); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (rep == kRepWord8 || rep == kRepBit) { 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch val = g.UseByteRegister(value); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch val = g.UseRegister(value); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArchOpcode opcode; 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (rep) { 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepFloat32: 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movss; 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepFloat64: 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movsd; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepBit: // Fall through. 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepWord8: 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movb; 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepWord16: 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movw; 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepTagged: // Fall through. 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRepWord32: 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kIA32Movl; 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(base)) { 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Int32Matcher(index).Is(0)) { // store [#base], %|#value 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MI), NULL, 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseImmediate(base), val); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // store [#base + %index], %|#value 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(index), g.UseImmediate(base), val); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (g.CanBeImmediate(index)) { // store [%base + #index], %|#value 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(base), g.UseImmediate(index), val); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // store [%base + %index], %|#value 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL, 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(base), g.UseRegister(index), val); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Shared routine for multiple binary operations. 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void VisitBinop(InstructionSelector* selector, Node* node, 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionCode opcode, FlagsContinuation* cont) { 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(selector); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Int32BinopMatcher m(node); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* inputs[4]; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t input_count = 0; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* outputs[2]; 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t output_count = 0; 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): match complex addressing modes. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): if commutative, pick the non-live-in operand as the left as 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this might be the last use and therefore its register can be reused. 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(m.right().node())) { 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inputs[input_count++] = g.Use(m.left().node()); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inputs[input_count++] = g.UseImmediate(m.right().node()); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inputs[input_count++] = g.UseRegister(m.left().node()); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inputs[input_count++] = g.Use(m.right().node()); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cont->IsBranch()) { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inputs[input_count++] = g.Label(cont->true_block()); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inputs[input_count++] = g.Label(cont->false_block()); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outputs[output_count++] = g.DefineSameAsFirst(node); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cont->IsSet()) { 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): Use byte register here. 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outputs[output_count++] = g.DefineAsRegister(cont->result()); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(0, input_count); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(0, output_count); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_GE(arraysize(inputs), input_count); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_GE(arraysize(outputs), output_count); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outputs, input_count, inputs); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cont->IsBranch()) instr->MarkAsControl(); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Shared routine for multiple binary operations. 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void VisitBinop(InstructionSelector* selector, Node* node, 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionCode opcode) { 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation cont; 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(selector, node, opcode, &cont); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32And(Node* node) { 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32And); 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Or(Node* node) { 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32Or); 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Xor(Node* node) { 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Int32BinopMatcher m(node); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (m.right().Is(-1)) { 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32Not, g.DefineSameAsFirst(node), g.Use(m.left().node())); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32Xor); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Shared routine for multiple shift operations. 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void VisitShift(InstructionSelector* selector, Node* node, 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArchOpcode opcode) { 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(selector); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* left = node->InputAt(0); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* right = node->InputAt(1); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): assembler only supports some addressing modes for shifts. 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(right)) { 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseImmediate(right)); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Int32BinopMatcher m(node); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (m.right().IsWord32And()) { 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Int32BinopMatcher mright(right); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mright.right().Is(0x1F)) { 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch right = mright.left().node(); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseFixed(right, ecx)); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Shl(Node* node) { 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitShift(this, node, kIA32Shl); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Shr(Node* node) { 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitShift(this, node, kIA32Shr); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Sar(Node* node) { 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitShift(this, node, kIA32Sar); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Ror(Node* node) { 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitShift(this, node, kIA32Ror); 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Add(Node* node) { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32Add); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Sub(Node* node) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Int32BinopMatcher m(node); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (m.left().Is(0)) { 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32Sub); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Mul(Node* node) { 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* left = node->InputAt(0); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* right = node->InputAt(1); 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(right)) { 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseImmediate(right)); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (g.CanBeImmediate(left)) { 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right), 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseImmediate(left)); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): select better left operand. 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.Use(right)); 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void VisitDiv(InstructionSelector* selector, Node* node, 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArchOpcode opcode) { 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(selector); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* temps[] = {g.TempRegister(edx)}; 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t temp_count = arraysize(temps); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch selector->Emit(opcode, g.DefineAsFixed(node, eax), 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseFixed(node->InputAt(0), eax), 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseUnique(node->InputAt(1)), temp_count, temps); 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Div(Node* node) { 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitDiv(this, node, kIA32Idiv); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32UDiv(Node* node) { 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitDiv(this, node, kIA32Udiv); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void VisitMod(InstructionSelector* selector, Node* node, 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArchOpcode opcode) { 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(selector); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* temps[] = {g.TempRegister(eax), g.TempRegister(edx)}; 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t temp_count = arraysize(temps); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch selector->Emit(opcode, g.DefineAsFixed(node, edx), 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseFixed(node->InputAt(0), eax), 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseUnique(node->InputAt(1)), temp_count, temps); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32Mod(Node* node) { 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitMod(this, node, kIA32Idiv); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32UMod(Node* node) { 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitMod(this, node, kIA32Udiv); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(turbofan): IA32 SSE LoadUint32() should take an operand. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(node->InputAt(0))); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Add(Node* node) { 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64Add, g.DefineSameAsFirst(node), 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Sub(Node* node) { 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node), 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Mul(Node* node) { 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node), 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Div(Node* node) { 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Mod(Node* node) { 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* temps[] = {g.TempRegister(eax)}; 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch temps); 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Sqrt(Node* node) { 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32AddWithOverflow(Node* node, 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation* cont) { 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32Add, cont); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitInt32SubWithOverflow(Node* node, 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation* cont) { 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitBinop(this, node, kIA32Sub, cont); 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Shared routine for multiple compare operations. 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void VisitCompare(InstructionSelector* selector, 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionCode opcode, 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* left, 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionOperand* right, 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation* cont) { 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(selector); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cont->IsBranch()) { 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch selector->Emit(cont->Encode(opcode), NULL, left, right, 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.Label(cont->true_block()), 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.Label(cont->false_block()))->MarkAsControl(); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cont->IsSet()); 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(titzer): Needs byte register. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()), 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch left, right); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Shared routine for multiple word compare operations. 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void VisitWordCompare(InstructionSelector* selector, Node* node, 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionCode opcode, 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation* cont, bool commutative) { 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(selector); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* left = node->InputAt(0); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* right = node->InputAt(1); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Match immediates on left or right side of comparison. 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g.CanBeImmediate(right)) { 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (g.CanBeImmediate(left)) { 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!commutative) cont->Commute(); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (node->opcode()) { 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kInt32Sub: 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return VisitWordCompare(this, node, kIA32Cmp, cont, false); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kWord32And: 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return VisitWordCompare(this, node, kIA32Test, cont, true); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitCompare(this, kIA32Test, g.Use(node), g.TempImmediate(-1), cont); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitWord32Compare(Node* node, 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation* cont) { 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitWordCompare(this, node, kIA32Cmp, cont, false); 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitFloat64Compare(Node* node, 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsContinuation* cont) { 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* left = node->InputAt(0); 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* right = node->InputAt(1); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitCompare(this, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), cont); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BasicBlock* deoptimization) { 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IA32OperandGenerator g(this); 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameStateDescriptor* frame_state_descriptor = NULL; 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (descriptor->NeedsFrameState()) { 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_state_descriptor = 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetFrameStateDescriptor(call->InputAt(descriptor->InputCount())); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallBuffer buffer(zone(), descriptor, frame_state_descriptor); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute InstructionOperands for inputs and outputs. 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InitializeCallBuffer(call, &buffer, true, true); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push any stack arguments. 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (NodeVectorRIter input = buffer.pushed_nodes.rbegin(); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch input != buffer.pushed_nodes.rend(); input++) { 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(titzer): handle pushing double parameters. 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(kIA32Push, NULL, 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g.CanBeImmediate(*input) ? g.UseImmediate(*input) : g.Use(*input)); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Select the appropriate opcode based on the call type. 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionCode opcode; 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (descriptor->kind()) { 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallDescriptor::kCallCodeObject: { 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kArchCallCodeObject; 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallDescriptor::kCallJSFunction: 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode = kArchCallJSFunction; 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch opcode |= MiscField::encode(descriptor->flags()); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the call instruction. 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* call_instr = 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(), 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer.instruction_args.size(), &buffer.instruction_args.front()); 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_instr->MarkAsCall(); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (deoptimization != NULL) { 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(continuation != NULL); 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_instr->MarkAsControl(); 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace compiler 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace internal 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8 564