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