macro-assembler-x64.cc revision 014dc512cdd3e367bee49a713fdc5ed92584a3e5
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/division-by-constant.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/heap.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/register-configuration.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/x64/assembler-x64.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/x64/macro-assembler-x64.h"
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               CodeObjectRequired create_code_object)
228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      generating_stub_(false),
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_frame_(false),
258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      root_array_available_(true) {
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (create_code_object == CodeObjectRequired::kYes) {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    code_object_ =
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int64_t kInvalidRootRegisterDelta = -1;
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint64_t MacroAssembler::RootRegisterDelta(ExternalReference other) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (predictable_code_size() &&
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (other.address() < reinterpret_cast<Address>(isolate()) ||
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       other.address() >= reinterpret_cast<Address>(isolate() + 1))) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kInvalidRootRegisterDelta;
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address roots_register_value = kRootRegisterBias +
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<Address>(isolate()->heap()->roots_array_start());
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int64_t delta = kInvalidRootRegisterDelta;  // Bogus initialization.
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delta = other.address() - roots_register_value;
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For x32, zero extend the address to 64-bit and calculate the delta.
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint64_t o = static_cast<uint32_t>(
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<intptr_t>(other.address()));
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint64_t r = static_cast<uint32_t>(
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<intptr_t>(roots_register_value));
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delta = o - r;
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return delta;
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockOperand MacroAssembler::ExternalOperand(ExternalReference target,
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch) {
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (root_array_available_ && !serializer_enabled()) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int64_t delta = RootRegisterDelta(target);
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return Operand(kRootRegister, static_cast<int32_t>(delta));
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(scratch, target);
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Operand(scratch, 0);
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Load(Register destination, ExternalReference source) {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (root_array_available_ && !serializer_enabled()) {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int64_t delta = RootRegisterDelta(source);
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (destination.is(rax)) {
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    load_rax(source);
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(kScratchRegister, source);
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(destination, Operand(kScratchRegister, 0));
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Store(ExternalReference destination, Register source) {
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (root_array_available_ && !serializer_enabled()) {
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int64_t delta = RootRegisterDelta(destination);
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (source.is(rax)) {
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    store_rax(destination);
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(kScratchRegister, destination);
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(kScratchRegister, 0), source);
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::LoadAddress(Register destination,
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 ExternalReference source) {
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (root_array_available_ && !serializer_enabled()) {
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int64_t delta = RootRegisterDelta(source);
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      leap(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Safe code.
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(destination, source);
12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::LoadAddressSize(ExternalReference source) {
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (root_array_available_ && !serializer_enabled()) {
12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // This calculation depends on the internals of LoadAddress.
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // It's correctness is ensured by the asserts in the Call
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instruction below.
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int64_t delta = RootRegisterDelta(source);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Operand is leap(scratch, Operand(kRootRegister, delta));
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Opcodes : REX.W 8D ModRM Disp8/Disp32  - 4 or 7.
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int size = 4;
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!is_int8(static_cast<int32_t>(delta))) {
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        size += 3;  // Need full four-byte displacement in lea.
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return size;
13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Size of movp(destination, src);
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Assembler::kMoveAddressIntoScratchRegisterInstructionLength;
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PushAddress(ExternalReference source) {
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int64_t address = reinterpret_cast<int64_t>(source.address());
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_int32(address) && !serializer_enabled()) {
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (emit_debug_code()) {
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(kScratchRegister, kZapValue, Assembler::RelocInfoNone());
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(Immediate(static_cast<int32_t>(address)));
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadAddress(kScratchRegister, source);
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(kScratchRegister);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(root_array_available_);
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(destination, Operand(kRootRegister,
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            (index << kPointerSizeLog2) - kRootRegisterBias));
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadRootIndexed(Register destination,
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Register variable_offset,
167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     int fixed_offset) {
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(root_array_available_);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(destination,
170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch       Operand(kRootRegister,
171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               variable_offset, times_pointer_size,
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               (fixed_offset << kPointerSizeLog2) - kRootRegisterBias));
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(root_array_available_);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch       source);
18125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
18225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
18325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushRoot(Heap::RootListIndex index) {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(root_array_available_);
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(root_array_available_);
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(with, Operand(kRootRegister,
193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     (index << kPointerSizeLog2) - kRootRegisterBias));
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CompareRoot(const Operand& with,
1981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Heap::RootListIndex index) {
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(root_array_available_);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!with.AddressUsesRegister(kScratchRegister));
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(kScratchRegister, index);
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(with, kScratchRegister);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register addr,
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Register scratch,
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         SaveFPRegsMode save_fp,
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         RememberedSetFinalAction and_then) {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load store buffer top.
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(scratch, Heap::kStoreBufferTopRootIndex);
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(scratch, 0), addr);
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(scratch, Immediate(kPointerSize));
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StoreRoot(scratch, Heap::kStoreBufferTopRootIndex);
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(not_equal, &buffer_overflowed, Label::kNear);
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &done, Label::kNear);
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InNewSpace(Register object,
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch,
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Condition cc,
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* branch,
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label::Distance distance) {
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (serializer_enabled()) {
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Can't do arithmetic on external references if it might get serialized.
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The mask isn't really an address.  We load it as an external reference in
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // case the size of the new space is different between the snapshot maker
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // and the running system.
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (scratch.is(object)) {
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(kScratchRegister, ExternalReference::new_space_mask(isolate()));
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      andp(scratch, kScratchRegister);
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(scratch, ExternalReference::new_space_mask(isolate()));
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      andp(scratch, object);
265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(kScratchRegister, ExternalReference::new_space_start(isolate()));
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(scratch, kScratchRegister);
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(cc, branch, distance);
269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerSize == kInt64Size
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : kPointerSize == kInt32Size);
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    intptr_t new_space_start =
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart());
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start),
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Assembler::RelocInfoNone());
277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (scratch.is(object)) {
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(scratch, kScratchRegister);
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      leap(scratch, Operand(object, kScratchRegister, times_1, 0));
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(scratch,
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask())));
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(cc, branch, distance);
285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
2987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(dst, FieldOperand(object, offset));
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testb(dst, Immediate((1 << kPointerSizeLog2) - 1));
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&done);
3244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(value, kZapValue, Assembler::RelocInfoNone());
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, kZapValue, Assembler::RelocInfoNone());
3304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index,
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp,
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
3428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
3448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
3458defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3508defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address. Index is not a smi.
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(dst, Operand(object, index, times_pointer_size,
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
3588defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
3608defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
3628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(value, kZapValue, Assembler::RelocInfoNone());
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(index, kZapValue, Assembler::RelocInfoNone());
3668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
3678defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
3688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3698defd9ff6930b4e24729971a61cf7469daf119beSteve Block
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(Register object,
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register map,
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register dst,
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       SaveFPRegsMode fp_mode) {
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(kScratchRegister));
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(map));
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(dst));
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!map.is(dst));
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
3794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) pushq(map);
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompareMap(map, isolate()->factory()->meta_map());
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) popq(map);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok, Label::kNear);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
3884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) pushq(map);
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(map, FieldOperand(object, HeapObject::kMapOffset));
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) popq(map);
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok, Label::kNear);
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(dst, FieldOperand(object, HeapObject::kMapOffset));
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // First, check if a write barrier is even needed. The tests below
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // catch stores of smis and stores into the young generation.
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlag(map,
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                map,  // Used as scratch.
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                MemoryChunk::kPointersToHereAreInterestingMask,
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                zero,
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                &done,
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label::kNear);
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, kZapValue, Assembler::RelocInfoNone());
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(map, kZapValue, Assembler::RelocInfoNone());
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(value, Operand(address, 0));
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of smis and stores into the young generation.
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
5034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(address, kZapValue, Assembler::RelocInfoNone());
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(value, kZapValue, Assembler::RelocInfoNone());
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
519756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
520756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedArrayMapRootIndex);
521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
522756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kFixedDoubleArrayMapRootIndex);
5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok, Label::kNear);
5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
526756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedCOWArrayMapRootIndex);
527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
529756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
532756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label L;
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L, Label::kNear);
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Control will not return here.
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label alignment_as_expected;
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(rsp, Immediate(frame_alignment_mask));
550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &alignment_as_expected, Label::kNear);
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(result, result);
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &ok, Label::kNear);
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(op, op);
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(sign, then_label);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, Smi::FromInt(static_cast<int>(reason)),
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Assembler::RelocInfoNone());
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(kScratchRegister);
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntime(Runtime::kAbort, 1);
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntime(Runtime::kAbort, 1);
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Control will not return here.
597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs
603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) {
608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
61285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
61485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
617592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
62680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
62880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hash.is(index)) {
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(index, hash);
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
6331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
63644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 int num_arguments,
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
6454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
6464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
6474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
6488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
64944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(f, isolate()));
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), f->result_size, save_doubles);
6514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
6578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0]                 : return address
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8]                 : argument num_arguments - 1
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  ...
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- rax                    : number of  arguments
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Set(rax, function->nargs);
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
682bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
683bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
684bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CEntryStub ces(isolate(), 1);
6893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag,
694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   const CallWrapper& call_wrapper) {
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a builtin without a valid frame.
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Fake a parameter count to avoid emitting code to do the check.
699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadNativeContextSlot(native_context_index, rdi);
701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(rdi, no_reg, expected, expected, flag, call_wrapper);
702791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REG(Name) \
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  { Register::kCode_##Name }
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register saved_regs[] = {
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  REG(r9), REG(r10), REG(r11)
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef REG
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion1,
7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion2,
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion3) {
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // store the registers in any particular way, but we do have to store and
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // restore them.
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = saved_regs[i];
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      pushq(reg);
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // R12 to r15 are callee save on all platforms.
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fp_mode == kSaveFPRegs) {
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      XMMRegister reg = XMMRegister::from_code(i);
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(Operand(rsp, i * kDoubleSize), reg);
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode,
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion1,
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion2,
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion3) {
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fp_mode == kSaveFPRegs) {
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      XMMRegister reg = XMMRegister::from_code(i);
749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(reg, Operand(rsp, i * kDoubleSize));
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = saved_regs[i];
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      popq(reg);
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtss2sd(XMMRegister dst, XMMRegister src) {
763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtss2sd(dst, src, src);
766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtss2sd(dst, src);
768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtss2sd(XMMRegister dst, const Operand& src) {
773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtss2sd(dst, dst, src);
776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtss2sd(dst, src);
778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtsd2ss(XMMRegister dst, XMMRegister src) {
783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtsd2ss(dst, src, src);
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtsd2ss(dst, src);
788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtsd2ss(XMMRegister dst, const Operand& src) {
793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtsd2ss(dst, dst, src);
796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtsd2ss(dst, src);
798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtlsi2sd(XMMRegister dst, Register src) {
803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtlsi2sd(dst, dst, src);
807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtlsi2sd(dst, src);
810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtlsi2sd(dst, dst, src);
819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtlsi2sd(dst, src);
822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2ss(XMMRegister dst, Register src) {
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorps(dst, dst, dst);
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2ss(dst, dst, src);
831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorps(dst, dst);
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2ss(dst, src);
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2ss(XMMRegister dst, const Operand& src) {
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorps(dst, dst, dst);
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2ss(dst, dst, src);
843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorps(dst, dst);
845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2ss(dst, src);
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2sd(XMMRegister dst, Register src) {
851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2sd(dst, dst, src);
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2sd(dst, src);
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2sd(XMMRegister dst, const Operand& src) {
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2sd(dst, dst, src);
867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2sd(dst, src);
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqui2ss(XMMRegister dst, Register src, Register tmp) {
875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label msb_set_src;
876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label jmp_return;
877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  testq(src, src);
878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2ss(dst, src);
880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&jmp_return, Label::kNear);
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&msb_set_src);
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movq(tmp, src);
883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  shrq(src, Immediate(1));
884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Recover the least significant bit to avoid rounding errors.
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  andq(tmp, Immediate(1));
886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  orq(src, tmp);
887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2ss(dst, src);
888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  addss(dst, dst);
889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&jmp_return);
890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) {
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label msb_set_src;
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label jmp_return;
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  testq(src, src);
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2sd(dst, src);
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&jmp_return, Label::kNear);
900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&msb_set_src);
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movq(tmp, src);
902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  shrq(src, Immediate(1));
903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  andq(tmp, Immediate(1));
904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  orq(src, tmp);
905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2sd(dst, src);
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  addsd(dst, dst);
907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&jmp_return);
908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtsd2si(Register dst, XMMRegister src) {
912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtsd2si(dst, src);
915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtsd2si(dst, src);
917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2si(Register dst, XMMRegister src) {
922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2si(dst, src);
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2si(dst, src);
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2si(Register dst, const Operand& src) {
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2si(dst, src);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2si(dst, src);
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttss2siq(Register dst, XMMRegister src) {
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttss2siq(dst, src);
945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttss2siq(dst, src);
947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttss2siq(Register dst, const Operand& src) {
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttss2siq(dst, src);
955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttss2siq(dst, src);
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2siq(Register dst, XMMRegister src) {
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2siq(dst, src);
965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2siq(dst, src);
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2siq(Register dst, const Operand& src) {
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2siq(dst, src);
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2siq(dst, src);
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxbq(dst, src);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzxbl(dst, src);
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxwq(dst, src);
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzxwl(dst, src);
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger32()) {
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, src);
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movb(dst, src);
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movw(dst, src);
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger32()) {
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, src);
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) {
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x == 0) {
10208defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_uint32(x)) {
1022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movl(dst, Immediate(static_cast<uint32_t>(x)));
10238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (is_int32(x)) {
10248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movq(dst, Immediate(static_cast<int32_t>(x)));
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movq(dst, x);
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Set(const Operand& dst, intptr_t x) {
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (is_int32(x)) {
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, Immediate(static_cast<int32_t>(x)));
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Set(kScratchRegister, x);
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, kScratchRegister);
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, Immediate(static_cast<int32_t>(x)));
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection.
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool MacroAssembler::IsUnsafeInt(const int32_t x) {
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMaxBits = 17;
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_intn(x, kMaxBits);
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, Smi* src) {
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // JIT cookie can be converted to Smi.
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, Smi::FromInt(src->value() ^ jit_cookie()));
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(kScratchRegister, Smi::FromInt(jit_cookie()));
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(dst, kScratchRegister);
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t value = static_cast<int32_t>(reinterpret_cast<intptr_t>(src));
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, Immediate(value ^ jit_cookie()));
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(dst, Immediate(jit_cookie()));
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, src);
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafePush(Smi* src) {
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // JIT cookie can be converted to Smi.
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Push(Smi::FromInt(src->value() ^ jit_cookie()));
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(kScratchRegister, Smi::FromInt(jit_cookie()));
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(Operand(rsp, 0), kScratchRegister);
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t value = static_cast<int32_t>(reinterpret_cast<intptr_t>(src));
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Push(Immediate(value ^ jit_cookie()));
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(Operand(rsp, 0), Immediate(jit_cookie()));
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(src);
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10938defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) {
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
10958defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
10968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 0) {
10978defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(kScratchRegister, kScratchRegister);
10988defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kScratchRegister;
10998defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
11008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(kScratchRegister, source);
11018defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return kScratchRegister;
11028defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
11038defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11058defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int value = source->value();
110844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (value == 0) {
11098defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(dst, source, Assembler::RelocInfoNone());
11128defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
11138defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
11148defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
111769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(dst, src);
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(dst, Immediate(kSmiShift));
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
11279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    testb(dst, Immediate(0x01));
1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &ok, Label::kNear);
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kInteger32ToSmiFieldWritingToNonSmiLocation);
11319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bind(&ok);
11329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiShift % kBitsPerByte == 0);
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(Operand(dst, kSmiShift / kBitsPerByte), src);
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Integer32ToSmi(kScratchRegister, src);
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
11429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
11439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
11463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Register src,
11473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                int constant) {
11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
114944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    addl(dst, Immediate(constant));
11503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    leal(dst, Operand(src, constant));
11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(dst, Immediate(kSmiShift));
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
115869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shrp(dst, Immediate(kSmiShift));
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sarl(dst, Immediate(kSmiShift));
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, Operand(src, kSmiShift / kBitsPerByte));
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, src);
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sarl(dst, Immediate(kSmiShift));
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
118469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
11853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sarp(dst, Immediate(kSmiShift));
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt32Size) {
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Sign extend to 64-bit.
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, dst);
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger64(dst, dst);
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
12049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
12059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) {
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(src);
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src, src);
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiCompare(Register smi1, Register smi2) {
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(smi1);
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(smi2);
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(smi1, smi2);
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Cmp(dst, src);
122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
122444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
122544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
122644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(Register dst, Smi* src) {
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
12283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src->value() == 0) {
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(dst, dst);
12303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Register constant_reg = GetSmiConstant(src);
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(dst, constant_reg);
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(src);
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(dst, src);
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(src);
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(dst, src);
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(dst, Immediate(src));
125844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Smi* src) {
126344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The Operand cannot use the smi register.
126444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register smi_reg = GetSmiConstant(src);
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.AddressUsesRegister(smi_reg));
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(dst, smi_reg);
126744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
126844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(kScratchRegister, dst);
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(kScratchRegister, src);
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
12789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
12799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           Register src,
12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           int power) {
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(power >= 0);
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(power < 64);
12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power == 0) {
12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src);
12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return;
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power < kSmiShift) {
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sarp(dst, Immediate(kSmiShift - power));
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (power > kSmiShift) {
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shlp(dst, Immediate(power - kSmiShift));
12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
13027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         Register src,
13037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         int power) {
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((0 <= power) && (power < 32));
13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (dst.is(src)) {
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shrp(dst, Immediate(power + kSmiShift));
13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    UNIMPLEMENTED();  // Not used.
13097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* on_not_smis,
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label::Distance near_jump) {
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1) || dst.is(src2)) {
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(kScratchRegister));
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src2.is(kScratchRegister));
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(kScratchRegister, src2);
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump);
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(dst, src2);
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(dst, on_not_smis, near_jump);
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) {
133269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(src, Immediate(kSmiTagMask));
13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13381e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition MacroAssembler::CheckSmi(const Operand& src) {
133969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
13401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  testb(src, Immediate(kSmiTagMask));
13411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return zero;
13421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
13431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
13441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1345f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckNonNegativeSmi(Register src) {
134669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Test that both bits of the mask 0x8000000000000001 are zero.
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister, src);
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rolp(kScratchRegister, Immediate(1));
13508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(3));
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return zero;
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first.is(second)) {
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CheckSmi(first);
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
135969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leal(kScratchRegister, Operand(first, second, times_1, 0));
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(kScratchRegister, Immediate(0x03));
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(kScratchRegister, first);
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orl(kScratchRegister, second);
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(kScratchRegister, Immediate(kSmiTagMask));
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1373f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckBothNonNegativeSmi(Register first,
1374f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                                  Register second) {
1375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (first.is(second)) {
1376f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return CheckNonNegativeSmi(first);
1377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister, first);
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  orp(kScratchRegister, second);
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rolp(kScratchRegister, Immediate(1));
1381f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  testl(kScratchRegister, Immediate(3));
1382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
1383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1384d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1385d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1386bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first,
1387bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register second,
1388bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register scratch) {
1389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (first.is(second)) {
1390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return CheckSmi(first);
1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1392bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (scratch.is(second)) {
1393bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, first);
1394bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
1395bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (!scratch.is(first)) {
1396bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      movl(scratch, first);
1397bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
1398bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, second);
1399bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1400bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  testb(scratch, Immediate(kSmiTagMask));
1401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
1402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
14053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // A 32-bit integer value can always be converted to a smi.
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return always;
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(src, Immediate(0xc0000000));
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return positive;
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // An unsigned 32-bit integer value is valid as long as the high bit
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is not set.
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(src, src);
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return positive;
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(src, Immediate(0xc0000000));
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return zero;
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, Register src) {
14321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (dst.is(src)) {
14331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
14341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
14351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
14361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
14371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
14381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
14391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
14401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
14411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) {
14421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!(src.AddressUsesRegister(dst))) {
14431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
14441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
14451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
14461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, src);
14471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
14481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
14491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
14501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
14511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfValidSmiValue(Register src,
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* on_valid,
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label::Distance near_jump) {
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition is_valid = CheckInteger32ValidSmiValue(src);
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(is_valid, on_valid, near_jump);
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotValidSmiValue(Register src,
1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label* on_invalid,
1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label::Distance near_jump) {
1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckInteger32ValidSmiValue(src);
1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfUIntValidSmiValue(Register src,
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label* on_valid,
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label::Distance near_jump) {
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition is_valid = CheckUInteger32ValidSmiValue(src);
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(is_valid, on_valid, near_jump);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label* on_invalid,
1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label::Distance near_jump) {
1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckUInteger32ValidSmiValue(src);
1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmi(Register src,
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label* on_smi,
1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label::Distance near_jump) {
1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(smi, on_smi, near_jump);
1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotSmi(Register src,
1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smi,
1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(smi), on_not_smi, near_jump);
1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessNonNegativeSmi(
1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register src, Label* on_not_smi_or_negative,
1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition non_negative_smi = CheckNonNegativeSmi(src);
1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump);
1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Smi* constant,
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label* on_equals,
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label::Distance near_jump) {
1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiCompare(src, constant);
1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, on_equals, near_jump);
1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSmi(Register src1,
1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register src2,
1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label* on_not_both_smi,
1520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label::Distance near_jump) {
1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothSmi(src1, src2);
1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Register src2,
1528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label* on_not_both_smi,
1529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label::Distance near_jump) {
1530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
1531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
15363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
15373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
15393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
15408defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register constant_reg = GetSmiConstant(constant);
1544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    addp(dst, constant_reg);
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadSmiConstant(dst, constant);
1547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    addp(dst, src);
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (constant->value() != 0) {
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addl(Operand(dst, kSmiShift / kBitsPerByte),
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Immediate(constant->value()));
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, Immediate(constant));
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant,
1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    SmiOperationConstraints constraints,
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Label* bailout_label,
1568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(kScratchRegister, constant);
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(dst, kScratchRegister);
1577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (constraints & SmiOperationConstraint::kBailoutOnNoOverflow) {
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(no_overflow, bailout_label, near_jump);
1579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      subp(dst, kScratchRegister);
1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (constraints & SmiOperationConstraint::kBailoutOnOverflow) {
1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (constraints & SmiOperationConstraint::kPreserveSourceRegister) {
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label done;
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(no_overflow, &done, Label::kNear);
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        subp(dst, kScratchRegister);
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jmp(bailout_label, near_jump);
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&done);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Bailout if overflow without reserving src.
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(overflow, bailout_label, near_jump);
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kBailoutOnOverflow);
1598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, constant);
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(dst, src);
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(overflow, bailout_label, near_jump);
1601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!dst.is(src)) {
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
16103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
16128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(dst, constant_reg);
16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
16168defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
16179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
16189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, src);
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
16219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
16228defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, src);
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant,
1630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    SmiOperationConstraints constraints,
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Label* bailout_label,
1632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadSmiConstant(kScratchRegister, constant);
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(dst, kScratchRegister);
1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (constraints & SmiOperationConstraint::kBailoutOnNoOverflow) {
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(no_overflow, bailout_label, near_jump);
1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, kScratchRegister);
1645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (constraints & SmiOperationConstraint::kBailoutOnOverflow) {
1646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (constraints & SmiOperationConstraint::kPreserveSourceRegister) {
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label done;
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(no_overflow, &done, Label::kNear);
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        addp(dst, kScratchRegister);
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jmp(bailout_label, near_jump);
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&done);
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Bailout if overflow without reserving src.
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(overflow, bailout_label, near_jump);
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kBailoutOnOverflow);
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (constant->value() == Smi::kMinValue) {
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!dst.is(kScratchRegister));
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LoadSmiConstant(kScratchRegister, constant);
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      subp(dst, kScratchRegister);
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(overflow, bailout_label, near_jump);
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtract by adding the negation.
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, src);
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(overflow, bailout_label, near_jump);
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiNeg(Register dst,
1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src,
1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_smi_result,
1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src);
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negp(dst);  // Low 32 bits are retained as zero by negation.
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Test if result is zero or Smi::kMinValue.
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(dst, kScratchRegister);
1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src, kScratchRegister);
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negp(dst);
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(dst, src);
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SmiAddHelper(MacroAssembler* masm,
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register src1,
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         T src2,
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* on_not_smi_result,
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label::Distance near_jump) {
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (dst.is(src1)) {
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->addp(dst, src2);
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(no_overflow, &done, Label::kNear);
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore src1.
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->subp(dst, src2);
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->jmp(on_not_smi_result, near_jump);
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->bind(&done);
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->movp(dst, src1);
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->addp(dst, src2);
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(overflow, on_not_smi_result, near_jump);
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiAddHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.AddressUsesRegister(dst));
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiAddHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
17450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiAdd(Register dst,
17460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src1,
17470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src2) {
17480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
17490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible.
175044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(kScratchRegister, src1);
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(kScratchRegister, src2);
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Check(no_overflow, kSmiAdditionOverflow);
1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leap(dst, Operand(src1, src2, times_1, 0));
1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(dst, src2);
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(no_overflow, kSmiAdditionOverflow);
1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SmiSubHelper(MacroAssembler* masm,
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register src1,
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         T src2,
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* on_not_smi_result,
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label::Distance near_jump) {
1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->subp(dst, src2);
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(no_overflow, &done, Label::kNear);
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore src1.
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->addp(dst, src2);
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->jmp(on_not_smi_result, near_jump);
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->bind(&done);
1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->movp(dst, src1);
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->subp(dst, src2);
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(overflow, on_not_smi_result, near_jump);
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SmiSub(Register dst,
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register src1,
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register src2,
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label* on_not_smi_result,
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label::Distance near_jump) {
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17980d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst,
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.AddressUsesRegister(dst));
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SmiSubNoOverflowHelper(MacroAssembler* masm,
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register dst,
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register src1,
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   T src2) {
18140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
18150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible (e.g., subtracting two positive smis).
181644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->movp(dst, src1);
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->subp(dst, src2);
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->Assert(no_overflow, kSmiSubtractionOverflow);
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubNoOverflowHelper<Register>(this, dst, src1, src2);
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SmiSub(Register dst,
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register src1,
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            const Operand& src2) {
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubNoOverflowHelper<Operand>(this, dst, src1, src2);
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMul(Register dst,
1838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
1846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label failure, zero_correct_result;
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);  // Create backup for later testing.
1850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imulp(dst, src2);
1852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, &failure, Label::kNear);
1853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(dst, dst);
1858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, src2);
1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Result was positive zero.
1863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &zero_correct_result, Label::kNear);
1864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&failure);  // Reused failure exit, restores src1.
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&zero_correct_result);
1870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Set(dst, 0);
1871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imulp(dst, src2);
1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(dst, dst);
1881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // One of src1 and src2 is zero, the check whether the other is
1883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // negative.
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(kScratchRegister, src2);
1886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiDiv(Register dst,
1893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rax));
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rdx));
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(rdx));
1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for 0 divisor (result is +/-Infinity).
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src2, src2);
1906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
1912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We need to rule out dividing Smi::kMinValue by -1, since that would
1913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // overflow in idiv and raise an exception.
1914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We combine this with negative zero test (negative zero only happens
1915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // when dividing zero by a negative number).
1916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We overshoot a little and go to slow case if we divide min-value
1918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by any negative value, not just -1.
1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testl(rax, Immediate(~Smi::kMinValue));
1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &safe_div, Label::kNear);
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src2, src2);
1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &safe_div, Label::kNear);
1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
1931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend src1 into edx:eax.
1934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
1935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
1936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the remainder is zero.
1938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
1939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label smi_result;
1941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &smi_result, Label::kNear);
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&smi_result);
1945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, on_not_smi_result, near_jump);
1947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src1) && src1.is(rax)) {
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rax);
1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMod(Register dst,
1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rax));
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rdx));
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(rdx));
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(src2));
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src2, src2);
1969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
1976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(rax, Immediate(Smi::kMinValue));
1980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
1981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(src2, Immediate(-1));
1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
1983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Retag inputs and go slow case.
1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(on_not_smi_result, near_jump);
1989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
1990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend eax into edx:eax.
1992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
1993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore smi tags on inputs.
1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
1996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for a negative zero result.  If the result is zero, and the
2000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dividend is negative, go slow to return a floating point negative zero.
2001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label smi_result;
2002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &smi_result, Label::kNear);
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src1, src1);
2005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(negative, on_not_smi_result, near_jump);
2006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&smi_result);
2007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rdx);
2008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) {
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.is(kScratchRegister));
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Set tag and padding bits before negating, so that they are zero
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // afterwards.
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(kScratchRegister, Immediate(~0));
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(kScratchRegister, Immediate(1));
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, kScratchRegister);
2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leap(dst, Operand(src, kScratchRegister, times_1, 0));
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  notp(dst);
2028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(dst, src2);
2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
20413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
20429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Set(dst, 0);
20433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
20458defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(dst, constant_reg);
20473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20488defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(dst, src);
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  orp(dst, src2);
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
20668defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(dst, constant_reg);
20683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20698defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(dst, src);
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorp(dst, src2);
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
20853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
20878defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, constant_reg);
20893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
20908defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, src);
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Register src,
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     int shift_value) {
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint5(shift_value));
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_value > 0) {
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (dst.is(src)) {
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarp(dst, Immediate(shift_value + kSmiShift));
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(kSmiShift));
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // Not used.
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src,
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          int shift_value,
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* on_not_smi_result,
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance near_jump) {
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift_value > 0) {
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Shift amount specified by lower 5 bits, not six as the shl opcode.
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlq(dst, Immediate(shift_value & 0x1f));
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (dst.is(src)) {
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();  // Not used.
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(dst, src);
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shll(dst, Immediate(shift_value));
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpIfNotValidSmiValue(dst, on_not_smi_result, near_jump);
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Integer32ToSmi(dst, dst);
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRightConstant(
2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register dst, Register src, int shift_value,
2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_not_smi_result, Label::Distance near_jump) {
2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Logic right shift interprets its result as an *unsigned* number.
2142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
2143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNIMPLEMENTED();  // Not used.
2144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (shift_value == 0) {
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      testp(src, src);
2147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(negative, on_not_smi_result, near_jump);
2148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shrp(dst, Immediate(shift_value + kSmiShift));
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(kSmiShift));
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(dst, src);
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shrp(dst, Immediate(shift_value));
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpIfUIntNotValidSmiValue(dst, on_not_smi_result, near_jump);
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Integer32ToSmi(dst, dst);
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst,
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Register src2,
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label* on_not_smi_result,
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label::Distance near_jump) {
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(rcx));
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src1)) {
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src1);
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Untag shift amount.
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(rcx, src2);
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Shift amount specified by lower 5 bits, not six as the shl opcode.
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(rcx, Immediate(0x1f));
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shlq_cl(dst);
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(kScratchRegister));
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src2.is(kScratchRegister));
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(src2));
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(rcx));
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src1.is(rcx) || src2.is(rcx)) {
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movq(kScratchRegister, rcx);
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (dst.is(src1)) {
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();  // Not used.
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label valid_result;
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(dst, src1);
2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(rcx, src2);
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shll_cl(dst);
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpIfValidSmiValue(dst, &valid_result, Label::kNear);
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // As src1 or src2 could not be dst, we do not need to restore them for
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // clobbering dst.
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (src1.is(rcx) || src2.is(rcx)) {
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (src1.is(rcx)) {
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          movq(src1, kScratchRegister);
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          movq(src2, kScratchRegister);
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jmp(on_not_smi_result, near_jump);
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bind(&valid_result);
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Integer32ToSmi(dst, dst);
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src1,
2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src2,
2218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label* on_not_smi_result,
2219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label::Distance near_jump) {
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(rcx));
2225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rcx) || src2.is(rcx)) {
2226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, rcx);
2227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (dst.is(src1)) {
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNIMPLEMENTED();  // Not used.
2230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label valid_result;
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(dst, src1);
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(rcx, src2);
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shrl_cl(dst);
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfUIntValidSmiValue(dst, &valid_result, Label::kNear);
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // As src1 or src2 could not be dst, we do not need to restore them for
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // clobbering dst.
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src1.is(rcx) || src2.is(rcx)) {
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (src1.is(rcx)) {
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        movq(src1, kScratchRegister);
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        movq(src2, kScratchRegister);
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     }
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(on_not_smi_result, near_jump);
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&valid_result);
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Integer32ToSmi(dst, dst);
2248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src1,
2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src2) {
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(rcx));
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!dst.is(src1)) {
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
22633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiToInteger32(dst, dst);
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sarl_cl(dst);
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Integer32ToSmi(dst, dst);
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SelectNonSmi(Register dst,
2271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src1,
2272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src2,
2273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smis,
2274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src1));
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
2280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Both operands must not be smis.
2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi);
2284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
228569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
2287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movl(kScratchRegister, Immediate(kSmiTagMask));
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(kScratchRegister, src1);
2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(kScratchRegister, src2);
2290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If non-zero then both are smis.
2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, on_not_smis, near_jump);
2292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exactly one operand is a smi.
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, static_cast<int>(kSmiTagMask));
2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subp(kScratchRegister, Immediate(1));
2297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(dst, src1);
2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorp(dst, src2);
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(dst, kScratchRegister);
2301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorp(dst, src1);
2303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
23073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst,
23083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Register src,
23093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    int shift) {
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_uint6(shift));
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There is a possible optimization if shift is in the range 60-63, but that
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // will (and must) never happen.
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift < kSmiShift) {
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarp(dst, Immediate(kSmiShift - shift));
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(shift - kSmiShift));
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, times_1);
23233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(shift >= times_1 && shift <= (static_cast<int>(times_8) + 1));
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We have to sign extend the index register to 64-bit as the SMI might
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // be negative.
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, dst);
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift == times_1) {
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarq(dst, Immediate(kSmiShift));
2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return SmiIndex(dst, times_1);
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, static_cast<ScaleFactor>(shift - 1));
23373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register src,
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            int shift) {
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Register src holds a positive smi.
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_uint6(shift));
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negp(dst);
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift < kSmiShift) {
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarp(dst, Immediate(kSmiShift - shift));
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(shift - kSmiShift));
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, times_1);
23573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(shift >= times_1 && shift <= (static_cast<int>(times_8) + 1));
2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negq(dst);
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift == times_1) {
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarq(dst, Immediate(kSmiShift));
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return SmiIndex(dst, times_1);
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, static_cast<ScaleFactor>(shift - 1));
23693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AddSmiField(Register dst, const Operand& src) {
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiShift % kBitsPerByte);
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addl(dst, Operand(src, kSmiShift / kBitsPerByte));
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(kScratchRegister, src);
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addl(dst, kScratchRegister);
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Push(Smi* source) {
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t smi = reinterpret_cast<intptr_t>(source);
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_int32(smi)) {
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(Immediate(static_cast<int32_t>(smi)));
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register constant = GetSmiConstant(source);
2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(constant);
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) {
2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.is(scratch));
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, src);
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // High bits.
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrp(src, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(src, Immediate(kSmiShift));
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(src);
2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Low bits.
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(scratch, Immediate(kSmiShift));
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(scratch);
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) {
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(scratch));
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(scratch);
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Low bits.
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrp(scratch, Immediate(kSmiShift));
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(dst);
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrp(dst, Immediate(kSmiShift));
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // High bits.
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(dst, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  orp(dst, scratch);
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Test(const Operand& src, Smi* source) {
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(Operand(src, kIntSize), Immediate(source->value()));
2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(src, Immediate(source));
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotString(Register object,
2436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register object_map,
2437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* not_string,
2438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label::Distance near_jump) {
2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_smi = CheckSmi(object);
2440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(is_smi, not_string, near_jump);
2441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map);
2442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above_equal, not_string, near_jump);
2443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first_object, Register second_object, Register scratch1,
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2, Label* on_fail, Label::Distance near_jump) {
2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both objects are not smis.
2450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition either_smi = CheckEitherSmi(first_object, second_object);
2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(either_smi, on_fail, near_jump);
2452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kNotStringTag != 0);
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch1, Immediate(kFlatOneByteStringMask));
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch2, Immediate(kFlatOneByteStringMask));
2468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch1, Operand(scratch1, scratch2, times_8, 0));
2471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3)));
2473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register instance_type, Register scratch, Label* failure,
2479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!scratch.is(instance_type)) {
2481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movl(scratch, instance_type);
2482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch, Immediate(kFlatOneByteStringMask));
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kOneByteStringTag));
2489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, failure, near_jump);
2490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first_object_instance_type, Register second_object_instance_type,
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1, Register scratch2, Label* on_fail,
2496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch1, first_object_instance_type);
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch2, second_object_instance_type);
2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kNotStringTag != 0);
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch1, Immediate(kFlatOneByteStringMask));
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch2, Immediate(kFlatOneByteStringMask));
2510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch1, Operand(scratch1, scratch2, times_8, 0));
2513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3)));
2515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void JumpIfNotUniqueNameHelper(MacroAssembler* masm,
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      T operand_or_register,
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label* not_unique_name,
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label::Distance distance) {
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->testb(operand_or_register,
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->j(zero, &succeed, Label::kNear);
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->cmpb(operand_or_register, Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->j(not_equal, not_unique_name, distance);
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->bind(&succeed);
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotUniqueNameHelper<Operand>(this, operand, not_unique_name, distance);
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotUniqueNameHelper<Register>(this, reg, not_unique_name, distance);
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25500d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
25510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
25536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
25546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
25556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
25603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MoveHeapObject(dst, source);
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
25703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MoveHeapObject(kScratchRegister, source);
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) {
2579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (src == 0) {
2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Xorpd(dst, dst);
2581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    unsigned pop = base::bits::CountPopulation32(src);
2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NE(0u, pop);
2584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (pop == 32) {
2585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movl(kScratchRegister, Immediate(src));
2588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movq(dst, kScratchRegister);
2589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) {
2595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (src == 0) {
2596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Xorpd(dst, dst);
2597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros64(src);
2599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros64(src);
2600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    unsigned pop = base::bits::CountPopulation64(src);
2601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NE(0u, pop);
2602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (pop == 64) {
2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (pop + ntz == 64) {
2605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Psllq(dst, ntz);
2607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (pop + nlz == 64) {
2608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Psrlq(dst, nlz);
2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t lower = static_cast<uint32_t>(src);
2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t upper = static_cast<uint32_t>(src >> 32);
2613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (upper == 0) {
2614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Move(dst, lower);
2615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        movq(kScratchRegister, src);
2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Movq(dst, kScratchRegister);
2618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movaps(XMMRegister dst, XMMRegister src) {
2625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovaps(dst, src);
26283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movaps(dst, src);
26303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movapd(XMMRegister dst, XMMRegister src) {
2635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovapd(dst, src);
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movapd(dst, src);
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movsd(XMMRegister dst, XMMRegister src) {
2645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovsd(dst, dst, src);
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movsd(dst, src);
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movsd(XMMRegister dst, const Operand& src) {
2655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovsd(dst, src);
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movsd(dst, src);
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movsd(const Operand& dst, XMMRegister src) {
2665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovsd(dst, src);
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movsd(dst, src);
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movss(XMMRegister dst, XMMRegister src) {
2675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovss(dst, dst, src);
2678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movss(dst, src);
2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movss(XMMRegister dst, const Operand& src) {
2685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovss(dst, src);
2688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movss(dst, src);
2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movss(const Operand& dst, XMMRegister src) {
2695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovss(dst, src);
2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movss(dst, src);
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movd(XMMRegister dst, Register src) {
2705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovd(dst, src);
2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movd(XMMRegister dst, const Operand& src) {
2715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovd(dst, src);
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movd(Register dst, XMMRegister src) {
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovd(dst, src);
27283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
27303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
27313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
27323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
27333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movq(XMMRegister dst, Register src) {
2735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovq(dst, src);
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movq(dst, src);
2740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movq(Register dst, XMMRegister src) {
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovq(dst, src);
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movq(dst, src);
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movmskpd(Register dst, XMMRegister src) {
2755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovmskpd(dst, src);
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movmskpd(dst, src);
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Roundss(XMMRegister dst, XMMRegister src,
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             RoundingMode mode) {
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vroundss(dst, dst, src, mode);
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    roundss(dst, src, mode);
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Roundsd(XMMRegister dst, XMMRegister src,
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             RoundingMode mode) {
2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vroundsd(dst, dst, src, mode);
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    roundsd(dst, src, mode);
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Sqrtsd(XMMRegister dst, XMMRegister src) {
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsqrtsd(dst, dst, src);
2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sqrtsd(dst, src);
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Sqrtsd(XMMRegister dst, const Operand& src) {
2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsqrtsd(dst, dst, src);
2800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sqrtsd(dst, src);
2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomiss(XMMRegister src1, XMMRegister src2) {
2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomiss(src1, src2);
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomiss(src1, src2);
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomiss(XMMRegister src1, const Operand& src2) {
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomiss(src1, src2);
2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomiss(src1, src2);
2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomisd(XMMRegister src1, XMMRegister src2) {
2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomisd(src1, src2);
2830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomisd(src1, src2);
2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomisd(XMMRegister src1, const Operand& src2) {
2837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomisd(src1, src2);
2840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomisd(src1, src2);
2842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
2847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference smi_check;
2848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (source->IsSmi()) {
2849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Cmp(dst, Smi::cast(*source));
2850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MoveHeapObject(kScratchRegister, source);
2852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cmpp(dst, kScratchRegister);
2853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference smi_check;
2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (source->IsSmi()) {
2860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Cmp(dst, Smi::cast(*source));
2861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MoveHeapObject(kScratchRegister, source);
2863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cmpp(dst, kScratchRegister);
2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(Handle<Object> source) {
2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference smi_check;
2870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (source->IsSmi()) {
2871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(Smi::cast(*source));
2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MoveHeapObject(kScratchRegister, source);
2874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(kScratchRegister);
2875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::MoveHeapObject(Register result,
2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Handle<Object> object) {
2881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference using_raw_address;
2882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(object->IsHeapObject());
2883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(result, cell, RelocInfo::CELL);
2886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(result, Operand(result, 0));
2887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(result, object, RelocInfo::EMBEDDED_OBJECT);
2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalCell(Register dst, Handle<Cell> cell) {
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (dst.is(rax)) {
2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    AllowDeferredHandleDereference embedding_raw_address;
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    load_rax(cell.location(), RelocInfo::CELL);
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(dst, cell, RelocInfo::CELL);
2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(dst, Operand(dst, 0));
2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Register scratch) {
2906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(scratch, cell, RelocInfo::EMBEDDED_OBJECT);
2907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
2912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(value, cell, RelocInfo::EMBEDDED_OBJECT);
2913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(value, FieldOperand(value, WeakCell::kValueOffset));
2914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
2919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
2920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(value, miss);
2921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Drop(int stack_elements) {
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (stack_elements > 0) {
2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    addp(rsp, Immediate(stack_elements * kPointerSize));
2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::DropUnderReturnAddress(int stack_elements,
2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                            Register scratch) {
2933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(stack_elements > 0);
2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size && stack_elements == 1) {
2935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popq(MemOperand(rsp, 0));
2936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PopReturnAddressTo(scratch);
2940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Drop(stack_elements);
2941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PushReturnAddressFrom(scratch);
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(Register src) {
2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(src);
2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // x32 uses 64-bit push for rbp in the prologue.
2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(src.code() != rbp.code());
2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), src);
2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(const Operand& src) {
2958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
2959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(src);
2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(kScratchRegister, src);
2962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), kScratchRegister);
2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushQuad(const Operand& src) {
2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(src);
2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(kScratchRegister, src);
2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(kScratchRegister);
2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(Immediate value) {
2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
2980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(value);
2981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), value);
2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushImm32(int32_t imm32) {
2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq_imm32(imm32);
2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), Immediate(imm32));
2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pop(Register dst) {
2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popq(dst);
3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // x32 uses 64-bit pop for rbp in the epilogue.
3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(dst.code() != rbp.code());
3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(dst, Operand(rsp, 0));
3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, 4));
3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pop(const Operand& dst) {
3011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popq(dst);
3013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register scratch = dst.AddressUsesRegister(kScratchRegister)
3015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ? kRootRegister : kScratchRegister;
3016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(scratch, Operand(rsp, 0));
3017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(dst, scratch);
3018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, 4));
3019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (scratch.is(kRootRegister)) {
3020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Restore kRootRegister.
3021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      InitializeRootRegister();
3022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PopQuad(const Operand& dst) {
3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popq(dst);
3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popq(kScratchRegister);
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadSharedFunctionInfoSpecialField(Register dst,
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        Register base,
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        int offset) {
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset > SharedFunctionInfo::kLengthOffset &&
3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         offset <= SharedFunctionInfo::kSize &&
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (((offset - SharedFunctionInfo::kLengthOffset) / kIntSize) % 2 == 1));
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, FieldOperand(base, offset));
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, FieldOperand(base, offset));
3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(dst, dst);
3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestBitSharedFunctionInfoSpecialField(Register base,
3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           int offset,
3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           int bits) {
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset > SharedFunctionInfo::kLengthOffset &&
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         offset <= SharedFunctionInfo::kSize &&
3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (((offset - SharedFunctionInfo::kLengthOffset) / kIntSize) % 2 == 1));
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt32Size) {
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // On x32, this field is represented by SMI.
3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bits += kSmiShift;
3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_offset = bits / kBitsPerByte;
30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int bit_in_byte = bits & (kBitsPerByte - 1);
3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testb(FieldOperand(base, offset + byte_offset), Immediate(1 << bit_in_byte));
30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) {
306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Jump(const Operand& op) {
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(op);
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, op);
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(kScratchRegister);
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, destination, rmode);
3086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
3087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
30913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Inline this
30923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(code_object, rmode);
3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(ExternalReference ext) {
309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return LoadAddressSize(ext) +
3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Assembler::kCallScratchRegisterInstructionLength;
310044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
310144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
310244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) {
310444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
310544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(ext);
310644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
310744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
310944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
311044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
311144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Call(const Operand& op) {
3116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size && !CpuFeatures::IsSupported(ATOM)) {
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(op);
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, op);
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(kScratchRegister);
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
312644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int end_position = pc_offset() + CallSize(destination);
312844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, destination, rmode);
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
313144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
313244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pc_offset(), end_position);
313344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(Handle<Code> code_object,
3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          RelocInfo::Mode rmode,
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          TypeFeedbackId ast_id) {
314044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
314144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(code_object);
314244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode) ||
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rmode == RelocInfo::CODE_AGE_SEQUENCE);
3145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(code_object, rmode, ast_id);
314644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
314744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
314844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
3153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 0) {
3154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movd(dst, src);
3155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, imm8);
3158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
3159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
3160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pextrd(dst, src, imm8);
3161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movq(dst, src);
3164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  shrq(dst, Immediate(32));
3165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, Register src, int8_t imm8) {
3169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
3170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
3171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movd(xmm0, src);
3175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
3176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
3177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movss(dst, xmm0);
3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
3185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(imm8 == 0 || imm8 == 1);
3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movd(xmm0, src);
3192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
3193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
3196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movss(dst, xmm0);
3197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntl(Register dst, Register src) {
3202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntl(dst, src);
3205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrl(dst, src);
3209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 63);  // 63^31 == 32
3211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(31));  // for x in [0..31], 31^x == 31 - x
3213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntl(Register dst, const Operand& src) {
3217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntl(dst, src);
3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrl(dst, src);
3224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 63);  // 63^31 == 32
3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(31));  // for x in [0..31], 31^x == 31 - x
3228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntq(Register dst, Register src) {
3232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntq(dst, src);
3235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrq(dst, src);
3239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 127);  // 127^63 == 64
3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(63));  // for x in [0..63], 63^x == 63 - x
3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntq(Register dst, const Operand& src) {
3247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntq(dst, src);
3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrq(dst, src);
3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 127);  // 127^63 == 64
3256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(63));  // for x in [0..63], 63^x == 63 - x
3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntq(Register dst, Register src) {
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntq(dst, src);
3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfq(dst, src);
3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Define the result of tzcnt(0) separately, because bsf(0) is undefined.
3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 64);
3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntq(Register dst, const Operand& src) {
3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntq(dst, src);
3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfq(dst, src);
3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Define the result of tzcnt(0) separately, because bsf(0) is undefined.
3286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 64);
3287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntl(Register dst, Register src) {
3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntl(dst, src);
3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfl(dst, src);
3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 32);  // The result of tzcnt is 32 if src = 0.
3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntl(Register dst, const Operand& src) {
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntl(dst, src);
3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfl(dst, src);
3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 32);  // The result of tzcnt is 32 if src = 0.
3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntl(Register dst, Register src) {
3320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntl(dst, src);
3323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntl(Register dst, const Operand& src) {
3330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntl(dst, src);
3333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntq(Register dst, Register src) {
3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntq(dst, src);
3343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntq(Register dst, const Operand& src) {
3350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntq(dst, src);
3353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Pushad() {
3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rax);
3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rcx);
3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rdx);
3363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rbx);
33641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Not pushing rsp or rbp.
3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rsi);
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rdi);
3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r8);
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r9);
33691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r10 is kScratchRegister.
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r11);
3371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Push(r12);
33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r13 is kRootRegister.
3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r14);
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r15);
3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(12 == kNumSafepointSavedRegisters);
3376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Use lea for symmetry with Popad.
3377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
3378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(rsp, Operand(rsp, -sp_delta));
33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
33811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Popad() {
3384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Popad must not change the flags, so use lea instead of addq.
3385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
3386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(rsp, Operand(rsp, sp_delta));
3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r15);
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r14);
3390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Pop(r12);
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r11);
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r9);
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r8);
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rdi);
3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rsi);
3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rbx);
3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rdx);
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rcx);
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rax);
34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Dropad() {
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Order general registers are pushed by Pushad:
340944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
34103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int
34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    0,
34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    1,
34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    2,
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    3,
34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    4,
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    5,
34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    6,
34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    7,
34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    8,
342444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    9,
3425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    -1,
3426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    10,
3427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    11
34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst,
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  const Immediate& imm) {
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(SafepointRegisterSlot(dst), imm);
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(SafepointRegisterSlot(dst), src);
3439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(dst, SafepointRegisterSlot(src));
3444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
3448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
3449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
3453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
3454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
34553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
34563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
34583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(ExternalOperand(handler_address));
3460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
34613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(ExternalOperand(handler_address), rsp);
3463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
34673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
34683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(ExternalOperand(handler_address));
3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
3471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
3475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
3476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PopReturnAddressTo(scratch);
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(rsp, Immediate(bytes_dropped));
3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushReturnAddressFrom(scratch);
34861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
34923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  fucomip();
34938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  fstp(0);
3494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
3498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
3499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
3501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
3502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
3506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
3507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       Immediate(static_cast<int8_t>(type)));
3508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
35183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
35213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
35263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
35333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
3534592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
3536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  j(above, fail, distance);
3537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
3538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map,
3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* fail,
3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance distance) {
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
35453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
35523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
35533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
35543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register index,
35553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister xmm_scratch,
3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* fail,
3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int elements_offset) {
3558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label smi_value, done;
35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
35613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
35633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
35643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
35653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
35663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Double value, turn potential sNaN into qNaN.
3568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(xmm_scratch, 1.0);
3569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mulsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset));
3570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&done, Label::kNear);
35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
35733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. convert to a double and store.
35743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiToInteger32(kScratchRegister, maybe_number);
3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtlsi2sd(xmm_scratch, kScratchRegister);
3577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
3578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movsd(FieldOperand(elements, index, times_8,
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     FixedDoubleArray::kHeaderSize - elements_offset),
35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        xmm_scratch);
35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
35903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
35913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
35943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    JumpIfSmi(obj, fail);
35953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
35983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
35993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
36003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
36013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
3603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(reg, Immediate(0xFFFFFF00));
3605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
3607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  decb(reg);  // 0 if negative, 255 if positive.
3608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
3609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
3613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister temp_xmm_reg,
3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Register result_reg) {
3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label conv_failure;
3617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Xorpd(temp_xmm_reg, temp_xmm_reg);
3618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtsd2si(result_reg, input_reg);
3619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(result_reg, Immediate(0xFFFFFF00));
3620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpl(result_reg, Immediate(1));
3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(overflow, &conv_failure, Label::kNear);
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(result_reg, Immediate(0));
3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subl(result_reg, Immediate(1));
3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(result_reg, Immediate(255));
3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Set(result_reg, 0);
3630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Ucomisd(input_reg, temp_xmm_reg);
3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &done, Label::kNear);
3632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, 255);
3633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
3634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadUint32(XMMRegister dst,
3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Register src) {
3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpq(src, Immediate(0xffffffff));
3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared);
3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2sd(dst, src);
3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
3658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvttsd2siq(result_reg, xmm0);
3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpq(result_reg, Immediate(1));
3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Slow case.
3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_reg.is(result_reg)) {
3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(kDoubleSize));
3666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movsd(MemOperand(rsp, 0), xmm0);
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SlowTruncateToI(result_reg, rsp, 0);
3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(rsp, Immediate(kDoubleSize));
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SlowTruncateToI(result_reg, input_reg);
3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep our invariant that the upper 32 bits are zero.
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(result_reg, result_reg);
3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       XMMRegister input_reg) {
3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
3682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvttsd2siq(result_reg, input_reg);
3683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpq(result_reg, Immediate(1));
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subp(rsp, Immediate(kDoubleSize));
3687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movsd(MemOperand(rsp, 0), input_reg);
3688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, rsp, 0);
3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(rsp, Immediate(kDoubleSize));
3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep our invariant that the upper 32 bits are zero.
3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(result_reg, result_reg);
3694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               XMMRegister scratch,
3699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
3702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvttsd2si(result_reg, input_reg);
3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtlsi2sd(xmm0, result_reg);
3704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Ucomisd(xmm0, input_reg);
3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);  // NaN.
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The integer converted back is equal to the original. We
3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // only have to test if we got -0 as an input.
3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(result_reg, result_reg);
3712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
3713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movmskpd(result_reg, input_reg);
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bit 0 contains the sign of the double in input_reg.
3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If input was positive, we are ok and return 0, otherwise
3716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump to minus_zero.
3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andl(result_reg, Immediate(1));
3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
3731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(dst, FieldOperand(map, Map::kBitField3Offset));
3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(dst, FieldOperand(map, Map::kBitField3Offset));
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(dst, Immediate(Map::EnumLengthBits::kMask));
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Integer32ToSmi(dst, dst);
3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
3745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
3746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
3747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, FieldOperand(holder, HeapObject::kMapOffset));
3748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
3749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
3750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
3751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
3752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, FieldOperand(dst, offset));
3753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
3757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
3758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
3759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
3760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
3761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
3763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  movq(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
3765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success, RelocInfo::CODE_TARGET);
3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
3768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
3772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(is_smi, &ok, Label::kNear);
3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Cmp(FieldOperand(object, HeapObject::kMapOffset),
3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotANumber);
3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3781402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
3782402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(NegateCondition(is_smi), kOperandIsASmi);
3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3789756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3790756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3791756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(is_smi, kOperandIsNotASmi);
3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
379744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
379844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
379944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(const Operand& object) {
3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(is_smi, kOperandIsNotASmi);
3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertZeroExtended(Register int32_register) {
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!int32_register.is(kScratchRegister));
3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movq(kScratchRegister, V8_INT64_C(0x0000000100000000));
3812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpq(kScratchRegister, int32_register);
3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(object, Immediate(kSmiTagMask));
3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(object);
3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(object, FieldOperand(object, HeapObject::kMapOffset));
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Pop(object);
3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
38286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
38296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
38306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(object, Immediate(kSmiTagMask));
3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(object);
3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(object, FieldOperand(object, HeapObject::kMapOffset));
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Pop(object);
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
3845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
3846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    testb(object, Immediate(kSmiTagMask));
3847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
3848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
3849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
3850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
3851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
3852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
3857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
3858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    testb(object, Immediate(kSmiTagMask));
3859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
3860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
3861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
3862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
3863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
3864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Cmp(object, isolate()->factory()->undefined_value());
3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Cmp(FieldOperand(object, 0), isolate()->factory()->allocation_site_map());
3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertRootValue(Register src,
3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Heap::RootListIndex root_value_index,
3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     BailoutReason reason) {
3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src.is(kScratchRegister));
3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(kScratchRegister, root_value_index);
3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(src, kScratchRegister);
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, reason);
3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
38909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
38919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
38929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
38939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
3895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register map,
3896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register instance_type) {
3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
38984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
389969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
3900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testb(instance_type, Immediate(kIsNotStringMask));
3901d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
3902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
3903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpb(instance_type, Immediate(static_cast<uint8_t>(LAST_NAME_TYPE)));
3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
3916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
3917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
3918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
3919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
3920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
3921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
3922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
3923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
3924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
3925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
3926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
39273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
3930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Label* miss) {
3931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(result,
3933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
3936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
3937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
3938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareRoot(result, Heap::kTheHoleValueRootIndex);
3939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, miss);
3940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
3942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, kScratchRegister);
3944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &done, Label::kNear);
3945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
3947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(result, FieldOperand(result, Map::kPrototypeOffset));
3948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
3950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
3951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
3955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
39578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movl(counter_operand, Immediate(value));
3958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
3964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
3966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      incl(counter_operand);
3968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addl(counter_operand, Immediate(value));
3970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
3977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
3979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      decl(counter_operand);
3981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subl(counter_operand, Immediate(value));
3983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3988402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
39899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Set(rax, 0);  // No arguments.
3990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadAddress(rbx,
3991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              ExternalReference(Runtime::kHandleDebuggerStatement, isolate()));
3992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
3993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(&ces));
3994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
3995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Register function,
3999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
4000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& actual,
4001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    InvokeFlag flag,
4002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const CallWrapper& call_wrapper) {
4003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(rbx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
4004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadSharedFunctionInfoSpecialField(
4005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      rbx, rbx, SharedFunctionInfo::kFormalParameterCountOffset);
4006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ParameterCount expected(rbx);
4008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunction(function, new_target, expected, actual, flag, call_wrapper);
4009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
4013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& expected,
4014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& actual,
4015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    InvokeFlag flag,
4016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const CallWrapper& call_wrapper) {
4017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(rdi, function);
4018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunction(rdi, no_reg, expected, actual, flag, call_wrapper);
4019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Register function,
4023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
4024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& expected,
4025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& actual,
4026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    InvokeFlag flag,
4027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const CallWrapper& call_wrapper) {
4028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(rdi));
4029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(rsi, FieldOperand(function, JSFunction::kContextOffset));
4030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(rdi, new_target, expected, actual, flag, call_wrapper);
4031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
4035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
4036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
4037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
4038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
4041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(rdi));
4042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(rdx));
4043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call_wrapper.NeedsDebugStepCheck()) {
4045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FloodFunctionIfStepping(function, new_target, expected, actual);
4046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
4049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
4050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
4051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
40543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InvokePrologue(expected,
4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 actual,
4057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 &done,
40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &definitely_mismatches,
4059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 flag,
4060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Label::kNear,
4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 call_wrapper);
40623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
4063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
4064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
4065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
4066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
40733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
40743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
4076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
4081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const ParameterCount& actual,
4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
40833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
4084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    InvokeFlag flag,
4085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump,
4086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
4087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool definitely_matches = false;
40883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
4089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label invoke;
4090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (expected.is_immediate()) {
4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
4092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Set(rax, actual.immediate());
4093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (expected.immediate() == actual.immediate()) {
4094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      definitely_matches = true;
4095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
4096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (expected.immediate() ==
4097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
4098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't worry about adapting arguments for built-ins that
4099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // don't want that done. Skip adaption code by making it look
4100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // like we have a match between expected and actual number of
4101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // arguments.
4102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        definitely_matches = true;
4103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
4105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Set(rbx, expected.immediate());
4106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
4107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (actual.is_immediate()) {
4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Expected is in register, actual is immediate. This is the
4111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // case when we invoke function values without going through the
4112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // IC mechanism.
4113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Set(rax, actual.immediate());
4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmpp(expected.reg(), Immediate(actual.immediate()));
4115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(rbx));
4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (!expected.reg().is(actual.reg())) {
4118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Both expected and actual are in (different) registers. This
4119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // is the case when we invoke functions using call and apply.
4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmpp(expected.reg(), actual.reg());
4121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(rax));
4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(rbx));
4124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(rax, actual.reg());
4126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!definitely_matches) {
4130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
4131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (flag == CALL_FUNCTION) {
4132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
4133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Call(adaptor, RelocInfo::CODE_TARGET);
4134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
41363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, near_jump);
41373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
4139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Jump(adaptor, RelocInfo::CODE_TARGET);
4140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&invoke);
41421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
4143402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
4144402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4145402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
4147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& expected,
4148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& actual) {
4149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip_flooding;
4150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference step_in_enabled =
4151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::debug_step_in_enabled_address(isolate());
4152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Operand step_in_enabled_operand = ExternalOperand(step_in_enabled);
4153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpb(step_in_enabled_operand, Immediate(0));
4154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &skip_flooding);
4155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
4156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
4157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
4158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Integer32ToSmi(expected.reg(), expected.reg());
4160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
4161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Integer32ToSmi(actual.reg(), actual.reg());
4164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
4165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
4168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1);
4172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
4173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
4175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
4178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiToInteger64(actual.reg(), actual.reg());
4179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
4182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiToInteger64(expected.reg(), expected.reg());
4183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&skip_flooding);
4186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StubPrologue() {
4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pushq(rbp);  // Caller's frame pointer.
4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(rbp, rsp);
4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(rsi);  // Callee's context.
4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(Smi::FromInt(StackFrame::STUB));
4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         RelocInfo::CODE_AGE_SEQUENCE);
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength);
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pushq(rbp);  // Caller's frame pointer.
4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(rbp, rsp);
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(rsi);  // Callee's context.
4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(rdi);  // Callee's JS function.
4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
4215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
4217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
4218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
4222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
4223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on x64.
4224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
4225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pushq(rbp);
4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbp, rsp);
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rsi);  // Context.
42323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Push(Smi::FromInt(type));
4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(kScratchRegister);
423544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(kScratchRegister,
4237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         isolate()->factory()->undefined_value(),
4238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         RelocInfo::EMBEDDED_OBJECT);
4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(Operand(rsp, 0), kScratchRegister);
4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
4241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
424644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
42473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, Smi::FromInt(type));
4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
4250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rsp, rbp);
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  popq(rbp);
4253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
425680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) {
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
4258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All constants are relative to the frame pointer of the exit frame.
4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ExitFrameConstants::kCallerSPDisplacement ==
4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         kFPOnStackSize + kPCOnStackSize);
4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ExitFrameConstants::kCallerPCOffset == kFPOnStackSize);
4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pushq(rbp);
4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbp, rsp);
4265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(Immediate(0));  // Saved entry sp, patched before call.
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(kScratchRegister);  // Accessed from EditFrame::code_slot.
4271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
4273bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (save_rax) {
4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(r14, rax);  // Backup rax in callee-save register.
4275bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
4276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp);
4278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi);
4279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Store(ExternalReference(Isolate::kCFunctionAddress, isolate()), rbx);
4280bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
42831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
42841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool save_doubles) {
4285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64
42861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kShadowSpace = 4;
42871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  arg_stack_space += kShadowSpace;
4288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
42891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Optionally save all XMM registers.
42901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
4291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
4292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                arg_stack_space * kRegisterSize;
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(space));
42941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = -2 * kPointerSize;
4295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const RegisterConfiguration* config =
4296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
4297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DoubleRegister reg =
4299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
4300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
43011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
43021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (arg_stack_space > 0) {
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(arg_stack_space * kRegisterSize));
43048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
4305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
4308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_int8(kFrameAlignment));
4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(rsp, Immediate(-kFrameAlignment));
4312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
4316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
432080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(true);
4321bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame,
4323bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
4324bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(r15, Operand(rbp, r14, times_pointer_size, offset));
4326bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
43271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, save_doubles);
4328bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4329bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4330bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
43318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
433280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(false);
43331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, false);
4334bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4335bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4336bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
4338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Registers:
433944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r15 : argv
43401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
43411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = -2 * kPointerSize;
4342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const RegisterConfiguration* config =
4343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
4344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DoubleRegister reg =
4346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
4347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
43481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
43491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
4350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
4352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
4353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(rcx, Operand(rbp, kFPOnStackSize));
4354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(rbp, Operand(rbp, 0 * kPointerSize));
4355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Drop everything up to and including the arguments and the receiver
4357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // from the caller stack.
4358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leap(rsp, Operand(r15, 1 * kPointerSize));
4359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PushReturnAddressFrom(rcx);
4361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
4362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
4363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
4364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
43658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
43678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
43688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
43698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rsp, rbp);
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  popq(rbp);
43738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
43758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
43768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
43778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
4379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
4380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
438144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand context_operand = ExternalOperand(context_address);
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(rsi, context_operand);
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(context_operand, Immediate(0));
4387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
4388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
4390589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
439144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
439244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(c_entry_fp_operand, Immediate(0));
4394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
4398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
4399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
4400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
4401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!holder_reg.is(scratch));
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(kScratchRegister));
4404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
4406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
440844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(scratch, Immediate(0));
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
4411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the native context of the current context.
4413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
4414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
441644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->native_context_map());
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
4420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
4424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, &same_contexts);
4425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens.
4427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
4428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
4429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
4430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
443244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Preserve original value of holder_reg.
4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(holder_reg);
4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(holder_reg,
4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
4437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
4439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Read the first word and compare to native_context_map(),
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Pop(holder_reg);
4445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister,
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
44493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int token_offset =
44503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, FieldOperand(scratch, token_offset));
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch, FieldOperand(kScratchRegister, token_offset));
4453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
4454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
4456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
4462c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
4463c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // First of all we assign the hash seed to scratch.
4464c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  LoadRoot(scratch, Heap::kHashSeedRootIndex);
4465c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiToInteger32(scratch, scratch);
4466c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4467c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
4468c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4470c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Compute the hash code from the untagged key.  This must be kept in sync
4471c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // with ComputeIntegerHash in utils.h.
4472c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //
4473c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
4474c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4475c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  notl(r0);
4476c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shll(scratch, Immediate(15));
4477c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  addl(r0, scratch);
4478c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
4479c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4480c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(12));
4481c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4482c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
4483c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  leal(r0, Operand(r0, r0, times_4, 0));
4484c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
4485c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4486c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(4));
4487c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4488c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
4489c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imull(r0, r0, Immediate(2057));
4490c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
4491c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4492c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(16));
4493c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  andl(r0, Immediate(0x3fffffff));
4495c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
4496c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4497c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4498c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
44993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
45003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
45013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
45023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
45033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
45043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
45053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
45063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
45073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver on entry.
45093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
45103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry.
45123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
45133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
45153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
45173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
45193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
45213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
45223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeded.
45233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Allowed to be the same as 'key' or 'result'.
45243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Unchanged on bailout so 'key' or 'result' can be used
45253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          in further computation.
45263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
45283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4529c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(r0, r1);
45303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
4532c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiToInteger32(r1, FieldOperand(elements,
4533c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                  SeededNumberDictionary::kCapacityOffset));
45343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  decl(r1);
45353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kNumberDictionaryProbes; i++) {
45383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(r2, r0);
45403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
45413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
4542c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
45433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(r2, r1);
45453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SeededNumberDictionary::kEntrySize == 3);
4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leap(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
45493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(key, FieldOperand(elements,
45523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           r2,
45533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           times_pointer_size,
4554c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                           SeededNumberDictionary::kElementsStartOffset));
4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != (kNumberDictionaryProbes - 1)) {
45563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
45573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
45583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
45593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
45603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
45613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
4563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the value is a field property.
45643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
4565c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
4566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(DATA, 0);
45673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
4568589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       Smi::FromInt(PropertyDetails::TypeField::kMask));
45693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
45703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
45723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
4573c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
45753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
45763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
4579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
4580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
4585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
4586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!scratch.is_valid());
4588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
4589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand top_operand = ExternalOperand(allocation_top);
4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(result, top_operand);
4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
4593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
4594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
4595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Move address of new object to result. Use scratch register if available,
45986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and keep address in scratch until call to UpdateAllocationTopHelper.
45996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is_valid()) {
4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadAddress(scratch, allocation_top);
4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(result, Operand(scratch, 0));
4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Load(result, allocation_top);
4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MakeSureDoubleAlignedHelper(Register result,
4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch,
4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required,
4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 AllocationFlags flags) {
4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kDoubleSize) {
4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_debug_code) {
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      testl(result, Immediate(kDoubleAlignmentMask));
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Check(zero, kAllocationIsNotDoubleAligned);
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
46176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Align the next allocation. Storing the filler map without checking top
4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is safe in new-space because the limit of the heap is aligned there.
4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerSize * 2 == kDoubleSize);
4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make sure scratch is not clobbered by this function as it might be
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // used in UpdateAllocationTopHelper later.
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!scratch.is(kScratchRegister));
4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(result, Immediate(kDoubleAlignmentMask));
4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
4628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((flags & PRETENURE) != 0) {
4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference allocation_limit =
4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmpp(result, ExternalOperand(allocation_limit));
4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(kScratchRegister, Heap::kOnePointerFillerMapRootIndex);
4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(result, 0), kScratchRegister);
4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(result, Immediate(kDoubleSize / 2));
4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
4638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
464544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(result_end, Immediate(kObjectAlignmentMask));
4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
4648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top.
465444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is_valid()) {
465544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Scratch already contains address of allocation top.
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(scratch, 0), result_end);
4657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Store(allocation_top, result_end);
4659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
46715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
467244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
46735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
46745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
46755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
46765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(result_end, Immediate(0x7191));
46775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
46785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
46795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
46805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
46815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
46825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
46835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
46845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
4686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
46888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
4689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
46976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register top_reg = result_end.is_valid() ? result_end : result;
46996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(top_reg, result);
47026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(top_reg, Immediate(object_size));
47041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand limit_operand = ExternalOperand(allocation_limit);
4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(top_reg, limit_operand);
4707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
4708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
4710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(top_reg, scratch, flags);
4711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool tag_result = (flags & TAG_OBJECT) != 0;
47136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (tag_result) {
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      subp(result, Immediate(object_size - kHeapObjectTag));
47166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      subp(result, Immediate(object_size));
47186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (tag_result) {
47206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Tag the result if requested.
4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incp(result);
4723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(result_end, Operand(element_count, element_size, header_size));
4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(result_end, result, result_end, scratch, gc_required, flags);
4738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
47485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
474944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
47505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
47515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
47525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result_end, Immediate(0x7191));
47535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
47545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
47555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
47565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
47575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
47585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
47595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
47605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
47625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
4763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
47648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
4765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(result_end, object_size);
4775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(result_end, result);
47771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  j(carry, gc_required);
4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand limit_operand = ExternalOperand(allocation_limit);
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(result_end, limit_operand);
4780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
4781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update allocation top.
4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateAllocationTopHelper(result_end, scratch, flags);
4784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag the result if requested.
4786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(result, Immediate(kHeapObjectTag));
4788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
47933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch,
4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
47963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::RootListIndex map_index = mode == MUTABLE
4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Heap::kMutableHeapNumberMapRootIndex
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Heap::kHeapNumberMapRootIndex;
48023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, map_index);
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
48063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
48073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result,
4810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register length,
4811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch1,
4812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch2,
4813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch3,
4814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Label* gc_required) {
4815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
4816e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
48176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
48186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kShortSize == 2);
4820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
48226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                kHeaderAlignment));
4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(scratch1, Immediate(~kObjectAlignmentMask));
48246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(scratch1, Immediate(kHeaderAlignment));
48266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate two byte string in new space.
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqTwoByteString::kHeaderSize,
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           times_1,
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch1,
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           result,
4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch2,
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch3,
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required,
4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
4837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
4839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
48416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
4842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kLengthOffset), scratch1);
4843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kHashFieldOffset),
4844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
4845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch3,
4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
4852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
4853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kHeaderAlignment = SeqOneByteString::kHeaderSize &
48556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
4856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movl(scratch1, length);
4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kCharSize == 1);
4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(scratch1, Immediate(~kObjectAlignmentMask));
48606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(scratch1, Immediate(kHeaderAlignment));
48626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SeqOneByteString::kHeaderSize,
4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           times_1,
4867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch1,
4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           result,
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch2,
4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch3,
4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required,
4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
4873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kOneByteStringMapRootIndex);
4876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
48776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kLengthOffset), scratch1);
4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kHashFieldOffset),
4880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
4881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
4885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch1,
4886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch2,
4887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* gc_required) {
4888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
4891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
4893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
4895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result,
4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch1,
4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch2,
4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Label* gc_required) {
4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize,
4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           result,
4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch1,
4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           scratch2,
4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           gc_required,
4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
4908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kConsOneByteStringMapRootIndex);
4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
4912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4915589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
4916589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Register scratch1,
4917589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Register scratch2,
4918589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Label* gc_required) {
4919589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Allocate heap number in new space.
4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
4922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set the map. The other fields are left uninitialized.
4924589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
4926589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
4927589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch1,
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch2,
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required) {
4933589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Allocate heap number in new space.
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           TAG_OBJECT);
4936589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4937589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set the map. The other fields are left uninitialized.
4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kSlicedOneByteStringMapRootIndex);
4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
4940589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
4941589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4942589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
4944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
4945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
4946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
4947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
4948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
4949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
4951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
4952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
4954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
4955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), scratch);
4956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
4957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
4958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, JSObject::kElementsOffset), scratch);
4959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, JSValue::kValueOffset), value);
4960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
4961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
496444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Copy memory, byte-by-byte, from source to destination.  Not optimized for
496544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// long or aligned copies.  The contents of scratch and length are destroyed.
496644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Destination is incremented by length, source, length and scratch are
496744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// clobbered.
496844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A simpler loop is faster on small copies, but slower on large ones.
496944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The cld() instruction must have been emitted, to set the direction flag(),
497044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// before calling this function.
497144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CopyBytes(Register destination,
497244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register source,
497344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register length,
497444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               int min_length,
497544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch) {
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(min_length >= 0);
4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
497844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpl(length, Immediate(min_length));
4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(greater_equal, kInvalidMinLength);
498044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label short_loop, len8, len16, len24, done, short_string;
498244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kLongStringLimit = 4 * kPointerSize;
498444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(kPointerSize));
4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below, &short_string, Label::kNear);
498744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
498844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(source.is(rsi));
4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(destination.is(rdi));
4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length.is(rcx));
4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (min_length <= kLongStringLimit) {
4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(2 * kPointerSize));
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below_equal, &len8, Label::kNear);
4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(3 * kPointerSize));
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below_equal, &len16, Label::kNear);
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(4 * kPointerSize));
4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below_equal, &len24, Label::kNear);
5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
500244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Because source is 8-byte aligned in our uses of this function,
500344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // we keep source aligned for the rep movs operation by copying the odd bytes
500444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // at the end of the ranges.
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, length);
5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrl(length, Immediate(kPointerSizeLog2));
5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  repmovsp();
500844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move remaining bytes of length.
5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch, Immediate(kPointerSize - 1));
5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(length, Operand(source, scratch, times_1, -kPointerSize));
5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(destination, scratch, times_1, -kPointerSize), length);
5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(destination, scratch);
501344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
501444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&len24);
5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, 2 * kPointerSize));
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, 2 * kPointerSize), scratch);
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&len16);
5020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, kPointerSize));
5021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, kPointerSize), scratch);
5022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&len8);
5023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, 0));
5024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, 0), scratch);
5025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move remaining bytes of length.
5026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, length, times_1, -kPointerSize));
5027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, length, times_1, -kPointerSize), scratch);
5028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(destination, length);
5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
503044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
503144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_string);
503244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (min_length == 0) {
503344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      testl(length, length);
5034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(zero, &done, Label::kNear);
503544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
503644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
503744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_loop);
5038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movb(scratch, Operand(source, 0));
5039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movb(Operand(destination, 0), scratch);
5040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incp(source);
5041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incp(destination);
5042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    decl(length);
5043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &short_loop);
504444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
504744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
504844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
504944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
5051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
50523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
50533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
50543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  jmp(&entry);
50553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
5056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(Operand(current_address, 0), filler);
5057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  addp(current_address, Immediate(kPointerSize));
50583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
5059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpp(current_address, end_address);
5060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(below, &loop);
50613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
5065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
5066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
5067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
5068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
5069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
5070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
5071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
5072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Slot is in the current function context.  Move it into the
5073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // destination register in case we store into it (the write barrier
5074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // cannot be allowed to destroy the context in rsi).
5075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, rsi);
5076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
50783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context
50793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // chain (i.e., the static scope chain and runtime context chain do
50803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // not agree).  A variable occurring in such a scope should have
50813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot type LOOKUP and not CONTEXT.
508244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
50833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
50843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kWithContextMapRootIndex);
5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
5086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
5087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
5088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
50893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
50913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
50923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
50933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
50943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
50953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
5096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(expected_kind));
5097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(transitioned_kind));
50983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
5100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(scratch, NativeContextOperand());
5101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpp(map_in_out,
5102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       ContextOperand(scratch, Context::ArrayMapIndex(expected_kind)));
51033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
51043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
5106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(map_in_out,
5107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
51083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
51093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
511144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64
511244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
511344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
511444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 6;
511544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
51167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
5119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, NativeContextOperand());
5120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, ContextOperand(dst, index));
5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
5125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Register map) {
5126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the initial map.  The global functions all have initial maps.
5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
512844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
5129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Label ok, fail;
5130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
5131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    jmp(&ok);
5132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&fail);
5133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
5134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&ok);
5135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
51394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
51407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On Windows 64 stack slots are reserved by the caller for all arguments
51417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // including the ones passed in registers, and space is always allocated for
51427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the four register arguments even if the function takes fewer than four
51437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // arguments.
51447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
51457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and the caller does not reserve stack slots for them.
5146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_arguments >= 0);
51474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64
514844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kMinimumStackSlots = kRegisterPassedArguments;
51497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
51507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments;
51514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else
51527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kRegisterPassedArguments) return 0;
51537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments - kRegisterPassedArguments;
51544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif
51554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
51564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
51577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
5159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
5161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
5162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
5163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object);
5164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
5165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
5166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(value);
5168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(value, FieldOperand(string, HeapObject::kMapOffset));
5169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzxbp(value, FieldOperand(value, Map::kInstanceTypeOffset));
5170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
5172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(value, Immediate(encoding_mask));
5173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(value);
5174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
5175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
5177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
5178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
5179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Integer32ToSmi(index, index);
5180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiCompare(index, FieldOperand(string, String::kLengthOffset));
5181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
5182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiCompare(index, Smi::FromInt(0));
5184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
5185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
5187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiToInteger32(index, index);
5188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
5192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
5193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(frame_alignment != 0);
5194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_arguments >= 0);
519544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
51964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Make stack end at alignment and allocate space for arguments and old rsp.
5197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister, rsp);
5198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
51994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
52004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
5201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subp(rsp, Immediate((argument_slots_on_stack + 1) * kRegisterSize));
5202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rsp, Immediate(-frame_alignment));
5203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(rsp, argument_slots_on_stack * kRegisterSize), kScratchRegister);
52044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
52054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
52064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
52074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function,
52084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                   int num_arguments) {
520944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rax, function);
52104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallCFunction(rax, num_arguments);
52114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
52124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
52134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
52144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
52166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
521744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
52186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
52196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
52206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
52214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  call(function);
5222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::OS::ActivationFrameAlignment() != 0);
5223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_arguments >= 0);
52244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
52254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
5226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rsp, Operand(rsp, argument_slots_on_stack * kRegisterSize));
52274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
52284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
5231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
5232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
5233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
5234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
5235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
5236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
5237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
5238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
5239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
5240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
5241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
5242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
5244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
5245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
5246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
5247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
5248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
5249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
5250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
5251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
5252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
5253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
52553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
52573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
52608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
52618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
5262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
5263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
5264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
5265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
5266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
5267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
5271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
5272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
5273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
5275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
5276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
5277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
52813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
52823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
52833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
52843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
52853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
52863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
5287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
52883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
5289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(scratch, Immediate(~Page::kPageAlignmentMask));
52903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Immediate(~Page::kPageAlignmentMask));
5292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(scratch, object);
52933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
52953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testb(Operand(scratch, MemoryChunk::kFlagsOffset),
52963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Immediate(static_cast<uint8_t>(mask)));
52973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
52983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
52993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
53003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
53013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
53053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_scratch,
53063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_scratch,
53073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
53083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_distance) {
5309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, rcx));
5310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
53113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
53123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
53143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The mask_scratch register contains a 1 at the position of the first bit
5315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and a 1 at a position of the second bit. All other positions are zero.
5316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, mask_scratch);
5317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
5318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(mask_scratch, rcx);
53193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(equal, on_black, on_black_distance);
53203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
53243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
53253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
5326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx));
5327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(bitmap_reg, addr_reg);
53283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sign extended 32 bit immediate.
5329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
5330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, addr_reg);
53313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
53323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
53333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shrl(rcx, Immediate(shift));
5334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rcx,
53353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate((Page::kPageAlignmentMask >> shift) &
53363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 ~(Bitmap::kBytesPerCell - 1)));
53373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(bitmap_reg, rcx);
5339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, addr_reg);
53403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shrl(rcx, Immediate(kPointerSizeLog2));
5341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1));
5342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movl(mask_reg, Immediate(3));
5343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp_cl(mask_reg);
53443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
5348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
5349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
5350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, rcx));
53513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
53523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
5354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
5355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
5356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
5357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
53583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
53603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
5361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
5362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, distance);
53633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
5367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
53683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register empty_fixed_array_value = r8;
53693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
5370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, rax);
5371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
5373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
5374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
5375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(rdx, rbx);
5377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cmp(rdx, Smi::FromInt(kInvalidEnumCacheSentinel));
5378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
5379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
5381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
53833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
5387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(rdx, rbx);
5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cmp(rdx, Smi::FromInt(0));
53893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
53903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
53923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
5394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
5395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
5396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(empty_fixed_array_value,
5397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       FieldOperand(rcx, JSObject::kElementsOffset));
5398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
53993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kEmptySlowElementDictionaryRootIndex);
5402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(kScratchRegister, FieldOperand(rcx, JSObject::kElementsOffset));
54033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
54043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
5406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
5407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(rcx, null_value);
54083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
54093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
54103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
5412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
5413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
5414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
5415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_start =
5416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_start(isolate());
5417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
5418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
5419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch_reg, Operand(receiver_reg,
5421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
5422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, new_space_start);
5423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch_reg, kScratchRegister);
5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(less, no_memento_found);
5425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch_reg, ExternalOperand(new_space_allocation_top));
5426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(greater, no_memento_found);
5427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize),
5428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Heap::kAllocationMementoMapRootIndex);
5429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
5433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
5434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch0,
5435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
5436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* found) {
5437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister)));
5438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch0));
5439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register current = scratch0;
5440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop_again, end;
5441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(current, object);
5443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(current, FieldOperand(current, HeapObject::kMapOffset));
5444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(current, FieldOperand(current, Map::kPrototypeOffset));
5445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompareRoot(current, Heap::kNullValueRootIndex);
5446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &end);
5447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop based on the map going up the prototype chain.
5449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop_again);
5450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(current, FieldOperand(current, HeapObject::kMapOffset));
5451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
5452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
5453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpInstanceType(current, JS_OBJECT_TYPE);
5454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(below, found);
5455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch1, FieldOperand(current, Map::kBitField2Offset));
5456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::ElementsKindBits>(scratch1);
5457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS));
5458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, found);
5459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(current, FieldOperand(current, Map::kPrototypeOffset));
5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareRoot(current, Heap::kNullValueRootIndex);
5461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, &loop_again);
5462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&end);
5464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
5468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(rax));
5469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(rdx));
5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
5471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
5472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(rax, Immediate(mag.multiplier));
5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imull(dividend);
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
5475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) addl(rdx, dividend);
5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) subl(rdx, dividend);
5477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sarl(rdx, Immediate(mag.shift));
5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(rax, dividend);
5479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrl(rax, Immediate(31));
5480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addl(rdx, rax);
5481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
54833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
5485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
5486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
5488