17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2013 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/code-generator.h"
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
77d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/code-generator-impl.h"
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/gap-resolver.h"
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-matchers.h"
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-properties-inl.h"
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/ia32/assembler-ia32.h"
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/ia32/macro-assembler-ia32.h"
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/scopes.h"
147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define __ masm()->
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Adds IA-32 specific methods for decoding operands.
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass IA32OperandConverter : public InstructionOperandConverter {
247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandConverter(CodeGenerator* gen, Instruction* instr)
267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : InstructionOperandConverter(gen, instr) {}
277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand InputOperand(int index) { return ToOperand(instr_->InputAt(index)); }
297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Immediate InputImmediate(int index) {
317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ToImmediate(instr_->InputAt(index));
327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand OutputOperand() { return ToOperand(instr_->Output()); }
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand TempOperand(int index) { return ToOperand(instr_->TempAt(index)); }
377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand ToOperand(InstructionOperand* op, int extra = 0) {
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (op->IsRegister()) {
40e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(extra == 0);
417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return Operand(ToRegister(op));
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else if (op->IsDoubleRegister()) {
43e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(extra == 0);
447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return Operand(ToDoubleRegister(op));
457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
46e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // The linkage computes where all spill slots are located.
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra);
497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand HighOperand(InstructionOperand* op) {
53e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(op->IsDoubleStackSlot());
547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ToOperand(op, kPointerSize);
557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Immediate ToImmediate(InstructionOperand* operand) {
587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Constant constant = ToConstant(operand);
597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (constant.type()) {
607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case Constant::kInt32:
617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Immediate(constant.ToInt32());
627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case Constant::kFloat64:
637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Immediate(
647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org            isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case Constant::kExternalReference:
667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Immediate(constant.ToExternalReference());
677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case Constant::kHeapObject:
687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Immediate(constant.ToHeapObject());
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case Constant::kInt64:
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    UNREACHABLE();
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Immediate(-1);
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand MemoryOperand(int* first_input) {
777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    const int offset = *first_input;
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (AddressingModeField::decode(instr_->opcode())) {
797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kMode_MR1I:
807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        *first_input += 2;
817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Operand(InputRegister(offset + 0), InputRegister(offset + 1),
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                       times_1,
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                       0);  // TODO(dcarney): K != 0
847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kMode_MRI:
857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        *first_input += 2;
867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Operand::ForRegisterPlusImmediate(InputRegister(offset + 0),
877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                                 InputImmediate(offset + 1));
887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case kMode_MI:
897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        *first_input += 1;
907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Operand(InputImmediate(offset + 0));
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        UNREACHABLE();
937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Operand(no_reg);
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Operand MemoryOperand() {
987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int first_input = 0;
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return MemoryOperand(&first_input);
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
1027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic bool HasImmediateInput(Instruction* instr, int index) {
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return instr->InputAt(index)->IsImmediate();
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Assembles an instruction after register allocation, producing machine code.
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssembleArchInstruction(Instruction* instr) {
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandConverter i(this, instr);
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (ArchOpcodeField::decode(instr->opcode())) {
1147b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    case kArchCallCodeObject: {
11506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      EnsureSpaceForLazyDeopt();
1167b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      if (HasImmediateInput(instr, 0)) {
1177b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org        Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
1187b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org        __ call(code, RelocInfo::CODE_TARGET);
1197b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      } else {
1207b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org        Register reg = i.InputRegister(0);
1217b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org        __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
1227b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      }
1237b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      AddSafepointAndDeopt(instr);
1247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1257b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    }
1267b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    case kArchCallJSFunction: {
12706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      EnsureSpaceForLazyDeopt();
1287b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      Register func = i.InputRegister(0);
1299aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org      if (FLAG_debug_code) {
1309aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org        // Check the function's context matches the context argument.
1319aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org        __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
1329aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org        __ Assert(equal, kWrongFunctionContext);
1339aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org      }
1347b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
1357b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      AddSafepointAndDeopt(instr);
1367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1377b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    }
1387b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    case kArchJmp:
1397b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      __ jmp(code()->GetLabel(i.InputBlock(0)));
1407b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      break;
1417b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    case kArchNop:
1427b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      // don't emit code for nops.
1437b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      break;
1447b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    case kArchRet:
1457b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      AssembleReturn();
1467b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      break;
1477dae5b9f8500ada1f217a27db8a1f5c62becd404machenbach@chromium.org    case kArchTruncateDoubleToI:
1487dae5b9f8500ada1f217a27db8a1f5c62becd404machenbach@chromium.org      __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
1497dae5b9f8500ada1f217a27db8a1f5c62becd404machenbach@chromium.org      break;
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Add:
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ add(i.InputOperand(0), i.InputImmediate(1));
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ add(i.InputRegister(0), i.InputOperand(1));
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32And:
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ and_(i.InputOperand(0), i.InputImmediate(1));
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
1617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ and_(i.InputRegister(0), i.InputOperand(1));
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Cmp:
1657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
1667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ cmp(i.InputOperand(0), i.InputImmediate(1));
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
1687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ cmp(i.InputRegister(0), i.InputOperand(1));
1697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Test:
1727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
1737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ test(i.InputOperand(0), i.InputImmediate(1));
1747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
1757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ test(i.InputRegister(0), i.InputOperand(1));
1767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Imul:
1797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
1807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
1817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
1827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ imul(i.OutputRegister(), i.InputOperand(1));
1837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Idiv:
1867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ cdq();
1877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ idiv(i.InputOperand(1));
1887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Udiv:
1907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ xor_(edx, edx);
1917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ div(i.InputOperand(1));
1927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Not:
1947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ not_(i.OutputOperand());
1957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Neg:
1977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ neg(i.OutputOperand());
1987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
1997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Or:
2007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ or_(i.InputOperand(0), i.InputImmediate(1));
2027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
2037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ or_(i.InputRegister(0), i.InputOperand(1));
2047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Xor:
2077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ xor_(i.InputOperand(0), i.InputImmediate(1));
2097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
2107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ xor_(i.InputRegister(0), i.InputOperand(1));
2117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Sub:
2147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ sub(i.InputOperand(0), i.InputImmediate(1));
2167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
2177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ sub(i.InputRegister(0), i.InputOperand(1));
2187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Shl:
2217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ shl(i.OutputRegister(), i.InputInt5(1));
2237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
2247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ shl_cl(i.OutputRegister());
2257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Shr:
2287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ shr(i.OutputRegister(), i.InputInt5(1));
2307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
2317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ shr_cl(i.OutputRegister());
2327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32Sar:
2357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ sar(i.OutputRegister(), i.InputInt5(1));
2377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
2387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ sar_cl(i.OutputRegister());
2397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
2407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2415e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    case kIA32Ror:
2425e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      if (HasImmediateInput(instr, 1)) {
2435e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        __ ror(i.OutputRegister(), i.InputInt5(1));
2445e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      } else {
2455e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org        __ ror_cl(i.OutputRegister());
2465e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      }
2475e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      break;
2487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64Cmp:
2497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
2507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64Add:
2527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
2537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64Sub:
2557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
2567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64Mul:
2587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mulsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
2597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64Div:
2617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ divsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
2627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64Mod: {
2647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // TODO(dcarney): alignment is wrong.
2657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ sub(esp, Immediate(kDoubleSize));
2667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Move values to st(0) and st(1).
2677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(Operand(esp, 0), i.InputDoubleRegister(1));
2687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ fld_d(Operand(esp, 0));
2697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
2707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ fld_d(Operand(esp, 0));
2717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Loop while fprem isn't done.
2727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Label mod_loop;
2737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ bind(&mod_loop);
2747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // This instructions traps on all kinds inputs, but we are assuming the
2757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // floating point control word is set to ignore them all.
2767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ fprem();
2777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // The following 2 instruction implicitly use eax.
2787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ fnstsw_ax();
2797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ sahf();
2807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, &mod_loop);
2817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Move output to stack and clean up.
2827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ fstp(1);
2837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ fstp_d(Operand(esp, 0));
2847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
2857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ add(esp, Immediate(kDoubleSize));
2867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
288b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    case kSSEFloat64Sqrt:
289b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
290b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      break;
2917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64ToInt32:
2927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
2937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
2947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEFloat64ToUint32: {
2957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      XMMRegister scratch = xmm0;
2967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ Move(scratch, -2147483648.0);
297a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ addsd(scratch, i.InputOperand(0));
2987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ cvttsd2si(i.OutputRegister(), scratch);
2997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ add(i.OutputRegister(), Immediate(0x80000000));
3007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEInt32ToFloat64:
3037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
3047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSSEUint32ToFloat64:
3067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
3077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ LoadUint32(i.OutputDoubleRegister(), i.InputRegister(0));
3087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movsxbl:
3106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movsx_b(i.OutputRegister(), i.MemoryOperand());
3117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movzxbl:
3137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movzx_b(i.OutputRegister(), i.MemoryOperand());
3147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movb: {
3167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int index = 0;
3177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Operand operand = i.MemoryOperand(&index);
3186474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (HasImmediateInput(instr, index)) {
3196474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov_b(operand, i.InputInt8(index));
3206474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      } else {
3216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov_b(operand, i.InputRegister(index));
3226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
3237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movsxwl:
3266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      __ movsx_w(i.OutputRegister(), i.MemoryOperand());
3277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movzxwl:
3297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movzx_w(i.OutputRegister(), i.MemoryOperand());
3307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movw: {
3327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int index = 0;
3337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Operand operand = i.MemoryOperand(&index);
3346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (HasImmediateInput(instr, index)) {
3356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov_w(operand, i.InputInt16(index));
3366474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      } else {
3376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov_w(operand, i.InputRegister(index));
3386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
3397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movl:
3426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (instr->HasOutput()) {
3436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ mov(i.OutputRegister(), i.MemoryOperand());
3446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      } else {
3456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        int index = 0;
3466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        Operand operand = i.MemoryOperand(&index);
3476474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        if (HasImmediateInput(instr, index)) {
3486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org          __ mov(operand, i.InputImmediate(index));
3496474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        } else {
3506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org          __ mov(operand, i.InputRegister(index));
3516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        }
3526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
3537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org    case kIA32Movsd:
3556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      if (instr->HasOutput()) {
3566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
3576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      } else {
3586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        int index = 0;
3596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        Operand operand = i.MemoryOperand(&index);
3606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org        __ movsd(operand, i.InputDoubleRegister(index));
3616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      }
3627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
363fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    case kIA32Movss:
364fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      if (instr->HasOutput()) {
365fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
366fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
367fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      } else {
368fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        int index = 0;
369fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        Operand operand = i.MemoryOperand(&index);
370fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        __ cvtsd2ss(xmm0, i.InputDoubleRegister(index));
371fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        __ movss(operand, xmm0);
372fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      }
373fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      break;
3747b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org    case kIA32Push:
3757b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      if (HasImmediateInput(instr, 0)) {
3767b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org        __ push(i.InputImmediate(0));
3777b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      } else {
3787b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org        __ push(i.InputOperand(0));
3797b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      }
3807b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org      break;
3817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kIA32StoreWriteBarrier: {
3827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Register object = i.InputRegister(0);
3837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Register index = i.InputRegister(1);
3847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Register value = i.InputRegister(2);
3857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(Operand(object, index, times_1, 0), value);
3867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ lea(index, Operand(object, index, times_1, 0));
3877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
3887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                ? kSaveFPRegs
3897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                : kDontSaveFPRegs;
3907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ RecordWrite(object, index, value, mode);
3917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
3927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Assembles branches after an instruction.
3987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssembleArchBranch(Instruction* instr,
3997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                       FlagsCondition condition) {
4007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandConverter i(this, instr);
4017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label done;
4027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Emit a branch. The true and false targets are always the last two inputs
4047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // to the instruction.
4057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
4067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
4077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool fallthru = IsNextInAssemblyOrder(fblock);
4087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label* tlabel = code()->GetLabel(tblock);
4097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
4107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label::Distance flabel_distance = fallthru ? Label::kNear : Label::kFar;
4117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (condition) {
4127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedEqual:
4137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, flabel, flabel_distance);
4147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kEqual:
4167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(equal, tlabel);
4177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedNotEqual:
4197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, tlabel);
4207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kNotEqual:
4227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(not_equal, tlabel);
4237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedLessThan:
4257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(less, tlabel);
4267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedGreaterThanOrEqual:
4287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(greater_equal, tlabel);
4297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedLessThanOrEqual:
4317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(less_equal, tlabel);
4327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedGreaterThan:
4347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(greater, tlabel);
4357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedLessThan:
4377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, flabel, flabel_distance);
4387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedLessThan:
4407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(below, tlabel);
4417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedGreaterThanOrEqual:
4437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, tlabel);
4447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedGreaterThanOrEqual:
4467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(above_equal, tlabel);
4477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedLessThanOrEqual:
4497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, flabel, flabel_distance);
4507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedLessThanOrEqual:
4527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(below_equal, tlabel);
4537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedGreaterThan:
4557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_even, tlabel);
4567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedGreaterThan:
4587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(above, tlabel);
4597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
460aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    case kOverflow:
461aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      __ j(overflow, tlabel);
462aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      break;
463aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    case kNotOverflow:
464aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      __ j(no_overflow, tlabel);
465aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      break;
4667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (!fallthru) __ jmp(flabel, flabel_distance);  // no fallthru to flabel.
4687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  __ bind(&done);
4697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Assembles boolean materializations after an instruction.
4737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssembleArchBoolean(Instruction* instr,
4747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                        FlagsCondition condition) {
4757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandConverter i(this, instr);
4767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label done;
4777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
478aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  // Materialize a full 32-bit 1 or 0 value. The result register is always the
479aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  // last output of the instruction.
4807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label check;
481e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_NE(0, instr->OutputCount());
482aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org  Register reg = i.OutputRegister(instr->OutputCount() - 1);
4837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Condition cc = no_condition;
4847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (condition) {
4857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedEqual:
4867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_odd, &check, Label::kNear);
4877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(reg, Immediate(0));
4887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ jmp(&done, Label::kNear);
4897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kEqual:
4917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = equal;
4927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
4937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedNotEqual:
4947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_odd, &check, Label::kNear);
4957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(reg, Immediate(1));
4967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ jmp(&done, Label::kNear);
4977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
4987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kNotEqual:
4997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = not_equal;
5007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedLessThan:
5027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = less;
5037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedGreaterThanOrEqual:
5057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = greater_equal;
5067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedLessThanOrEqual:
5087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = less_equal;
5097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kSignedGreaterThan:
5117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = greater;
5127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedLessThan:
5147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_odd, &check, Label::kNear);
5157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(reg, Immediate(0));
5167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ jmp(&done, Label::kNear);
5177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
5187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedLessThan:
5197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = below;
5207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedGreaterThanOrEqual:
5227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_odd, &check, Label::kNear);
5237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(reg, Immediate(1));
5247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ jmp(&done, Label::kNear);
5257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
5267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedGreaterThanOrEqual:
5277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = above_equal;
5287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedLessThanOrEqual:
5307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_odd, &check, Label::kNear);
5317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(reg, Immediate(0));
5327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ jmp(&done, Label::kNear);
5337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
5347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedLessThanOrEqual:
5357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = below_equal;
5367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
5377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnorderedGreaterThan:
5387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(parity_odd, &check, Label::kNear);
5397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(reg, Immediate(1));
5407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ jmp(&done, Label::kNear);
5417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Fall through.
5427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case kUnsignedGreaterThan:
5437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      cc = above;
5447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
545aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    case kOverflow:
546aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      cc = overflow;
547aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      break;
548aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org    case kNotOverflow:
549aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      cc = no_overflow;
550aca8beeda619beb0f9758b04d1eaebdea5538a44machenbach@chromium.org      break;
5517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  __ bind(&check);
5537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (reg.is_byte_register()) {
5547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // setcc for byte registers (al, bl, cl, dl).
5557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ setcc(cc, reg);
5567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movzx_b(reg, reg);
5577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
5587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Emit a branch to set a register to either 1 or 0.
5597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Label set;
5607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ j(cc, &set, Label::kNear);
5617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(reg, Immediate(0));
5627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ jmp(&done, Label::kNear);
5637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ bind(&set);
5647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(reg, Immediate(1));
5657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  __ bind(&done);
5677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
570ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgvoid CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) {
571ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
572ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org      isolate(), deoptimization_id, Deoptimizer::LAZY);
573ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
574ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org}
575ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org
576ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org
5777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// The calling convention for JSFunctions on IA32 passes arguments on the
5787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// stack and the JSFunction and context in EDI and ESI, respectively, thus
5797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// the steps of the call look as follows:
5807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ before the call instruction }--------------------------------------------
5827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         |  caller frame |
5837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         ^ esp           ^ ebp
5847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ push arguments and setup ESI, EDI }--------------------------------------
5867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       | args + receiver |  caller frame |
5877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       ^ esp                             ^ ebp
5887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                 [edi = JSFunction, esi = context]
5897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ call [edi + kCodeEntryOffset] }------------------------------------------
5917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                 | RET | args + receiver |  caller frame |
5927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                 ^ esp                                   ^ ebp
5937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ prologue of called function }============================================
5957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ push ebp }---------------------------------------------------------------
5967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                            | FP | RET | args + receiver |  caller frame |
5977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                            ^ esp                                        ^ ebp
5987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ mov ebp, esp }-----------------------------------------------------------
6007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                            | FP | RET | args + receiver |  caller frame |
6017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                            ^ ebp,esp
6027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ push esi }---------------------------------------------------------------
6047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                      | CTX | FP | RET | args + receiver |  caller frame |
6057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                      ^esp  ^ ebp
6067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ push edi }---------------------------------------------------------------
6087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                | FNC | CTX | FP | RET | args + receiver |  caller frame |
6097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                ^esp        ^ ebp
6107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ subi esp, #N }-----------------------------------------------------------
6127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// | callee frame | FNC | CTX | FP | RET | args + receiver |  caller frame |
6137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// ^esp                       ^ ebp
6147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ body of called function }================================================
6167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ epilogue of called function }============================================
6187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ mov esp, ebp }-----------------------------------------------------------
6197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                            | FP | RET | args + receiver |  caller frame |
6207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                            ^ esp,ebp
6217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ pop ebp }-----------------------------------------------------------
6237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// |                               | RET | args + receiver |  caller frame |
6247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                 ^ esp                                   ^ ebp
6257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ ret #A+1 }-----------------------------------------------------------
6277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// |                                                       |  caller frame |
6287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         ^ esp           ^ ebp
6297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Runtime function calls are accomplished by doing a stub call to the
6327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// CEntryStub (a real code object). On IA32 passes arguments on the
6337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// stack, the number of arguments in EAX, the address of the runtime function
6347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// in EBX, and the context in ESI.
6357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ before the call instruction }--------------------------------------------
6377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         |  caller frame |
6387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         ^ esp           ^ ebp
6397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ push arguments and setup EAX, EBX, and ESI }-----------------------------
6417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       | args + receiver |  caller frame |
6427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       ^ esp                             ^ ebp
6437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//              [eax = #args, ebx = runtime function, esi = context]
6447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ call #CEntryStub }-------------------------------------------------------
6467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                 | RET | args + receiver |  caller frame |
6477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                 ^ esp                                   ^ ebp
6487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ body of runtime function }===============================================
6507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ runtime returns }--------------------------------------------------------
6527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         |  caller frame |
6537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         ^ esp           ^ ebp
6547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Other custom linkages (e.g. for calling directly into and out of C++) may
6567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// need to save callee-saved registers on the stack, which is done in the
6577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// function prologue of generated code.
6587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ before the call instruction }--------------------------------------------
6607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         |  caller frame |
6617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                         ^ esp           ^ ebp
6627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ set up arguments in registers on stack }---------------------------------
6647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                  | args |  caller frame |
6657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                                  ^ esp                  ^ ebp
6667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                  [r0 = arg0, r1 = arg1, ...]
6677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ call code }--------------------------------------------------------------
6697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                            | RET | args |  caller frame |
6707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                            ^ esp                        ^ ebp
6717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ prologue of called function }============================================
6737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ push ebp }---------------------------------------------------------------
6747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       | FP | RET | args |  caller frame |
6757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       ^ esp                             ^ ebp
6767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ mov ebp, esp }-----------------------------------------------------------
6787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       | FP | RET | args |  caller frame |
6797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       ^ ebp,esp
6807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ save registers }---------------------------------------------------------
6827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                | regs | FP | RET | args |  caller frame |
6837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                ^ esp  ^ ebp
6847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ subi esp, #N }-----------------------------------------------------------
6867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                 | callee frame | regs | FP | RET | args |  caller frame |
6877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                 ^esp                  ^ ebp
6887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ body of called function }================================================
6907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// =={ epilogue of called function }============================================
6927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ restore registers }------------------------------------------------------
6937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                | regs | FP | RET | args |  caller frame |
6947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                ^ esp  ^ ebp
6957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ mov esp, ebp }-----------------------------------------------------------
6977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       | FP | RET | args |  caller frame |
6987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                       ^ esp,ebp
6997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// --{ pop ebp }----------------------------------------------------------------
7017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                            | RET | args |  caller frame |
7027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org//                                            ^ esp                        ^ ebp
7037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssemblePrologue() {
7067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
7077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Frame* frame = code_->frame();
7087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int stack_slots = frame->GetSpillSlotCount();
7097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (descriptor->kind() == CallDescriptor::kCallAddress) {
7107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Assemble a prologue similar the to cdecl calling convention.
7117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ push(ebp);
7127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(ebp, esp);
7137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    const RegList saves = descriptor->CalleeSavedRegisters();
7147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (saves != 0) {  // Save callee-saved registers.
7157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int register_save_area_size = 0;
7167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
7177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        if (!((1 << i) & saves)) continue;
7187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ push(Register::from_code(i));
7197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        register_save_area_size += kPointerSize;
7207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
7217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      frame->SetRegisterSaveAreaSize(register_save_area_size);
7227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
7237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (descriptor->IsJSFunctionCall()) {
7247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CompilationInfo* info = linkage()->info();
7257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ Prologue(info->IsCodePreAgingActive());
7267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    frame->SetRegisterSaveAreaSize(
7277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        StandardFrameConstants::kFixedFrameSizeFromFp);
7287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Sloppy mode functions and builtins need to replace the receiver with the
7307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // global proxy when called as functions (without an explicit receiver
7317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // object).
7327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
7337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (info->strict_mode() == SLOPPY && !info->is_native()) {
7347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Label ok;
7357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // +2 for return address and saved frame pointer.
7367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int receiver_slot = info->scope()->num_parameters() + 2;
7377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(ecx, Operand(ebp, receiver_slot * kPointerSize));
7387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ cmp(ecx, isolate()->factory()->undefined_value());
7397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ j(not_equal, &ok, Label::kNear);
7407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(ecx, GlobalObjectOperand());
7417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
7427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(Operand(ebp, receiver_slot * kPointerSize), ecx);
7437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ bind(&ok);
7447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
7457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
7477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ StubPrologue();
7487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    frame->SetRegisterSaveAreaSize(
7497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        StandardFrameConstants::kFixedFrameSizeFromFp);
7507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (stack_slots > 0) {
7527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ sub(esp, Immediate(stack_slots * kPointerSize));
7537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssembleReturn() {
7587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
7597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (descriptor->kind() == CallDescriptor::kCallAddress) {
7607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    const RegList saves = descriptor->CalleeSavedRegisters();
7617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (frame()->GetRegisterSaveAreaSize() > 0) {
7627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Remove this frame's spill slots first.
7637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int stack_slots = frame()->GetSpillSlotCount();
7647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (stack_slots > 0) {
7657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ add(esp, Immediate(stack_slots * kPointerSize));
7667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
7677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Restore registers.
7687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (saves != 0) {
7697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        for (int i = 0; i < Register::kNumRegisters; i++) {
7707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          if (!((1 << i) & saves)) continue;
7717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          __ pop(Register::from_code(i));
7727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        }
7737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
7747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ pop(ebp);  // Pop caller's frame pointer.
7757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ ret(0);
7767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
7777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // No saved registers.
7787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
7797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ pop(ebp);       // Pop caller's frame pointer.
7807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ ret(0);
7817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
7827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
7837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
7847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ pop(ebp);       // Pop caller's frame pointer.
7859aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    int pop_count = descriptor->IsJSFunctionCall()
7869aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org                        ? static_cast<int>(descriptor->JSParameterCount())
7879aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org                        : 0;
7887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ ret(pop_count * kPointerSize);
7897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssembleMove(InstructionOperand* source,
7947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                 InstructionOperand* destination) {
7957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandConverter g(this, NULL);
7967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Dispatch on the source and destination operand kinds.  Not all
7977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // combinations are possible.
7987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (source->IsRegister()) {
799e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination->IsRegister() || destination->IsStackSlot());
8007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register src = g.ToRegister(source);
8017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand dst = g.ToOperand(destination);
8027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ mov(dst, src);
8037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsStackSlot()) {
804e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination->IsRegister() || destination->IsStackSlot());
8057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand src = g.ToOperand(source);
8067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (destination->IsRegister()) {
8077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Register dst = g.ToRegister(destination);
8087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(dst, src);
8097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
8107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Operand dst = g.ToOperand(destination);
8117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ push(src);
8127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ pop(dst);
8137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
8147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsConstant()) {
8157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Constant src_constant = g.ToConstant(source);
8167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (src_constant.type() == Constant::kHeapObject) {
8177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Handle<HeapObject> src = src_constant.ToHeapObject();
8187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (destination->IsRegister()) {
8197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Register dst = g.ToRegister(destination);
8207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ LoadHeapObject(dst, src);
8217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
822e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(destination->IsStackSlot());
8237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Operand dst = g.ToOperand(destination);
8247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        AllowDeferredHandleDereference embedding_raw_address;
8257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        if (isolate()->heap()->InNewSpace(*src)) {
8267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          __ PushHeapObject(src);
8277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          __ pop(dst);
8287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        } else {
8297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          __ mov(dst, src);
8307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        }
8317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
8327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else if (destination->IsRegister()) {
8337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Register dst = g.ToRegister(destination);
8347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(dst, g.ToImmediate(source));
8357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else if (destination->IsStackSlot()) {
8367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Operand dst = g.ToOperand(destination);
8377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ mov(dst, g.ToImmediate(source));
8387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
8397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      double v = g.ToDouble(source);
840e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      uint64_t int_val = bit_cast<uint64_t, double>(v);
8417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int32_t lower = static_cast<int32_t>(int_val);
8427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
8437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (destination->IsDoubleRegister()) {
8447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        XMMRegister dst = g.ToDoubleRegister(destination);
8457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ Move(dst, v);
8467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
847e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(destination->IsDoubleStackSlot());
8487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Operand dst0 = g.ToOperand(destination);
8497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Operand dst1 = g.HighOperand(destination);
8507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ mov(dst0, Immediate(lower));
8517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        __ mov(dst1, Immediate(upper));
8527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
8537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
8547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsDoubleRegister()) {
8557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    XMMRegister src = g.ToDoubleRegister(source);
8567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (destination->IsDoubleRegister()) {
8577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      XMMRegister dst = g.ToDoubleRegister(destination);
8587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movaps(dst, src);
8597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
860e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
8617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Operand dst = g.ToOperand(destination);
8627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(dst, src);
8637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
8647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsDoubleStackSlot()) {
865e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
8667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand src = g.ToOperand(source);
8677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (destination->IsDoubleRegister()) {
8687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      XMMRegister dst = g.ToDoubleRegister(destination);
8697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(dst, src);
8707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
8717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // We rely on having xmm0 available as a fixed scratch register.
8727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Operand dst = g.ToOperand(destination);
8737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(xmm0, src);
8747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      __ movsd(dst, xmm0);
8757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
8767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
8777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    UNREACHABLE();
8787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
8807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AssembleSwap(InstructionOperand* source,
8837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                 InstructionOperand* destination) {
8847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  IA32OperandConverter g(this, NULL);
8857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Dispatch on the source and destination operand kinds.  Not all
8867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // combinations are possible.
8877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (source->IsRegister() && destination->IsRegister()) {
8887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Register-register.
8897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register src = g.ToRegister(source);
8907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Register dst = g.ToRegister(destination);
8917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ xchg(dst, src);
8927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsRegister() && destination->IsStackSlot()) {
8937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Register-memory.
8947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ xchg(g.ToRegister(source), g.ToOperand(destination));
8957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsStackSlot() && destination->IsStackSlot()) {
8967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Memory-memory.
8977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand src = g.ToOperand(source);
8987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand dst = g.ToOperand(destination);
8997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ push(dst);
9007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ push(src);
9017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ pop(dst);
9027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ pop(src);
9037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
9047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // XMM register-register swap. We rely on having xmm0
9057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // available as a fixed scratch register.
9067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    XMMRegister src = g.ToDoubleRegister(source);
9077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    XMMRegister dst = g.ToDoubleRegister(destination);
9087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movaps(xmm0, src);
9097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movaps(src, dst);
9107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movaps(dst, xmm0);
9117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsDoubleRegister() && source->IsDoubleStackSlot()) {
9127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // XMM register-memory swap.  We rely on having xmm0
9137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // available as a fixed scratch register.
9147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    XMMRegister reg = g.ToDoubleRegister(source);
9157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand other = g.ToOperand(destination);
9167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movsd(xmm0, other);
9177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movsd(other, reg);
9187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movaps(reg, xmm0);
9197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
9207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Double-width memory-to-memory.
9217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand src0 = g.ToOperand(source);
9227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand src1 = g.HighOperand(source);
9237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand dst0 = g.ToOperand(destination);
9247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Operand dst1 = g.HighOperand(destination);
9257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movsd(xmm0, dst0);  // Save destination in xmm0.
9267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ push(src0);         // Then use stack to copy source to destination.
9277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ pop(dst0);
9287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ push(src1);
9297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ pop(dst1);
9307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    __ movsd(src0, xmm0);
9317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  } else {
9327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // No other combinations are possible.
9337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    UNREACHABLE();
9347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
9357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
9367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgvoid CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
9397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
94006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
94106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid CodeGenerator::EnsureSpaceForLazyDeopt() {
94206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  int space_needed = Deoptimizer::patch_size();
94306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (!linkage()->info()->IsStub()) {
94406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Ensure that we have enough space after the previous lazy-bailout
94506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // instruction for patching the code here.
94606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    int current_pc = masm()->pc_offset();
94706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
94806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
94906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ Nop(padding_size);
95006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
95106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
95206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  MarkLazyDeoptSite();
95306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
95406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
9557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#undef __
9567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
957d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org}  // namespace compiler
958d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org}  // namespace internal
959d4f11c0cf476dd854eaebec1cbacb1afc7bea18emachenbach@chromium.org}  // namespace v8
960