macro-assembler-x64.cc revision 756813857a4c2a4d8ad2e805969d5768d3cf43a0
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
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::FunctionForId(id), num_arguments);
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
400bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int num_arguments) {
401bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
402bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
403bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
404bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IllegalOperation(num_arguments);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
4154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
4164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
4174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
4188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
4194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rbx, ExternalReference(f));
4204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub ces(f->result_size);
4214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
425bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
426bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int num_arguments) {
427bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (f->nargs >= 0 && f->nargs != num_arguments) {
428bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    IllegalOperation(num_arguments);
429bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    // Since we did not call the stub, there was no allocation failure.
430bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    // Return some non-failure object.
431bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    return Heap::undefined_value();
432bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
433bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
434bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // TODO(1236192): Most runtime routines don't need the number of
435bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // arguments passed in because it is constant. At some point we
436bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // should remove this need and make the runtime routine entry code
437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // smarter.
438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Set(rax, num_arguments);
439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(rbx, ExternalReference(f));
440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CEntryStub ces(f->result_size);
441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return TryCallStub(&ces);
442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
4478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rbx, ext);
449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub stub(1);
451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8] : argument num_arguments - 1
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  ...
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1236192): Most runtime routines don't need the number of
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments passed in because it is constant. At some point we
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should remove this need and make the runtime routine entry code
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // smarter.
4698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpToExternalReference(ext, result_size);
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int num_arguments,
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int result_size) {
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
481bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic int Offset(ExternalReference ref0, ExternalReference ref1) {
482bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int64_t offset = (ref0.address() - ref1.address());
483bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Check that fits into int.
484bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(static_cast<int>(offset) == offset);
485bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return static_cast<int>(offset);
486bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
487bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
488bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
489bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PushHandleScope(Register scratch) {
490bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ExternalReference extensions_address =
491bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_extensions_address();
492bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kExtensionsOffset = 0;
493bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kNextOffset = Offset(
494bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_next_address(),
495bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
496bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kLimitOffset = Offset(
497bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_limit_address(),
498bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
499bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Push the number of extensions, smi-tagged so the gc will ignore it.
501bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(kScratchRegister, extensions_address);
502bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(scratch, Operand(kScratchRegister, kExtensionsOffset));
503bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
504bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Integer32ToSmi(scratch, scratch);
505bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(scratch);
506bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Push next and limit pointers which will be wordsize aligned and
507bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // hence automatically smi tagged.
508bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(Operand(kScratchRegister, kNextOffset));
509bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(Operand(kScratchRegister, kLimitOffset));
510bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
511bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
512bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
513bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::PopHandleScopeHelper(Register saved,
514bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                             Register scratch,
515bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                             bool gc_allowed) {
516bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ExternalReference extensions_address =
517bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_extensions_address();
518bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kExtensionsOffset = 0;
519bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kNextOffset = Offset(
520bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_next_address(),
521bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
522bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  const int kLimitOffset = Offset(
523bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      ExternalReference::handle_scope_limit_address(),
524bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      extensions_address);
525bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
526bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* result = NULL;
527bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label write_back;
528bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(kScratchRegister, extensions_address);
529bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
530bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  j(equal, &write_back);
531bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  push(saved);
532bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (gc_allowed) {
533bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
534bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
535bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
536bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (result->IsFailure()) return result;
537bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
538bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(saved);
539bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(kScratchRegister, extensions_address);
540bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
541bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  bind(&write_back);
542bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(Operand(kScratchRegister, kLimitOffset));
543bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(Operand(kScratchRegister, kNextOffset));
544bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  pop(scratch);
545bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  SmiToInteger32(scratch, scratch);
546bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  movq(Operand(kScratchRegister, kExtensionsOffset), scratch);
547bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
548bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return result;
549bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
550bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
551bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
552bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::PopHandleScope(Register saved, Register scratch) {
553bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  PopHandleScopeHelper(saved, scratch, true);
554bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
555bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
556bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
557bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
558bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return PopHandleScopeHelper(saved, scratch, false);
559bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
560bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
561bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             int result_size) {
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbx, ext);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub ces(result_size);
5673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Calls are not allowed in some stubs.
573402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Rely on the assertion to check that the number of provided
576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // arguments match the expected number of arguments. Fake a
577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // parameter count to avoid emitting code to do the check.
578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GetBuiltinEntry(rdx, id);
580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  InvokeCode(rdx, expected, expected, flag);
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
583402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!target.is(rdi));
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the builtins object into target register.
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Load the JavaScript builtin function from the builtins object.
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(rdi, FieldOperand(target, JSBuiltinsObject::OffsetOfFunctionWithId(id)));
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the code entry point from the builtins object.
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(target, FieldOperand(target, JSBuiltinsObject::OffsetOfCodeWithId(id)));
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (FLAG_debug_code) {
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make sure the code objects in the builtins object and in the
5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // builtin function are the same.
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    push(target);
600756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    movq(target, FieldOperand(rdi, JSFunction::kCodeOffset));
6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    cmpq(target, Operand(rsp, 0));
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Assert(equal, "Builtin code object changed");
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pop(target);
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(target, FieldOperand(target, Code::kHeaderSize));
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) {
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x == 0) {
6118defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_int32(x)) {
613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Immediate(static_cast<int32_t>(x)));
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_uint32(x)) {
615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movl(dst, Immediate(static_cast<uint32_t>(x)));
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, x, RelocInfo::NONE);
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(const Operand& dst, int64_t x) {
6229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (is_int32(x)) {
623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Immediate(static_cast<int32_t>(x)));
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, x, RelocInfo::NONE);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection.
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic int kSmiShift = kSmiTagSize + kSmiShiftSize;
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6358defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) {
6368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
6378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 0) {
6388defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(kScratchRegister, kScratchRegister);
6398defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kScratchRegister;
6408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6418defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 1) {
6428defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kSmiConstantRegister;
6438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(kScratchRegister, source);
6458defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return kScratchRegister;
6468defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
6478defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6488defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
6498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (FLAG_debug_code) {
6508defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(dst,
6518defd9ff6930b4e24729971a61cf7469daf119beSteve Block         reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
6528defd9ff6930b4e24729971a61cf7469daf119beSteve Block         RelocInfo::NONE);
6538defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmpq(dst, kSmiConstantRegister);
6548defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (allow_stub_calls()) {
6558defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Assert(equal, "Uninitialized kSmiConstantRegister");
6568defd9ff6930b4e24729971a61cf7469daf119beSteve Block    } else {
6578defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Label ok;
6588defd9ff6930b4e24729971a61cf7469daf119beSteve Block      j(equal, &ok);
6598defd9ff6930b4e24729971a61cf7469daf119beSteve Block      int3();
6608defd9ff6930b4e24729971a61cf7469daf119beSteve Block      bind(&ok);
6618defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
6628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6638defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (source->value() == 0) {
6648defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
6658defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
6668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
6678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
6688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bool negative = value < 0;
6698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  unsigned int uvalue = negative ? -value : value;
6708defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  switch (uvalue) {
6728defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 9:
6738defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
6748defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 8:
6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
6778defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
6788defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6798defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 4:
6808defd9ff6930b4e24729971a61cf7469daf119beSteve Block      xorl(dst, dst);
6818defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
6828defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6838defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 5:
6848defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
6858defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6868defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 3:
6878defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
6888defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6898defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 2:
6908defd9ff6930b4e24729971a61cf7469daf119beSteve Block      lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
6918defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6928defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 1:
6938defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, kSmiConstantRegister);
6948defd9ff6930b4e24729971a61cf7469daf119beSteve Block      break;
6958defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 0:
6968defd9ff6930b4e24729971a61cf7469daf119beSteve Block      UNREACHABLE();
6978defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
6988defd9ff6930b4e24729971a61cf7469daf119beSteve Block    default:
6998defd9ff6930b4e24729971a61cf7469daf119beSteve Block      movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE);
7008defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return;
7018defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
7028defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (negative) {
7038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    neg(dst);
7048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
7058defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
7068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
7093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movl(dst, src);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Integer32ToSmi(Register dst,
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register src,
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* on_overflow) {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
7203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 32-bit integer always fits in a long smi.
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(dst, src);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
7299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (FLAG_debug_code) {
7309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    testb(dst, Immediate(0x01));
7319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Label ok;
7329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(zero, &ok);
7339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (allow_stub_calls()) {
7349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Abort("Integer32ToSmiField writing to non-smi location");
7359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
7369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      int3();
7379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
7389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bind(&ok);
7399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
7409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(kSmiShift % kBitsPerByte == 0);
7419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movl(Operand(dst, kSmiShift / kBitsPerByte), src);
7429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
7439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Register src,
7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                int constant) {
7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
7493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    addq(dst, Immediate(constant));
7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
7513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    lea(dst, Operand(src, constant));
7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shr(dst, Immediate(kSmiShift));
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
7677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movl(dst, Operand(src, kSmiShift / kBitsPerByte));
7687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
7697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
7707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  sar(dst, Immediate(kSmiShift));
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
7819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
7829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
7839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) {
7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src, src);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Register src) {
7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpq(dst, src);
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src->value() == 0) {
7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
800756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Register constant_reg = GetSmiConstant(src);
801756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmpq(dst, constant_reg);
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(dst, src);
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpq(dst, src);
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
8177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
8229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
8239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
8249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           Register src,
8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           int power) {
8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power >= 0);
8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(power < 64);
8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power == 0) {
8323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src);
8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return;
8343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
8363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power < kSmiShift) {
8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - power));
8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (power > kSmiShift) {
8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(power - kSmiShift));
8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
8477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         Register src,
8487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         int power) {
8497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((0 <= power) && (power < 32));
8507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (dst.is(src)) {
8517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    shr(dst, Immediate(power + kSmiShift));
8527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
8537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    UNIMPLEMENTED();  // Not used.
8547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
8557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
8567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) {
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(src, Immediate(kSmiTagMask));
8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckPositiveSmi(Register src) {
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Make mask 0x8000000000000001 and test that both bits are zero.
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(kScratchRegister, src);
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  rol(kScratchRegister, Immediate(1));
8708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(3));
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return zero;
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first.is(second)) {
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CheckSmi(first);
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
8808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  leal(kScratchRegister, Operand(first, second, times_1, 0));
8818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(0x03));
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::CheckBothPositiveSmi(Register first,
887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                               Register second) {
888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (first.is(second)) {
889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return CheckPositiveSmi(first);
890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block  movq(kScratchRegister, first);
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  or_(kScratchRegister, second);
893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  rol(kScratchRegister, Immediate(1));
894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testl(kScratchRegister, Immediate(0x03));
895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
897d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
899bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first,
900bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register second,
901bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register scratch) {
902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (first.is(second)) {
903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return CheckSmi(first);
904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
905bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (scratch.is(second)) {
906bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, first);
907bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
908bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (!scratch.is(first)) {
909bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      movl(scratch, first);
910bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
911bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, second);
912bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
913bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  testb(scratch, Immediate(kSmiTagMask));
914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckIsMinSmi(Register src) {
9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!src.is(kScratchRegister));
9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If we overflow by subtracting one, it's the minimal smi value.
9218defd9ff6930b4e24729971a61cf7469daf119beSteve Block  cmpq(src, kSmiConstantRegister);
9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return overflow;
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
9273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // A 32-bit integer value can always be converted to a smi.
9283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return always;
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // An unsigned 32-bit integer value is valid as long as the high bit
9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // is not set.
9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testl(src, src);
9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return positive;
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiNeg(Register dst, Register src, Label* on_smi_result) {
9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src);
9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    neg(dst);  // Low 32 bits are retained as zero by negation.
9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Test if result is zero or Smi::kMinValue.
9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, kScratchRegister);
9473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_equal, on_smi_result);
9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src, kScratchRegister);
9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
9513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    neg(dst);
9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, src);
9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_equal, on_smi_result);
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAdd(Register dst,
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (on_not_smi_result == NULL) {
9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // No overflow checking. Use only when it's known that
9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // overflowing is impossible.
9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (dst.is(src1)) {
9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      addq(dst, src2);
9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(dst, src1);
9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      addq(dst, src2);
9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Assert(no_overflow, "Smi addition overflow");
9746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (dst.is(src1)) {
9759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(kScratchRegister, src1);
9769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    addq(kScratchRegister, src2);
9779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
9789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(dst, kScratchRegister);
9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    addq(dst, src2);
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSub(Register dst,
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
992d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (on_not_smi_result == NULL) {
993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // No overflow checking. Use only when it's known that
994d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // overflowing is impossible (e.g., subtracting two positive smis).
995d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (dst.is(src1)) {
996d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      subq(dst, src2);
997d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
998d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      movq(dst, src1);
999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      subq(dst, src2);
1000d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
10019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Assert(no_overflow, "Smi subtraction overflow");
1002d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (dst.is(src1)) {
10039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    cmpq(dst, src2);
10049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    subq(dst, src2);
10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    subq(dst, src2);
10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::SmiSub(Register dst,
10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            Register src1,
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            const Operand& src2,
10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            Label* on_not_smi_result) {
10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (on_not_smi_result == NULL) {
10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // No overflow checking. Use only when it's known that
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // overflowing is impossible (e.g., subtracting two positive smis).
10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (dst.is(src1)) {
10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(dst, src2);
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(dst, src1);
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(dst, src2);
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Assert(no_overflow, "Smi subtraction overflow");
10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (dst.is(src1)) {
10298defd9ff6930b4e24729971a61cf7469daf119beSteve Block    movq(kScratchRegister, src2);
10308defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmpq(src1, kScratchRegister);
10319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
10328defd9ff6930b4e24729971a61cf7469daf119beSteve Block    subq(src1, kScratchRegister);
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(dst, src1);
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(dst, src2);
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    j(overflow, on_not_smi_result);
10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMul(Register dst,
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
10453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
10473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src1)) {
10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label failure, zero_correct_result;
10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);  // Create backup for later testing.
10523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src1);
10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    imul(dst, src2);
10543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, &failure);
10553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Check for negative zero result.  If product is zero, and one
10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // argument is negative, go to slow case.
10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label correct_result;
10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_zero, &correct_result);
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, kScratchRegister);
10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, src2);
10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(positive, &zero_correct_result);  // Result was positive zero.
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&failure);  // Reused failure exit, restores src1.
10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&zero_correct_result);
10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, dst);
10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&correct_result);
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src1);
10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    imul(dst, src2);
10773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
10783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Check for negative zero result.  If product is zero, and one
10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // argument is negative, go to slow case.
10803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label correct_result;
10813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    testq(dst, dst);
10823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_zero, &correct_result);
10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // One of src1 and src2 is zero, the check whether the other is
10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // negative.
10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(kScratchRegister, src2);
10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(negative, on_not_smi_result);
10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&correct_result);
10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiTryAddConstant(Register dst,
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register src,
10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       Smi* constant,
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Label* on_not_smi_result) {
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Does not assume that src is a smi.
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask));
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src.is(kScratchRegister));
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  JumpIfNotSmi(src, on_not_smi_result);
11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Register tmp = (dst.is(src) ? kScratchRegister : dst);
11058defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(tmp, constant);
11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  addq(tmp, src);
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(overflow, on_not_smi_result);
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, tmp);
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
11198defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
11228defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
11238defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
11248defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, kSmiConstantRegister);
11258defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11268defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
11278defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
11288defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11298defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
11308defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
11318defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11328defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
11338defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
11348defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11358defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
11368defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Register constant_reg = GetSmiConstant(constant);
11378defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, constant_reg);
11388defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11398defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
11418defd9ff6930b4e24729971a61cf7469daf119beSteve Block    switch (constant->value()) {
11428defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 1:
11438defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_1, 0));
11448defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11458defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 2:
11468defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
11478defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11488defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 4:
11498defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
11508defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11518defd9ff6930b4e24729971a61cf7469daf119beSteve Block      case 8:
11528defd9ff6930b4e24729971a61cf7469daf119beSteve Block        lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block      default:
11558defd9ff6930b4e24729971a61cf7469daf119beSteve Block        LoadSmiConstant(dst, constant);
11568defd9ff6930b4e24729971a61cf7469daf119beSteve Block        addq(dst, src);
11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block        return;
11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (constant->value() != 0) {
11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
1166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAddConstant(Register dst,
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register src,
11723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Smi* constant,
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* on_not_smi_result) {
11743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
11753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
11763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
11783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
11793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11818defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(kScratchRegister, constant);
11828defd9ff6930b4e24729971a61cf7469daf119beSteve Block    addq(kScratchRegister, src);
11839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    j(overflow, on_not_smi_result);
11849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    movq(dst, kScratchRegister);
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
11868defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    addq(dst, src);
11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(overflow, on_not_smi_result);
11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
11943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!dst.is(src)) {
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
12008defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
12018defd9ff6930b4e24729971a61cf7469daf119beSteve Block    subq(dst, constant_reg);
12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
12048defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
12059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
12069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
12079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(dst, src);
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
12099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
12108defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      addq(dst, src);
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiSubConstant(Register dst,
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register src,
12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Smi* constant,
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* on_not_smi_result) {
12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(dst, src);
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
12253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
12273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
12289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtracting min-value from any non-negative value will overflow.
12299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // We test the non-negativeness before doing the subtraction.
12309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      testq(src, src);
12319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      j(not_sign, on_not_smi_result);
12328defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(kScratchRegister, constant);
12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      subq(dst, kScratchRegister);
12349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
12359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
12368defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value()));
12379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(kScratchRegister, dst);
12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      j(overflow, on_not_smi_result);
12399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      movq(dst, kScratchRegister);
12409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
12419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
12429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (constant->value() == Smi::kMinValue) {
12439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtracting min-value from any non-negative value will overflow.
12449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // We test the non-negativeness before doing the subtraction.
12459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      testq(src, src);
12469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      j(not_sign, on_not_smi_result);
12478defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
12489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
12499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
12509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      addq(dst, src);
12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
12529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
12538defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      addq(dst, src);
12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      j(overflow, on_not_smi_result);
12563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiDiv(Register dst,
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rax));
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rdx));
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src1.is(rdx));
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for 0 divisor (result is +/-Infinity).
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label positive_divisor;
12743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src2, src2);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, on_not_smi_result);
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
12803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rax, src1);
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We need to rule out dividing Smi::kMinValue by -1, since that would
12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // overflow in idiv and raise an exception.
12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We combine this with negative zero test (negative zero only happens
12843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // when dividing zero by a negative number).
12853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // We overshoot a little and go to slow case if we divide min-value
12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // by any negative value, not just -1.
12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label safe_div;
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testl(rax, Immediate(0x7fffffff));
12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_zero, &safe_div);
12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src2, src2);
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(positive, &safe_div);
12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(negative, on_not_smi_result);
12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&safe_div);
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(src2, src2);
13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Sign extend src1 into edx:eax.
13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cdq();
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  idivl(src2);
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(src2, src2);
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the remainder is zero.
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(rdx, rdx);
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label smi_result;
13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(zero, &smi_result);
13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&smi_result);
13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(not_zero, on_not_smi_result);
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1) && src1.is(rax)) {
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Integer32ToSmi(dst, rax);
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiMod(Register dst,
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src2,
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* on_not_smi_result) {
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(kScratchRegister));
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src1.is(kScratchRegister));
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(kScratchRegister));
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rax));
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src2.is(rdx));
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!src1.is(rdx));
13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(src2));
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src2, src2);
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, on_not_smi_result);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (src1.is(rax)) {
13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rax, src1);
13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(src2, src2);
13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label safe_div;
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpl(rax, Immediate(Smi::kMinValue));
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_equal, &safe_div);
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cmpl(src2, Immediate(-1));
13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_equal, &safe_div);
13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Retag inputs and go slow case.
13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(src2, src2);
13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rax)) {
13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(on_not_smi_result);
13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&safe_div);
13583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign extend eax into edx:eax.
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cdq();
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  idivl(src2);
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore smi tags on inputs.
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(src2, src2);
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (src1.is(rax)) {
13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check for a negative zero result.  If the result is zero, and the
13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // dividend is negative, go slow to return a floating point negative zero.
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label smi_result;
13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testl(rdx, rdx);
13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(not_zero, &smi_result);
13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(src1, src1);
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(negative, on_not_smi_result);
13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&smi_result);
13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Integer32ToSmi(dst, rdx);
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) {
13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src.is(kScratchRegister));
13823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set tag and padding bits before negating, so that they are zero afterwards.
13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movl(kScratchRegister, Immediate(~0));
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
13853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, kScratchRegister);
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    lea(dst, Operand(src, kScratchRegister, times_1, 0));
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_(dst);
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(src2));
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
13963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(dst, src2);
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
14033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
14043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, dst);
14053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
14063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14078defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14088defd9ff6930b4e24729971a61cf7469daf119beSteve Block    and_(dst, constant_reg);
14093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
14113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    and_(dst, src);
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  or_(dst, src2);
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
14263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14278defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14288defd9ff6930b4e24729971a61cf7469daf119beSteve Block    or_(dst, constant_reg);
14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14308defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
14313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    or_(dst, src);
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src2);
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
14463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(!dst.is(kScratchRegister));
14478defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
14488defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xor_(dst, constant_reg);
14493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
14508defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
14513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    xor_(dst, src);
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Register src,
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     int shift_value) {
14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(is_uint5(shift_value));
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_value > 0) {
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (dst.is(src)) {
14623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      sar(dst, Immediate(shift_value + kSmiShift));
14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      shl(dst, Immediate(kSmiShift));
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // Not used.
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRightConstant(Register dst,
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Register src,
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  int shift_value,
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Label* on_not_smi_result) {
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Logic right shift interprets its result as an *unsigned* number.
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNIMPLEMENTED();  // Not used.
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
14793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
14803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (shift_value == 0) {
14813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      testq(dst, dst);
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(negative, on_not_smi_result);
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
14843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shr(dst, Immediate(shift_value + kSmiShift));
14853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(kSmiShift));
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src,
149225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                          int shift_value) {
14933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
14943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
14953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift_value > 0) {
14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift_value));
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst,
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
150425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                  Register src2) {
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label result_ok;
15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Untag shift amount.
15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
15093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiToInteger32(rcx, src2);
15123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Shift amount specified by lower 5 bits, not six as the shl opcode.
15133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  and_(rcx, Immediate(0x1f));
1514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  shl_cl(dst);
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src1,
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src2,
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Label* on_not_smi_result) {
15223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
15233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
15243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label result_ok;
15273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx) || src2.is(rcx)) {
15283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, rcx);
15293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
15313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
15323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
15343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  orl(rcx, Immediate(kSmiShift));
1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  shr_cl(dst);  // Shift is rcx modulo 0x1f + 32.
15363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
15373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  testq(dst, dst);
15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx) || src2.is(rcx)) {
15393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label positive_result;
15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(positive, &positive_result);
15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (src1.is(rcx)) {
15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(src1, kScratchRegister);
15433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
15443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      movq(src2, kScratchRegister);
15453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    jmp(on_not_smi_result);
15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bind(&positive_result);
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    j(negative, on_not_smi_result);  // src2 was zero and src1 negative.
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src1,
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src2) {
15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
15583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(rcx));
15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src1);
15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(kScratchRegister, src2);
15653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src1)) {
15673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src1);
15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  orl(rcx, Immediate(kSmiShift));
1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  sar_cl(dst);  // Shift 32 + original rcx & 0x1f.
15723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  shl(dst, Immediate(kSmiShift));
15733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src1.is(rcx)) {
15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src1, kScratchRegister);
15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (src2.is(rcx)) {
15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(src2, kScratchRegister);
15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SelectNonSmi(Register dst,
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src2,
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Label* on_not_smis) {
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!dst.is(kScratchRegister));
15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src1.is(kScratchRegister));
15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!src2.is(kScratchRegister));
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src1));
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(src2));
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Both operands must not be smis.
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (allow_stub_calls()) {  // Check contains a stub call.
15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
15943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Check(not_both_smis, "Both registers were smis in SelectNonSmi.");
15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, kSmiTag);
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, Smi::FromInt(0));
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movl(kScratchRegister, Immediate(kSmiTagMask));
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(kScratchRegister, src1);
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(kScratchRegister, src2);
16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // If non-zero then both are smis.
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_zero, on_not_smis);
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Exactly one operand is a smi.
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1, static_cast<int>(kSmiTagMask));
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  subq(kScratchRegister, Immediate(1));
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(dst, src1);
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src2);
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(dst, kScratchRegister);
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  xor_(dst, src1);
16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16188defd9ff6930b4e24729971a61cf7469daf119beSteve Block
16193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst,
16203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Register src,
16213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    int shift) {
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
16233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // There is a possible optimization if shift is in the range 60-63, but that
16243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // will (and must) never happen.
16253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
16263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
16293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register src,
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            int shift) {
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register src holds a positive smi.
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint6(shift));
16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    movq(dst, src);
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  neg(dst);
16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (shift < kSmiShift) {
16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    sar(dst, Immediate(kSmiShift - shift));
16473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
16483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shl(dst, Immediate(shift - kSmiShift));
16493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SmiIndex(dst, times_1);
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmi(Register src, Label* on_smi) {
16553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT_EQ(0, kSmiTag);
16563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition smi = CheckSmi(src);
16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(smi, on_smi);
16583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) {
16623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition smi = CheckSmi(src);
16633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(smi), on_not_smi);
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotPositiveSmi(Register src,
16683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                          Label* on_not_positive_smi) {
16693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition positive_smi = CheckPositiveSmi(src);
16703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(positive_smi), on_not_positive_smi);
16713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
16753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                             Smi* constant,
16763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                             Label* on_equals) {
16773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiCompare(src, constant);
16783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(equal, on_equals);
16793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) {
16833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition is_valid = CheckInteger32ValidSmiValue(src);
16843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(is_valid), on_invalid);
16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Label* on_invalid) {
16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition is_valid = CheckUInteger32ValidSmiValue(src);
16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(is_valid), on_invalid);
16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::JumpIfNotBothSmi(Register src1, Register src2,
16963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      Label* on_not_both_smi) {
16973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition both_smi = CheckBothSmi(src1, src2);
16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  j(NegateCondition(both_smi), on_not_both_smi);
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothPositiveSmi(Register src1, Register src2,
1703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                              Label* on_not_both_smi) {
1704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Condition both_smi = CheckBothPositiveSmi(src1, src2);
1705d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  j(NegateCondition(both_smi), on_not_both_smi);
1706d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1707d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1709d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object,
1711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Register second_object,
1712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Register scratch1,
1713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Register scratch2,
1714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                                         Label* on_fail) {
1715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that both objects are not smis.
1716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition either_smi = CheckEitherSmi(first_object, second_object);
1717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  j(either_smi, on_fail);
1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load instance type for both strings.
1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
1721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that both are flat ascii strings.
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kNotStringTag != 0);
1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const int kFlatAsciiStringMask =
1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
1729d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
1730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  andl(scratch1, Immediate(kFlatAsciiStringMask));
1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  andl(scratch2, Immediate(kFlatAsciiStringMask));
1733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Interleave the bits to check both scratch1 and scratch2 in one test.
1734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  cmpl(scratch1,
1737d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  j(not_equal, on_fail);
1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
17426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
17436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register instance_type,
17446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch,
17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label *failure) {
17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!scratch.is(instance_type)) {
17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movl(scratch, instance_type);
17486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
17496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kFlatAsciiStringMask =
17516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
17526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  andl(scratch, Immediate(kFlatAsciiStringMask));
17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  j(not_equal, failure);
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register first_object_instance_type,
17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register second_object_instance_type,
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch1,
17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch2,
17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* on_fail) {
17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load instance type for both strings.
17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(scratch1, first_object_instance_type);
17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(scratch2, second_object_instance_type);
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that both are flat ascii strings.
17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(kNotStringTag != 0);
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kFlatAsciiStringMask =
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  andl(scratch1, Immediate(kFlatAsciiStringMask));
17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  andl(scratch2, Immediate(kFlatAsciiStringMask));
17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Interleave the bits to check both scratch1 and scratch2 in one test.
17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpl(scratch1,
17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  j(not_equal, on_fail);
17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!source->IsFailure());
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
17893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, source, RelocInfo::EMBEDDED_OBJECT);
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(!source->IsFailure());
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(dst, kScratchRegister);
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
18083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (source->IsSmi()) {
18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiCompare(dst, Smi::cast(*source));
18103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, source);
18123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    cmpq(dst, kScratchRegister);
18133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
18193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiCompare(dst, Smi::cast(*source));
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(dst, kScratchRegister);
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Handle<Object> source) {
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
18303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Push(Smi::cast(*source));
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(source->IsHeapObject());
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(kScratchRegister);
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Push(Smi* source) {
18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  intptr_t smi = reinterpret_cast<intptr_t>(source);
18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (is_int32(smi)) {
18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    push(Immediate(static_cast<int32_t>(smi)));
18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
18448defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant = GetSmiConstant(source);
18458defd9ff6930b4e24729971a61cf7469daf119beSteve Block    push(constant);
18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int stack_elements) {
1851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (stack_elements > 0) {
1852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    addq(rsp, Immediate(stack_elements * kPointerSize));
1853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1854e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Test(const Operand& src, Smi* source) {
1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  testl(Operand(src, kIntSize), Immediate(source->value()));
1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) {
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, ext);
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
18753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Inline this
18763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(code_object, rmode);
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) {
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, ext);
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, destination, rmode);
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(RelocInfo::IsCodeTarget(rmode));
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WriteRecordedPositions();
18953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  call(code_object, rmode);
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location,
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    HandlerType type) {
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The pc (return address) is already on TOS.  This code pushes state,
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // frame pointer and current handler.  Check that they are expected
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // next on the stack, in that order.
1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(StackHandlerConstants::kStateOffset,
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            StackHandlerConstants::kPCOffset - kPointerSize);
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(StackHandlerConstants::kFPOffset,
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            StackHandlerConstants::kStateOffset - kPointerSize);
1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(StackHandlerConstants::kNextOffset,
1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            StackHandlerConstants::kFPOffset - kPointerSize);
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_location == IN_JAVASCRIPT) {
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (type == TRY_CATCH_HANDLER) {
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Immediate(StackHandler::TRY_CATCH));
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Immediate(StackHandler::TRY_FINALLY));
1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(rbp);
1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(try_location == IN_JS_ENTRY);
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The frame pointer does not point to a JS frame so we save NULL
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // for rbp. We expect the code throwing an exception to check rbp
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // before dereferencing it to restore the context.
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(Immediate(StackHandler::ENTRY));
1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(Immediate(0));  // NULL frame pointer.
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the current handler.
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(Operand(kScratchRegister, 0));
1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Link this handler.
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), rsp);
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() {
1938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
1939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Unlink this handler.
1940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
1941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  pop(Operand(kScratchRegister, 0));
1942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Remove the remaining fields.
1943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
1944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
19533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  fucomip();
19548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  fstp(0);
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       Immediate(static_cast<int8_t>(type)));
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
19733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
19743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
19753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              bool is_heap_object) {
19763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (!is_heap_object) {
19773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    JumpIfSmi(obj, fail);
19783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
19793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
19803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
19813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotNumber(Register object) {
1985402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label ok;
1986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Condition is_smi = CheckSmi(object);
1987402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  j(is_smi, &ok);
1988402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Cmp(FieldOperand(object, HeapObject::kMapOffset),
1989402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      Factory::heap_number_map());
1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Assert(equal, "Operand not a number");
1991402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  bind(&ok);
1992402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1994402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1995756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) {
1996756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label ok;
1997756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Condition is_smi = CheckSmi(object);
1998756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(NegateCondition(is_smi), "Operand is a smi");
1999756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2000756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2001756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::AbortIfNotSmi(Register object) {
20036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label ok;
20046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Condition is_smi = CheckSmi(object);
2005756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(is_smi, "Operand is not a smi");
20066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
20076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AbortIfNotRootValue(Register src,
20109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         Heap::RootListIndex root_value_index,
20119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                         const char* message) {
20129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!src.is(kScratchRegister));
20139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  LoadRoot(kScratchRegister, root_value_index);
20149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  cmpq(src, kScratchRegister);
20159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Check(equal, message);
20169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
20179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
20189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
20199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
2021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register map,
2022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register instance_type) {
2023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
20244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
2025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(kNotStringTag != 0);
2026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testb(instance_type, Immediate(kIsNotStringMask));
2027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
2028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result,
2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Label* miss) {
2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(function, Immediate(kSmiTagMask));
2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(zero, miss);
2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(function, JS_FUNCTION_TYPE, result);
2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function has an instance prototype.
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_instance;
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(FieldOperand(result, Map::kBitFieldOffset),
2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Immediate(1 << Map::kHasNonInstancePrototype));
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_zero, &non_instance);
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result,
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareRoot(result, Heap::kTheHoleValueRootIndex);
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, miss);
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, kScratchRegister);
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, &done);
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kPrototypeOffset));
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(&done);
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Non-instance prototype: Fetch prototype from constructor field
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in initial map.
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&non_instance);
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(result, FieldOperand(result, Map::kConstructorOffset));
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, ExternalReference(counter));
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(Operand(kScratchRegister, 0), Immediate(value));
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, ExternalReference(counter));
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand(kScratchRegister, 0);
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      incl(operand);
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addl(operand, Immediate(value));
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, ExternalReference(counter));
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Operand operand(kScratchRegister, 0);
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      decl(operand);
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      subl(operand, Immediate(value));
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRegistersFromMemory(RegList regs) {
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((regs & ~kJSCallerSaved) == 0);
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the content of the memory location to the stack.
2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kNumJSCallerSaved; i++) {
2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int r = JSCallerSavedCode(i);
2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((regs & (1 << r)) != 0) {
2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference reg_addr =
2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ExternalReference(Debug_Address::Register(i));
2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, reg_addr);
2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      push(Operand(kScratchRegister, 0));
2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SaveRegistersToMemory(RegList regs) {
2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((regs & ~kJSCallerSaved) == 0);
2131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy the content of registers to memory location.
2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kNumJSCallerSaved; i++) {
2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int r = JSCallerSavedCode(i);
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((regs & (1 << r)) != 0) {
2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Register reg = { r };
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference reg_addr =
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ExternalReference(Debug_Address::Register(i));
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, reg_addr);
2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(Operand(kScratchRegister, 0), reg);
2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((regs & ~kJSCallerSaved) == 0);
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy the content of memory location to registers.
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int r = JSCallerSavedCode(i);
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((regs & (1 << r)) != 0) {
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Register reg = { r };
2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference reg_addr =
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ExternalReference(Debug_Address::Register(i));
2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, reg_addr);
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(reg, Operand(kScratchRegister, 0));
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PopRegistersToMemory(RegList regs) {
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((regs & ~kJSCallerSaved) == 0);
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop the content from the stack to the memory location.
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int r = JSCallerSavedCode(i);
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((regs & (1 << r)) != 0) {
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference reg_addr =
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ExternalReference(Debug_Address::Register(i));
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, reg_addr);
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      pop(Operand(kScratchRegister, 0));
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CopyRegistersFromStackToMemory(Register base,
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                    Register scratch,
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                    RegList regs) {
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(kScratchRegister));
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!base.is(kScratchRegister));
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!base.is(scratch));
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((regs & ~kJSCallerSaved) == 0);
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy the content of the stack to the memory location and adjust base.
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int r = JSCallerSavedCode(i);
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((regs & (1 << r)) != 0) {
2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(scratch, Operand(base, 0));
2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference reg_addr =
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ExternalReference(Debug_Address::Register(i));
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, reg_addr);
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(Operand(kScratchRegister, 0), scratch);
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      lea(base, Operand(base, kPointerSize));
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2197402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
2198402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(allow_stub_calls());
2199402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  xor_(rax, rax);  // no arguments
2200402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rbx, ExternalReference(Runtime::kDebugBreak));
2201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub ces(1);
2202402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2204402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // ENABLE_DEBUGGER_SUPPORT
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Handle<Code> code_constant,
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register code_register,
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* done,
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    InvokeFlag flag) {
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke;
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(actual.is_immediate());
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
22208defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Set(rax, actual.immediate());
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() ==
22223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for built-ins that
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
22298defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Set(rbx, expected.immediate());
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Expected is in register, actual is immediate. This is the
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // case when we invoke function values without going through the
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IC mechanism.
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmpq(expected.reg(), Immediate(actual.immediate()));
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(expected.reg().is(rbx));
22408defd9ff6930b4e24729971a61cf7469daf119beSteve Block      Set(rax, actual.immediate());
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!expected.reg().is(actual.reg())) {
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Both expected and actual are in (different) registers. This
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // is the case when we invoke functions using call and apply.
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmpq(expected.reg(), actual.reg());
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      j(equal, &invoke);
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(actual.reg().is(rax));
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(expected.reg().is(rbx));
2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!code_constant.is_null()) {
2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (!code_register.is(rdx)) {
2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(rdx, code_register);
2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Call(adaptor, RelocInfo::CODE_TARGET);
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jmp(done);
2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Jump(adaptor, RelocInfo::CODE_TARGET);
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&invoke);
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code,
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                InvokeFlag flag) {
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    call(code);
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    jmp(code);
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                RelocInfo::Mode rmode,
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                InvokeFlag flag) {
2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register dummy = rax;
2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InvokePrologue(expected, actual, code, dummy, &done, flag);
2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Call(code, rmode);
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Jump(code, rmode);
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register function,
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    InvokeFlag flag) {
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function.is(rdi));
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movsxlq(rbx,
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
2314756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Advances rdx to the end of the Code object header, to the start of
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the executable code.
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(rbx);
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InvokeCode(rdx, expected, actual, flag);
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeFunction(JSFunction* function,
2325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
2326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    InvokeFlag flag) {
2327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(function->is_compiled());
2328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
2329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Move(rdi, Handle<JSFunction>(function));
2330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Invoke the cached code.
2333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Handle<Code> code(function->code());
2334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(function->shared()->formal_parameter_count());
2335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
2336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rsi);  // Context.
23433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Push(Smi::FromInt(type));
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(kScratchRegister);
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister,
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Factory::undefined_value(),
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         RelocInfo::EMBEDDED_OBJECT);
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rsp, 0), kScratchRegister);
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "code object not properly patched");
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
23583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, Smi::FromInt(type));
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "stack frame types must match");
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsp, rbp);
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pop(rbp);
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode,
2368bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                            bool save_rax) {
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the frame structure on the stack.
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All constants are relative to the frame pointer of the exit frame.
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rbp);
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, rsp);
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserve room for entry stack pointer and push the debug marker.
23783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
2379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(Immediate(0));  // Saved entry sp, patched before call.
2380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
2381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  push(kScratchRegister);  // Accessed from EditFrame::code_slot.
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference context_address(Top::k_context_address);
2386bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (save_rax) {
2387bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    movq(r14, rax);  // Backup rax before we use it.
2388bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rax, rbp);
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  store_rax(c_entry_fp_address);
2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rax, rsi);
2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  store_rax(context_address);
2394bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2396bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode,
2397bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                            int result_size,
2398bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                            int argc) {
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the state of all registers to the stack from the memory
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // location. This is needed to allow nested break points.
2402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (mode == ExitFrame::MODE_DEBUG) {
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // TODO(1243899): This should be symmetric to
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // correct here, but computed for the other call. Very error
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // prone! FIX THIS.  Actually there are deeper problems with
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register saving than this asymmetry (see the bug report
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // associated with this issue).
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PushRegistersFromMemory(kJSCallerSaved);
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserve space on stack for result and argument structures, if necessary.
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize;
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserve space for the Arguments object.  The Windows 64-bit ABI
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requires us to pass this structure as a pointer to its location on
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the stack.  The structure contains 2 values.
2419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int argument_stack_space = argc * kPointerSize;
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We also need backing space for 4 parameters, even though
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // we only pass one or two parameter, and it is in a register.
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int argument_mirror_space = 4 * kPointerSize;
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total_stack_space =
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      argument_mirror_space + argument_stack_space + result_stack_space;
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  subq(rsp, Immediate(total_stack_space));
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kFrameAlignment = OS::ActivationFrameAlignment();
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(IsPowerOf2(kFrameAlignment));
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, Immediate(-kFrameAlignment));
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    and_(rsp, kScratchRegister);
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
2442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  EnterExitFramePrologue(mode, true);
2443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
2445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
2446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
2447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  lea(r12, Operand(rbp, r14, times_pointer_size, offset));
2448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  EnterExitFrameEpilogue(mode, result_size, 2);
2450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2453bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode,
2454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int stack_space,
2455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int argc,
2456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                       int result_size) {
2457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  EnterExitFramePrologue(mode, false);
2458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2459bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
2460bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
2461bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
2462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
2463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2464bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  EnterExitFrameEpilogue(mode, result_size, argc);
2465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2466bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2467bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) {
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Registers:
24708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r12 : argv
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore the memory copy of the registers by digging them out from
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the stack. This is needed to allow nested break points.
2474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (mode == ExitFrame::MODE_DEBUG) {
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // It's okay to clobber register rbx below because we don't need
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the function pointer after this.
2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
2478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    lea(rbx, Operand(rbp, kOffset));
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved);
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the return address from the stack and restore the frame pointer.
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rcx, Operand(rbp, 1 * kPointerSize));
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rbp, Operand(rbp, 0 * kPointerSize));
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop everything up to and including the arguments and the receiver
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the caller stack.
24908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  lea(rsp, Operand(r12, 1 * kPointerSize));
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference context_address(Top::k_context_address);
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, context_address);
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(rsi, Operand(kScratchRegister, 0));
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), Immediate(0));
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the return address to get ready to return.
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(rcx);
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, c_entry_fp_address);
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), Immediate(0));
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(scratch));
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(kScratchRegister));
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(scratch, Immediate(0));
2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "we should not have an empty lexical context");
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context of the current context.
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, offset));
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Factory::global_context_map());
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, &same_contexts);
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens.
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Preserve original value of holder_reg.
2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(not_equal, "JSGlobalProxy::context() should not be null.");
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to global_context_map(),
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex);
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "JSGlobalObject::global_context should be a global context.");
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister,
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
25633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int token_offset =
25643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(scratch, FieldOperand(scratch, token_offset));
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(scratch, FieldOperand(kScratchRegister, token_offset));
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result_end,
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_top_address();
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
25836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!scratch.is_valid());
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(kScratchRegister, new_space_allocation_top);
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmpq(result, Operand(kScratchRegister, 0));
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(equal, "Unexpected allocation top");
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Move address of new object to result. Use scratch register if available,
25946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and keep address in scratch until call to UpdateAllocationTopHelper.
25956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is_valid()) {
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!scratch.is(result_end));
2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(scratch, new_space_allocation_top);
2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result, Operand(scratch, 0));
25996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (result.is(rax)) {
26006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    load_rax(new_space_allocation_top);
26016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
26026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(kScratchRegister, new_space_allocation_top);
26036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    movq(result, Operand(kScratchRegister, 0));
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               Register scratch) {
2610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (FLAG_debug_code) {
2611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    testq(result_end, Immediate(kObjectAlignmentMask));
2612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Check(zero, "Unaligned allocation in new space");
2613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_top_address();
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top.
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result_end.is(rax)) {
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // rax can be stored directly to a memory location.
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    store_rax(new_space_allocation_top);
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Register required - use scratch provided if available.
26246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (scratch.is_valid()) {
26256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      movq(Operand(scratch, 0), result_end);
26266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(kScratchRegister, new_space_allocation_top);
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      movq(Operand(kScratchRegister, 0), result_end);
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadAllocationTopHelper(result, result_end, scratch, flags);
2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_limit_address();
26486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register top_reg = result_end.is_valid() ? result_end : result;
26506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
26526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    addq(top_reg, Immediate(object_size));
26536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
26546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    lea(top_reg, Operand(result, object_size));
26556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_limit);
26576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmpq(top_reg, Operand(kScratchRegister, 0));
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
26616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  UpdateAllocationTopHelper(top_reg, scratch);
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
26646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if ((flags & TAG_OBJECT) != 0) {
26656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size - kHeapObjectTag));
26666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
26676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      subq(result, Immediate(object_size));
26686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
26696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if ((flags & TAG_OBJECT) != 0) {
26706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Tag the result if requested.
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int header_size,
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        ScaleFactor element_size,
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register element_count,
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(result_end));
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadAllocationTopHelper(result, result_end, scratch, flags);
2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_limit_address();
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  lea(result_end, Operand(result, element_count, element_size, header_size));
2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_limit);
2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(result_end, Operand(kScratchRegister, 0));
2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result_end,
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch,
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadAllocationTopHelper(result, result_end, scratch, flags);
2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_limit =
2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_limit_address();
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movq(result_end, object_size);
2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addq(result_end, result);
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_limit);
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(result_end, Operand(kScratchRegister, 0));
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UpdateAllocationTopHelper(result_end, scratch);
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addq(result, Immediate(kHeapObjectTag));
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object) {
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::new_space_allocation_top_address();
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object has no tag before resetting top.
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(object, Immediate(~kHeapObjectTagMask));
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(kScratchRegister, new_space_allocation_top);
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpq(object, Operand(kScratchRegister, 0));
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(below, "Undo allocation of non allocated memory");
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  movq(Operand(kScratchRegister, 0), object);
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
27533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch,
27543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Label* gc_required) {
27553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
27563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  AllocateInNewSpace(HeapNumber::kSize,
27573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     result,
27583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     scratch,
27593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     no_reg,
27603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     gc_required,
27613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                     TAG_OBJECT);
27623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
27643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
27653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
27663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
27673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result,
2770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register length,
2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch1,
2772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch2,
2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch3,
2774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Label* gc_required) {
2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
27776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
27786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
2779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kShortSize == 2);
2780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
27816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
27826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                kHeaderAlignment));
2783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
27846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
27856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
27866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate two byte string in new space.
2789e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
2790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
2791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
2795e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
2799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
2800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
28016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
28026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
2804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
2805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiString(Register result,
2809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register length,
2810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch1,
2811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch2,
2812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Register scratch3,
2813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                         Label* gc_required) {
2814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
2815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
28166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqAsciiString::kHeaderSize &
28176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
2818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movl(scratch1, length);
2819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(kCharSize == 1);
28206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
2821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  and_(scratch1, Immediate(~kObjectAlignmentMask));
28226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
28236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    subq(scratch1, Immediate(kHeaderAlignment));
28246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate ascii string in new space.
2827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(SeqAsciiString::kHeaderSize,
2828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     times_1,
2829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch3,
2833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
2837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
2838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
28396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
28406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  movq(FieldOperand(result, String::kLengthOffset), scratch1);
28417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  movq(FieldOperand(result, String::kHashFieldOffset),
2842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
2843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateConsString(Register result,
2847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch1,
2848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch2,
2849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* gc_required) {
2850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
2851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
2852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2854e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
2859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
2860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateAsciiConsString(Register result,
2865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch1,
2866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Register scratch2,
2867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                             Label* gc_required) {
2868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AllocateInNewSpace(ConsString::kSize,
2870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     result,
2871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch1,
2872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     scratch2,
2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     gc_required,
2874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     TAG_OBJECT);
2875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
2877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
2878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
2885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
2886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the function context (which is the incoming, outer context).
2887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
2888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
2889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
2890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
2891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // The context may be an intermediate context, not a function context.
2893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {  // context is the current function context.
2895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // The context may be an intermediate context, not a function context.
2896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
29007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
29027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On Windows 64 stack slots are reserved by the caller for all arguments
29037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // including the ones passed in registers, and space is always allocated for
29047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the four register arguments even if the function takes fewer than four
29057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // arguments.
29067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
29077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and the caller does not reserve stack slots for them.
29084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
29094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64
29107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kMinimumStackSlots = 4;
29117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
29127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments;
29134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else
29147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kRegisterPassedArguments = 6;
29157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kRegisterPassedArguments) return 0;
29167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments - kRegisterPassedArguments;
29174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif
29184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
29194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
29224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int frame_alignment = OS::ActivationFrameAlignment();
29234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(frame_alignment != 0);
29244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Make stack end at alignment and allocate space for arguments and old rsp.
29264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(kScratchRegister, rsp);
29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(IsPowerOf2(frame_alignment));
29284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
29294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize));
29314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  and_(rsp, Immediate(-frame_alignment));
29324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister);
29334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
29344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function,
29374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                   int num_arguments) {
29384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rax, function);
29394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallCFunction(rax, num_arguments);
29404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
29414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
29434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
29446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
29456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (FLAG_debug_code) {
29466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
29476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
29486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  call(function);
29504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(OS::ActivationFrameAlignment() != 0);
29514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(num_arguments >= 0);
29524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
29534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
29544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
29554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
29564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int size)
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : address_(address), size_(size), masm_(address, size + Assembler::kGap) {
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(address_, size_);
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.pc_ == address_ + size_);
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
2977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
2979