macro-assembler-x64.cc revision 80d68eab642096c1a48b6474d6ec33064b0ad1f5
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler-x64.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler-x64.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "heap.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMacroAssembler::MacroAssembler(void* buffer, int size)
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    : Assembler(buffer, size),
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      generating_stub_(false),
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      allow_stub_calls_(true),
473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      code_object_(Heap::undefined_value()) {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(destination, Operand(kRootRegister, index << kPointerSizeLog2));
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
5725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  movq(Operand(kRootRegister, index << kPointerSizeLog2), source);
5825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
5925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
6025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  push(Operand(kRootRegister, index << kPointerSizeLog2));
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2));
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) {
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(kScratchRegister, index);
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(with, kScratchRegister);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CompareRoot(rsp, Heap::kStackLimitRootIndex);
79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  j(below, on_stack_overflow);
80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
81d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
82d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::RecordWriteHelper(Register object,
846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       Register addr,
856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       Register scratch) {
866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (FLAG_debug_code) {
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the object is not in new space.
886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label not_in_new_space;
896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    InNewSpace(object, scratch, not_equal, &not_in_new_space);
906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Abort("new-space object passed to RecordWriteHelper");
916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&not_in_new_space);
926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the page start address from the heap object pointer, and reuse
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the 'object' register for it.
967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  and_(object, Immediate(~Page::kPageAlignmentMask));
977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Compute number of region covering addr. See Page::GetRegionNumberForAddress
997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // method for more details.
1007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  shrl(addr, Immediate(Page::kRegionSizeLog2));
1019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  andl(addr, Immediate(Page::kPageAlignmentMask >> Page::kRegionSizeLog2));
1027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Set dirty mark for region.
1047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bts(Operand(object, Page::kDirtyFlagOffset), addr);
1057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RecordWrite(Register object,
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 int offset,
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register value,
1119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                 Register index) {
1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // The compiled code assumes that record write doesn't change the
1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // context register, so we check that none of the clobbered
1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // registers are rsi.
1159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi));
1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
1187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // catch stores of Smis and stores into young gen.
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  JumpIfSmi(value, &done);
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  RecordWriteNonSmi(object, offset, value, index);
1233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&done);
1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Clobber all input registers when running with the debug-code flag
1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors. This clobbering repeats the
1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // clobbering done inside RecordWriteNonSmi but it's necessary to
1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // avoid having the fast case for smis leave the registers
1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // unchanged.
1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (FLAG_debug_code) {
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
1339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1388defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::RecordWrite(Register object,
1398defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register address,
1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register value) {
1418defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // The compiled code assumes that record write doesn't change the
1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // context register, so we check that none of the clobbered
1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // registers are esi.
1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi));
1458defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1468defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
1478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // catch stores of Smis and stores into young gen.
1488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
1498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  JumpIfSmi(value, &done);
1508defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  InNewSpace(object, value, equal, &done);
1528defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  RecordWriteHelper(object, address, value);
1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Clobber all input registers when running with the debug-code flag
1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (FLAG_debug_code) {
1608defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
1628defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
1638defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::RecordWriteNonSmi(Register object,
1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       int offset,
1693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       Register scratch,
1709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                       Register index) {
1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label done;
1724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (FLAG_debug_code) {
1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Label okay;
1754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    JumpIfNotSmi(object, &okay);
1764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis");
1774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    bind(&okay);
1789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (offset == 0) {
1809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // index must be int32.
1819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Register tmp = index.is(rax) ? rbx : rax;
1829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      push(tmp);
1839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      movl(tmp, index);
1849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      cmpq(tmp, index);
1859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Check(equal, "Index register for RecordWrite must be untagged int32.");
1869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      pop(tmp);
1879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
1884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Test that the object address is not in the new space. We cannot
1917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // update page dirty marks for new space pages.
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InNewSpace(object, scratch, equal, &done);
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The offset is relative to a tagged or untagged HeapObject pointer,
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // so either offset or offset + kHeapObjectTag must be a
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // multiple of kPointerSize.
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsAligned(offset, kPointerSize) ||
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block         IsAligned(offset + kHeapObjectTag, kPointerSize));
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Register dst = index;
2017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (offset != 0) {
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    lea(dst, Operand(object, offset));
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // array access: calculate the destination address in the same manner as
2057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // KeyedStoreIC::GenerateGeneric.
2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    lea(dst, FieldOperand(object,
2079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          index,
2089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          times_pointer_size,
2097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          FixedArray::kHeaderSize));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  RecordWriteHelper(object, dst, scratch);
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Clobber all input registers when running with the debug-code flag
2164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
2174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (FLAG_debug_code) {
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
2209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InNewSpace(Register object,
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                Register scratch,
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                Condition cc,
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                Label* branch) {
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (Serializer::enabled()) {
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Can't do arithmetic on external references if it might get serialized.
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // The mask isn't really an address.  We load it as an external reference in
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // case the size of the new space is different between the snapshot maker
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the running system.
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (scratch.is(object)) {
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(kScratchRegister, ExternalReference::new_space_mask());
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      and_(scratch, kScratchRegister);
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(scratch, ExternalReference::new_space_mask());
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      and_(scratch, object);
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(kScratchRegister, ExternalReference::new_space_start());
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    cmpq(scratch, kScratchRegister);
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(cc, branch);
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    intptr_t new_space_start =
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        reinterpret_cast<intptr_t>(Heap::NewSpaceStart());
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(kScratchRegister, -new_space_start, RelocInfo::NONE);
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (scratch.is(object)) {
2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      addq(scratch, kScratchRegister);
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      lea(scratch, Operand(object, kScratchRegister, times_1, 0));
2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(cc, branch);
2564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Assert(Condition cc, const char* msg) {
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) Check(cc, msg);
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (FLAG_debug_code) {
267756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
268756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedArrayMapRootIndex);
270756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
271756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
272756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedCOWArrayMapRootIndex);
273756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(equal, &ok);
274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Abort("JSObject with fast elements map has slow elements");
275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
276756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
277756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
278756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
279756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Check(Condition cc, const char* msg) {
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(cc, &L);
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Abort(msg);
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment = OS::ActivationFrameAlignment();
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(IsPowerOf2(frame_alignment));
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label alignment_as_expected;
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    testq(rsp, Immediate(frame_alignment_mask));
2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(zero, &alignment_as_expected);
2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label ok;
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(result, result);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_zero, &ok);
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(op, op);
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(sign, then_label);
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) {
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We want to pass the msg string like a smi to avoid GC
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // problems, however msg is not guaranteed to be aligned
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properly. Instead, we pass an aligned pointer that is
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a proper v8 smi, but also pass the alignment difference
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the real pointer as a smi.
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag.
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Disable stub call restrictions to always allow calls to abort.
333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  set_allow_stub_calls(true);
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rax);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, p0, RelocInfo::NONE);
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))),
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       RelocInfo::NONE);
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::kAbort, 2);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallStub(CodeStub* stub) {
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Call(stub->GetCode(), RelocInfo::CODE_TARGET);
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
354bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallStub(CodeStub* stub) {
355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* result = stub->TryGetCode();
357bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (!result->IsFailure()) {
358bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return result;
361bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) {
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
370bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryTailCallStub(CodeStub* stub) {
371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* result = stub->TryGetCode();
373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (!result->IsFailure()) {
374bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
375bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
376bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return result;
377bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
378bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
379bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::StubReturn(int argc) {
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(argc >= 1 && generating_stub());
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret((argc - 1) * kPointerSize);
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) {
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_arguments > 0) {
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(rsp, Immediate(num_arguments * kPointerSize));
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(rax, Heap::kUndefinedValueRootIndex);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
39580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
39680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
39780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
39880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
39980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
40080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // We want the smi-tagged index in key. Even if we subsequently go to
40180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the slow case, converting the key to a smi is always valid.
40280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // key: string key
40380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // hash: key's hash field, including its array index value.
40480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  and_(hash, Immediate(String::kArrayIndexValueMask));
40580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  shr(hash, Immediate(String::kHashShift));
40680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Here we actually clobber the key which will be used if calling into
40780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // runtime later. However as the new key is the numeric value of a string key
40880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // there is no difference in using either key.
40980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Integer32ToSmi(index, hash);
41080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
41180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
41280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::FunctionForId(id), num_arguments);
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int num_arguments) {
420bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
421bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
423bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IllegalOperation(num_arguments);
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
4344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
4354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
4364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
4378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
4384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rbx, ExternalReference(f));
4394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub ces(f->result_size);
4404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int num_arguments) {
446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (f->nargs >= 0 && f->nargs != num_arguments) {
447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    IllegalOperation(num_arguments);
448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    // Since we did not call the stub, there was no allocation failure.
449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    // Return some non-failure object.
450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    return Heap::undefined_value();
451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
453bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // TODO(1236192): Most runtime routines don't need the number of
454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // arguments passed in because it is constant. At some point we
455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // should remove this need and make the runtime routine entry code
456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // smarter.
457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Set(rax, num_arguments);
458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(rbx, ExternalReference(f));
459bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CEntryStub ces(f->result_size);
460bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return TryCallStub(&ces);
461bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
4668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rbx, ext);
468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub stub(1);
470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8] : argument num_arguments - 1
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  ...
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1236192): Most runtime routines don't need the number of
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments passed in because it is constant. At some point we
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should remove this need and make the runtime routine entry code
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // smarter.
4888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpToExternalReference(ext, result_size);
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int num_arguments,
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int result_size) {
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) {
501bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int64_t offset = (ref0.address() - ref1.address());
502bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Check that fits into int.
503bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(static_cast<int>(offset) == offset);
504bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return static_cast<int>(offset);
505bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
506bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
507bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
508bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PushHandleScope(Register scratch) {
509bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ExternalReference extensions_address =
510bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_extensions_address();
511bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kExtensionsOffset = 0;
512bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kNextOffset = Offset(
513bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_next_address(),
514bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
515bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kLimitOffset = Offset(
516bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_limit_address(),
517bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
518bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
519bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Push the number of extensions, smi-tagged so the gc will ignore it.
520bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(kScratchRegister, extensions_address);
521bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(scratch, Operand(kScratchRegister, kExtensionsOffset));
522bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
523bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Integer32ToSmi(scratch, scratch);
524bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(scratch);
525bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Push next and limit pointers which will be wordsize aligned and
526bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // hence automatically smi tagged.
527bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(Operand(kScratchRegister, kNextOffset));
528bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(Operand(kScratchRegister, kLimitOffset));
529bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
530bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
531bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
532bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::PopHandleScopeHelper(Register saved,
533bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                             Register scratch,
534bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                             bool gc_allowed) {
535bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ExternalReference extensions_address =
536bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_extensions_address();
537bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kExtensionsOffset = 0;
538bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kNextOffset = Offset(
539bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_next_address(),
540bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
541bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kLimitOffset = Offset(
542bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_limit_address(),
543bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
544bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
545bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* result = NULL;
546bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label write_back;
547bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(kScratchRegister, extensions_address);
548bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
549bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  j(equal, &write_back);
550bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(saved);
551bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (gc_allowed) {
552bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
553bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
554bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
555bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (result->IsFailure()) return result;
556bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
557bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(saved);
558bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(kScratchRegister, extensions_address);
559bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
560bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  bind(&write_back);
561bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(Operand(kScratchRegister, kLimitOffset));
562bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(Operand(kScratchRegister, kNextOffset));
563bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(scratch);
564bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  SmiToInteger32(scratch, scratch);
565bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(Operand(kScratchRegister, kExtensionsOffset), scratch);
566bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
567bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return result;
568bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
569bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
570bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
571bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PopHandleScope(Register saved, Register scratch) {
572bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  PopHandleScopeHelper(saved, scratch, true);
573bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
574bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
575bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
576bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
577bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return PopHandleScopeHelper(saved, scratch, false);
578bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
579bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
580bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             int result_size) {
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbx, ext);
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub ces(result_size);
5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Calls are not allowed in some stubs.
592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Rely on the assertion to check that the number of provided
595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // arguments match the expected number of arguments. Fake a
596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // parameter count to avoid emitting code to do the check.
597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GetBuiltinEntry(rdx, id);
599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  InvokeCode(rdx, expected, expected, flag);
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
603791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target,
604791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                        Builtins::JavaScript id) {
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the builtins object into target register.
6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
608791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(target, FieldOperand(target,
609791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            JSBuiltinsObject::OffsetOfFunctionWithId(id)));
610791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
613791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
614791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(!target.is(rdi));
615791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Load the JavaScript builtin function from the builtins object.
616791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  GetBuiltinFunction(rdi, id);
617791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) {
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x == 0) {
6238defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_int32(x)) {
625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Immediate(static_cast<int32_t>(x)));
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_uint32(x)) {
627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movl(dst, Immediate(static_cast<uint32_t>(x)));
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, x, RelocInfo::NONE);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) {
6349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (is_int32(x)) {
635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Immediate(static_cast<int32_t>(x)));
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, x, RelocInfo::NONE);
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection.
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic int kSmiShift = kSmiTagSize + kSmiShiftSize;
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6478defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) {
6488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
6498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 0) {
6508defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(kScratchRegister, kScratchRegister);
6518defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kScratchRegister;
6528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 1) {
6548defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kSmiConstantRegister;
6558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(kScratchRegister, source);
6578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return kScratchRegister;
6588defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
6598defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6608defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
6618defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (FLAG_debug_code) {
6628defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(dst,
6638defd9ff6930b4e24729971a61cf7469daf119beSteve Block         reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
6648defd9ff6930b4e24729971a61cf7469daf119beSteve Block         RelocInfo::NONE);
6658defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmpq(dst, kSmiConstantRegister);
6668defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (allow_stub_calls()) {
6678defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Assert(equal, "Uninitialized kSmiConstantRegister");
6688defd9ff6930b4e24729971a61cf7469daf119beSteve Block    } else {
6698defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Label ok;
6708defd9ff6930b4e24729971a61cf7469daf119beSteve Block      j(equal, &ok);
6718defd9ff6930b4e24729971a61cf7469daf119beSteve Block      int3();
6728defd9ff6930b4e24729971a61cf7469daf119beSteve Block      bind(&ok);
6738defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
6748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (source->value() == 0) {
6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
6778defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
6788defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
6808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bool negative = value < 0;
6818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  unsigned int uvalue = negative ? -value : value;
6828defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  switch (uvalue) {
6848defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 9:
6858defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
6868defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6878defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 8:
6888defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
6898defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
6908defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6918defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 4:
6928defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
6938defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
6948defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6958defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 5:
6968defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
6978defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6988defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 3:
6998defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
7008defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
7018defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 2:
7028defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
7038defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
7048defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 1:
7058defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, kSmiConstantRegister);
7068defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
7078defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 0:
7088defd9ff6930b4e24729971a61cf7469daf119beSteve Block      UNREACHABLE();
7098defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
7108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    default:
7118defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE);
7128defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
7138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
7148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (negative) {
7158defd9ff6930b4e24729971a61cf7469daf119beSteve Block    neg(dst);
7168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
7178defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
7188defd9ff6930b4e24729971a61cf7469daf119beSteve Block
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
7223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movl(dst, src);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst,
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register src,
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* on_overflow) {
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
7323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 32-bit integer always fits in a long smi.
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(dst, src);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
7419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (FLAG_debug_code) {
7429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    testb(dst, Immediate(0x01));
7439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Label ok;
7449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(zero, &ok);
7459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (allow_stub_calls()) {
7469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Abort("Integer32ToSmiField writing to non-smi location");
7479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
7489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      int3();
7499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
7509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bind(&ok);
7519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
7529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(kSmiShift % kBitsPerByte == 0);
7539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movl(Operand(dst, kSmiShift / kBitsPerByte), src);
7549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
7559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Register src,
7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                int constant) {
7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    addq(dst, Immediate(constant));
7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    lea(dst, Operand(src, constant));
7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shr(dst, Immediate(kSmiShift));
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
7797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movl(dst, Operand(src, kSmiShift / kBitsPerByte));
7807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
7817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
7827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  sar(dst, Immediate(kSmiShift));
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
7939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
7949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
7959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) {
7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src, src);
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Register src) {
8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpq(dst, src);
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src->value() == 0) {
8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
812756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Register constant_reg = GetSmiConstant(src);
813756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmpq(dst, constant_reg);
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(dst, src);
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpq(dst, src);
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
8297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
8349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
8359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
8369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           Register src,
8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           int power) {
8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power >= 0);
8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power < 64);
8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power == 0) {
8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src);
8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return;
8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
8493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power < kSmiShift) {
8513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - power));
8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (power > kSmiShift) {
8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(power - kSmiShift));
8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
8597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         Register src,
8607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         int power) {
8617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((0 <= power) && (power < 32));
8627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (dst.is(src)) {
8637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    shr(dst, Immediate(power + kSmiShift));
8647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
8657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    UNIMPLEMENTED();  // Not used.
8667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
8677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
8687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) {
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(src, Immediate(kSmiTagMask));
8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckPositiveSmi(Register src) {
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
8798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Make mask 0x8000000000000001 and test that both bits are zero.
8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(kScratchRegister, src);
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  rol(kScratchRegister, Immediate(1));
8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(3));
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return zero;
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first.is(second)) {
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CheckSmi(first);
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  leal(kScratchRegister, Operand(first, second, times_1, 0));
8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(0x03));
8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::CheckBothPositiveSmi(Register first,
899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                               Register second) {
900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (first.is(second)) {
901d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return CheckPositiveSmi(first);
902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block  movq(kScratchRegister, first);
9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  or_(kScratchRegister, second);
905d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  rol(kScratchRegister, Immediate(1));
906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testl(kScratchRegister, Immediate(0x03));
907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
911bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first,
912bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register second,
913bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register scratch) {
914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (first.is(second)) {
915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return CheckSmi(first);
916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
917bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (scratch.is(second)) {
918bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, first);
919bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
920bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (!scratch.is(first)) {
921bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      movl(scratch, first);
922bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
923bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, second);
924bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
925bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  testb(scratch, Immediate(kSmiTagMask));
926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) {
9318defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!src.is(kScratchRegister));
9328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If we overflow by subtracting one, it's the minimal smi value.
9338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  cmpq(src, kSmiConstantRegister);
9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return overflow;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // A 32-bit integer value can always be converted to a smi.
9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return always;
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // An unsigned 32-bit integer value is valid as long as the high bit
9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // is not set.
9478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testl(src, src);
9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return positive;
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiNeg(Register dst, Register src, Label* on_smi_result) {
9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src);
9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    neg(dst);  // Low 32 bits are retained as zero by negation.
9573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Test if result is zero or Smi::kMinValue.
9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, kScratchRegister);
9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_equal, on_smi_result);
9603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src, kScratchRegister);
9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
9633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    neg(dst);
9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, src);
9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_equal, on_smi_result);
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAdd(Register dst,
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (on_not_smi_result == NULL) {
9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // No overflow checking. Use only when it's known that
9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // overflowing is impossible.
9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (dst.is(src1)) {
9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      addq(dst, src2);
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
9826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(dst, src1);
9836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      addq(dst, src2);
9846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Assert(no_overflow, "Smi addition overflow");
9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (dst.is(src1)) {
9879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(kScratchRegister, src1);
9889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    addq(kScratchRegister, src2);
9899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
9909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(dst, kScratchRegister);
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    addq(dst, src2);
9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSub(Register dst,
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
1004d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (on_not_smi_result == NULL) {
1005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // No overflow checking. Use only when it's known that
1006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // overflowing is impossible (e.g., subtracting two positive smis).
1007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (dst.is(src1)) {
1008d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      subq(dst, src2);
1009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
1010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      movq(dst, src1);
1011d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      subq(dst, src2);
1012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
10139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Assert(no_overflow, "Smi subtraction overflow");
1014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (dst.is(src1)) {
10159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    cmpq(dst, src2);
10169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    subq(dst, src2);
10183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
10193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    subq(dst, src2);
10213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::SmiSub(Register dst,
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            Register src1,
1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            const Operand& src2,
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            Label* on_not_smi_result) {
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (on_not_smi_result == NULL) {
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // No overflow checking. Use only when it's known that
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // overflowing is impossible (e.g., subtracting two positive smis).
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (dst.is(src1)) {
10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(dst, src2);
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(dst, src1);
10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(dst, src2);
10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Assert(no_overflow, "Smi subtraction overflow");
10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (dst.is(src1)) {
10418defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(kScratchRegister, src2);
10428defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmpq(src1, kScratchRegister);
10439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
10448defd9ff6930b4e24729971a61cf7469daf119beSteve Block    subq(src1, kScratchRegister);
10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
10466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(dst, src1);
10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(dst, src2);
10486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(overflow, on_not_smi_result);
10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMul(Register dst,
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src1)) {
10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label failure, zero_correct_result;
10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);  // Create backup for later testing.
10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src1);
10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    imul(dst, src2);
10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, &failure);
10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Check for negative zero result.  If product is zero, and one
10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // argument is negative, go to slow case.
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label correct_result;
10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_zero, &correct_result);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, kScratchRegister);
10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, src2);
10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(positive, &zero_correct_result);  // Result was positive zero.
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&failure);  // Reused failure exit, restores src1.
10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
10803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&zero_correct_result);
10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, dst);
10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&correct_result);
10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src1);
10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    imul(dst, src2);
10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Check for negative zero result.  If product is zero, and one
10913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // argument is negative, go to slow case.
10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label correct_result;
10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_zero, &correct_result);
10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // One of src1 and src2 is zero, the check whether the other is
10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // negative.
10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(kScratchRegister, src2);
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(negative, on_not_smi_result);
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&correct_result);
11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiTryAddConstant(Register dst,
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register src,
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       Smi* constant,
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Label* on_not_smi_result) {
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Does not assume that src is a smi.
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask));
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src.is(kScratchRegister));
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  JumpIfNotSmi(src, on_not_smi_result);
11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Register tmp = (dst.is(src) ? kScratchRegister : dst);
11178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(tmp, constant);
11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  addq(tmp, src);
11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(overflow, on_not_smi_result);
11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, tmp);
11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
11293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
11303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
11318defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
11348defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
11358defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
11368defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, kSmiConstantRegister);
11378defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11388defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
11398defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
11408defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11418defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
11428defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
11438defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11448defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
11458defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
11468defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11478defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
11488defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Register constant_reg = GetSmiConstant(constant);
11498defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, constant_reg);
11508defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11518defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
11558defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_1, 0));
11568defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
11598defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11608defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
11618defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
11628defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11638defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
11658defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11668defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
11678defd9ff6930b4e24729971a61cf7469daf119beSteve Block        LoadSmiConstant(dst, constant);
11688defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, src);
11698defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11708defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (constant->value() != 0) {
11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
1178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAddConstant(Register dst,
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register src,
11843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Smi* constant,
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* on_not_smi_result) {
11863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
11913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
11923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11938defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(kScratchRegister, constant);
11948defd9ff6930b4e24729971a61cf7469daf119beSteve Block    addq(kScratchRegister, src);
11959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
11969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(dst, kScratchRegister);
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
11988defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    addq(dst, src);
12003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
12013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!dst.is(src)) {
12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
12128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
12138defd9ff6930b4e24729971a61cf7469daf119beSteve Block    subq(dst, constant_reg);
12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
12168defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
12179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
12189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
12199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(dst, src);
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
12219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
12228defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      addq(dst, src);
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSubConstant(Register dst,
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register src,
12313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Smi* constant,
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* on_not_smi_result) {
12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
12409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtracting min-value from any non-negative value will overflow.
12419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // We test the non-negativeness before doing the subtraction.
12429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      testq(src, src);
12439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      j(not_sign, on_not_smi_result);
12448defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(kScratchRegister, constant);
12453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      subq(dst, kScratchRegister);
12469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
12479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
12488defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value()));
12499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(kScratchRegister, dst);
12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      j(overflow, on_not_smi_result);
12519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      movq(dst, kScratchRegister);
12529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
12539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
12549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (constant->value() == Smi::kMinValue) {
12559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtracting min-value from any non-negative value will overflow.
12569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // We test the non-negativeness before doing the subtraction.
12579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      testq(src, src);
12589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      j(not_sign, on_not_smi_result);
12598defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
12609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
12619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
12629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(dst, src);
12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
12649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
12658defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      addq(dst, src);
12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      j(overflow, on_not_smi_result);
12683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiDiv(Register dst,
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rax));
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rdx));
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src1.is(rdx));
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for 0 divisor (result is +/-Infinity).
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label positive_divisor;
12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src2, src2);
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, on_not_smi_result);
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rax, src1);
12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We need to rule out dividing Smi::kMinValue by -1, since that would
12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // overflow in idiv and raise an exception.
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We combine this with negative zero test (negative zero only happens
12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // when dividing zero by a negative number).
12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We overshoot a little and go to slow case if we divide min-value
12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // by any negative value, not just -1.
13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label safe_div;
13013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testl(rax, Immediate(0x7fffffff));
13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_zero, &safe_div);
13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src2, src2);
13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(positive, &safe_div);
13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(negative, on_not_smi_result);
13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&safe_div);
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(src2, src2);
13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Sign extend src1 into edx:eax.
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cdq();
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  idivl(src2);
13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(src2, src2);
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the remainder is zero.
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(rdx, rdx);
13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label smi_result;
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(zero, &smi_result);
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&smi_result);
13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_zero, on_not_smi_result);
13283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1) && src1.is(rax)) {
13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Integer32ToSmi(dst, rax);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMod(Register dst,
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(kScratchRegister));
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src1.is(kScratchRegister));
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(kScratchRegister));
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rax));
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rdx));
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src1.is(rdx));
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(src2));
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src2, src2);
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, on_not_smi_result);
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (src1.is(rax)) {
13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rax, src1);
13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(src2, src2);
13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
13583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label safe_div;
13593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpl(rax, Immediate(Smi::kMinValue));
13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_equal, &safe_div);
13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpl(src2, Immediate(-1));
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_equal, &safe_div);
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Retag inputs and go slow case.
13643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(src2, src2);
13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
13663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(on_not_smi_result);
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&safe_div);
13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign extend eax into edx:eax.
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cdq();
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  idivl(src2);
13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore smi tags on inputs.
13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(src2, src2);
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (src1.is(rax)) {
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check for a negative zero result.  If the result is zero, and the
13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // dividend is negative, go slow to return a floating point negative zero.
13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label smi_result;
13823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testl(rdx, rdx);
13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_zero, &smi_result);
13843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src1, src1);
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(negative, on_not_smi_result);
13863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&smi_result);
13873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(dst, rdx);
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) {
13923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
13933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src.is(kScratchRegister));
13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set tag and padding bits before negating, so that they are zero afterwards.
13953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movl(kScratchRegister, Immediate(~0));
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
13973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, kScratchRegister);
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    lea(dst, Operand(src, kScratchRegister, times_1, 0));
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_(dst);
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
14063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(src2));
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
14083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(dst, src2);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
14153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
14163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, dst);
14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14198defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14208defd9ff6930b4e24729971a61cf7469daf119beSteve Block    and_(dst, constant_reg);
14213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14228defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
14233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    and_(dst, src);
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
14303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  or_(dst, src2);
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
14373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14398defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14408defd9ff6930b4e24729971a61cf7469daf119beSteve Block    or_(dst, constant_reg);
14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14428defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    or_(dst, src);
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src2);
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14598defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14608defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xor_(dst, constant_reg);
14613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14628defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, src);
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Register src,
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     int shift_value) {
14713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(is_uint5(shift_value));
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_value > 0) {
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (dst.is(src)) {
14743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      sar(dst, Immediate(shift_value + kSmiShift));
14753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      shl(dst, Immediate(kSmiShift));
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // Not used.
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRightConstant(Register dst,
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Register src,
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  int shift_value,
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Label* on_not_smi_result) {
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Logic right shift interprets its result as an *unsigned* number.
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNIMPLEMENTED();  // Not used.
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
14913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
14923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (shift_value == 0) {
14933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      testq(dst, dst);
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(negative, on_not_smi_result);
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shr(dst, Immediate(shift_value + kSmiShift));
14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(kSmiShift));
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src,
150425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                          int shift_value) {
15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
15063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift_value > 0) {
15093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift_value));
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst,
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
151625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                  Register src2) {
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label result_ok;
15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Untag shift amount.
15203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rcx, src2);
15243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Shift amount specified by lower 5 bits, not six as the shl opcode.
15253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  and_(rcx, Immediate(0x1f));
1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  shl_cl(dst);
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src1,
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src2,
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Label* on_not_smi_result) {
15343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
15353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
15363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label result_ok;
15393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx) || src2.is(rcx)) {
15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, rcx);
15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
15433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
15443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  orl(rcx, Immediate(kSmiShift));
1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  shr_cl(dst);  // Shift is rcx modulo 0x1f + 32.
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(dst, dst);
15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx) || src2.is(rcx)) {
15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label positive_result;
15523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(positive, &positive_result);
15533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (src1.is(rcx)) {
15543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(src1, kScratchRegister);
15553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
15563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(src2, kScratchRegister);
15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
15583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&positive_result);
15603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(negative, on_not_smi_result);  // src2 was zero and src1 negative.
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src1,
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src2) {
15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
15713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
15733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src2);
15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  orl(rcx, Immediate(kSmiShift));
1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  sar_cl(dst);  // Shift 32 + original rcx & 0x1f.
15843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
15883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src2, kScratchRegister);
15893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SelectNonSmi(Register dst,
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src2,
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Label* on_not_smis) {
15973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src1));
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Both operands must not be smis.
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (allow_stub_calls()) {  // Check contains a stub call.
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Check(not_both_smis, "Both registers were smis in SelectNonSmi.");
16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, Smi::FromInt(0));
16113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movl(kScratchRegister, Immediate(kSmiTagMask));
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(kScratchRegister, src1);
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(kScratchRegister, src2);
16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // If non-zero then both are smis.
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_zero, on_not_smis);
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Exactly one operand is a smi.
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1, static_cast<int>(kSmiTagMask));
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  subq(kScratchRegister, Immediate(1));
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(dst, src1);
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src2);
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(dst, kScratchRegister);
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src1);
16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16308defd9ff6930b4e24729971a61cf7469daf119beSteve Block
16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst,
16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Register src,
16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    int shift) {
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // There is a possible optimization if shift is in the range 60-63, but that
16363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // will (and must) never happen.
16373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
16383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
16393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
16443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register src,
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            int shift) {
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register src holds a positive smi.
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  neg(dst);
16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
16583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
16603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmi(Register src, Label* on_smi) {
16673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT_EQ(0, kSmiTag);
16683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition smi = CheckSmi(src);
16693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(smi, on_smi);
16703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) {
16743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition smi = CheckSmi(src);
16753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(smi), on_not_smi);
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotPositiveSmi(Register src,
16803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                          Label* on_not_positive_smi) {
16813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition positive_smi = CheckPositiveSmi(src);
16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(positive_smi), on_not_positive_smi);
16833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                             Smi* constant,
16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                             Label* on_equals) {
16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiCompare(src, constant);
16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(equal, on_equals);
16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) {
16953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition is_valid = CheckInteger32ValidSmiValue(src);
16963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(is_valid), on_invalid);
16973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
17013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Label* on_invalid) {
17023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition is_valid = CheckUInteger32ValidSmiValue(src);
17033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(is_valid), on_invalid);
17043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register src1, Register src2,
17083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      Label* on_not_both_smi) {
17093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition both_smi = CheckBothSmi(src1, src2);
17103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(both_smi), on_not_both_smi);
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothPositiveSmi(Register src1, Register src2,
1715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                              Label* on_not_both_smi) {
1716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Condition both_smi = CheckBothPositiveSmi(src1, src2);
1717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(NegateCondition(both_smi), on_not_both_smi);
1718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object,
1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Register second_object,
1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Register scratch1,
1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Register scratch2,
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Label* on_fail) {
1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that both objects are not smis.
1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition either_smi = CheckEitherSmi(first_object, second_object);
1729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  j(either_smi, on_fail);
1730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load instance type for both strings.
1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
1733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
1734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that both are flat ascii strings.
1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kNotStringTag != 0);
1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const int kFlatAsciiStringMask =
1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
1741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
1742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  andl(scratch1, Immediate(kFlatAsciiStringMask));
1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  andl(scratch2, Immediate(kFlatAsciiStringMask));
1745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Interleave the bits to check both scratch1 and scratch2 in one test.
1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
1747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  cmpl(scratch1,
1749d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
1750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  j(not_equal, on_fail);
1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register instance_type,
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch,
17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label *failure) {
17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!scratch.is(instance_type)) {
17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movl(scratch, instance_type);
17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kFlatAsciiStringMask =
17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  andl(scratch, Immediate(kFlatAsciiStringMask));
17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  j(not_equal, failure);
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register first_object_instance_type,
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register second_object_instance_type,
17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch1,
17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch2,
17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* on_fail) {
17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load instance type for both strings.
17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(scratch1, first_object_instance_type);
17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(scratch2, second_object_instance_type);
17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that both are flat ascii strings.
17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(kNotStringTag != 0);
17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kFlatAsciiStringMask =
17846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
17856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
17866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  andl(scratch1, Immediate(kFlatAsciiStringMask));
17886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  andl(scratch2, Immediate(kFlatAsciiStringMask));
17896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Interleave the bits to check both scratch1 and scratch2 in one test.
17906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
17916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
17926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpl(scratch1,
17936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
17946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  j(not_equal, on_fail);
17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!source->IsFailure());
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
18013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, source, RelocInfo::EMBEDDED_OBJECT);
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!source->IsFailure());
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
18113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
18203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (source->IsSmi()) {
18213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiCompare(dst, Smi::cast(*source));
18223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, source);
18243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, kScratchRegister);
18253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
18313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiCompare(dst, Smi::cast(*source));
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(dst, kScratchRegister);
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) {
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Push(Smi::cast(*source));
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(kScratchRegister);
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) {
18523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  intptr_t smi = reinterpret_cast<intptr_t>(source);
18533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (is_int32(smi)) {
18543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    push(Immediate(static_cast<int32_t>(smi)));
18553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18568defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant = GetSmiConstant(source);
18578defd9ff6930b4e24729971a61cf7469daf119beSteve Block    push(constant);
18583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
1863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
1864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    addq(rsp, Immediate(stack_elements * kPointerSize));
1865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) {
1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  testl(Operand(src, kIntSize), Immediate(source->value()));
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) {
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, ext);
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
18873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Inline this
18883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(code_object, rmode);
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) {
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, ext);
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(RelocInfo::IsCodeTarget(rmode));
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WriteRecordedPositions();
19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  call(code_object, rmode);
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location,
1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    HandlerType type) {
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The pc (return address) is already on TOS.  This code pushes state,
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // frame pointer and current handler.  Check that they are expected
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // next on the stack, in that order.
1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(StackHandlerConstants::kStateOffset,
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            StackHandlerConstants::kPCOffset - kPointerSize);
1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(StackHandlerConstants::kFPOffset,
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            StackHandlerConstants::kStateOffset - kPointerSize);
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(StackHandlerConstants::kNextOffset,
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            StackHandlerConstants::kFPOffset - kPointerSize);
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_location == IN_JAVASCRIPT) {
1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (type == TRY_CATCH_HANDLER) {
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Immediate(StackHandler::TRY_CATCH));
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Immediate(StackHandler::TRY_FINALLY));
1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(rbp);
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(try_location == IN_JS_ENTRY);
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The frame pointer does not point to a JS frame so we save NULL
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // for rbp. We expect the code throwing an exception to check rbp
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // before dereferencing it to restore the context.
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(Immediate(StackHandler::ENTRY));
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(Immediate(0));  // NULL frame pointer.
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the current handler.
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Operand(kScratchRegister, 0));
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Link this handler.
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), rsp);
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() {
1950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
1951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Unlink this handler.
1952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
1953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  pop(Operand(kScratchRegister, 0));
1954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Remove the remaining fields.
1955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
1956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
19653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  fucomip();
19668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  fstp(0);
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       Immediate(static_cast<int8_t>(type)));
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
19853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
19863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
19873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              bool is_heap_object) {
19883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (!is_heap_object) {
19893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    JumpIfSmi(obj, fail);
19903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
19913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
19923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
19933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) {
1997402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label ok;
1998402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Condition is_smi = CheckSmi(object);
1999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  j(is_smi, &ok);
2000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Cmp(FieldOperand(object, HeapObject::kMapOffset),
2001402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      Factory::heap_number_map());
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Assert(equal, "Operand not a number");
2003402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  bind(&ok);
2004402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2005402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2006402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2007756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) {
2008756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label ok;
2009756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Condition is_smi = CheckSmi(object);
2010756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(NegateCondition(is_smi), "Operand is a smi");
2011756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2012756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2013756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) {
20156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label ok;
20166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Condition is_smi = CheckSmi(object);
2017756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(is_smi, "Operand is not a smi");
20186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
20196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src,
20229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         Heap::RootListIndex root_value_index,
20239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         const char* message) {
20249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!src.is(kScratchRegister));
20259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  LoadRoot(kScratchRegister, root_value_index);
20269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpq(src, kScratchRegister);
20279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Check(equal, message);
20289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
20299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
20309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
20319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
2033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register map,
2034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register instance_type) {
2035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
20364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
2037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(kNotStringTag != 0);
2038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testb(instance_type, Immediate(kIsNotStringMask));
2039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
2040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result,
2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Label* miss) {
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(function, Immediate(kSmiTagMask));
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, miss);
2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(function, JS_FUNCTION_TYPE, result);
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function has an instance prototype.
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_instance;
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(FieldOperand(result, Map::kBitFieldOffset),
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(1 << Map::kHasNonInstancePrototype));
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_zero, &non_instance);
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result,
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareRoot(result, Heap::kTheHoleValueRootIndex);
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, miss);
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, kScratchRegister);
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, &done);
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kPrototypeOffset));
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(&done);
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Non-instance prototype: Fetch prototype from constructor field
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in initial map.
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&non_instance);
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kConstructorOffset));
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, ExternalReference(counter));
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(Operand(kScratchRegister, 0), Immediate(value));
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, ExternalReference(counter));
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand(kScratchRegister, 0);
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      incl(operand);
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addl(operand, Immediate(value));
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, ExternalReference(counter));
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand(kScratchRegister, 0);
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      decl(operand);
2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      subl(operand, Immediate(value));
2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
212580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef ENABLE_DEBUGGER_SUPPORT
2126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
2127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(allow_stub_calls());
2128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  xor_(rax, rax);  // no arguments
2129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rbx, ExternalReference(Runtime::kDebugBreak));
2130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub ces(1);
2131402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2133402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // ENABLE_DEBUGGER_SUPPORT
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Handle<Code> code_constant,
2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register code_register,
2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* done,
2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    InvokeFlag flag) {
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(actual.is_immediate());
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
21498defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Set(rax, actual.immediate());
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() ==
21513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for built-ins that
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
21588defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Set(rbx, expected.immediate());
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmpq(expected.reg(), Immediate(actual.immediate()));
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(expected.reg().is(rbx));
21698defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Set(rax, actual.immediate());
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmpq(expected.reg(), actual.reg());
2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(actual.reg().is(rax));
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(expected.reg().is(rbx));
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!code_constant.is_null()) {
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!code_register.is(rdx)) {
2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(rdx, code_register);
2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Call(adaptor, RelocInfo::CODE_TARGET);
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(done);
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Jump(adaptor, RelocInfo::CODE_TARGET);
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code,
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                InvokeFlag flag) {
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    call(code);
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    jmp(code);
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                RelocInfo::Mode rmode,
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                InvokeFlag flag) {
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register dummy = rax;
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InvokePrologue(expected, actual, code, dummy, &done, flag);
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Call(code, rmode);
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Jump(code, rmode);
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function,
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    InvokeFlag flag) {
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function.is(rdi));
2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movsxlq(rbx,
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Advances rdx to the end of the Code object header, to the start of
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the executable code.
2245791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(rbx);
2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InvokeCode(rdx, expected, actual, flag);
2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2252402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeFunction(JSFunction* function,
2253402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    InvokeFlag flag) {
2255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(function->is_compiled());
2256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
2257402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Move(rdi, Handle<JSFunction>(function));
2258402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2259402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2260402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Invoke the cached code.
2261402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Handle<Code> code(function->code());
2262402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(function->shared()->formal_parameter_count());
2263402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
2264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2265402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rsi);  // Context.
22713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Push(Smi::FromInt(type));
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister,
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Factory::undefined_value(),
2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         RelocInfo::EMBEDDED_OBJECT);
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rsp, 0), kScratchRegister);
2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "code object not properly patched");
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
22863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, Smi::FromInt(type));
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "stack frame types must match");
2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsp, rbp);
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pop(rbp);
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) {
2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the frame structure on the stack.
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All constants are relative to the frame pointer of the exit frame.
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
23053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
2306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
2307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
2308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(kScratchRegister);  // Accessed from EditFrame::code_slot.
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference context_address(Top::k_context_address);
2313bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (save_rax) {
2314bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    movq(r14, rax);  // Backup rax before we use it.
2315bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rax, rbp);
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  store_rax(c_entry_fp_address);
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rax, rsi);
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  store_rax(context_address);
2321bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFrameEpilogue(int result_size,
2324bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                            int argc) {
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserve space on stack for result and argument structures, if necessary.
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize;
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserve space for the Arguments object.  The Windows 64-bit ABI
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requires us to pass this structure as a pointer to its location on
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the stack.  The structure contains 2 values.
2331bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int argument_stack_space = argc * kPointerSize;
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We also need backing space for 4 parameters, even though
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // we only pass one or two parameter, and it is in a register.
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int argument_mirror_space = 4 * kPointerSize;
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total_stack_space =
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      argument_mirror_space + argument_stack_space + result_stack_space;
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  subq(rsp, Immediate(total_stack_space));
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kFrameAlignment = OS::ActivationFrameAlignment();
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(IsPowerOf2(kFrameAlignment));
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, Immediate(-kFrameAlignment));
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(rsp, kScratchRegister);
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
235380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFrame(int result_size) {
235480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(true);
2355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
2357bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
2358bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
2359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  lea(r12, Operand(rbp, r14, times_pointer_size, offset));
2360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
236180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFrameEpilogue(result_size, 2);
2362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2364bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
236580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterApiExitFrame(int stack_space,
2366bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int argc,
2367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int result_size) {
236880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(false);
2369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2370bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
2371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
2372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
2373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
2374bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
237580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFrameEpilogue(result_size, argc);
2376bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2377bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2378bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
237980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::LeaveExitFrame(int result_size) {
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Registers:
23818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r12 : argv
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the return address from the stack and restore the frame pointer.
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rcx, Operand(rbp, 1 * kPointerSize));
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, Operand(rbp, 0 * kPointerSize));
2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop everything up to and including the arguments and the receiver
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the caller stack.
23898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  lea(rsp, Operand(r12, 1 * kPointerSize));
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference context_address(Top::k_context_address);
2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, context_address);
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsi, Operand(kScratchRegister, 0));
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), Immediate(0));
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the return address to get ready to return.
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rcx);
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, c_entry_fp_address);
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), Immediate(0));
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(scratch));
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(kScratchRegister));
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(scratch, Immediate(0));
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "we should not have an empty lexical context");
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context of the current context.
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, offset));
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Factory::global_context_map());
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, &same_contexts);
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens.
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Preserve original value of holder_reg.
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "JSGlobalProxy::context() should not be null.");
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to global_context_map(),
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex);
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
24623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int token_offset =
24633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, token_offset));
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(kScratchRegister, token_offset));
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result_end,
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_top_address();
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
24826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!scratch.is_valid());
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, new_space_allocation_top);
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(result, Operand(kScratchRegister, 0));
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "Unexpected allocation top");
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Move address of new object to result. Use scratch register if available,
24936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and keep address in scratch until call to UpdateAllocationTopHelper.
24946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is_valid()) {
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!scratch.is(result_end));
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(scratch, new_space_allocation_top);
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result, Operand(scratch, 0));
24986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (result.is(rax)) {
24996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    load_rax(new_space_allocation_top);
25006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
25016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(kScratchRegister, new_space_allocation_top);
25026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(result, Operand(kScratchRegister, 0));
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               Register scratch) {
2509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (FLAG_debug_code) {
2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    testq(result_end, Immediate(kObjectAlignmentMask));
2511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Check(zero, "Unaligned allocation in new space");
2512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_top_address();
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top.
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result_end.is(rax)) {
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // rax can be stored directly to a memory location.
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    store_rax(new_space_allocation_top);
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Register required - use scratch provided if available.
25236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (scratch.is_valid()) {
25246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(Operand(scratch, 0), result_end);
25256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, new_space_allocation_top);
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(Operand(kScratchRegister, 0), result_end);
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadAllocationTopHelper(result, result_end, scratch, flags);
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_limit_address();
25476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register top_reg = result_end.is_valid() ? result_end : result;
25496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
25516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    addq(top_reg, Immediate(object_size));
25526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
25536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    lea(top_reg, Operand(result, object_size));
25546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_limit);
25566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(top_reg, Operand(kScratchRegister, 0));
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
25606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  UpdateAllocationTopHelper(top_reg, scratch);
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
25636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if ((flags & TAG_OBJECT) != 0) {
25646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size - kHeapObjectTag));
25656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
25666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size));
25676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
25686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if ((flags & TAG_OBJECT) != 0) {
25696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Tag the result if requested.
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size,
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        ScaleFactor element_size,
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register element_count,
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadAllocationTopHelper(result, result_end, scratch, flags);
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_limit_address();
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  lea(result_end, Operand(result, element_count, element_size, header_size));
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_limit);
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(result_end, Operand(kScratchRegister, 0));
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadAllocationTopHelper(result, result_end, scratch, flags);
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_limit_address();
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result_end, object_size);
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addq(result_end, result);
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_limit);
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(result_end, Operand(kScratchRegister, 0));
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_top_address();
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object has no tag before resetting top.
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(object, Immediate(~kHeapObjectTagMask));
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_top);
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(object, Operand(kScratchRegister, 0));
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(below, "Undo allocation of non allocated memory");
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), object);
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch,
26533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Label* gc_required) {
26543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
26553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  AllocateInNewSpace(HeapNumber::kSize,
26563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     result,
26573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     scratch,
26583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     no_reg,
26593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     gc_required,
26603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     TAG_OBJECT);
26613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
26623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
26633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
26643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
26653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
26663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
26673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result,
2669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register length,
2670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch1,
2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch2,
2672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch3,
2673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Label* gc_required) {
2674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
2675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
26766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
26776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
2678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kShortSize == 2);
2679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
26806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
26816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                kHeaderAlignment));
2682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
26836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
26846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
26856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate two byte string in new space.
2688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
2689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
2690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
2694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
2698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
2699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
27006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
27027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
2703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
2704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result,
2708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register length,
2709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch1,
2710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch2,
2711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch3,
2712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Label* gc_required) {
2713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
2714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqAsciiString::kHeaderSize &
27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
2717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movl(scratch1, length);
2718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kCharSize == 1);
27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
2720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
27226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
27236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate ascii string in new space.
2726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqAsciiString::kHeaderSize,
2727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
2728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
2732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
2736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
2737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
27386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
27396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
27407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
2741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateConsString(Register result,
2746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch1,
2747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch2,
2748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* gc_required) {
2749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
2750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
2751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
2758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
2759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result,
2764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch1,
2765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch2,
2766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Label* gc_required) {
2767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
2768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
2769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
2777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the function context (which is the incoming, outer context).
2786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
2789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
2790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // The context may be an intermediate context, not a function context.
2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {  // context is the current function context.
2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // The context may be an intermediate context, not a function context.
2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
27997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
28017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On Windows 64 stack slots are reserved by the caller for all arguments
28027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // including the ones passed in registers, and space is always allocated for
28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the four register arguments even if the function takes fewer than four
28047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // arguments.
28057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
28067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and the caller does not reserve stack slots for them.
28074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
28084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64
28097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kMinimumStackSlots = 4;
28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
28117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments;
28124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else
28137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kRegisterPassedArguments = 6;
28147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kRegisterPassedArguments) return 0;
28157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments - kRegisterPassedArguments;
28164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif
28174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
28184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
28214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int frame_alignment = OS::ActivationFrameAlignment();
28224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(frame_alignment != 0);
28234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
28244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Make stack end at alignment and allocate space for arguments and old rsp.
28254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(kScratchRegister, rsp);
28264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(IsPowerOf2(frame_alignment));
28274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
28284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
28294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize));
28304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  and_(rsp, Immediate(-frame_alignment));
28314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister);
28324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
28334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function,
28364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                   int num_arguments) {
28374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rax, function);
28384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallCFunction(rax, num_arguments);
28394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
28404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
28424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
28436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
28446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (FLAG_debug_code) {
28456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
28466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  call(function);
28494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(OS::ActivationFrameAlignment() != 0);
28504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
28514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
28524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
28534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
28544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
28554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size)
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : address_(address), size_(size), masm_(address, size + Assembler::kGap) {
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(address_, size_);
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.pc_ == address_ + size_);
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
2876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
2878