macro-assembler-x64.cc revision bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8
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.
2183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  ExternalReference store_buffer =
2193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      ExternalReference::store_buffer_top(isolate());
2203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(scratch, ExternalOperand(store_buffer));
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store pointer to buffer.
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(scratch, 0), addr);
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increment buffer top.
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(scratch, Immediate(kPointerSize));
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Write back new top of buffer.
2263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(ExternalOperand(store_buffer), scratch);
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call stub on end of buffer.
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for end of buffer.
2303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  testp(scratch, Immediate(StoreBuffer::kStoreBufferMask));
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label buffer_overflowed;
2333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(equal, &buffer_overflowed, Label::kNear);
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&buffer_overflowed);
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    j(not_equal, &done, Label::kNear);
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&store_buffer_overflow);
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (and_then == kReturnAtEnd) {
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ret(0);
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(and_then == kFallThroughAtEnd);
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InNewSpace(Register object,
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch,
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Condition cc,
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* branch,
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label::Distance distance) {
256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int mask =
257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      (1 << MemoryChunk::IN_FROM_SPACE) | (1 << MemoryChunk::IN_TO_SPACE);
258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(object, scratch, mask, cc, branch, distance);
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::RecordWriteField(
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset,
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value,
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register dst,
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SaveFPRegsMode save_fp,
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RememberedSetAction remembered_set_action,
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
2717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // First, check if a write barrier is even needed. The tests below
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Although the object register is tagged, the offset is relative to the start
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object, so so offset must be a multiple of kPointerSize.
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(offset, kPointerSize));
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(dst, FieldOperand(object, offset));
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (emit_debug_code()) {
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testb(dst, Immediate((1 << kPointerSizeLog2) - 1));
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(zero, &ok, Label::kNear);
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bind(&done);
2974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // turned on to provoke errors.
30044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(value, kZapValue, Assembler::RelocInfoNone());
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, kZapValue, Assembler::RelocInfoNone());
3034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteArray(
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index,
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode save_fp,
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
3158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, check if a write barrier is even needed. The tests below
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of Smis.
3178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
3188defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Skip barrier if writing a smi.
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3238defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array access: calculate the destination address. Index is not a smi.
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = index;
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(dst, Operand(object, index, times_pointer_size,
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   FixedArray::kHeaderSize - kHeapObjectTag));
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWrite(object, dst, value, save_fp, remembered_set_action,
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              OMIT_SMI_CHECK, pointers_to_here_check_for_value);
3318defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
3338defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered input registers when running with the debug-code flag
3358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
33644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(value, kZapValue, Assembler::RelocInfoNone());
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(index, kZapValue, Assembler::RelocInfoNone());
3398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
3408defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
3418defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3428defd9ff6930b4e24729971a61cf7469daf119beSteve Block
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWriteForMap(Register object,
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register map,
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register dst,
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       SaveFPRegsMode fp_mode) {
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(kScratchRegister));
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(map));
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(dst));
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!map.is(dst));
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
3524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) pushq(map);
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompareMap(map, isolate()->factory()->meta_map());
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) popq(map);
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok, Label::kNear);
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
3614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
3624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) {
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) pushq(map);
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(map, FieldOperand(object, HeapObject::kMapOffset));
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map.is(kScratchRegister)) popq(map);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &ok, Label::kNear);
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the address.
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(dst, FieldOperand(object, HeapObject::kMapOffset));
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // First, check if a write barrier is even needed. The tests below
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // catch stores of smis and stores into the young generation.
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // A single check of the map's pages interesting flag suffices, since it is
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only set during incremental collection, and then it's also guaranteed that
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the from object's page's interesting flag is also set.  This optimization
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relies on the fact that maps can never be in new space.
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckPageFlag(map,
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                map,  // Used as scratch.
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                MemoryChunk::kPointersToHereAreInterestingMask,
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                zero,
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                &done,
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label::kNear);
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallStub(&stub);
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // turned on to provoke errors.
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, kZapValue, Assembler::RelocInfoNone());
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(map, kZapValue, Assembler::RelocInfoNone());
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::RecordWrite(
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address,
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveFPRegsMode fp_mode,
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RememberedSetAction remembered_set_action,
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck smi_check,
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PointersToHereCheck pointers_to_here_check_for_value) {
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(value));
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!object.is(address));
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!value.is(address));
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertNotSmi(object);
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (remembered_set_action == OMIT_REMEMBERED_SET &&
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !FLAG_incremental_marking) {
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ok;
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(value, Operand(address, 0));
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    j(equal, &ok, Label::kNear);
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int3();
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&ok);
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First, check if a write barrier is even needed. The tests below
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // catch stores of smis and stores into the young generation.
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (smi_check == INLINE_SMI_CHECK) {
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip barrier if writing a smi.
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JumpIfSmi(value, &done);
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckPageFlag(value,
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  value,  // Used as scratch.
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MemoryChunk::kPointersToHereAreInterestingMask,
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  zero,
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &done,
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label::kNear);
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPageFlag(object,
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                value,  // Used as scratch.
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask,
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                zero,
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &done,
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label::kNear);
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       fp_mode);
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallStub(&stub);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Count number of write barriers in generated code.
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->write_barriers_static()->Increment();
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clobber clobbered registers when running with the debug-code flag
4764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(address, kZapValue, Assembler::RelocInfoNone());
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(value, kZapValue, Assembler::RelocInfoNone());
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
483109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::RecordWriteCodeEntryField(Register js_function,
484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register code_entry,
485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               Register scratch) {
486109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int offset = JSFunction::kCodeEntryOffset;
487109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
488109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // The input registers are fixed to make calling the C write barrier function
489109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // easier.
490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(js_function.is(rdi));
491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(code_entry.is(rcx));
492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(scratch.is(r15));
493109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
494109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Since a code entry (value) is always in old space, we don't need to update
495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // remembered set. If incremental marking is off, there is nothing for us to
496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // do.
497109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!FLAG_incremental_marking) return;
498109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  AssertNotSmi(js_function);
500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
501109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label ok;
503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    leap(scratch, FieldOperand(js_function, offset));
504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cmpp(code_entry, Operand(scratch, 0));
505109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(equal, &ok, Label::kNear);
506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int3();
507109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&ok);
508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // First, check if a write barrier is even needed. The tests below
511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // catch stores of Smis and stores into young gen.
512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label done;
513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
514109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(code_entry, scratch,
515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CheckPageFlag(js_function, scratch,
518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                Label::kNear);
520109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save input registers.
522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Push(js_function);
523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Push(code_entry);
524109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const Register dst = scratch;
526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  leap(dst, FieldOperand(js_function, offset));
527109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
528109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save caller-saved registers.
529109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
530109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int argument_count = 3;
532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PrepareCallCFunction(argument_count);
533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Load the argument registers.
535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (arg_reg_1.is(rcx)) {
536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Windows calling convention.
537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(arg_reg_2.is(rdx) && arg_reg_3.is(r8));
538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    movp(arg_reg_1, js_function);  // rcx gets rdi.
540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    movp(arg_reg_2, dst);          // rdx gets r15.
541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // AMD64 calling convention.
543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(arg_reg_1.is(rdi) && arg_reg_2.is(rsi) && arg_reg_3.is(rdx));
544109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
545109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // rdi is already loaded with js_function.
546bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    movp(arg_reg_2, dst);  // rsi gets r15.
547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Move(arg_reg_3, ExternalReference::isolate_address(isolate()));
549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  {
551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AllowExternalCallThatCantCauseGC scope(this);
552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallCFunction(
553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        ExternalReference::incremental_marking_record_write_code_entry_function(
554109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            isolate()),
555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        argument_count);
556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore caller-saved registers.
559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
560109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore input registers.
562109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Pop(code_entry);
563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Pop(js_function);
564109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
565109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bind(&done);
566109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Assert(Condition cc, BailoutReason reason) {
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) Check(cc, reason);
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
57444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
576756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
577756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedArrayMapRootIndex);
578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
579756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kFixedDoubleArrayMapRootIndex);
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(equal, &ok, Label::kNear);
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
583756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                Heap::kFixedCOWArrayMapRootIndex);
584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(equal, &ok, Label::kNear);
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kJSObjectWithFastElementsMapHasSlowElements);
586756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
587756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
588756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
589756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
590756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Check(Condition cc, BailoutReason reason) {
592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label L;
593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(cc, &L, Label::kNear);
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(reason);
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Control will not return here.
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CheckStackAlignment() {
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_alignment_mask = frame_alignment - 1;
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label alignment_as_expected;
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(rsp, Immediate(frame_alignment_mask));
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &alignment_as_expected, Label::kNear);
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Abort if stack is not aligned.
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int3();
6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&alignment_as_expected);
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::NegativeZeroTest(Register result,
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register op,
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* then_label) {
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(result, result);
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &ok, Label::kNear);
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testl(op, op);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(sign, then_label);
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&ok);
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Abort(BailoutReason reason) {
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* msg = GetBailoutReason(reason);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trap_on_abort) {
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int3();
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, Smi::FromInt(static_cast<int>(reason)),
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Assembler::RelocInfoNone());
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(kScratchRegister);
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!has_frame_) {
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We don't actually want to generate a pile of code for this, so just
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // claim there is a stack frame, without generating one.
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(this, StackFrame::NONE);
649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kAbort);
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kAbort);
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Control will not return here.
654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int3();
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs
660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::TailCallStub(CodeStub* stub) {
665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
66985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid MacroAssembler::StubReturn(int argc) {
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(argc >= 1 && generating_stub());
67185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ret((argc - 1) * kPointerSize);
672592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
673592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return has_frame_ || !stub->SometimesSetsUpAFrame();
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
68180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The assert checks that the constants for the maximum number of digits
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // for an array index cached in the hash field and the number of bits
68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // reserved for it does not conflict.
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
68580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hash.is(index)) {
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(index, hash);
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
6901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
69344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 int num_arguments,
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SaveFPRegsMode save_doubles) {
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(f->nargs < 0 || f->nargs == num_arguments);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
7024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
7034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
7044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
7058defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ExternalReference(f, isolate()));
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), f->result_size, save_doubles);
7084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallStub(&ces);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
7148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Set(rax, num_arguments);
71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate(), 1);
718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0]                 : return address
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8]                 : argument num_arguments - 1
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  ...
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  For runtime functions with variable arguments:
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //  -- rax                    : number of  arguments
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const Runtime::Function* function = Runtime::FunctionForId(fid);
734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, function->result_size);
735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (function->nargs >= 0) {
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Set(rax, function->nargs);
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpToExternalReference(ExternalReference(fid, isolate()));
739bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
740bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
741bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the entry point and jump to the C entry runtime stub.
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rbx, ext);
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CEntryStub ces(isolate(), 1);
7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REG(Name) \
751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  { Register::kCode_##Name }
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register saved_regs[] = {
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  REG(r9), REG(r10), REG(r11)
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef REG
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion1,
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion2,
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Register exclusion3) {
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We don't allow a GC during a store buffer overflow so there is no need to
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // store the registers in any particular way, but we do have to store and
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // restore them.
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < kNumberOfSavedRegs; i++) {
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = saved_regs[i];
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      pushq(reg);
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // R12 to r15 are callee save on all platforms.
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fp_mode == kSaveFPRegs) {
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      XMMRegister reg = XMMRegister::from_code(i);
781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(Operand(rsp, i * kDoubleSize), reg);
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode,
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion1,
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion2,
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Register exclusion3) {
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (fp_mode == kSaveFPRegs) {
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      XMMRegister reg = XMMRegister::from_code(i);
794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(reg, Operand(rsp, i * kDoubleSize));
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = saved_regs[i];
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      popq(reg);
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtss2sd(XMMRegister dst, XMMRegister src) {
808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtss2sd(dst, src, src);
811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtss2sd(dst, src);
813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtss2sd(XMMRegister dst, const Operand& src) {
818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtss2sd(dst, dst, src);
821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtss2sd(dst, src);
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtsd2ss(XMMRegister dst, XMMRegister src) {
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtsd2ss(dst, src, src);
831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtsd2ss(dst, src);
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtsd2ss(XMMRegister dst, const Operand& src) {
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtsd2ss(dst, dst, src);
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtsd2ss(dst, src);
843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtlsi2sd(XMMRegister dst, Register src) {
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtlsi2sd(dst, dst, src);
852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtlsi2sd(dst, src);
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtlsi2sd(dst, dst, src);
864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtlsi2sd(dst, src);
867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtlsi2ss(XMMRegister dst, Register src) {
872109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
873109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CpuFeatureScope scope(this, AVX);
874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vxorps(dst, dst, dst);
875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vcvtlsi2ss(dst, dst, src);
876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    xorps(dst, dst);
878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cvtlsi2ss(dst, src);
879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
880109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
881109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvtlsi2ss(XMMRegister dst, const Operand& src) {
884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
885109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CpuFeatureScope scope(this, AVX);
886109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vxorps(dst, dst, dst);
887109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vcvtlsi2ss(dst, dst, src);
888109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
889109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    xorps(dst, dst);
890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cvtlsi2ss(dst, src);
891109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
892109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
893109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
894109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2ss(XMMRegister dst, Register src) {
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorps(dst, dst, dst);
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2ss(dst, dst, src);
900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorps(dst, dst);
902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2ss(dst, src);
903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2ss(XMMRegister dst, const Operand& src) {
908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorps(dst, dst, dst);
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2ss(dst, dst, src);
912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorps(dst, dst);
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2ss(dst, src);
915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2sd(XMMRegister dst, Register src) {
920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2sd(dst, dst, src);
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2sd(dst, src);
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqsi2sd(XMMRegister dst, const Operand& src) {
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vxorpd(dst, dst, dst);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtqsi2sd(dst, dst, src);
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    xorpd(dst, dst);
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtqsi2sd(dst, src);
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqui2ss(XMMRegister dst, Register src, Register tmp) {
944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label msb_set_src;
945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label jmp_return;
946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  testq(src, src);
947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2ss(dst, src);
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&jmp_return, Label::kNear);
950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&msb_set_src);
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movq(tmp, src);
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  shrq(src, Immediate(1));
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Recover the least significant bit to avoid rounding errors.
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  andq(tmp, Immediate(1));
955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  orq(src, tmp);
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2ss(dst, src);
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  addss(dst, dst);
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&jmp_return);
959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) {
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label msb_set_src;
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label jmp_return;
965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  testq(src, src);
966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(sign, &msb_set_src, Label::kNear);
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2sd(dst, src);
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&jmp_return, Label::kNear);
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&msb_set_src);
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movq(tmp, src);
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  shrq(src, Immediate(1));
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  andq(tmp, Immediate(1));
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  orq(src, tmp);
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2sd(dst, src);
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  addsd(dst, dst);
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&jmp_return);
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvtsd2si(Register dst, XMMRegister src) {
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvtsd2si(dst, src);
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvtsd2si(dst, src);
986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
990109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvttss2si(Register dst, XMMRegister src) {
991109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CpuFeatureScope scope(this, AVX);
993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vcvttss2si(dst, src);
994109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
995109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cvttss2si(dst, src);
996109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
998109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
999109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1000109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::Cvttss2si(Register dst, const Operand& src) {
1001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CpuFeatureScope scope(this, AVX);
1003109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    vcvttss2si(dst, src);
1004109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
1005109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    cvttss2si(dst, src);
1006109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1007109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1008109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1009109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2si(Register dst, XMMRegister src) {
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2si(dst, src);
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2si(dst, src);
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2si(Register dst, const Operand& src) {
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2si(dst, src);
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2si(dst, src);
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttss2siq(Register dst, XMMRegister src) {
1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttss2siq(dst, src);
1034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttss2siq(dst, src);
1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttss2siq(Register dst, const Operand& src) {
1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttss2siq(dst, src);
1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttss2siq(dst, src);
1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2siq(Register dst, XMMRegister src) {
1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2siq(dst, src);
1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2siq(dst, src);
1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cvttsd2siq(Register dst, const Operand& src) {
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vcvttsd2siq(dst, src);
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cvttsd2siq(dst, src);
1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8()) {
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxbq(dst, src);
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger8()) {
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzxbl(dst, src);
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16()) {
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxwq(dst, src);
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsUInteger16()) {
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movzxwl(dst, src);
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger32()) {
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, src);
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!r.IsDouble());
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger8() || r.IsUInteger8()) {
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movb(dst, src);
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger16() || r.IsUInteger16()) {
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movw(dst, src);
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsInteger32()) {
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, src);
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsHeapObject()) {
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertNotSmi(src);
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AssertSmi(src);
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Set(Register dst, int64_t x) {
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (x == 0) {
11098defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (is_uint32(x)) {
1111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    movl(dst, Immediate(static_cast<uint32_t>(x)));
11128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (is_int32(x)) {
11138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movq(dst, Immediate(static_cast<int32_t>(x)));
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movq(dst, x);
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Set(const Operand& dst, intptr_t x) {
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (is_int32(x)) {
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, Immediate(static_cast<int32_t>(x)));
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Set(kScratchRegister, x);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, kScratchRegister);
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, Immediate(static_cast<int32_t>(x)));
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Smi tagging, untagging and tag detection.
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool MacroAssembler::IsUnsafeInt(const int32_t x) {
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMaxBits = 17;
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_intn(x, kMaxBits);
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafeMove(Register dst, Smi* src) {
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // JIT cookie can be converted to Smi.
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(dst, Smi::FromInt(src->value() ^ jit_cookie()));
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(kScratchRegister, Smi::FromInt(jit_cookie()));
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(dst, kScratchRegister);
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t value = static_cast<int32_t>(reinterpret_cast<intptr_t>(src));
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, Immediate(value ^ jit_cookie()));
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(dst, Immediate(jit_cookie()));
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(dst, src);
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SafePush(Smi* src) {
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // JIT cookie can be converted to Smi.
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Push(Smi::FromInt(src->value() ^ jit_cookie()));
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Move(kScratchRegister, Smi::FromInt(jit_cookie()));
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(Operand(rsp, 0), kScratchRegister);
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t value = static_cast<int32_t>(reinterpret_cast<intptr_t>(src));
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Push(Immediate(value ^ jit_cookie()));
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      xorp(Operand(rsp, 0), Immediate(jit_cookie()));
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(src);
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11818defd9ff6930b4e24729971a61cf7469daf119beSteve BlockRegister MacroAssembler::GetSmiConstant(Smi* source) {
1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
11838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int value = source->value();
11848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (value == 0) {
11858defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(kScratchRegister, kScratchRegister);
11868defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return kScratchRegister;
11878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
11888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  LoadSmiConstant(kScratchRegister, source);
11898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return kScratchRegister;
11908defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
11918defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11938defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int value = source->value();
119644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (value == 0) {
11978defd9ff6930b4e24729971a61cf7469daf119beSteve Block    xorl(dst, dst);
1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(dst, source, Assembler::RelocInfoNone());
12008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
12018defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
12028defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Integer32ToSmi(Register dst, Register src) {
120569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    movl(dst, src);
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(dst, Immediate(kSmiShift));
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
121444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
12159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    testb(dst, Immediate(0x01));
1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &ok, Label::kNear);
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kInteger32ToSmiFieldWritingToNonSmiLocation);
12199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bind(&ok);
12209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kSmiShift % kBitsPerByte == 0);
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(Operand(dst, kSmiShift / kBitsPerByte), src);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Integer32ToSmi(kScratchRegister, src);
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
12309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
12319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::Integer64PlusConstantToSmi(Register dst,
12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                Register src,
12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                int constant) {
12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
123744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    addl(dst, Immediate(constant));
12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
123944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    leal(dst, Operand(src, constant));
12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(dst, Immediate(kSmiShift));
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger32(Register dst, Register src) {
124669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src)) {
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shrp(dst, Immediate(kSmiShift));
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sarl(dst, Immediate(kSmiShift));
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, Operand(src, kSmiShift / kBitsPerByte));
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(dst, src);
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sarl(dst, Immediate(kSmiShift));
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
12687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiToInteger64(Register dst, Register src) {
127269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sarp(dst, Immediate(kSmiShift));
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt32Size) {
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Sign extend to 64-bit.
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, dst);
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger64(dst, dst);
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
12929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
12939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiTest(Register src) {
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(src);
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src, src);
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::SmiCompare(Register smi1, Register smi2) {
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(smi1);
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(smi2);
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(smi1, smi2);
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(Register dst, Smi* src) {
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
131044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Cmp(dst, src);
131144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
131244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
131344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
131444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(Register dst, Smi* src) {
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (src->value() == 0) {
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(dst, dst);
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
1319756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Register constant_reg = GetSmiConstant(src);
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(dst, constant_reg);
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiCompare(Register dst, const Operand& src) {
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(src);
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(dst, src);
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Register src) {
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(src);
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(dst, src);
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AssertSmi(dst);
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(dst, Immediate(src));
134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Cmp(const Operand& dst, Smi* src) {
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The Operand cannot use the smi register.
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register smi_reg = GetSmiConstant(src);
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.AddressUsesRegister(smi_reg));
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(dst, smi_reg);
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(kScratchRegister, dst);
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(kScratchRegister, src);
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
13669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
13679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           Register src,
13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                           int power) {
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(power >= 0);
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(power < 64);
13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power == 0) {
13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiToInteger64(dst, src);
13763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return;
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!dst.is(src)) {
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (power < kSmiShift) {
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sarp(dst, Immediate(kSmiShift - power));
13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (power > kSmiShift) {
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shlp(dst, Immediate(power - kSmiShift));
13853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
13907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         Register src,
13917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                         int power) {
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((0 <= power) && (power < 32));
13937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (dst.is(src)) {
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shrp(dst, Immediate(power + kSmiShift));
13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
13967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    UNIMPLEMENTED();  // Not used.
13977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
13987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* on_not_smis,
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label::Distance near_jump) {
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1) || dst.is(src2)) {
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(kScratchRegister));
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src2.is(kScratchRegister));
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(kScratchRegister, src2);
1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump);
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(dst, src2);
1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfNotSmi(dst, on_not_smis, near_jump);
1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckSmi(Register src) {
142069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  testb(src, Immediate(kSmiTagMask));
14223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14261e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition MacroAssembler::CheckSmi(const Operand& src) {
142769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
14281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  testb(src, Immediate(kSmiTagMask));
14291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return zero;
14301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
14311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
14321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1433f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckNonNegativeSmi(Register src) {
143469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
1435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Test that both bits of the mask 0x8000000000000001 are zero.
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister, src);
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rolp(kScratchRegister, Immediate(1));
14388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  testb(kScratchRegister, Immediate(3));
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return zero;
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCondition MacroAssembler::CheckBothSmi(Register first, Register second) {
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first.is(second)) {
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CheckSmi(first);
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
144769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leal(kScratchRegister, Operand(first, second, times_1, 0));
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(kScratchRegister, Immediate(0x03));
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(kScratchRegister, first);
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orl(kScratchRegister, second);
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(kScratchRegister, Immediate(kSmiTagMask));
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return zero;
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1461f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochCondition MacroAssembler::CheckBothNonNegativeSmi(Register first,
1462f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                                                  Register second) {
1463d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (first.is(second)) {
1464f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return CheckNonNegativeSmi(first);
1465d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister, first);
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  orp(kScratchRegister, second);
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rolp(kScratchRegister, Immediate(1));
1469f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  testl(kScratchRegister, Immediate(3));
1470d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
1471d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1472d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1473d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1474bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochCondition MacroAssembler::CheckEitherSmi(Register first,
1475bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register second,
1476bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         Register scratch) {
1477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (first.is(second)) {
1478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return CheckSmi(first);
1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1480bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (scratch.is(second)) {
1481bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, first);
1482bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
1483bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (!scratch.is(first)) {
1484bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      movl(scratch, first);
1485bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
1486bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    andl(scratch, second);
1487bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1488bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  testb(scratch, Immediate(kSmiTagMask));
1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return zero;
1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
14933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // A 32-bit integer value can always be converted to a smi.
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return always;
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(src, Immediate(0xc0000000));
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return positive;
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockCondition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // An unsigned 32-bit integer value is valid as long as the high bit
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is not set.
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(src, src);
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return positive;
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(src, Immediate(0xc0000000));
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return zero;
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, Register src) {
15201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (dst.is(src)) {
15211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
15221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
15231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
15241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
15251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
15261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
15271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
15281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
15291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) {
15301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!(src.AddressUsesRegister(dst))) {
15311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, Immediate(kSmiTagMask));
15321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, src);
15331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
15341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    movl(dst, src);
15351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    andl(dst, Immediate(kSmiTagMask));
15361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
15371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
15381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
15391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfValidSmiValue(Register src,
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* on_valid,
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label::Distance near_jump) {
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition is_valid = CheckInteger32ValidSmiValue(src);
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(is_valid, on_valid, near_jump);
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotValidSmiValue(Register src,
1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label* on_invalid,
1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Label::Distance near_jump) {
1551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckInteger32ValidSmiValue(src);
1552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfUIntValidSmiValue(Register src,
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label* on_valid,
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label::Distance near_jump) {
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition is_valid = CheckUInteger32ValidSmiValue(src);
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(is_valid, on_valid, near_jump);
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label* on_invalid,
1566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                Label::Distance near_jump) {
1567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_valid = CheckUInteger32ValidSmiValue(src);
1568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(is_valid), on_invalid, near_jump);
1569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmi(Register src,
1573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label* on_smi,
1574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Label::Distance near_jump) {
1575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(smi, on_smi, near_jump);
1577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotSmi(Register src,
1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smi,
1582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
1583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition smi = CheckSmi(src);
1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(smi), on_not_smi, near_jump);
1585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessNonNegativeSmi(
1589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register src, Label* on_not_smi_or_negative,
1590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
1591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition non_negative_smi = CheckNonNegativeSmi(src);
1592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump);
1593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfSmiEqualsConstant(Register src,
1597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Smi* constant,
1598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label* on_equals,
1599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Label::Distance near_jump) {
1600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiCompare(src, constant);
1601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, on_equals, near_jump);
1602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotBothSmi(Register src1,
1606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Register src2,
1607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label* on_not_both_smi,
1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      Label::Distance near_jump) {
1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothSmi(src1, src2);
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Register src2,
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label* on_not_both_smi,
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                  Label::Distance near_jump) {
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(NegateCondition(both_smi), on_not_both_smi, near_jump);
1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
16233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
16243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
16253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!dst.is(src)) {
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
16288defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return;
16293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register constant_reg = GetSmiConstant(constant);
1632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    addp(dst, constant_reg);
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadSmiConstant(dst, constant);
1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    addp(dst, src);
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (constant->value() != 0) {
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addl(Operand(dst, kSmiShift / kBitsPerByte),
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Immediate(constant->value()));
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, Immediate(constant));
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant,
1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    SmiOperationConstraints constraints,
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Label* bailout_label,
1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(kScratchRegister, constant);
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(dst, kScratchRegister);
1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (constraints & SmiOperationConstraint::kBailoutOnNoOverflow) {
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(no_overflow, bailout_label, near_jump);
1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      subp(dst, kScratchRegister);
1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (constraints & SmiOperationConstraint::kBailoutOnOverflow) {
1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (constraints & SmiOperationConstraint::kPreserveSourceRegister) {
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label done;
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(no_overflow, &done, Label::kNear);
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        subp(dst, kScratchRegister);
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jmp(bailout_label, near_jump);
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&done);
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Bailout if overflow without reserving src.
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(overflow, bailout_label, near_jump);
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kBailoutOnOverflow);
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadSmiConstant(dst, constant);
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(dst, src);
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(overflow, bailout_label, near_jump);
1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
16943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!dst.is(src)) {
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
17008defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(dst, constant_reg);
17023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
17033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (constant->value() == Smi::kMinValue) {
17048defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, constant);
17059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Adding and subtracting the min-value gives the same result, it only
17069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // differs on the overflow bit, which we don't check here.
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, src);
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
17099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Subtract by adding the negation.
17108defd9ff6930b4e24729971a61cf7469daf119beSteve Block      LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, src);
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant,
1718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    SmiOperationConstraints constraints,
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Label* bailout_label,
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump) {
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (constant->value() == 0) {
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (dst.is(src)) {
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadSmiConstant(kScratchRegister, constant);
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(dst, kScratchRegister);
1729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (constraints & SmiOperationConstraint::kBailoutOnNoOverflow) {
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(no_overflow, bailout_label, near_jump);
1731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, kScratchRegister);
1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (constraints & SmiOperationConstraint::kBailoutOnOverflow) {
1734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (constraints & SmiOperationConstraint::kPreserveSourceRegister) {
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label done;
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(no_overflow, &done, Label::kNear);
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        addp(dst, kScratchRegister);
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jmp(bailout_label, near_jump);
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        bind(&done);
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Bailout if overflow without reserving src.
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        j(overflow, bailout_label, near_jump);
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
1749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(constraints & SmiOperationConstraint::kBailoutOnOverflow);
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (constant->value() == Smi::kMinValue) {
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!dst.is(kScratchRegister));
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LoadSmiConstant(kScratchRegister, constant);
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      subp(dst, kScratchRegister);
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(overflow, bailout_label, near_jump);
1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Subtract by adding the negation.
1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(dst, src);
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(overflow, bailout_label, near_jump);
1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiNeg(Register dst,
1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src,
1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_smi_result,
1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src);
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negp(dst);  // Low 32 bits are retained as zero by negation.
1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Test if result is zero or Smi::kMinValue.
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(dst, kScratchRegister);
1776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src, kScratchRegister);
1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negp(dst);
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(dst, src);
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If the result is zero or Smi::kMinValue, negation failed to create a smi.
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_equal, on_smi_result, near_jump);
1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SmiAddHelper(MacroAssembler* masm,
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register src1,
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         T src2,
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* on_not_smi_result,
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label::Distance near_jump) {
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (dst.is(src1)) {
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->addp(dst, src2);
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(no_overflow, &done, Label::kNear);
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore src1.
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->subp(dst, src2);
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->jmp(on_not_smi_result, near_jump);
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->bind(&done);
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->movp(dst, src1);
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->addp(dst, src2);
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(overflow, on_not_smi_result, near_jump);
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiAddHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiAdd(Register dst,
1823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.AddressUsesRegister(dst));
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiAddHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
1830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
18330d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiAdd(Register dst,
18340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src1,
18350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                            Register src2) {
18360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
18370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible.
183844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
1839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (emit_debug_code()) {
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(kScratchRegister, src1);
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      addp(kScratchRegister, src2);
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Check(no_overflow, kSmiAdditionOverflow);
1843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leap(dst, Operand(src1, src2, times_1, 0));
1845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(dst, src2);
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(no_overflow, kSmiAdditionOverflow);
1848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SmiSubHelper(MacroAssembler* masm,
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register src1,
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         T src2,
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* on_not_smi_result,
1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label::Distance near_jump) {
1859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->subp(dst, src2);
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(no_overflow, &done, Label::kNear);
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore src1.
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->addp(dst, src2);
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->jmp(on_not_smi_result, near_jump);
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->bind(&done);
1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->movp(dst, src1);
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->subp(dst, src2);
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->j(overflow, on_not_smi_result, near_jump);
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SmiSub(Register dst,
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register src1,
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register src2,
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label* on_not_smi_result,
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label::Distance near_jump) {
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::SmiSub(Register dst,
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register src1,
1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            const Operand& src2,
1889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_NOT_NULL(on_not_smi_result);
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.AddressUsesRegister(dst));
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
1894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void SmiSubNoOverflowHelper(MacroAssembler* masm,
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register dst,
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register src1,
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   T src2) {
19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // No overflow checking. Use only when it's known that
19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // overflowing is impossible (e.g., subtracting two positive smis).
190444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!dst.is(src1)) {
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->movp(dst, src1);
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->subp(dst, src2);
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->Assert(no_overflow, kSmiSubtractionOverflow);
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubNoOverflowHelper<Register>(this, dst, src1, src2);
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SmiSub(Register dst,
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register src1,
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            const Operand& src2) {
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiSubNoOverflowHelper<Operand>(this, dst, src1, src2);
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMul(Register dst,
1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
1934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src1)) {
1936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label failure, zero_correct_result;
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);  // Create backup for later testing.
1938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imulp(dst, src2);
1940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, &failure, Label::kNear);
1941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(dst, dst);
1946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, src2);
1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Result was positive zero.
1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &zero_correct_result, Label::kNear);
1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&failure);  // Reused failure exit, restores src1.
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&zero_correct_result);
1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Set(dst, 0);
1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SmiToInteger64(dst, src1);
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imulp(dst, src2);
1964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(overflow, on_not_smi_result, near_jump);
1965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check for negative zero result.  If product is zero, and one
1966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is negative, go to slow case.
1967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label correct_result;
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(dst, dst);
1969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, &correct_result, Label::kNear);
1970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // One of src1 and src2 is zero, the check whether the other is
1971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // negative.
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(kScratchRegister, src2);
1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&correct_result);
1976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiDiv(Register dst,
1981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
1983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rax));
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rdx));
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(rdx));
1991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for 0 divisor (result is +/-Infinity).
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src2, src2);
1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
1998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
2000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We need to rule out dividing Smi::kMinValue by -1, since that would
2001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // overflow in idiv and raise an exception.
2002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We combine this with negative zero test (negative zero only happens
2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // when dividing zero by a negative number).
2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We overshoot a little and go to slow case if we divide min-value
2006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by any negative value, not just -1.
2007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testl(rax, Immediate(~Smi::kMinValue));
2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &safe_div, Label::kNear);
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src2, src2);
2011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
2012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(positive, &safe_div, Label::kNear);
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
2014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
2015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(negative, on_not_smi_result, near_jump);
2017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend src1 into edx:eax.
2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
2023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
2024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the remainder is zero.
2026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
2027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
2028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label smi_result;
2029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(zero, &smi_result, Label::kNear);
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
2031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    jmp(on_not_smi_result, near_jump);
2032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&smi_result);
2033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    j(not_zero, on_not_smi_result, near_jump);
2035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src1) && src1.is(rax)) {
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
2038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rax);
2040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiMod(Register dst,
2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src1,
2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register src2,
2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* on_not_smi_result,
2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label::Distance near_jump) {
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rax));
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(rdx));
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(rdx));
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(src2));
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src2, src2);
2057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, on_not_smi_result, near_jump);
2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, src1);
2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(rax, src1);
2063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiToInteger32(src2, src2);
2064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
2066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label safe_div;
2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(rax, Immediate(Smi::kMinValue));
2068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
2069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(src2, Immediate(-1));
2070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &safe_div, Label::kNear);
2071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Retag inputs and go slow case.
2072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
2073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  jmp(on_not_smi_result, near_jump);
2077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&safe_div);
2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Sign extend eax into edx:eax.
2080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cdq();
2081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  idivl(src2);
2082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore smi tags on inputs.
2083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(src2, src2);
2084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rax)) {
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(src1, kScratchRegister);
2086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for a negative zero result.  If the result is zero, and the
2088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dividend is negative, go slow to return a floating point negative zero.
2089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label smi_result;
2090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(rdx, rdx);
2091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, &smi_result, Label::kNear);
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(src1, src1);
2093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(negative, on_not_smi_result, near_jump);
2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&smi_result);
2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Integer32ToSmi(dst, rdx);
2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiNot(Register dst, Register src) {
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.is(kScratchRegister));
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Set tag and padding bits before negating, so that they are zero
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // afterwards.
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(kScratchRegister, Immediate(~0));
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movl(kScratchRegister, Immediate(1));
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(src)) {
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, kScratchRegister);
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leap(dst, Operand(src, kScratchRegister, times_1, 0));
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  notp(dst);
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(dst, src2);
2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
21293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (constant->value() == 0) {
21309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Set(dst, 0);
21313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (dst.is(src)) {
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
21338defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(dst, constant_reg);
21353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
21368defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(dst, src);
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  orp(dst, src2);
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
21523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
21548defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(dst, constant_reg);
21563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
21578defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    orp(dst, src);
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!dst.is(src1)) {
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorp(dst, src2);
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
21733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (dst.is(src)) {
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
21758defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Register constant_reg = GetSmiConstant(constant);
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, constant_reg);
21773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
21788defd9ff6930b4e24729971a61cf7469daf119beSteve Block    LoadSmiConstant(dst, constant);
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    xorp(dst, src);
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Register src,
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     int shift_value) {
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint5(shift_value));
2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_value > 0) {
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (dst.is(src)) {
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarp(dst, Immediate(shift_value + kSmiShift));
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(kSmiShift));
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // Not used.
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeftConstant(Register dst,
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Register src,
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          int shift_value,
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* on_not_smi_result,
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance near_jump) {
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift_value > 0) {
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Shift amount specified by lower 5 bits, not six as the shl opcode.
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlq(dst, Immediate(shift_value & 0x1f));
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (dst.is(src)) {
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();  // Not used.
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(dst, src);
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shll(dst, Immediate(shift_value));
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpIfNotValidSmiValue(dst, on_not_smi_result, near_jump);
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Integer32ToSmi(dst, dst);
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRightConstant(
2227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register dst, Register src, int shift_value,
2228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* on_not_smi_result, Label::Distance near_jump) {
2229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Logic right shift interprets its result as an *unsigned* number.
2230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (dst.is(src)) {
2231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    UNIMPLEMENTED();  // Not used.
2232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (shift_value == 0) {
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      testp(src, src);
2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(negative, on_not_smi_result, near_jump);
2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shrp(dst, Immediate(shift_value + kSmiShift));
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(kSmiShift));
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(SmiValuesAre31Bits());
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(dst, src);
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shrp(dst, Immediate(shift_value));
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpIfUIntNotValidSmiValue(dst, on_not_smi_result, near_jump);
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Integer32ToSmi(dst, dst);
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftLeft(Register dst,
2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register src1,
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Register src2,
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label* on_not_smi_result,
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label::Distance near_jump) {
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(rcx));
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src1)) {
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src1);
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Untag shift amount.
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(rcx, src2);
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Shift amount specified by lower 5 bits, not six as the shl opcode.
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(rcx, Immediate(0x1f));
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shlq_cl(dst);
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(kScratchRegister));
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(kScratchRegister));
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src2.is(kScratchRegister));
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(src2));
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!dst.is(rcx));
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src1.is(rcx) || src2.is(rcx)) {
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movq(kScratchRegister, rcx);
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (dst.is(src1)) {
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();  // Not used.
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label valid_result;
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(dst, src1);
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiToInteger32(rcx, src2);
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shll_cl(dst);
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JumpIfValidSmiValue(dst, &valid_result, Label::kNear);
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // As src1 or src2 could not be dst, we do not need to restore them for
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // clobbering dst.
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (src1.is(rcx) || src2.is(rcx)) {
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (src1.is(rcx)) {
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          movq(src1, kScratchRegister);
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          movq(src2, kScratchRegister);
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jmp(on_not_smi_result, near_jump);
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bind(&valid_result);
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Integer32ToSmi(dst, dst);
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SmiShiftLogicalRight(Register dst,
2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src1,
2305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register src2,
2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label* on_not_smi_result,
2307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Label::Distance near_jump) {
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(rcx));
2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (src1.is(rcx) || src2.is(rcx)) {
2314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movq(kScratchRegister, rcx);
2315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (dst.is(src1)) {
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNIMPLEMENTED();  // Not used.
2318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label valid_result;
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(dst, src1);
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(rcx, src2);
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shrl_cl(dst);
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JumpIfUIntValidSmiValue(dst, &valid_result, Label::kNear);
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // As src1 or src2 could not be dst, we do not need to restore them for
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // clobbering dst.
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src1.is(rcx) || src2.is(rcx)) {
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (src1.is(rcx)) {
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        movq(src1, kScratchRegister);
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        movq(src2, kScratchRegister);
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     }
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(on_not_smi_result, near_jump);
2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&valid_result);
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Integer32ToSmi(dst, dst);
2336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiShiftArithmeticRight(Register dst,
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src1,
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register src2) {
2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(rcx));
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmiToInteger32(rcx, src2);
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!dst.is(src1)) {
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src1);
23513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiToInteger32(dst, dst);
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sarl_cl(dst);
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Integer32ToSmi(dst, dst);
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SelectNonSmi(Register dst,
2359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src1,
2360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Register src2,
2361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label* on_not_smis,
2362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  Label::Distance near_jump) {
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(kScratchRegister));
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(kScratchRegister));
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.is(kScratchRegister));
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src1));
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(src2));
2368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Both operands must not be smis.
2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi);
2372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
237369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
2375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movl(kScratchRegister, Immediate(kSmiTagMask));
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(kScratchRegister, src1);
2377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(kScratchRegister, src2);
2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If non-zero then both are smis.
2379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_zero, on_not_smis, near_jump);
2380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exactly one operand is a smi.
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, static_cast<int>(kSmiTagMask));
2383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subp(kScratchRegister, Immediate(1));
2385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, then scratch register all 1s, else it is all 0s.
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(dst, src1);
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorp(dst, src2);
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(dst, kScratchRegister);
2389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  xorp(dst, src1);
2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
23953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockSmiIndex MacroAssembler::SmiToIndex(Register dst,
23963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    Register src,
23973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                    int shift) {
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_uint6(shift));
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There is a possible optimization if shift is in the range 60-63, but that
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // will (and must) never happen.
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift < kSmiShift) {
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarp(dst, Immediate(kSmiShift - shift));
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(shift - kSmiShift));
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, times_1);
24113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(shift >= times_1 && shift <= (static_cast<int>(times_8) + 1));
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We have to sign extend the index register to 64-bit as the SMI might
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // be negative.
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, dst);
2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift == times_1) {
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarq(dst, Immediate(kSmiShift));
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return SmiIndex(dst, times_1);
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, static_cast<ScaleFactor>(shift - 1));
24253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register src,
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            int shift) {
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Register src holds a positive smi.
2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_uint6(shift));
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negp(dst);
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift < kSmiShift) {
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarp(dst, Immediate(kSmiShift - shift));
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shlp(dst, Immediate(shift - kSmiShift));
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, times_1);
24453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(shift >= times_1 && shift <= (static_cast<int>(times_8) + 1));
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, src);
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    negq(dst);
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift == times_1) {
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sarq(dst, Immediate(kSmiShift));
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return SmiIndex(dst, times_1);
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SmiIndex(dst, static_cast<ScaleFactor>(shift - 1));
24573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::AddSmiField(Register dst, const Operand& src) {
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, kSmiShift % kBitsPerByte);
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addl(dst, Operand(src, kSmiShift / kBitsPerByte));
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(kScratchRegister, src);
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addl(dst, kScratchRegister);
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Push(Smi* source) {
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t smi = reinterpret_cast<intptr_t>(source);
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_int32(smi)) {
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(Immediate(static_cast<int32_t>(smi)));
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register constant = GetSmiConstant(source);
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(constant);
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) {
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.is(scratch));
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, src);
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // High bits.
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrp(src, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(src, Immediate(kSmiShift));
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(src);
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Low bits.
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(scratch, Immediate(kSmiShift));
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(scratch);
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) {
2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(scratch));
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(scratch);
2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Low bits.
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrp(scratch, Immediate(kSmiShift));
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(dst);
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrp(dst, Immediate(kSmiShift));
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // High bits.
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp(dst, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  orp(dst, scratch);
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Test(const Operand& src, Smi* source) {
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (SmiValuesAre32Bits()) {
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(Operand(src, kIntSize), Immediate(source->value()));
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(src, Immediate(source));
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::JumpIfNotString(Register object,
2524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register object_map,
2525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label* not_string,
2526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Label::Distance near_jump) {
2527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition is_smi = CheckSmi(object);
2528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(is_smi, not_string, near_jump);
2529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map);
2530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(above_equal, not_string, near_jump);
2531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotBothSequentialOneByteStrings(
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first_object, Register second_object, Register scratch1,
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2, Label* on_fail, Label::Distance near_jump) {
2537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both objects are not smis.
2538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition either_smi = CheckEitherSmi(first_object, second_object);
2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(either_smi, on_fail, near_jump);
2540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
2544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kNotStringTag != 0);
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch1, Immediate(kFlatOneByteStringMask));
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch2, Immediate(kFlatOneByteStringMask));
2556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch1, Operand(scratch1, scratch2, times_8, 0));
2559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3)));
2561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register instance_type, Register scratch, Label* failure,
2567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!scratch.is(instance_type)) {
2569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    movl(scratch, instance_type);
2570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch, Immediate(kFlatOneByteStringMask));
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kOneByteStringTag));
2577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, failure, near_jump);
2578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register first_object_instance_type, Register second_object_instance_type,
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1, Register scratch2, Label* on_fail,
2584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label::Distance near_jump) {
2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load instance type for both strings.
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch1, first_object_instance_type);
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch2, second_object_instance_type);
2588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are flat one-byte strings.
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kNotStringTag != 0);
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringMask =
2592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFlatOneByteStringTag =
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTag | kOneByteStringTag | kSeqStringTag;
2595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch1, Immediate(kFlatOneByteStringMask));
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch2, Immediate(kFlatOneByteStringMask));
2598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interleave the bits to check both scratch1 and scratch2 in one test.
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch1, Operand(scratch1, scratch2, times_8, 0));
2601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmpl(scratch1,
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3)));
2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, on_fail, near_jump);
2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void JumpIfNotUniqueNameHelper(MacroAssembler* masm,
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      T operand_or_register,
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label* not_unique_name,
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Label::Distance distance) {
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label succeed;
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->testb(operand_or_register,
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->j(zero, &succeed, Label::kNear);
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->cmpb(operand_or_register, Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->j(not_equal, not_unique_name, distance);
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->bind(&succeed);
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotUniqueNameHelper<Operand>(this, operand, not_unique_name, distance);
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label* not_unique_name,
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     Label::Distance distance) {
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotUniqueNameHelper<Register>(this, reg, not_unique_name, distance);
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
263744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid MacroAssembler::Move(Register dst, Register src) {
26390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!dst.is(src)) {
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, src);
26416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
26426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(Register dst, Handle<Object> source) {
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
26483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MoveHeapObject(dst, source);
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (source->IsSmi()) {
26583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(dst, Smi::cast(*source));
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MoveHeapObject(kScratchRegister, source);
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint32_t src) {
2667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (src == 0) {
2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Xorpd(dst, dst);
2669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    unsigned pop = base::bits::CountPopulation32(src);
2671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NE(0u, pop);
2672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (pop == 32) {
2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      movl(kScratchRegister, Immediate(src));
2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movq(dst, kScratchRegister);
2677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::Move(XMMRegister dst, uint64_t src) {
2683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (src == 0) {
2684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Xorpd(dst, dst);
2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned nlz = base::bits::CountLeadingZeros64(src);
2687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    unsigned ntz = base::bits::CountTrailingZeros64(src);
2688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    unsigned pop = base::bits::CountPopulation64(src);
2689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NE(0u, pop);
2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (pop == 64) {
2691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (pop + ntz == 64) {
2693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Psllq(dst, ntz);
2695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (pop + nlz == 64) {
2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pcmpeqd(dst, dst);
2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Psrlq(dst, nlz);
2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t lower = static_cast<uint32_t>(src);
2700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t upper = static_cast<uint32_t>(src >> 32);
2701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (upper == 0) {
2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Move(dst, lower);
2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        movq(kScratchRegister, src);
2705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Movq(dst, kScratchRegister);
2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movaps(XMMRegister dst, XMMRegister src) {
2713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovaps(dst, src);
27163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movaps(dst, src);
27183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movapd(XMMRegister dst, XMMRegister src) {
2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovapd(dst, src);
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movapd(dst, src);
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movsd(XMMRegister dst, XMMRegister src) {
2733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovsd(dst, dst, src);
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movsd(dst, src);
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movsd(XMMRegister dst, const Operand& src) {
2743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovsd(dst, src);
27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movsd(dst, src);
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movsd(const Operand& dst, XMMRegister src) {
2753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovsd(dst, src);
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movsd(dst, src);
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movss(XMMRegister dst, XMMRegister src) {
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovss(dst, dst, src);
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movss(dst, src);
2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movss(XMMRegister dst, const Operand& src) {
2773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovss(dst, src);
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movss(dst, src);
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movss(const Operand& dst, XMMRegister src) {
2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovss(dst, src);
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movss(dst, src);
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movd(XMMRegister dst, Register src) {
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovd(dst, src);
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movd(XMMRegister dst, const Operand& src) {
2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovd(dst, src);
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movd(Register dst, XMMRegister src) {
2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovd(dst, src);
28163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movd(dst, src);
28183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
28193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
28203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
28213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movq(XMMRegister dst, Register src) {
2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovq(dst, src);
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movq(dst, src);
2828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movq(Register dst, XMMRegister src) {
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovq(dst, src);
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movq(dst, src);
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Movmskpd(Register dst, XMMRegister src) {
2843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vmovmskpd(dst, src);
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movmskpd(dst, src);
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Roundss(XMMRegister dst, XMMRegister src,
2853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             RoundingMode mode) {
2854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vroundss(dst, dst, src, mode);
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    roundss(dst, src, mode);
2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Roundsd(XMMRegister dst, XMMRegister src,
2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             RoundingMode mode) {
2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vroundsd(dst, dst, src, mode);
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    roundsd(dst, src, mode);
2870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Sqrtsd(XMMRegister dst, XMMRegister src) {
2875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsqrtsd(dst, dst, src);
2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sqrtsd(dst, src);
2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Sqrtsd(XMMRegister dst, const Operand& src) {
2885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsqrtsd(dst, dst, src);
2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sqrtsd(dst, src);
2890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomiss(XMMRegister src1, XMMRegister src2) {
2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomiss(src1, src2);
2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomiss(src1, src2);
2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomiss(XMMRegister src1, const Operand& src2) {
2905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomiss(src1, src2);
2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomiss(src1, src2);
2910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomisd(XMMRegister src1, XMMRegister src2) {
2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomisd(src1, src2);
2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomisd(src1, src2);
2920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Ucomisd(XMMRegister src1, const Operand& src2) {
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(AVX)) {
2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, AVX);
2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vucomisd(src1, src2);
2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ucomisd(src1, src2);
2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cmp(Register dst, Handle<Object> source) {
2935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference smi_check;
2936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (source->IsSmi()) {
2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Cmp(dst, Smi::cast(*source));
2938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MoveHeapObject(kScratchRegister, source);
2940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cmpp(dst, kScratchRegister);
2941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference smi_check;
2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (source->IsSmi()) {
2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Cmp(dst, Smi::cast(*source));
2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MoveHeapObject(kScratchRegister, source);
2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    cmpp(dst, kScratchRegister);
2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(Handle<Object> source) {
2957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference smi_check;
2958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (source->IsSmi()) {
2959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(Smi::cast(*source));
2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MoveHeapObject(kScratchRegister, source);
2962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(kScratchRegister);
2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::MoveHeapObject(Register result,
2968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Handle<Object> object) {
2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllowDeferredHandleDereference using_raw_address;
2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(object->IsHeapObject());
2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(result, cell, RelocInfo::CELL);
2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(result, Operand(result, 0));
2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(result, object, RelocInfo::EMBEDDED_OBJECT);
2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadGlobalCell(Register dst, Handle<Cell> cell) {
2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (dst.is(rax)) {
2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    AllowDeferredHandleDereference embedding_raw_address;
2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    load_rax(cell.location(), RelocInfo::CELL);
2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Move(dst, cell, RelocInfo::CELL);
2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(dst, Operand(dst, 0));
2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Register scratch) {
2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(scratch, cell, RelocInfo::EMBEDDED_OBJECT);
2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpp(value, FieldOperand(scratch, WeakCell::kValueOffset));
2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(value, cell, RelocInfo::EMBEDDED_OBJECT);
3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(value, FieldOperand(value, WeakCell::kValueOffset));
3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   Label* miss) {
3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GetWeakValue(value, cell);
3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(value, miss);
3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Drop(int stack_elements) {
3013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (stack_elements > 0) {
3014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    addp(rsp, Immediate(stack_elements * kPointerSize));
3015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::DropUnderReturnAddress(int stack_elements,
3020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                            Register scratch) {
3021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(stack_elements > 0);
3022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size && stack_elements == 1) {
3023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popq(MemOperand(rsp, 0));
3024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PopReturnAddressTo(scratch);
3028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Drop(stack_elements);
3029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PushReturnAddressFrom(scratch);
3030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(Register src) {
3034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(src);
3036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // x32 uses 64-bit push for rbp in the prologue.
3038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(src.code() != rbp.code());
3039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), src);
3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(const Operand& src) {
3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(src);
3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(kScratchRegister, src);
3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), kScratchRegister);
3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushQuad(const Operand& src) {
3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(src);
3059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(kScratchRegister, src);
3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(kScratchRegister);
3062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Push(Immediate value) {
3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq(value);
3069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), value);
3072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushImm32(int32_t imm32) {
3077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pushq_imm32(imm32);
3079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, -4));
3081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(Operand(rsp, 0), Immediate(imm32));
3082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pop(Register dst) {
3087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popq(dst);
3089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // x32 uses 64-bit pop for rbp in the epilogue.
3091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(dst.code() != rbp.code());
3092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(dst, Operand(rsp, 0));
3093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, 4));
3094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pop(const Operand& dst) {
3099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size) {
3100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popq(dst);
3101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register scratch = dst.AddressUsesRegister(kScratchRegister)
3103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ? kRootRegister : kScratchRegister;
3104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(scratch, Operand(rsp, 0));
3105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(dst, scratch);
3106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leal(rsp, Operand(rsp, 4));
3107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (scratch.is(kRootRegister)) {
3108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Restore kRootRegister.
3109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      InitializeRootRegister();
3110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::PopQuad(const Operand& dst) {
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popq(dst);
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popq(kScratchRegister);
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, kScratchRegister);
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadSharedFunctionInfoSpecialField(Register dst,
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        Register base,
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        int offset) {
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset > SharedFunctionInfo::kLengthOffset &&
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         offset <= SharedFunctionInfo::kSize &&
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (((offset - SharedFunctionInfo::kLengthOffset) / kIntSize) % 2 == 1));
3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movsxlq(dst, FieldOperand(base, offset));
3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, FieldOperand(base, offset));
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiToInteger32(dst, dst);
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestBitSharedFunctionInfoSpecialField(Register base,
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           int offset,
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           int bits) {
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset > SharedFunctionInfo::kLengthOffset &&
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         offset <= SharedFunctionInfo::kSize &&
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (((offset - SharedFunctionInfo::kLengthOffset) / kIntSize) % 2 == 1));
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt32Size) {
3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // On x32, this field is represented by SMI.
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bits += kSmiShift;
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int byte_offset = bits / kBitsPerByte;
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int bit_in_byte = bits & (kBitsPerByte - 1);
3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testb(FieldOperand(base, offset + byte_offset), Immediate(1 << bit_in_byte));
31533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(ExternalReference ext) {
315744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Jump(const Operand& op) {
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kInt64Size) {
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(op);
3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, op);
3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(kScratchRegister);
3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, destination, rmode);
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(kScratchRegister);
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
31793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Inline this
31803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  jmp(code_object, rmode);
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
318444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(ExternalReference ext) {
318544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return LoadAddressSize(ext) +
3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Assembler::kCallScratchRegisterInstructionLength;
318844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
318944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
319044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(ExternalReference ext) {
319244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
319344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(ext);
319444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
319544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(kScratchRegister, ext);
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
319744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
319844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
319944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Call(const Operand& op) {
3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (kPointerSize == kInt64Size && !CpuFeatures::IsSupported(ATOM)) {
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(op);
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(kScratchRegister, op);
3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call(kScratchRegister);
3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
321444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int end_position = pc_offset() + CallSize(destination);
321644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, destination, rmode);
3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  call(kScratchRegister);
321944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
322044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pc_offset(), end_position);
322144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(Handle<Code> code_object,
3226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          RelocInfo::Mode rmode,
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          TypeFeedbackId ast_id) {
322844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
322944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int end_position = pc_offset() + CallSize(code_object);
323044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode) ||
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rmode == RelocInfo::CODE_AGE_SEQUENCE);
3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  call(code_object, rmode, ast_id);
323444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
323544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(end_position, pc_offset());
323644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 0) {
3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movd(dst, src);
3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, imm8);
3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
3247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
3248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pextrd(dst, src, imm8);
3249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movq(dst, src);
3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  shrq(dst, Immediate(32));
3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, Register src, int8_t imm8) {
3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movd(xmm0, src);
3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movss(dst, xmm0);
3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(imm8 == 0 || imm8 == 1);
3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(SSE4_1)) {
3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope sse_scope(this, SSE4_1);
3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pinsrd(dst, src, imm8);
3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movd(xmm0, src);
3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm8 == 1) {
3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    punpckldq(dst, xmm0);
3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm8);
3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movss(dst, xmm0);
3285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntl(Register dst, Register src) {
3290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntl(dst, src);
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrl(dst, src);
3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 63);  // 63^31 == 32
3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(31));  // for x in [0..31], 31^x == 31 - x
3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntl(Register dst, const Operand& src) {
3305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntl(dst, src);
3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrl(dst, src);
3312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 63);  // 63^31 == 32
3314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(31));  // for x in [0..31], 31^x == 31 - x
3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntq(Register dst, Register src) {
3320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntq(dst, src);
3323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrq(dst, src);
3327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 127);  // 127^63 == 64
3329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(63));  // for x in [0..63], 63^x == 63 - x
3331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Lzcntq(Register dst, const Operand& src) {
3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(LZCNT)) {
3336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, LZCNT);
3337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    lzcntq(dst, src);
3338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsrq(dst, src);
3342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 127);  // 127^63 == 64
3344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  xorl(dst, Immediate(63));  // for x in [0..63], 63^x == 63 - x
3346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntq(Register dst, Register src) {
3350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntq(dst, src);
3353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfq(dst, src);
3357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Define the result of tzcnt(0) separately, because bsf(0) is undefined.
3359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 64);
3360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntq(Register dst, const Operand& src) {
3365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntq(dst, src);
3368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfq(dst, src);
3372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Define the result of tzcnt(0) separately, because bsf(0) is undefined.
3374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 64);
3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntl(Register dst, Register src) {
3380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntl(dst, src);
3383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfl(dst, src);
3387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 32);  // The result of tzcnt is 32 if src = 0.
3389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Tzcntl(Register dst, const Operand& src) {
3394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(BMI1)) {
3395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, BMI1);
3396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tzcntl(dst, src);
3397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label not_zero_src;
3400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bsfl(dst, src);
3401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_zero, &not_zero_src, Label::kNear);
3402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Set(dst, 32);  // The result of tzcnt is 32 if src = 0.
3403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&not_zero_src);
3404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntl(Register dst, Register src) {
3408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntl(dst, src);
3411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntl(Register dst, const Operand& src) {
3418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntl(dst, src);
3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntq(Register dst, Register src) {
3428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntq(dst, src);
3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::Popcntq(Register dst, const Operand& src) {
3438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(POPCNT)) {
3439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CpuFeatureScope scope(this, POPCNT);
3440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    popcntq(dst, src);
3441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
3442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
3444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
34471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Pushad() {
3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rax);
3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rcx);
3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rdx);
3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rbx);
34521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Not pushing rsp or rbp.
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rsi);
3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(rdi);
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r8);
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r9);
34571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r10 is kScratchRegister.
3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r11);
3459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Push(r12);
34601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r13 is kRootRegister.
3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r14);
3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(r15);
3463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(12 == kNumSafepointSavedRegisters);
3464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Use lea for symmetry with Popad.
3465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
3466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(rsp, Operand(rsp, -sp_delta));
34681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Popad() {
3472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Popad must not change the flags, so use lea instead of addq.
3473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sp_delta =
3474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(rsp, Operand(rsp, sp_delta));
3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r15);
3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r14);
3478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Pop(r12);
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r11);
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r9);
3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(r8);
3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rdi);
3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rsi);
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rbx);
3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rdx);
3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rcx);
3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(rax);
34881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Dropad() {
3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
34931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Order general registers are pushed by Pushad:
349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int
34993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
35001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    0,
35011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    1,
35021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    2,
35031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    3,
35041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
35051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
35061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    4,
35071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    5,
35081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    6,
35091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    7,
35101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    -1,
35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    8,
351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    9,
3513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    -1,
3514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    10,
3515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    11
35161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
35171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst,
3520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  const Immediate& imm) {
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(SafepointRegisterSlot(dst), imm);
3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(SafepointRegisterSlot(dst), src);
3527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(dst, SafepointRegisterSlot(src));
3532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
3536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
3537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PushStackHandler() {
3541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
3542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
35433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
35443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Link the current handler as the next handler.
35463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(ExternalOperand(handler_address));
3548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set this new handler as the current one.
3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(ExternalOperand(handler_address), rsp);
3551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::PopStackHandler() {
35553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(ExternalOperand(handler_address));
3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
3559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
3560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret() {
3563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ret(0);
3564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Ret(int bytes_dropped, Register scratch) {
35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_uint16(bytes_dropped)) {
35691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(bytes_dropped);
35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PopReturnAddressTo(scratch);
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(rsp, Immediate(bytes_dropped));
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushReturnAddressFrom(scratch);
35741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ret(0);
35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::FCmp() {
35803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  fucomip();
35818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  fstp(0);
3582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpObjectType(Register heap_object,
3586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   InstanceType type,
3587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register map) {
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
3589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpInstanceType(map, type);
3590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
3594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
3595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       Immediate(static_cast<int8_t>(type)));
3596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::CheckFastElements(Register map,
36003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label* fail,
36013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       Label::Distance distance) {
3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckFastObjectElements(Register map,
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* fail,
36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label::Distance distance) {
3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS == 2);
3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(below_equal, fail, distance);
3622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleyElementValue));
3624592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  j(above, fail, distance);
3625592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
3626592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CheckFastSmiElements(Register map,
3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* fail,
3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label::Distance distance) {
3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cmpb(FieldOperand(map, Map::kBitField2Offset),
3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(above, fail, distance);
36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::StoreNumberToDoubleElements(
36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register maybe_number,
36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register elements,
36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register index,
36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister xmm_scratch,
3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* fail,
3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int elements_offset) {
3646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label smi_value, done;
36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JumpIfSmi(maybe_number, &smi_value, Label::kNear);
36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckMap(maybe_number,
36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           isolate()->factory()->heap_number_map(),
36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fail,
36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           DONT_DO_SMI_CHECK);
36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Double value, turn potential sNaN into qNaN.
3656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(xmm_scratch, 1.0);
3657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mulsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset));
3658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&done, Label::kNear);
36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&smi_value);
36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a smi. convert to a double and store.
36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve original value.
36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SmiToInteger32(kScratchRegister, maybe_number);
3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtlsi2sd(xmm_scratch, kScratchRegister);
3665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
3666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movsd(FieldOperand(elements, index, times_8,
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     FixedDoubleArray::kHeaderSize - elements_offset),
36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        xmm_scratch);
36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
36783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
36793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              SmiCheckType smi_check_type) {
3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
36823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    JumpIfSmi(obj, fail);
36833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
36843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareMap(obj, map);
36863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  j(not_equal, fail);
36873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
36883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
36893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register reg) {
3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(reg, Immediate(0xFFFFFF00));
3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  setcc(negative, reg);  // 1 if negative, 0 if positive.
3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  decb(reg);  // 0 if negative, 255 if positive.
3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        XMMRegister temp_xmm_reg,
3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Register result_reg) {
3703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label conv_failure;
3705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Xorpd(temp_xmm_reg, temp_xmm_reg);
3706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtsd2si(result_reg, input_reg);
3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  testl(result_reg, Immediate(0xFFFFFF00));
3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(zero, &done, Label::kNear);
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpl(result_reg, Immediate(1));
3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(overflow, &conv_failure, Label::kNear);
3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(result_reg, Immediate(0));
3712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  setcc(sign, result_reg);
3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subl(result_reg, Immediate(1));
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(result_reg, Immediate(255));
3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&done, Label::kNear);
3716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&conv_failure);
3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Set(result_reg, 0);
3718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Ucomisd(input_reg, temp_xmm_reg);
3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(below, &done, Label::kNear);
3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Set(result_reg, 255);
3721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LoadUint32(XMMRegister dst,
3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Register src) {
3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpq(src, Immediate(0xffffffff));
3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared);
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvtqsi2sd(dst, src);
3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::SlowTruncateToI(Register result_reg,
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register input_reg,
3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     int offset) {
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  call(stub.GetCode(), RelocInfo::CODE_TARGET);
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateHeapNumberToI(Register result_reg,
3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register input_reg) {
3745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
3746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvttsd2siq(result_reg, xmm0);
3748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpq(result_reg, Immediate(1));
3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Slow case.
3752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input_reg.is(result_reg)) {
3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(kDoubleSize));
3754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movsd(MemOperand(rsp, 0), xmm0);
3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SlowTruncateToI(result_reg, rsp, 0);
3756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(rsp, Immediate(kDoubleSize));
3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SlowTruncateToI(result_reg, input_reg);
3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep our invariant that the upper 32 bits are zero.
3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(result_reg, result_reg);
3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncateDoubleToI(Register result_reg,
3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       XMMRegister input_reg) {
3769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
3770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvttsd2siq(result_reg, input_reg);
3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpq(result_reg, Immediate(1));
3772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(no_overflow, &done, Label::kNear);
3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subp(rsp, Immediate(kDoubleSize));
3775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Movsd(MemOperand(rsp, 0), input_reg);
3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlowTruncateToI(result_reg, rsp, 0);
3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(rsp, Immediate(kDoubleSize));
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep our invariant that the upper 32 bits are zero.
3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(result_reg, result_reg);
3782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               XMMRegister scratch,
3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MinusZeroMode minus_zero_mode,
3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* lost_precision, Label* is_nan,
3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* minus_zero, Label::Distance dst) {
3790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Cvttsd2si(result_reg, input_reg);
3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cvtlsi2sd(xmm0, result_reg);
3792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Ucomisd(xmm0, input_reg);
3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, lost_precision, dst);
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(parity_even, is_nan, dst);  // NaN.
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The integer converted back is equal to the original. We
3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // only have to test if we got -0 as an input.
3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(result_reg, result_reg);
3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, &done, Label::kNear);
3801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Movmskpd(result_reg, input_reg);
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bit 0 contains the sign of the double in input_reg.
3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If input was positive, we are ok and return 0, otherwise
3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump to minus_zero.
3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andl(result_reg, Immediate(1));
3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(not_zero, minus_zero, dst);
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done);
3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
3813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(dst, FieldOperand(map, Map::kBitField3Offset));
3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EnumLength(Register dst, Register map) {
3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(dst, FieldOperand(map, Map::kBitField3Offset));
3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(dst, Immediate(Map::EnumLengthBits::kMask));
3828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Integer32ToSmi(dst, dst);
3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadAccessor(Register dst, Register holder,
3833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int accessor_index,
3834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  AccessorComponent accessor) {
3835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, FieldOperand(holder, HeapObject::kMapOffset));
3836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadInstanceDescriptors(dst, dst);
3837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, FieldOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
3838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
3839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           : AccessorPair::kSetterOffset;
3840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, FieldOperand(dst, offset));
3841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
3845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register scratch2, Handle<WeakCell> cell,
3846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<Code> success,
3847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     SmiCheckType smi_check_type) {
3848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
3849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
3850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
3851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  movq(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
3853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CmpWeakValue(scratch1, cell, scratch2);
3854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(equal, success, RelocInfo::CODE_TARGET);
3855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
3856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNumber(Register object) {
3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label ok;
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(is_smi, &ok, Label::kNear);
3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Cmp(FieldOperand(object, HeapObject::kMapOffset),
3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->heap_number_map());
3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kOperandIsNotANumber);
3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&ok);
3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3869402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
3870402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
38713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::AssertNotNumber(Register object) {
38723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (emit_debug_code()) {
38733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Condition is_smi = CheckSmi(object);
38743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(NegateCondition(is_smi), kOperandIsANumber);
38753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Cmp(FieldOperand(object, HeapObject::kMapOffset),
38763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        isolate()->factory()->heap_number_map());
38773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(not_equal, kOperandIsANumber);
38783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
38793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
3880402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertNotSmi(Register object) {
3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(NegateCondition(is_smi), kOperandIsASmi);
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3886756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3887756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3888756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(Register object) {
3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(is_smi, kOperandIsNotASmi);
3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertSmi(const Operand& object) {
3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition is_smi = CheckSmi(object);
3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(is_smi, kOperandIsNotASmi);
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertZeroExtended(Register int32_register) {
3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!int32_register.is(kScratchRegister));
3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movq(kScratchRegister, V8_INT64_C(0x0000000100000000));
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpq(kScratchRegister, int32_register);
3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertString(Register object) {
3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(object, Immediate(kSmiTagMask));
3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAString);
3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(object);
3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(object, FieldOperand(object, HeapObject::kMapOffset));
3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, FIRST_NONSTRING_TYPE);
3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Pop(object);
3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below, kOperandIsNotAString);
3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
39256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
39266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
39276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertName(Register object) {
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testb(object, Immediate(kSmiTagMask));
3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kOperandIsASmiAndNotAName);
3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(object);
3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(object, FieldOperand(object, HeapObject::kMapOffset));
3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CmpInstanceType(object, LAST_NAME_TYPE);
3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Pop(object);
3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(below_equal, kOperandIsNotAName);
3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
39383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertFunction(Register object) {
3942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
3943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    testb(object, Immediate(kSmiTagMask));
3944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAFunction);
3945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
3946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_FUNCTION_TYPE, object);
3947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
3948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotAFunction);
3949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AssertBoundFunction(Register object) {
3954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (emit_debug_code()) {
3955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    testb(object, Immediate(kSmiTagMask));
3956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotABoundFunction);
3957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(object);
3958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
3959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(object);
3960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Check(equal, kOperandIsNotABoundFunction);
3961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3964bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::AssertGeneratorObject(Register object) {
3965bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (emit_debug_code()) {
3966bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    testb(object, Immediate(kSmiTagMask));
3967bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
3968bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Push(object);
3969bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
3970bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Pop(object);
3971bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Check(equal, kOperandIsNotAGeneratorObject);
3972bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
3973bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
3974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3975109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::AssertReceiver(Register object) {
3976109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (emit_debug_code()) {
3977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    testb(object, Immediate(kSmiTagMask));
3978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(not_equal, kOperandIsASmiAndNotAReceiver);
3979109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Push(object);
3980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
3981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
3982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Pop(object);
3983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Check(above_equal, kOperandIsNotAReceiver);
3984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3985109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
3989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
3990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done_checking;
3991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AssertNotSmi(object);
3992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Cmp(object, isolate()->factory()->undefined_value());
3993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(equal, &done_checking);
3994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Cmp(FieldOperand(object, 0), isolate()->factory()->allocation_site_map());
3995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(equal, kExpectedUndefinedOrCell);
3996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&done_checking);
3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3998e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AssertRootValue(Register src,
4002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Heap::RootListIndex root_value_index,
4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     BailoutReason reason) {
4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src.is(kScratchRegister));
4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(kScratchRegister, root_value_index);
4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(src, kScratchRegister);
4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, reason);
4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
40109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
40119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
40129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
40139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeCondition MacroAssembler::IsObjectStringType(Register heap_object,
4015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register map,
4016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             Register instance_type) {
4017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
40184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
401969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
4020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  testb(instance_type, Immediate(kIsNotStringMask));
4021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return zero;
4022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
4023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4024d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition MacroAssembler::IsObjectNameType(Register heap_object,
4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register map,
4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register instance_type) {
4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpb(instance_type, Immediate(static_cast<uint8_t>(LAST_NAME_TYPE)));
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return below_equal;
4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::GetMapConstructor(Register result, Register map,
4036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       Register temp) {
4037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label done, loop;
4038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
4039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&loop);
4040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JumpIfSmi(result, &done, Label::kNear);
4041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpObjectType(result, MAP_TYPE, temp);
4042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(not_equal, &done, Label::kNear);
4043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
4044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  jmp(&loop);
4045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&done);
4046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
4050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             Label* miss) {
4051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(result,
4053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
4054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
4056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
4057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
4058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareRoot(result, Heap::kTheHoleValueRootIndex);
4059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, miss);
4060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
4063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CmpObjectType(result, MAP_TYPE, kScratchRegister);
4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  j(not_equal, &done, Label::kNear);
4065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(result, FieldOperand(result, Map::kPrototypeOffset));
4068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
4070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
4071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value) {
4075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
40778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    movl(counter_operand, Immediate(value));
4078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
4084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
408544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
4086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
408744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      incl(counter_operand);
4088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
408944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      addl(counter_operand, Immediate(value));
4090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(value > 0);
4097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
409844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand counter_operand = ExternalOperand(ExternalReference(counter));
4099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value == 1) {
410044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      decl(counter_operand);
4101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
410244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      subl(counter_operand, Immediate(value));
4103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
41099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Set(rax, 0);  // No arguments.
4110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadAddress(rbx,
4111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              ExternalReference(Runtime::kHandleDebuggerStatement, isolate()));
4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1);
4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowThisStubCall(&ces));
4114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
4115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
41173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
41183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Register caller_args_count_reg,
41193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Register scratch0, Register scratch1,
41203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        ReturnAddressState ra_state) {
41213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
41223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
41233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
41243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                       scratch1));
41253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
41263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
41273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
41283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
41293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Calculate the destination address where we will put the return address
41313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // after we drop current frame.
41323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register new_sp_reg = scratch0;
41333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
41343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    subp(caller_args_count_reg, callee_args_count.reg());
41353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    leap(new_sp_reg, Operand(rbp, caller_args_count_reg, times_pointer_size,
41363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             StandardFrameConstants::kCallerPCOffset));
41373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
41383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    leap(new_sp_reg, Operand(rbp, caller_args_count_reg, times_pointer_size,
41393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             StandardFrameConstants::kCallerPCOffset -
41403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 callee_args_count.immediate() * kPointerSize));
41413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
41423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_debug_code) {
41443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmpp(rsp, new_sp_reg);
41453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Check(below, kStackAccessBelowStackPointer);
41463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
41473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Copy return address from caller's frame to current frame's return address
41493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to avoid its trashing and let the following loop copy it to the right
41503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // place.
41513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register tmp_reg = scratch1;
41523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (ra_state == ReturnAddressState::kOnStack) {
41533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    movp(tmp_reg, Operand(rbp, StandardFrameConstants::kCallerPCOffset));
41543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    movp(Operand(rsp, 0), tmp_reg);
41553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
41563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(ReturnAddressState::kNotOnStack == ra_state);
41573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(Operand(rbp, StandardFrameConstants::kCallerPCOffset));
41583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
41593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore caller's frame pointer now as it could be overwritten by
41613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the copying loop.
41623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(rbp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
41633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // +2 here is to copy both receiver and return address.
41653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register count_reg = caller_args_count_reg;
41663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (callee_args_count.is_reg()) {
41673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    leap(count_reg, Operand(callee_args_count.reg(), 2));
41683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
41693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    movp(count_reg, Immediate(callee_args_count.immediate() + 2));
41703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): Unroll copying loop for small immediate values.
41713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
41723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Now copy callee arguments to the caller frame going backwards to avoid
41743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // callee arguments corruption (source and destination areas could overlap).
41753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label loop, entry;
41763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&entry, Label::kNear);
41773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&loop);
41783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  decp(count_reg);
41793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(tmp_reg, Operand(rsp, count_reg, times_pointer_size, 0));
41803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg);
41813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&entry);
41823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpp(count_reg, Immediate(0));
41833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &loop, Label::kNear);
41843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
41853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Leave current frame.
41863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(rsp, new_sp_reg);
41873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
4188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Register function,
4190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
4191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& actual,
4192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    InvokeFlag flag,
4193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const CallWrapper& call_wrapper) {
4194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(rbx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
4195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadSharedFunctionInfoSpecialField(
4196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      rbx, rbx, SharedFunctionInfo::kFormalParameterCountOffset);
4197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ParameterCount expected(rbx);
4199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunction(function, new_target, expected, actual, flag, call_wrapper);
4200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Handle<JSFunction> function,
4204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& expected,
4205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& actual,
4206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    InvokeFlag flag,
4207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const CallWrapper& call_wrapper) {
4208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Move(rdi, function);
4209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunction(rdi, no_reg, expected, actual, flag, call_wrapper);
4210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunction(Register function,
4214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Register new_target,
4215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& expected,
4216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const ParameterCount& actual,
4217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    InvokeFlag flag,
4218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    const CallWrapper& call_wrapper) {
4219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(rdi));
4220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(rsi, FieldOperand(function, JSFunction::kContextOffset));
4221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InvokeFunctionCode(rdi, new_target, expected, actual, flag, call_wrapper);
4222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
4226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& expected,
4227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const ParameterCount& actual,
4228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        InvokeFlag flag,
4229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        const CallWrapper& call_wrapper) {
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // You can't call a function without a valid frame.
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(flag == JUMP_FUNCTION || has_frame());
4232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function.is(rdi));
4233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_IMPLIES(new_target.is_valid(), new_target.is(rdx));
4234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call_wrapper.NeedsDebugStepCheck()) {
4236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FloodFunctionIfStepping(function, new_target, expected, actual);
4237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the new.target register if not given.
4240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!new_target.is_valid()) {
4241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
4242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool definitely_mismatches = false;
4246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InvokePrologue(expected,
4247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 actual,
4248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 &done,
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &definitely_mismatches,
4250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 flag,
4251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Label::kNear,
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 call_wrapper);
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!definitely_mismatches) {
4254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We call indirectly through the code field in the function to
4255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // allow recompilation to take effect without changing any of the
4256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // call sites.
4257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset);
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (flag == CALL_FUNCTION) {
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.BeforeCall(CallSize(code));
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call(code);
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_wrapper.AfterCall();
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(flag == JUMP_FUNCTION);
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jmp(code);
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bind(&done);
4267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
4272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const ParameterCount& actual,
4273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label* done,
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool* definitely_mismatches,
4275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    InvokeFlag flag,
4276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    Label::Distance near_jump,
4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const CallWrapper& call_wrapper) {
4278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool definitely_matches = false;
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *definitely_mismatches = false;
4280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label invoke;
4281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (expected.is_immediate()) {
4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(actual.is_immediate());
4283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Set(rax, actual.immediate());
4284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (expected.immediate() == actual.immediate()) {
4285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      definitely_matches = true;
4286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
4287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (expected.immediate() ==
4288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
4289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Don't worry about adapting arguments for built-ins that
4290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // don't want that done. Skip adaption code by making it look
4291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // like we have a match between expected and actual number of
4292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // arguments.
4293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        definitely_matches = true;
4294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *definitely_mismatches = true;
4296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Set(rbx, expected.immediate());
4297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
4298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (actual.is_immediate()) {
4301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Expected is in register, actual is immediate. This is the
4302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // case when we invoke function values without going through the
4303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // IC mechanism.
4304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Set(rax, actual.immediate());
4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmpp(expected.reg(), Immediate(actual.immediate()));
4306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(rbx));
4308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (!expected.reg().is(actual.reg())) {
4309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Both expected and actual are in (different) registers. This
4310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // is the case when we invoke functions using call and apply.
4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmpp(expected.reg(), actual.reg());
4312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      j(equal, &invoke, Label::kNear);
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(actual.reg().is(rax));
4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(expected.reg().is(rbx));
4315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Move(rax, actual.reg());
4317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!definitely_matches) {
4321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
4322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (flag == CALL_FUNCTION) {
4323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor));
4324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Call(adaptor, RelocInfo::CODE_TARGET);
4325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!*definitely_mismatches) {
43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        jmp(done, near_jump);
43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
4330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Jump(adaptor, RelocInfo::CODE_TARGET);
4331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bind(&invoke);
43331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
4334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
4335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
4338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& expected,
4339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             const ParameterCount& actual) {
4340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip_flooding;
4341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference step_in_enabled =
4342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::debug_step_in_enabled_address(isolate());
4343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Operand step_in_enabled_operand = ExternalOperand(step_in_enabled);
4344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpb(step_in_enabled_operand, Immediate(0));
4345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &skip_flooding);
4346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
4347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(this,
4348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
4349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Integer32ToSmi(expected.reg(), expected.reg());
4351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(expected.reg());
4352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Integer32ToSmi(actual.reg(), actual.reg());
4355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(actual.reg());
4356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(new_target);
4359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(fun);
4362109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
4363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Pop(fun);
4364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (new_target.is_valid()) {
4365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(new_target);
4366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (actual.is_reg()) {
4368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(actual.reg());
4369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiToInteger64(actual.reg(), actual.reg());
4370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected.is_reg()) {
4372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Pop(expected.reg());
4373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SmiToInteger64(expected.reg(), expected.reg());
4374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&skip_flooding);
4377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
43793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid MacroAssembler::StubPrologue(StackFrame::Type type) {
43803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  pushq(rbp);  // Caller's frame pointer.
43813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(rbp, rsp);
43823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Push(Smi::FromInt(type));
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Prologue(bool code_pre_aging) {
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope predictible_code_size_scope(this,
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNoCodeAgeSequenceLength);
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_pre_aging) {
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pre-age the code.
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         RelocInfo::CODE_AGE_SEQUENCE);
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength);
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pushq(rbp);  // Caller's frame pointer.
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(rbp, rsp);
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(rsi);  // Callee's context.
4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(rdi);  // Callee's JS function.
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
4403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
4405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
4406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MacroAssembler::EnterFrame(StackFrame::Type type,
4410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                bool load_constant_pool_pointer_reg) {
4411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Out-of-line constant pool not implemented on x64.
4412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  UNREACHABLE();
4413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
4414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pushq(rbp);
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbp, rsp);
44193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Push(Smi::FromInt(type));
44203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (type == StackFrame::INTERNAL) {
44213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
44223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Push(kScratchRegister);
44233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
442444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Move(kScratchRegister,
4426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         isolate()->factory()->undefined_value(),
4427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         RelocInfo::EMBEDDED_OBJECT);
4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(Operand(rsp, 0), kScratchRegister);
4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kCodeObjectNotProperlyPatched);
4430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
443544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
44363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Move(kScratchRegister, Smi::FromInt(type));
44373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cmpp(Operand(rbp, CommonFrameConstants::kContextOrFrameTypeOffset),
44383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         kScratchRegister);
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kStackFrameTypesMustMatch);
4440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rsp, rbp);
4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  popq(rbp);
4443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::EnterExitFramePrologue(bool save_rax) {
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the frame structure on the stack.
4448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All constants are relative to the frame pointer of the exit frame.
44493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(kFPOnStackSize + kPCOnStackSize,
44503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            ExitFrameConstants::kCallerSPDisplacement);
44513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(kFPOnStackSize, ExitFrameConstants::kCallerPCOffset);
44523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pushq(rbp);
4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbp, rsp);
4455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reserve room for entry stack pointer and push the code object.
44573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Push(Smi::FromInt(StackFrame::EXIT));
44583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset);
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(Immediate(0));  // Saved entry sp, patched before call.
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(kScratchRegister);  // Accessed from EditFrame::code_slot.
4462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
4464bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (save_rax) {
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(r14, rax);  // Backup rax in callee-save register.
4466bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
4467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp);
4469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi);
4470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Store(ExternalReference(Isolate::kCFunctionAddress, isolate()), rbx);
4471bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
44741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
44751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool save_doubles) {
4476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64
44771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kShadowSpace = 4;
44781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  arg_stack_space += kShadowSpace;
4479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
44801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Optionally save all XMM registers.
44811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
4482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
4483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                arg_stack_space * kRegisterSize;
4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(space));
44853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
4486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const RegisterConfiguration* config =
4487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
4488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DoubleRegister reg =
4490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
4491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
44921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
44931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (arg_stack_space > 0) {
4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(rsp, Immediate(arg_stack_space * kRegisterSize));
44958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
4496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the required frame alignment for the OS.
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
4499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kFrameAlignment > 0) {
4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_int8(kFrameAlignment));
4502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(rsp, Immediate(-kFrameAlignment));
4503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the saved entry sp.
4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
4507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
451180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(true);
4512bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame,
4514bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // so it must be retained across the C-call.
4515bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(r15, Operand(rbp, r14, times_pointer_size, offset));
4517bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
45181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, save_doubles);
4519bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4520bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4521bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
45228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
452380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  EnterExitFramePrologue(false);
45241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  EnterExitFrameEpilogue(arg_stack_space, false);
4525bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4526bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4527bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
4529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Registers:
453044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r15 : argv
45311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (save_doubles) {
45323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
4533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const RegisterConfiguration* config =
4534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
4535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DoubleRegister reg =
4537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
4538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
45391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
45401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
4541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (pop_arguments) {
4543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get the return address from the stack and restore the frame pointer.
4544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(rcx, Operand(rbp, kFPOnStackSize));
4545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    movp(rbp, Operand(rbp, 0 * kPointerSize));
4546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Drop everything up to and including the arguments and the receiver
4548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // from the caller stack.
4549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leap(rsp, Operand(r15, 1 * kPointerSize));
4550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PushReturnAddressFrom(rcx);
4552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
4553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Otherwise just leave the exit frame.
4554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    leave();
4555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
45568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(true);
45588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
45598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
45608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveApiExitFrame(bool restore_context) {
4562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rsp, rbp);
4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  popq(rbp);
45648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LeaveExitFrameEpilogue(restore_context);
45668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
45678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
45688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
4570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
4571589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference context_address(Isolate::kContextAddress, isolate());
457244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand context_operand = ExternalOperand(context_address);
4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (restore_context) {
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(rsi, context_operand);
4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(context_operand, Immediate(0));
4578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
4579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the top frame.
4581589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
458244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       isolate());
458344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(c_entry_fp_operand, Immediate(0));
4585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
4589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
4590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
4591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
4592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!holder_reg.is(scratch));
4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(kScratchRegister));
45953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Load current lexical context from the active StandardFrame, which
45963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // may require crawling past STUB frames.
45973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label load_context;
45983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label has_context;
45993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(scratch, rbp);
46003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&load_context);
46013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(SmiValuesAre32Bits());
46023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // This is "JumpIfNotSmi" but without loading the value into a register.
46033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  cmpl(MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset),
46043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       Immediate(0));
46053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_equal, &has_context);
46063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(scratch, MemOperand(scratch, CommonFrameConstants::kCallerFPOffset));
46073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&load_context);
46083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&has_context);
46093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  movp(scratch,
46103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset));
4611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When generating debug code, make sure the lexical context is set.
461344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(scratch, Immediate(0));
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
4616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the native context of the current context.
4618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
4619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
462144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->native_context_map());
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
4625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
4629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(equal, &same_contexts);
4630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare security tokens.
4632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
4633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
4634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
4635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the context is a native context.
463744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Preserve original value of holder_reg.
4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Push(holder_reg);
4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(holder_reg,
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
4642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CompareRoot(holder_reg, Heap::kNullValueRootIndex);
4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
4644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Read the first word and compare to native_context_map(),
4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Pop(holder_reg);
4650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister,
4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
46543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int token_offset =
46553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, FieldOperand(scratch, token_offset));
4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch, FieldOperand(kScratchRegister, token_offset));
4658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(not_equal, miss);
4659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
4661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Compute the hash code from the untagged key.  This must be kept in sync with
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code-stub-hydrogen.cc
4667c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid MacroAssembler::GetNumberHash(Register r0, Register scratch) {
4668c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // First of all we assign the hash seed to scratch.
4669c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  LoadRoot(scratch, Heap::kHashSeedRootIndex);
4670c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiToInteger32(scratch, scratch);
4671c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4672c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Xor original key with a seed.
4673c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4674c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4675c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Compute the hash code from the untagged key.  This must be kept in sync
4676c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // with ComputeIntegerHash in utils.h.
4677c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //
4678c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = ~hash + (hash << 15);
4679c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4680c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  notl(r0);
4681c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shll(scratch, Immediate(15));
4682c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  addl(r0, scratch);
4683c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 12);
4684c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4685c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(12));
4686c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4687c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash + (hash << 2);
4688c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  leal(r0, Operand(r0, r0, times_4, 0));
4689c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 4);
4690c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4691c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(4));
4692c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4693c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash * 2057;
4694c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  imull(r0, r0, Immediate(2057));
4695c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // hash = hash ^ (hash >> 16);
4696c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  movl(scratch, r0);
4697c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  shrl(scratch, Immediate(16));
4698c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  xorl(r0, scratch);
4699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  andl(r0, Immediate(0x3fffffff));
4700c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
4701c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4702c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4703c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
47043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid MacroAssembler::LoadFromNumberDictionary(Label* miss,
47053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register elements,
47063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register key,
47073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r0,
47083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r1,
47093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register r2,
47103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              Register result) {
47113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Register use:
47123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // elements - holds the slow-case elements of the receiver on entry.
47143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
47153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // key      - holds the smi key on entry.
47173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //            Unchanged unless 'result' is the same register.
47183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Scratch registers:
47203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r0 - holds the untagged key on entry and holds the hash once computed.
47223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r1 - used to hold the capacity mask of the dictionary
47243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r2 - used for the index into the dictionary.
47263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //
47273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // result - holds the result on exit if the load succeeded.
47283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Allowed to be the same as 'key' or 'result'.
47293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          Unchanged on bailout so 'key' or 'result' can be used
47303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //          in further computation.
47313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
47333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4734c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GetNumberHash(r0, r1);
47353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute capacity mask.
4737c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  SmiToInteger32(r1, FieldOperand(elements,
4738c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                  SeededNumberDictionary::kCapacityOffset));
47393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  decl(r1);
47403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Generate an unrolled loop that performs a few probes before giving up.
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kNumberDictionaryProbes; i++) {
47433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Use r2 for index calculations and keep the hash intact in r0.
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(r2, r0);
47453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
47463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (i > 0) {
4747c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
47483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(r2, r1);
47503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Scale the index by multiplying by the entry size.
4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SeededNumberDictionary::kEntrySize == 3);
4753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    leap(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
47543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the key matches.
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(key, FieldOperand(elements,
47573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           r2,
47583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           times_pointer_size,
4759c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                           SeededNumberDictionary::kElementsStartOffset));
4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != (kNumberDictionaryProbes - 1)) {
47613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(equal, &done);
47623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
47633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      j(not_equal, miss);
47643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
47653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bind(&done);
4768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the value is a field property.
47693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kDetailsOffset =
4770c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
4771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(DATA, 0);
47723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
4773589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       Smi::FromInt(PropertyDetails::TypeField::kMask));
47743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  j(not_zero, miss);
47753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the value at the masked, scaled index.
47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kValueOffset =
4778c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
47803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
47813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadAllocationTopHelper(Register result,
4784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
4785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             AllocationFlags flags) {
4786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just return if allocation top is already known.
4790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) != 0) {
4791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // No use of scratch if allocation top is provided.
4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!scratch.is_valid());
4793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
4794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that result actually contains top on entry.
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand top_operand = ExternalOperand(allocation_top);
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpp(result, top_operand);
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(equal, kUnexpectedAllocationTop);
4798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
4799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
4800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Move address of new object to result. Use scratch register if available,
48036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and keep address in scratch until call to UpdateAllocationTopHelper.
48046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is_valid()) {
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadAddress(scratch, allocation_top);
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(result, Operand(scratch, 0));
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Load(result, allocation_top);
4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::MakeSureDoubleAlignedHelper(Register result,
4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch,
4815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required,
4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 AllocationFlags flags) {
4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (kPointerSize == kDoubleSize) {
4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_debug_code) {
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      testl(result, Immediate(kDoubleAlignmentMask));
4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Check(zero, kAllocationIsNotDoubleAligned);
4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
48226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Align the next allocation. Storing the filler map without checking top
4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is safe in new-space because the limit of the heap is aligned there.
4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerSize * 2 == kDoubleSize);
4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make sure scratch is not clobbered by this function as it might be
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // used in UpdateAllocationTopHelper later.
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!scratch.is(kScratchRegister));
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label aligned;
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testl(result, Immediate(kDoubleAlignmentMask));
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(zero, &aligned, Label::kNear);
4833bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (((flags & ALLOCATION_FOLDED) == 0) && ((flags & PRETENURE) != 0)) {
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference allocation_limit =
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cmpp(result, ExternalOperand(allocation_limit));
4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(above_equal, gc_required);
4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LoadRoot(kScratchRegister, Heap::kOnePointerFillerMapRootIndex);
4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(result, 0), kScratchRegister);
4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(result, Immediate(kDoubleSize / 2));
4842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&aligned);
4843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UpdateAllocationTopHelper(Register result_end,
4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch,
4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               AllocationFlags flags) {
485044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    testp(result_end, Immediate(kObjectAlignmentMask));
4852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(zero, kUnalignedAllocationInNewSpace);
4853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_top =
4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationTopReference(isolate(), flags);
4857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update new top.
485944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scratch.is_valid()) {
486044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Scratch already contains address of allocation top.
4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(scratch, 0), result_end);
4862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Store(allocation_top, result_end);
4864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int object_size,
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
4876bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
48775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
487844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
48795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
48805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
48815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (result_end.is_valid()) {
48825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(result_end, Immediate(0x7191));
48835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
48845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
48855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
48865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
48875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
48885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
48895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
48905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
4892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
48948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
4895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted.
4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
49036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
49046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register top_reg = result_end.is_valid() ? result_end : result;
49056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
49061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!top_reg.is(result)) {
4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(top_reg, result);
49086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(top_reg, Immediate(object_size));
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand limit_operand = ExternalOperand(allocation_limit);
4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(top_reg, limit_operand);
4912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
4913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4914bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4915bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
4916bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(top_reg, scratch, flags);
4917bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_reg.is(result)) {
4920bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    subp(result, Immediate(object_size - kHeapObjectTag));
4921bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
4922bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Tag the result.
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(kHeapObjectTag == 1);
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incp(result);
4925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(int header_size,
4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ScaleFactor element_size,
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register element_count,
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
4938bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
4939bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(result_end, Operand(element_count, element_size, header_size));
4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(result_end, result, result_end, scratch, gc_required, flags);
4942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::Allocate(Register object_size,
4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result_end,
4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch,
4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Label* gc_required,
4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              AllocationFlags flags) {
4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((flags & SIZE_IN_WORDS) == 0);
4952bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK((flags & ALLOCATION_FOLDED) == 0);
49535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
495444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
49555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
49565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result, Immediate(0x7091));
49575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      movl(result_end, Immediate(0x7191));
49585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (scratch.is_valid()) {
49595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        movl(scratch, Immediate(0x7291));
49605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
49615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // object_size is left unchanged by this function.
49625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
49635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
49645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
49655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(result_end));
49675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
4968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load address of new object into result.
49698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LoadAllocationTopHelper(result, scratch, flags);
4970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference allocation_limit =
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
4977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!object_size.is(result_end)) {
4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(result_end, object_size);
4979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(result_end, result);
4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand limit_operand = ExternalOperand(allocation_limit);
4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(result_end, limit_operand);
4983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  j(above, gc_required);
4984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4985bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
4986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The top pointer is not updated for allocation folding dominators.
4987bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateAllocationTopHelper(result_end, scratch, flags);
4988bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4989bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4990bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Tag the result.
4991bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  addp(result, Immediate(kHeapObjectTag));
4992bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
4993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4994bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(int object_size, Register result,
4995bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
4996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
4997bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
4998bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
4999bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5000bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
5001bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MakeSureDoubleAlignedHelper(result, no_reg, NULL, flags);
5002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5004bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  leap(result_end, Operand(result, object_size));
5005bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
5007bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5008bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  addp(result, Immediate(kHeapObjectTag));
5009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid MacroAssembler::FastAllocate(Register object_size, Register result,
5012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                  Register result_end, AllocationFlags flags) {
5013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!result.is(result_end));
5014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Load address of new object into result.
5015bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  LoadAllocationTopHelper(result, no_reg, flags);
5016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((flags & DOUBLE_ALIGNMENT) != 0) {
5018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MakeSureDoubleAlignedHelper(result, no_reg, NULL, flags);
5019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5021bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  leap(result_end, Operand(result, object_size, times_1, 0));
5022bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5023bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateAllocationTopHelper(result_end, no_reg, flags);
5024bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5025bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  addp(result, Immediate(kHeapObjectTag));
5026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
5027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
50293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        Register scratch,
5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Label* gc_required,
5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        MutableMode mode) {
50323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate heap number in new space.
5033bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required,
5034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
5035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::RootListIndex map_index = mode == MUTABLE
5037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Heap::kMutableHeapNumberMapRootIndex
5038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Heap::kHeapNumberMapRootIndex;
50393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
50403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Set the map.
5041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, map_index);
5042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
50433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
50443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
50453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::AllocateTwoByteString(Register result,
5047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register length,
5048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch1,
5049e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch2,
5050e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Register scratch3,
5051e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           Label* gc_required) {
5052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
5053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
50546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
50556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
5056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kShortSize == 2);
5057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // scratch1 = length * 2 + kObjectAlignmentMask.
5058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  leap(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
50596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                kHeaderAlignment));
5060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(scratch1, Immediate(~kObjectAlignmentMask));
50616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
5062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(scratch1, Immediate(kHeaderAlignment));
50636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate two byte string in new space.
5066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1, result, scratch2,
5067bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           scratch3, gc_required, NO_ALLOCATION_FLAGS);
5068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5069e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
5070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
5071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
50726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
5073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kLengthOffset), scratch1);
5074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kHashFieldOffset),
5075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
5076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
5077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteString(Register result, Register length,
5080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch1, Register scratch2,
5081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register scratch3,
5082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Label* gc_required) {
5083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Calculate the number of bytes needed for the characters in the string while
5084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // observing object alignment.
5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kHeaderAlignment = SeqOneByteString::kHeaderSize &
50866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               kObjectAlignmentMask;
5087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  movl(scratch1, length);
5088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kCharSize == 1);
5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
5090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(scratch1, Immediate(~kObjectAlignmentMask));
50916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (kHeaderAlignment > 0) {
5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    subp(scratch1, Immediate(kHeaderAlignment));
50936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5094e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate one-byte string in new space.
5096bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1, result, scratch2,
5097bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           scratch3, gc_required, NO_ALLOCATION_FLAGS);
5098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map, length and hash field.
5100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kOneByteStringMapRootIndex);
5101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
51026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Integer32ToSmi(scratch1, length);
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kLengthOffset), scratch1);
5104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, String::kHashFieldOffset),
5105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke       Immediate(String::kEmptyHashField));
5106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
5107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5109589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteConsString(Register result,
5110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch1,
5111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Register scratch2,
5112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* gc_required) {
5113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Allocate heap number in new space.
5114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
5115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
5116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
5118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
5119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
5120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
5121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteConsString(Register result,
5124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch1,
5125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register scratch2,
5126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Label* gc_required) {
5127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
5128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
5129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the map. The other fields are left uninitialized.
5131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kConsOneByteStringMapRootIndex);
5132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
5133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
5134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5136589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid MacroAssembler::AllocateTwoByteSlicedString(Register result,
5137589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Register scratch1,
5138589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Register scratch2,
5139589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                          Label* gc_required) {
5140589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Allocate heap number in new space.
5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
5142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
5143589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
5144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set the map. The other fields are left uninitialized.
5145589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
5146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
5147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
5148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
5149589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
5150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::AllocateOneByteSlicedString(Register result,
5151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch1,
5152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Register scratch2,
5153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                 Label* gc_required) {
5154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Allocate heap number in new space.
5155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
5156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
5157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
5158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set the map. The other fields are left uninitialized.
5159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kSlicedOneByteStringMapRootIndex);
5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
5161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
5162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
5163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
5164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::AllocateJSValue(Register result, Register constructor,
5165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register value, Register scratch,
5166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Label* gc_required) {
5167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(constructor));
5168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(scratch));
5169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!result.is(value));
5170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate JSValue in new space.
5172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
5173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           NO_ALLOCATION_FLAGS);
5174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize the JSValue.
5176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadGlobalFunctionInitialMap(constructor, scratch);
5177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, HeapObject::kMapOffset), scratch);
5178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
5179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
5180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, JSObject::kElementsOffset), scratch);
5181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(FieldOperand(result, JSValue::kValueOffset), value);
5182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
5183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
5184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
518644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Copy memory, byte-by-byte, from source to destination.  Not optimized for
518744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// long or aligned copies.  The contents of scratch and length are destroyed.
518844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Destination is incremented by length, source, length and scratch are
518944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// clobbered.
519044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A simpler loop is faster on small copies, but slower on large ones.
519144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The cld() instruction must have been emitted, to set the direction flag(),
519244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// before calling this function.
519344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CopyBytes(Register destination,
519444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register source,
519544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register length,
519644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               int min_length,
519744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch) {
5198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(min_length >= 0);
5199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (emit_debug_code()) {
520044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    cmpl(length, Immediate(min_length));
5201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assert(greater_equal, kInvalidMinLength);
520244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label short_loop, len8, len16, len24, done, short_string;
520444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kLongStringLimit = 4 * kPointerSize;
520644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
5207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(kPointerSize));
5208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below, &short_string, Label::kNear);
520944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
521044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(source.is(rsi));
5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(destination.is(rdi));
5213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length.is(rcx));
5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (min_length <= kLongStringLimit) {
5216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(2 * kPointerSize));
5217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below_equal, &len8, Label::kNear);
5218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(3 * kPointerSize));
5219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below_equal, &len16, Label::kNear);
5220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cmpl(length, Immediate(4 * kPointerSize));
5221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    j(below_equal, &len24, Label::kNear);
5222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
522344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
522444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Because source is 8-byte aligned in our uses of this function,
522544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // we keep source aligned for the rep movs operation by copying the odd bytes
522644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // at the end of the ranges.
5227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch, length);
5228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrl(length, Immediate(kPointerSizeLog2));
5229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  repmovsp();
523044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move remaining bytes of length.
5231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andl(scratch, Immediate(kPointerSize - 1));
5232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(length, Operand(source, scratch, times_1, -kPointerSize));
5233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(destination, scratch, times_1, -kPointerSize), length);
5234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(destination, scratch);
523544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
523644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_length <= kLongStringLimit) {
5237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
5238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&len24);
5239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, 2 * kPointerSize));
5240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, 2 * kPointerSize), scratch);
5241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&len16);
5242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, kPointerSize));
5243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, kPointerSize), scratch);
5244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&len8);
5245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, 0));
5246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, 0), scratch);
5247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move remaining bytes of length.
5248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Operand(source, length, times_1, -kPointerSize));
5249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(Operand(destination, length, times_1, -kPointerSize), scratch);
5250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    addp(destination, length);
5251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jmp(&done, Label::kNear);
525244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
525344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_string);
525444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (min_length == 0) {
525544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      testl(length, length);
5256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      j(zero, &done, Label::kNear);
525744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
525844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
525944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bind(&short_loop);
5260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movb(scratch, Operand(source, 0));
5261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movb(Operand(destination, 0), scratch);
5262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incp(source);
5263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incp(destination);
5264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    decl(length);
5265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    j(not_zero, &short_loop, Label::kNear);
526644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&done);
526944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
527044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
527144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::InitializeFieldsWithFiller(Register current_address,
5273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                Register end_address,
52743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Register filler) {
52753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry;
5276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jmp(&entry, Label::kNear);
52773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&loop);
5278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(Operand(current_address, 0), filler);
5279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  addp(current_address, Immediate(kPointerSize));
52803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&entry);
5281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpp(current_address, end_address);
5282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  j(below, &loop, Label::kNear);
52833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
5287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
5288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
5289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
5290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
5291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movp(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
5292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
5293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
5294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Slot is in the current function context.  Move it into the
5295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // destination register in case we store into it (the write barrier
5296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // cannot be allowed to destroy the context in rsi).
5297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(dst, rsi);
5298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
53003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We should not have found a with context by walking the context
53013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // chain (i.e., the static scope chain and runtime context chain do
53023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // not agree).  A variable occurring in such a scope should have
53033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot type LOOKUP and not CONTEXT.
530444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
53053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
53063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Heap::kWithContextMapRootIndex);
5307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Check(not_equal, kVariableResolvedToWithContext);
5308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
5309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
5310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
53113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::LoadTransitionedArrayMapConditional(
53133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind expected_kind,
53143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind transitioned_kind,
53153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register map_in_out,
53163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
53173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* no_map_match) {
5318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(expected_kind));
5319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsFastElementsKind(transitioned_kind));
53203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function's map is the same as the expected cached map.
5322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(scratch, NativeContextOperand());
5323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmpp(map_in_out,
5324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       ContextOperand(scratch, Context::ArrayMapIndex(expected_kind)));
53253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, no_map_match);
53263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use the transitioned cached map.
5328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(map_in_out,
5329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind)));
53303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
533344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef _WIN64
533444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
533544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
533644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 6;
533744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
53387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
5341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, NativeContextOperand());
5342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(dst, ContextOperand(dst, index));
5343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
5347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Register map) {
5348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the initial map.  The global functions all have initial maps.
5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
535044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
5351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Label ok, fail;
5352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
5353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    jmp(&ok);
5354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&fail);
5355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kGlobalFunctionsMustHaveInitialMap);
5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bind(&ok);
5357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkeint MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
53627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On Windows 64 stack slots are reserved by the caller for all arguments
53637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // including the ones passed in registers, and space is always allocated for
53647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the four register arguments even if the function takes fewer than four
53657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // arguments.
53667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
53677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and the caller does not reserve stack slots for them.
5368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_arguments >= 0);
53694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#ifdef _WIN64
537044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kMinimumStackSlots = kRegisterPassedArguments;
53717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
53727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments;
53734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#else
53747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (num_arguments < kRegisterPassedArguments) return 0;
53757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return num_arguments - kRegisterPassedArguments;
53764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke#endif
53774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
53784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
53797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::EmitSeqStringSetCharCheck(Register string,
5381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register index,
5382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Register value,
5383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               uint32_t encoding_mask) {
5384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_object;
5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JumpIfNotSmi(string, &is_object);
5386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Abort(kNonObject);
5387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&is_object);
5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Push(value);
5390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(value, FieldOperand(string, HeapObject::kMapOffset));
5391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movzxbp(value, FieldOperand(value, Map::kInstanceTypeOffset));
5392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
5394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(value, Immediate(encoding_mask));
5395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Pop(value);
5396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(equal, kUnexpectedStringType);
5397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The index is assumed to be untagged coming in, tag it to compare with the
5399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // string length without using a temp register, it is restored at the end of
5400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this function.
5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Integer32ToSmi(index, index);
5402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiCompare(index, FieldOperand(string, String::kLengthOffset));
5403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(less, kIndexIsTooLarge);
5404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiCompare(index, Smi::FromInt(0));
5406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Check(greater_equal, kIndexIsNegative);
5407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the index
5409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiToInteger32(index, index);
5410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
54134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::PrepareCallCFunction(int num_arguments) {
5414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int frame_alignment = base::OS::ActivationFrameAlignment();
5415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(frame_alignment != 0);
5416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_arguments >= 0);
541744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
54184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Make stack end at alignment and allocate space for arguments and old rsp.
5419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(kScratchRegister, rsp);
5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
54214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
54224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
5423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  subp(rsp, Immediate((argument_slots_on_stack + 1) * kRegisterSize));
5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rsp, Immediate(-frame_alignment));
5425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(Operand(rsp, argument_slots_on_stack * kRegisterSize), kScratchRegister);
54264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
54274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
54284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
54294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(ExternalReference function,
54304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                   int num_arguments) {
543144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LoadAddress(rax, function);
54324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CallCFunction(rax, num_arguments);
54334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
54344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
54354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
54364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid MacroAssembler::CallCFunction(Register function, int num_arguments) {
5437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(has_frame());
54386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check stack alignment.
543944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
54406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CheckStackAlignment();
54416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
54426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  call(function);
5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base::OS::ActivationFrameAlignment() != 0);
5445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num_arguments >= 0);
54464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int argument_slots_on_stack =
54474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ArgumentStackSlotsForCFunctionCall(num_arguments);
5448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rsp, Operand(rsp, argument_slots_on_stack * kRegisterSize));
54494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
54504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
5453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
5454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
5455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3,
5456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4,
5457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5,
5458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6,
5459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7,
5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8) {
5461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
5463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg7.is_valid() + reg8.is_valid();
5464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegList regs = 0;
5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is_valid()) regs |= reg1.bit();
5467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg2.is_valid()) regs |= reg2.bit();
5468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg3.is_valid()) regs |= reg3.bit();
5469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg4.is_valid()) regs |= reg4.bit();
5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg5.is_valid()) regs |= reg5.bit();
5471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg6.is_valid()) regs |= reg6.bit();
5472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg7.is_valid()) regs |= reg7.bit();
5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg8.is_valid()) regs |= reg8.bit();
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int n_of_non_aliasing_regs = NumRegs(regs);
5475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return n_of_valid_regs != n_of_non_aliasing_regs;
54773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
54793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodePatcher::CodePatcher(Isolate* isolate, byte* address, int size)
54828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : address_(address),
54838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      size_(size),
5484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      masm_(isolate, address, size + Assembler::kGap, CodeObjectRequired::kNo) {
5485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
5486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
5487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
5488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
5489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
5493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
5494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(masm_.isolate(), address_, size_);
5495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
5497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.pc_ == address_ + size_);
5498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
5499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::CheckPageFlag(
55033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register object,
55043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch,
55053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int mask,
55063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Condition cc,
55073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* condition_met,
55083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label::Distance condition_met_distance) {
5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc == zero || cc == not_zero);
55103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scratch.is(object)) {
5511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(scratch, Immediate(~Page::kPageAlignmentMask));
55123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    movp(scratch, Immediate(~Page::kPageAlignmentMask));
5514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    andp(scratch, object);
55153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
55163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mask < (1 << kBitsPerByte)) {
55173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testb(Operand(scratch, MemoryChunk::kFlagsOffset),
55183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Immediate(static_cast<uint8_t>(mask)));
55193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
55203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
55213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
55223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(cc, condition_met, condition_met_distance);
55233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::JumpIfBlack(Register object,
55273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_scratch,
55283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_scratch,
55293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* on_black,
55303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label::Distance on_black_distance) {
5531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, rcx));
5532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
55333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(object, bitmap_scratch, mask_scratch);
55343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
55363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The mask_scratch register contains a 1 at the position of the first bit
5537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and a 1 at a position of the second bit. All other positions are zero.
5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, mask_scratch);
5539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
5540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(mask_scratch, rcx);
55413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(equal, on_black, on_black_distance);
55423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MacroAssembler::GetMarkBits(Register addr_reg,
55463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register bitmap_reg,
55473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register mask_reg) {
5548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx));
5549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(bitmap_reg, addr_reg);
55503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sign extended 32 bit immediate.
5551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
5552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, addr_reg);
55533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int shift =
55543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
55553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shrl(rcx, Immediate(shift));
5556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rcx,
55573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       Immediate((Page::kPageAlignmentMask >> shift) &
55583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 ~(Bitmap::kBytesPerCell - 1)));
55593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addp(bitmap_reg, rcx);
5561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, addr_reg);
55623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  shrl(rcx, Immediate(kPointerSizeLog2));
5563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  andp(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1));
5564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movl(mask_reg, Immediate(3));
5565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shlp_cl(mask_reg);
55663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
5570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Register mask_scratch, Label* value_is_white,
5571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 Label::Distance distance) {
5572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, rcx));
55733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GetMarkBits(value, bitmap_scratch, mask_scratch);
55743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is black or grey we don't need to do anything.
5576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
5577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
5578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
5579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
55803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Since both black and grey have a 1 in the first position and white does
55823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not have a 1 there we only need to check one bit.
5583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  testp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
5584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(zero, value_is_white, distance);
55853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::CheckEnumCache(Label* call_runtime) {
5589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label next, start;
55903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register empty_fixed_array_value = r8;
55913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
5592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, rax);
5593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the enum length field is properly initialized, indicating that
5595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // there is an enum cache.
5596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
5597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(rdx, rbx);
5599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cmp(rdx, Smi::FromInt(kInvalidEnumCacheSentinel));
5600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, call_runtime);
5601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  jmp(&start);
5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bind(&next);
56053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
5607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For all objects but the receiver, check that the cache is empty.
5609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnumLength(rdx, rbx);
5610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cmp(rdx, Smi::FromInt(0));
56113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
56123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&start);
56143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there are no elements. Register rcx contains the current JS
5616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object we've reached through the prototype chain.
5617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_elements;
5618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(empty_fixed_array_value,
5619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       FieldOperand(rcx, JSObject::kElementsOffset));
5620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, &no_elements);
56213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Second chance, the object may be using the empty slow element dictionary.
5623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadRoot(kScratchRegister, Heap::kEmptySlowElementDictionaryRootIndex);
5624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(kScratchRegister, FieldOperand(rcx, JSObject::kElementsOffset));
56253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, call_runtime);
56263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&no_elements);
5628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
5629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CompareRoot(rcx, Heap::kNullValueRootIndex);
56303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  j(not_equal, &next);
56313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
56323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5633109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TestJSArrayForAllocationMemento(
5635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver_reg,
5636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_reg,
5637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* no_memento_found) {
56383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label map_check;
56393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label top_check;
5640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference new_space_allocation_top =
5641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::new_space_allocation_top_address(isolate());
56423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
56433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
56443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
56453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bail out if the object is not in new space.
56463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
56473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the object is in new space, we need to check whether it is on the same
56483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // page as the current top.
56493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  leap(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
56503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xorp(scratch_reg, ExternalOperand(new_space_allocation_top));
56513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  testp(scratch_reg, Immediate(~Page::kPageAlignmentMask));
56523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(zero, &top_check);
56533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The object is on a different page than allocation top. Bail out if the
56543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object sits on the page boundary as no memento can follow and we cannot
56553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // touch the memory following it.
56563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  leap(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
56573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  xorp(scratch_reg, receiver_reg);
56583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  testp(scratch_reg, Immediate(~Page::kPageAlignmentMask));
56593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  j(not_zero, no_memento_found);
56603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Continue with the actual map check.
56613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jmp(&map_check);
56623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If top is on the same page as the current object, we need to check whether
56633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // we are below top.
56643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&top_check);
56653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  leap(scratch_reg, Operand(receiver_reg, kMementoEndOffset));
5666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch_reg, ExternalOperand(new_space_allocation_top));
5667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(greater, no_memento_found);
56683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Memento map check.
56693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bind(&map_check);
56703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  CompareRoot(MemOperand(receiver_reg, kMementoMapOffset),
5671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Heap::kAllocationMementoMapRootIndex);
5672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::JumpIfDictionaryInPrototypeChain(
5676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object,
5677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch0,
5678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1,
5679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* found) {
5680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister)));
5681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(scratch0));
5682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register current = scratch0;
5683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop_again, end;
5684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(current, object);
5686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(current, FieldOperand(current, HeapObject::kMapOffset));
5687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  movp(current, FieldOperand(current, Map::kPrototypeOffset));
5688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompareRoot(current, Heap::kNullValueRootIndex);
5689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(equal, &end);
5690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop based on the map going up the prototype chain.
5692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bind(&loop_again);
5693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(current, FieldOperand(current, HeapObject::kMapOffset));
5694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
5695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
5696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CmpInstanceType(current, JS_OBJECT_TYPE);
5697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  j(below, found);
5698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(scratch1, FieldOperand(current, Map::kBitField2Offset));
5699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DecodeField<Map::ElementsKindBits>(scratch1);
5700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS));
5701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(equal, found);
5702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movp(current, FieldOperand(current, Map::kPrototypeOffset));
5703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareRoot(current, Heap::kNullValueRootIndex);
5704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  j(not_equal, &loop_again);
5705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bind(&end);
5707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
5711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(rax));
5712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(rdx));
5713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::MagicNumbersForDivision<uint32_t> mag =
5714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
5715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(rax, Immediate(mag.multiplier));
5716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  imull(dividend);
5717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
5718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 0 && neg) addl(rdx, dividend);
5719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0 && !neg && mag.multiplier > 0) subl(rdx, dividend);
5720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mag.shift > 0) sarl(rdx, Immediate(mag.shift));
5721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  movl(rax, dividend);
5722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shrl(rax, Immediate(31));
5723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  addl(rdx, rax);
5724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
57263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
5728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
5729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
5731