17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
27d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
37d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// found in the LICENSE file.
47d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
57d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/instruction-selector-impl.h"
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-matchers.h"
77d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-properties-inl.h"
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Adds IA32-specific methods for generating operands.
14ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass IA32OperandGenerator FINAL : public OperandGenerator {
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit IA32OperandGenerator(InstructionSelector* selector)
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : OperandGenerator(selector) {}
187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* UseByteRegister(Node* node) {
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(dcarney): relax constraint.
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return UseFixed(node, edx);
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool CanBeImmediate(Node* node) {
257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (node->opcode()) {
267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kInt32Constant:
277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kNumberConstant:
287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kExternalConstant:
297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return true;
307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kHeapConstant: {
317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        // Constants in new space cannot be used as immediates in V8 because
327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        // the GC does not scan code objects when collecting the new generation.
33e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org        Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node);
34e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org        return !isolate()->heap()->InNewSpace(*value.handle());
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return false;
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitLoad(Node* node) {
446313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
456313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* base = node->InputAt(0);
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* index = node->InputAt(1);
497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArchOpcode opcode;
515e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  // TODO(titzer): signed/unsigned small loads
527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (rep) {
53fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    case kRepFloat32:
54fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      opcode = kIA32Movss;
55fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      break;
565e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepFloat64:
576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kIA32Movsd;
587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
595e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepBit:  // Fall through.
605e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord8:
616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl;
627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
635e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord16:
646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl;
657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
665e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepTagged:  // Fall through.
675e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord32:
686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kIA32Movl;
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      UNREACHABLE();
727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(base)) {
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (Int32Matcher(index).Is(0)) {  // load [#base + #0]
76fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      Emit(opcode | AddressingModeField::encode(kMode_MI),
77fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org           g.DefineAsRegister(node), g.UseImmediate(base));
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {  // load [#base + %index]
79fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      Emit(opcode | AddressingModeField::encode(kMode_MRI),
80fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org           g.DefineAsRegister(node), g.UseRegister(index),
81fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org           g.UseImmediate(base));
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (g.CanBeImmediate(index)) {  // load [%base + #index]
84fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_MRI),
85fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {  // load [%base + %index + K]
87fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_MR1I),
88fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitStore(Node* node) {
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* base = node->InputAt(0);
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* index = node->InputAt(1);
987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* value = node->InputAt(2);
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
1016313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  MachineType rep = RepresentationOf(store_rep.machine_type());
1026313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
1035e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    DCHECK_EQ(kRepTagged, rep);
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(dcarney): refactor RecordWrite function to take temp registers
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    //                and pass them here instead of using fixed regs
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(dcarney): handle immediate indices.
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx),
109fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         temps);
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return;
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1136313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
1147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* val;
115fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  if (g.CanBeImmediate(value)) {
116fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    val = g.UseImmediate(value);
117fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  } else if (rep == kRepWord8 || rep == kRepBit) {
118fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    val = g.UseByteRegister(value);
1197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
120fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    val = g.UseRegister(value);
1217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArchOpcode opcode;
1237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (rep) {
124fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    case kRepFloat32:
125fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      opcode = kIA32Movss;
126fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      break;
1275e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepFloat64:
1286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kIA32Movsd;
1297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1305e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepBit:  // Fall through.
1315e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord8:
1326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kIA32Movb;
1337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1345e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord16:
1356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kIA32Movw;
1367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1375e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepTagged:  // Fall through.
1385e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kRepWord32:
1396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      opcode = kIA32Movl;
1407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
1427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      UNREACHABLE();
1437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
1447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(base)) {
1467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (Int32Matcher(index).Is(0)) {  // store [#base], %|#value
1477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Emit(opcode | AddressingModeField::encode(kMode_MI), NULL,
1487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.UseImmediate(base), val);
1497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {  // store [#base + %index], %|#value
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           g.UseRegister(index), g.UseImmediate(base), val);
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (g.CanBeImmediate(index)) {  // store [%base + #index], %|#value
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(base), g.UseImmediate(index), val);
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {  // store [%base + %index], %|#value
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseRegister(base), g.UseRegister(index), val);
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
1617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Shared routine for multiple binary operations.
165aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgstatic void VisitBinop(InstructionSelector* selector, Node* node,
166e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                       InstructionCode opcode, FlagsContinuation* cont) {
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(selector);
168aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  Int32BinopMatcher m(node);
169e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  InstructionOperand* inputs[4];
170aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  size_t input_count = 0;
171aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  InstructionOperand* outputs[2];
172aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  size_t output_count = 0;
173aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
174aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  // TODO(turbofan): match complex addressing modes.
175aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  // TODO(turbofan): if commutative, pick the non-live-in operand as the left as
176aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  // this might be the last use and therefore its register can be reused.
177aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  if (g.CanBeImmediate(m.right().node())) {
178aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[input_count++] = g.Use(m.left().node());
179aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[input_count++] = g.UseImmediate(m.right().node());
180aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  } else {
181aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[input_count++] = g.UseRegister(m.left().node());
182aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    inputs[input_count++] = g.Use(m.right().node());
183aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  }
184aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
185e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (cont->IsBranch()) {
186e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    inputs[input_count++] = g.Label(cont->true_block());
187e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    inputs[input_count++] = g.Label(cont->false_block());
188aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  }
189e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
190e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  outputs[output_count++] = g.DefineSameAsFirst(node);
191e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (cont->IsSet()) {
192aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    // TODO(turbofan): Use byte register here.
193e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    outputs[output_count++] = g.DefineAsRegister(cont->result());
194aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  }
195aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
196e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(0, input_count);
197e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(0, output_count);
198fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(inputs), input_count);
199fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK_GE(arraysize(outputs), output_count);
200e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
201e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
202e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                                      outputs, input_count, inputs);
203e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  if (cont->IsBranch()) instr->MarkAsControl();
204e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org}
205e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
206aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
207e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org// Shared routine for multiple binary operations.
208e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.orgstatic void VisitBinop(InstructionSelector* selector, Node* node,
209e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                       InstructionCode opcode) {
210e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  FlagsContinuation cont;
211e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitBinop(selector, node, opcode, &cont);
212aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org}
213aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
214aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org
2157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32And(Node* node) {
2167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kIA32And);
2177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Or(Node* node) {
2217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kIA32Or);
2227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Xor(Node* node) {
2267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
2277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
2287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.right().Is(-1)) {
2297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32Not, g.DefineSameAsFirst(node), g.Use(m.left().node()));
2307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
2317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    VisitBinop(this, node, kIA32Xor);
2327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Shared routine for multiple shift operations.
2377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void VisitShift(InstructionSelector* selector, Node* node,
2387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                              ArchOpcode opcode) {
2397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(selector);
2407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* left = node->InputAt(0);
2417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* right = node->InputAt(1);
2427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): assembler only supports some addressing modes for shifts.
2447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(right)) {
2457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
2467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   g.UseImmediate(right));
2477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
2487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Int32BinopMatcher m(node);
2497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (m.right().IsWord32And()) {
2507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Int32BinopMatcher mright(right);
2517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (mright.right().Is(0x1F)) {
2527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        right = mright.left().node();
2537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
2557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
2567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   g.UseFixed(right, ecx));
2577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Shl(Node* node) {
2627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitShift(this, node, kIA32Shl);
2637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Shr(Node* node) {
2677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitShift(this, node, kIA32Shr);
2687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Sar(Node* node) {
2727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitShift(this, node, kIA32Sar);
2737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2765e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgvoid InstructionSelector::VisitWord32Ror(Node* node) {
2775e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  VisitShift(this, node, kIA32Ror);
2785e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org}
2795e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
2805e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org
2817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Add(Node* node) {
2827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitBinop(this, node, kIA32Add);
2837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Sub(Node* node) {
2877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
2887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Int32BinopMatcher m(node);
2897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (m.left().Is(0)) {
2907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node()));
2917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
2927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    VisitBinop(this, node, kIA32Sub);
2937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Mul(Node* node) {
2987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
2997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* left = node->InputAt(0);
3007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* right = node->InputAt(1);
3017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(right)) {
3027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
3037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseImmediate(right));
3047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (g.CanBeImmediate(left)) {
3057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right),
3067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.UseImmediate(left));
3077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
3087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(turbofan): select better left operand.
3097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
3107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org         g.Use(right));
3117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void VisitDiv(InstructionSelector* selector, Node* node,
3167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                            ArchOpcode opcode) {
3177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(selector);
3187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* temps[] = {g.TempRegister(edx)};
319fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  size_t temp_count = arraysize(temps);
3207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(opcode, g.DefineAsFixed(node, eax),
3217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 g.UseFixed(node->InputAt(0), eax),
3227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 g.UseUnique(node->InputAt(1)), temp_count, temps);
3237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Div(Node* node) {
3277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitDiv(this, node, kIA32Idiv);
3287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32UDiv(Node* node) {
3327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitDiv(this, node, kIA32Udiv);
3337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void VisitMod(InstructionSelector* selector, Node* node,
3377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                            ArchOpcode opcode) {
3387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(selector);
3397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* temps[] = {g.TempRegister(eax), g.TempRegister(edx)};
340fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  size_t temp_count = arraysize(temps);
3417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  selector->Emit(opcode, g.DefineAsFixed(node, edx),
3427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 g.UseFixed(node->InputAt(0), eax),
3437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 g.UseUnique(node->InputAt(1)), temp_count, temps);
3447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32Mod(Node* node) {
3487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitMod(this, node, kIA32Idiv);
3497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitInt32UMod(Node* node) {
3537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitMod(this, node, kIA32Udiv);
3547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
357aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
3587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
359fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
3607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
363aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
3647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
3657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
366fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node),
3677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org       g.UseRegister(node->InputAt(0)));
3687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
371aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
3727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
3737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
3747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
377aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.orgvoid InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
3787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
379a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
3807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Add(Node* node) {
3847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
3857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
386fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
3877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Sub(Node* node) {
3917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
3927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node),
393fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
3947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Mul(Node* node) {
3987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
3997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node),
400fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
4017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Div(Node* node) {
4057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
4067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
407fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
4087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Mod(Node* node) {
4127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
4137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* temps[] = {g.TempRegister(eax)};
4147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
415fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
416fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org       temps);
4177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
420b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Sqrt(Node* node) {
421b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  IA32OperandGenerator g(this);
422b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
423b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org}
424b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org
425b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org
426e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.orgvoid InstructionSelector::VisitInt32AddWithOverflow(Node* node,
427e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                                                    FlagsContinuation* cont) {
428e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitBinop(this, node, kIA32Add, cont);
429e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org}
430e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
431e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
432e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.orgvoid InstructionSelector::VisitInt32SubWithOverflow(Node* node,
433e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org                                                    FlagsContinuation* cont) {
434e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  VisitBinop(this, node, kIA32Sub, cont);
435e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org}
436e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
437e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
4387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Shared routine for multiple compare operations.
4397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void VisitCompare(InstructionSelector* selector,
4407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                InstructionCode opcode,
4417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                InstructionOperand* left,
4427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                InstructionOperand* right,
4437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                FlagsContinuation* cont) {
4447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(selector);
4457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (cont->IsBranch()) {
4467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    selector->Emit(cont->Encode(opcode), NULL, left, right,
4477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   g.Label(cont->true_block()),
4487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   g.Label(cont->false_block()))->MarkAsControl();
4497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
450e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(cont->IsSet());
4517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(titzer): Needs byte register.
4527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()),
4537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   left, right);
4547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Shared routine for multiple word compare operations.
4597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic inline void VisitWordCompare(InstructionSelector* selector, Node* node,
4607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                    InstructionCode opcode,
4617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                    FlagsContinuation* cont, bool commutative) {
4627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(selector);
4637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* left = node->InputAt(0);
4647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* right = node->InputAt(1);
4657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Match immediates on left or right side of comparison.
4677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (g.CanBeImmediate(right)) {
4687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
4697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (g.CanBeImmediate(left)) {
4707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (!commutative) cont->Commute();
4717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
4727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
4737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
4747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) {
4797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (node->opcode()) {
4807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kInt32Sub:
4817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return VisitWordCompare(this, node, kIA32Cmp, cont, false);
4827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kWord32And:
4837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return VisitWordCompare(this, node, kIA32Test, cont, true);
4847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
4857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
4897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitCompare(this, kIA32Test, g.Use(node), g.TempImmediate(-1), cont);
4907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitWord32Compare(Node* node,
4947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                             FlagsContinuation* cont) {
4957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VisitWordCompare(this, node, kIA32Cmp, cont, false);
4967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitFloat64Compare(Node* node,
5007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                              FlagsContinuation* cont) {
5017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
5027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* left = node->InputAt(0);
5037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* right = node->InputAt(1);
504fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  VisitCompare(this, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), cont);
5057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
5097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                    BasicBlock* deoptimization) {
5107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandGenerator g(this);
5117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call);
512a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
513a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  FrameStateDescriptor* frame_state_descriptor = NULL;
514a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
515a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  if (descriptor->NeedsFrameState()) {
516a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    frame_state_descriptor =
517a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org        GetFrameStateDescriptor(call->InputAt(descriptor->InputCount()));
518a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
519a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
520a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
5217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Compute InstructionOperands for inputs and outputs.
523ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  InitializeCallBuffer(call, &buffer, true, true);
5247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Push any stack arguments.
526a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
527a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org       input != buffer.pushed_nodes.rend(); input++) {
5287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(titzer): handle pushing double parameters.
5297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Emit(kIA32Push, NULL,
530a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org         g.CanBeImmediate(*input) ? g.UseImmediate(*input) : g.Use(*input));
5317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Select the appropriate opcode based on the call type.
5347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode;
5357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (descriptor->kind()) {
5367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case CallDescriptor::kCallCodeObject: {
5377b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      opcode = kArchCallCodeObject;
5387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
5407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case CallDescriptor::kCallJSFunction:
5417b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      opcode = kArchCallJSFunction;
5427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
5447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      UNREACHABLE();
5457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return;
5467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
547d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org  opcode |= MiscField::encode(descriptor->flags());
5487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Emit the call instruction.
5507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction* call_instr =
551a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
552a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org           buffer.instruction_args.size(), &buffer.instruction_args.front());
5537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  call_instr->MarkAsCall();
5557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (deoptimization != NULL) {
556e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(continuation != NULL);
5577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    call_instr->MarkAsControl();
5587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace compiler
5627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace internal
5637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace v8
564