13ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Copyright 2009 the V8 project authors. All rights reserved.
23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without
33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are
43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met:
53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions of source code must retain the above copyright
73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       notice, this list of conditions and the following disclaimer.
83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions in binary form must reproduce the above
93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       copyright notice, this list of conditions and the following
103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       disclaimer in the documentation and/or other materials provided
113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       with the distribution.
123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Neither the name of Google Inc. nor the names of its
133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       contributors may be used to endorse or promote products derived
143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       from this software without specific prior written permission.
153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include <stdlib.h>
293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h"
313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "macro-assembler.h"
333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "factory.h"
343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "platform.h"
353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "serialize.h"
363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "cctest.h"
373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::Assembler;
398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::CodeDesc;
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::Condition;
418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::FUNCTION_CAST;
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::HandleScope;
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::Immediate;
448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::Isolate;
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::Label;
468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::MacroAssembler;
478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::OS;
488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::Operand;
493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::RelocInfo;
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::Smi;
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::SmiIndex;
528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::byte;
538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::carry;
548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::greater;
558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::greater_equal;
568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::kIntSize;
578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::kPointerSize;
588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::kSmiTagMask;
598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::kSmiValueSize;
608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::less_equal;
618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::negative;
628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::not_carry;
638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::not_equal;
648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::not_zero;
658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::positive;
668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::r11;
678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::r13;
688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::r14;
698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::r15;
708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::r8;
718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::r9;
723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::rax;
738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::rbp;
743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::rbx;
753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::rcx;
768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::rdi;
773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::rdx;
788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochusing v8::internal::rsi;
793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockusing v8::internal::rsp;
80f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeusing v8::internal::times_pointer_size;
813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Test the x64 assembler by compiling some simple functions into
833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// a buffer and executing them.  These tests do not initialize the
843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// V8 library, create a context, or use any V8 objects.
853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The AMD64 calling convention is used, with the first five arguments
863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// the XMM registers.  The return value is in RAX.
883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// This calling convention is used on Linux, with GCC, and on Mac OS,
893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// with GCC.  A different convention is used on 64-bit windows.
903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocktypedef int (*F0)();
923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ masm->
943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
958defd9ff6930b4e24729971a61cf7469daf119beSteve Block
968defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void EntryCode(MacroAssembler* masm) {
978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Smi constant register is callee save.
988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ push(v8::internal::kSmiConstantRegister);
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ push(v8::internal::kRootRegister);
1008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ InitializeSmiConstantRegister();
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ InitializeRootRegister();
1028defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1038defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1048defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1058defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void ExitCode(MacroAssembler* masm) {
1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Return -1 if kSmiConstantRegister was clobbered during the test.
1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ Move(rdx, Smi::FromInt(1));
1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmpq(rdx, v8::internal::kSmiConstantRegister);
1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movq(rdx, Immediate(-1));
1108defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmovq(not_equal, rax, rdx);
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ pop(v8::internal::kRootRegister);
1128defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ pop(v8::internal::kSmiConstantRegister);
1138defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1148defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1158defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(Smi) {
1173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that C++ Smi operations work as expected.
118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int64_t test_numbers[] = {
1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
1223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  };
1233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int test_number_count = 15;
1243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < test_number_count; i++) {
125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    int64_t number = test_numbers[i];
1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bool is_valid = Smi::IsValid(number);
1273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
1283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    CHECK_EQ(is_in_range, is_valid);
1293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (is_valid) {
1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Smi* smi_from_intptr = Smi::FromIntptr(number);
1313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      if (static_cast<int>(number) == number) {  // Is a 32-bit int.
1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
1333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CHECK_EQ(smi_from_int, smi_from_intptr);
1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int64_t smi_value = smi_from_intptr->value();
136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      CHECK_EQ(number, smi_value);
1373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
1383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
1433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
1443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(0));
1453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
1463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmpq(rcx, rdx);
1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Test that we can move a Smi value literally into a register.
1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiMove) {
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                   &actual_size,
1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                   true));
1593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
1603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
1618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
1628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
1638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
1643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;  // Create a pointer for the __ macro.
1653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
1673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
1703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r8, rcx);
1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r9, rdx);
2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiCompare(rcx, rdx);
2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (x < y) {
2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id + 1));
2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(greater_equal, exit);
2043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (x > y) {
2053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id + 2));
2063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(less_equal, exit);
2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT_EQ(x, y);
2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id + 3));
2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id + 4));
2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmpq(rcx, r8);
2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
2163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmpq(rdx, r9);
2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (x != y) {
2203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiCompare(rdx, rcx);
2213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (y < x) {
2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ movl(rax, Immediate(id + 9));
2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(greater_equal, exit);
2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
2253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      ASSERT(y > x);
2263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ movl(rax, Immediate(id + 10));
2273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(less_equal, exit);
2283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
2293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, rcx);
2313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id + 11));
2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
2333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
2343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ cmpq(rcx, r8);
2353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
2363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Test that we can compare smis for equality (and more).
2413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiCompare) {
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
2433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
2443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
2453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
24644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
2473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
2483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
2493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
2503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
2518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
2528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
2538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
2543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
2563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
2578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
2583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
2593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x10, 0, 0);
2613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x20, 0, 1);
2623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x30, 1, 0);
2633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x40, 1, 1);
2643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x50, 0, -1);
2653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x60, -1, 0);
2663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x70, -1, -1);
2673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
2683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
2693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
2703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
2713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
2723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
2733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
2743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
2753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
2763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
2773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
2783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
2793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
2813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
2828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
2833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
2843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
2863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
2873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
2883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
2893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
2903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
2913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(Integer32ToSmi) {
29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
2963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
2973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
2993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 &actual_size,
3003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 true));
3013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
3023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
3038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
3048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
3058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
3063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
3098defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
3113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(1));  // Test number.
3133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(0));
3143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
3153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
31644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, rdx);
3173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(2));  // Test number.
3203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(1024));
3213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
3223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, rdx);
3243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(3));  // Test number.
3273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(-1));
3283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
3293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, rdx);
3313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(4));  // Test number.
3343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(Smi::kMaxValue));
3353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
3363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, rdx);
3383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(5));  // Test number.
3413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(Smi::kMinValue));
3423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
3433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, rdx);
3453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Different target register.
3483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(6));  // Test number.
3503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(0));
3513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(r8, rcx);
3523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rdx);
3543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(7));  // Test number.
3573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(1024));
3583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(r8, rcx);
3593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rdx);
3613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(8));  // Test number.
3643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(-1));
3653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(r8, rcx);
3663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rdx);
3683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(9));  // Test number.
3713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(Smi::kMaxValue));
3723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(r8, rcx);
3733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rdx);
3753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rax, Immediate(10));  // Test number.
3783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(Smi::kMinValue));
3793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(r8, rcx);
3803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rdx);
3823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &exit);
3833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
3863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
3878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
3883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
3893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
3913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
3923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
3933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
3943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
3953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestI64PlusConstantToSmi(MacroAssembler* masm,
3993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              Label* exit,
4003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              int id,
4013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              int64_t x,
4023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              int y) {
4033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int64_t result = x + y;
4043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(Smi::IsValid(result));
4053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Move(r8, Smi::FromInt(static_cast<int>(result)));
4073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, x, RelocInfo::NONE);
4083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
4093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer64PlusConstantToSmi(rdx, rcx, y);
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rdx, r8);
4113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
41444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
4153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
4183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer64PlusConstantToSmi(rcx, rcx, y);
41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
4203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
4213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(Integer64PlusConstantToSmi) {
42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
4263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
4283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
4293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 &actual_size,
4303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 true));
4313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
4323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
4338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
4348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
4358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
4363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
4383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
4398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
4403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
4413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
4433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
4453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
4463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
4473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
4483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
4493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
4503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
4513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
4523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
4533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
4543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
4553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
4563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
4583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
4598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
4603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
4613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
4633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
4643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
4653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
4673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
4683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiCheck) {
47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
4723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
4733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
4743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
4753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                   &actual_size,
4763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                   true));
4773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
4783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
4798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
4808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
4818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
4823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
4843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
4858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
4863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
4873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Condition cond;
4883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(1));  // Test number.
4903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // CheckSmi
4923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(0));
4943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
4953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
4963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
4973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
4993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
5003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(-1));
5053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
5063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
5083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
5113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(Smi::kMaxValue));
5163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
5173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
5193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
5223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(Smi::kMinValue));
5273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
5283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
5303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
5333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckSmi(rcx);
5343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // CheckPositiveSmi
5373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(0));
5403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
541f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);
5423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
5433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
546f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);  // "zero" non-smi.
5473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(-1));
5513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
552f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);  // Negative smis are not positive.
5533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMinValue));
5573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);  // Most negative smi is not positive.
5593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
563f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);  // "Negative" non-smi.
5643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMaxValue));
5683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
569f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);  // Most positive smi is positive.
5703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
5713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
574f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  cond = masm->CheckNonNegativeSmi(rcx);  // "Positive" non-smi.
5753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // CheckIsMinSmi
5783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMaxValue));
5813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
5823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckIsMinSmi(rcx);
5833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(0));
5873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
5883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckIsMinSmi(rcx);
5893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
5903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMinValue));
5933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
5943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckIsMinSmi(rcx);
5953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
5963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
5983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMinValue + 1));
5993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
6003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckIsMinSmi(rcx);
6013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
6023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // CheckBothSmi
6043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMaxValue));
6073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
6083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rdx, Immediate(Smi::kMinValue));
6093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rdx, rdx);
6103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckBothSmi(rcx, rdx);
6113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
6123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
6153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckBothSmi(rcx, rdx);
6163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
6173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rdx, Immediate(kSmiTagMask));
6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckBothSmi(rcx, rdx);
6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
6223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckBothSmi(rcx, rdx);
6263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckBothSmi(rcx, rcx);
6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckBothSmi(rdx, rdx);
6343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(cond, &exit);
6353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // CheckInteger32ValidSmiValue
6373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(0));
6393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckInteger32ValidSmiValue(rax);
6403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
6413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(-1));
6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckInteger32ValidSmiValue(rax);
6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
6463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMaxValue));
6493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckInteger32ValidSmiValue(rax);
6503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
6513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
6533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, Immediate(Smi::kMinValue));
6543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  cond = masm->CheckInteger32ValidSmiValue(rax);
6553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(NegateCondition(cond), &exit);
6563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Success
6583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);
6593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
6618defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
6623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
6633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
6653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
6663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
6673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
6683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
6693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
6743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (x == Smi::kMinValue || x == 0) {
6773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Negation fails.
6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id + 8));
6793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiNeg(r9, rcx, exit);
6803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r11, rcx);
6833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
6843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiNeg(rcx, rcx, exit);
6873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r11, rcx);
6903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
6913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
6923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label smi_ok, smi_ok2;
6933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int result = -x;
6943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id));
6953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(r8, Smi::FromInt(result));
6963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiNeg(r9, rcx, &smi_ok);
6983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
6993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&smi_ok);
7003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
70144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
7023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
7033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r11, rcx);
7063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
7073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
7093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiNeg(rcx, rcx, &smi_ok2);
7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
7113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&smi_ok2);
7123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
7143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
7153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiNeg) {
72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
7223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
7233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
7253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
7263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
7273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
7283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
7298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
7308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
7318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
7323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
7358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
7373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x10, 0);
7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x20, 1);
7403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x30, -1);
7413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x40, 127);
7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x50, 65535);
7433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
7443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
7498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
7513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
7543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
7553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
7563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic void SmiAddTest(MacroAssembler* masm,
7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                       Label* exit,
7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                       int id,
7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                       int first,
7663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                       int second) {
7673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(first));
7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rdx, Immediate(second));
7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rdx, rdx);
7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(r8, Immediate(first + second));
7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(r8, r8);
7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));  // Test number.
7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAdd(r9, rcx, rdx, exit);
77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
7783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
7803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAdd(rcx, rcx, rdx, exit);                              \
78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(first));
7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rcx, Immediate(first));
7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Integer32ToSmi(rcx, rcx);
7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
8003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAddConstant(r9, rcx, Smi::FromInt(second), exit);
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
8023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
8053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), exit);
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiAdd) {
81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 &actual_size,
8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 true));
8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
8198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
8208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
8218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
8223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
8258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // No-overflow tests.
8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x10, 1, 2);
8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x20, 1, -2);
8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x30, -1, 2);
8323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x40, -1, -2);
8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
8343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
8353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
8363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
8408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
8473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic void SmiSubTest(MacroAssembler* masm,
8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      Label* exit,
8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      int id,
8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      int first,
8553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                      int second) {
8563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(first));
8573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(second));
8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(r8, Smi::FromInt(first - second));
8593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));  // Test 0.
8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiSub(r9, rcx, rdx, exit);
86244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);  // Test 1.
8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiSub(rcx, rcx, rdx, exit);
86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(first));
8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);  // Test 2.
8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);  // Test 3.
8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(first));
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);  // Test 4.
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiSubConstant(r9, rcx, Smi::FromInt(second), exit);
88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);  // Test 5.
8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), exit);
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic void SmiSubOverflowTest(MacroAssembler* masm,
8963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                               Label* exit,
8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                               int id,
8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                               int x) {
8993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Subtracts a Smi from x so that the subtraction overflows.
9003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(x != -1);  // Can't overflow by subtracting a Smi.
9013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
9023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
9033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
9053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);  // Store original Smi value of x in r11.
9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y_min));
9083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSub(r9, rcx, rdx, &overflow_ok);
9113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSub(rcx, rcx, rdx, &overflow_ok);
9223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, r11);
9303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), &overflow_ok);
9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
93744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), &overflow_ok);
9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
94844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y_max));
9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSub(r9, rcx, rdx, &overflow_ok);
9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSub(rcx, rcx, rdx, &overflow_ok);
9693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
97244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, r11);
9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSubConstant(r9, rcx, Smi::FromInt(y_max), &overflow_ok);
9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  {
9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok;
9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), &overflow_ok);
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiSub) {
100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
10103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
10118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
10128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
10138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
10178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
10183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
10193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x10, 1, 2);
10213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x20, 1, -2);
10223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x30, -1, 2);
10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x40, -1, -2);
10243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
10253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
10263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
10273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
10283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
10293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0xA0, 1);
10313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
10323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
10333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0xD0, -2);
10343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
10353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
10363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmiSubOverflowTest(masm, &exit, 0x100, 0);
10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
10393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
10408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
10453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
10473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
10543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool negative_zero = (result == 0) && (x < 0 || y < 0);
10553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (Smi::IsValid(result) && !negative_zero) {
10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id));
10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(r8, Smi::FromIntptr(result));
10613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiMul(r9, rcx, rdx, exit);
10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r11, rcx);
10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiMul(rcx, rcx, rdx, exit);
107144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movl(rax, Immediate(id + 8));
10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label overflow_ok, overflow_ok2;
10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiMul(r9, rcx, rdx, &overflow_ok);
10773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
10783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok);
10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
108044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r11, rcx);
10813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
10823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&overflow_ok2);
10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // 31-bit version doesn't preserve rcx on failure.
10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // __ incq(rax);
108844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // __ cmpq(r11, rcx);
10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // __ j(not_equal, exit);
10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiMul) {
109544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 &actual_size,
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                 true));
11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
11038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
11048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
11058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
11098defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x10, 0, 0);
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x20, -1, 0);
11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x30, 0, -1);
11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x40, -1, -1);
11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
11263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
11298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
11303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
11313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
11353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
11373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
11413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool division_by_zero = (y == 0);
11423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool negative_zero = (x == 0 && y < 0);
11433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef V8_TARGET_ARCH_X64
11443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool overflow = (x == Smi::kMinValue && y < 0);  // Safe approx. used.
11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#else
11463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool overflow = (x == Smi::kMinValue && y == -1);
11473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool fraction = !division_by_zero && !overflow && (x % y != 0);
11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(r11, Smi::FromInt(x));
11508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ Move(r14, Smi::FromInt(y));
11513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!fraction && !overflow && !negative_zero && !division_by_zero) {
11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Division succeeds
11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rcx, r11);
115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movq(r15, Immediate(id));
11553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int result = x / y;
11563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(r8, Smi::FromInt(result));
11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiDiv(r9, rcx, r14, exit);
11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Might have destroyed rcx and r14.
115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
11613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
11643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rcx, r11);
11658defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ Move(r14, Smi::FromInt(y));
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
11683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
11708defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiDiv(rcx, rcx, r14, exit);
11713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
11743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
11753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
11763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Division fails.
117744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movq(r15, Immediate(id + 8));
11783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label fail_ok, fail_ok2;
11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(rcx, r11);
11818defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiDiv(r9, rcx, r14, &fail_ok);
11823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
11833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&fail_ok);
11843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
11908defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiDiv(rcx, rcx, r14, &fail_ok2);
11913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
11923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&fail_ok2);
11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
11973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiDiv) {
120244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
12073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
12118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
12128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
12138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
12178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
12183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ push(r14);
122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ push(r15);
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x10, 1, 1);
12233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x20, 1, 0);
12243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x30, -1, 0);
12253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x40, 0, 1);
12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x50, 0, -1);
12273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x60, 4, 2);
12283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x70, -4, 2);
12293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x80, 4, -2);
12303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x90, -4, -2);
12313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0xa0, 3, 2);
12323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0xb0, 3, 4);
12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
124344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ xor_(r15, r15);  // Success.
12443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rax, r15);
124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ pop(r15);
12478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ pop(r14);
12488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
12533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
12563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
12603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool division_by_zero = (y == 0);
12613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool division_overflow = (x == Smi::kMinValue) && (y == -1);
12623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool negative_zero = (!fraction && x < 0);
12643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
12668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ Move(r14, Smi::FromInt(y));
12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!division_overflow && !negative_zero && !division_by_zero) {
12683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Modulo succeeds
126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movq(r15, Immediate(id));
12703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int result = x % y;
12713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(r8, Smi::FromInt(result));
12728defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiMod(r9, rcx, r14, exit);
12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
127844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
127944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
12803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
12838defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiMod(rcx, rcx, r14, exit);
12843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
128544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
128644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Modulo fails.
129044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movq(r15, Immediate(id + 8));
12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label fail_ok, fail_ok2;
12938defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiMod(r9, rcx, r14, &fail_ok);
12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&fail_ok);
12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
129744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
129844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
13028defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ SmiMod(rcx, rcx, r14, &fail_ok2);
13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ jmp(exit);
13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&fail_ok2);
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ incq(r15);
130744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r11);
13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
13093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiMod) {
131444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
13238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
13248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
13258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
13283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
13298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ push(r14);
133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ push(r15);
13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x10, 1, 1);
13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x20, 1, 0);
13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x30, -1, 0);
13373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x40, 0, 1);
13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x50, 0, -1);
13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x60, 4, 2);
13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x70, -4, 2);
13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x80, 4, -2);
13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x90, -4, -2);
13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0xa0, 3, 2);
13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0xb0, 3, 4);
13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ xor_(r15, r15);  // Success.
13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rax, r15);
135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ pop(r15);
13598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ pop(r14);
13608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
13643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
13663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
13673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
13733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < 8; i++) {
13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, Smi::FromInt(x));
13763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
13783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ shl(index.reg, Immediate(index.scale));
13793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Set(r8, static_cast<intptr_t>(x) << i);
138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(index.reg, r8);
13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
13823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, Smi::FromInt(x));
13843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    index = masm->SmiToIndex(rcx, rcx, i);
13853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(index.reg.is(rcx));
13863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ shl(rcx, Immediate(index.scale));
13873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Set(r8, static_cast<intptr_t>(x) << i);
138844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
13893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
13903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
13913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, Smi::FromInt(x));
13933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    index = masm->SmiToNegativeIndex(rdx, rcx, i);
13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
13953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ shl(index.reg, Immediate(index.scale));
13963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Set(r8, static_cast<intptr_t>(-x) << i);
139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(index.reg, r8);
13983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
13993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
14003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, Smi::FromInt(x));
14013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    index = masm->SmiToNegativeIndex(rcx, rcx, i);
14023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ASSERT(index.reg.is(rcx));
14033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ shl(rcx, Immediate(index.scale));
14043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Set(r8, static_cast<intptr_t>(-x) << i);
140544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
14063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
14073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
14083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiIndex) {
141244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
14133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
14143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
14153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
14168defd9ff6930b4e24729971a61cf7469daf119beSteve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
14203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
14218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
14228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
14238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
14243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
14263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
14278defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
14283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiIndex(masm, &exit, 0x10, 0);
14313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiIndex(masm, &exit, 0x20, 1);
14323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiIndex(masm, &exit, 0x30, 100);
14333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiIndex(masm, &exit, 0x40, 1000);
14343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
14373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
14388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
14393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
14403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
14443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
14463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
14513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
14523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
14533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rdx, Immediate(kSmiTagMask));
14543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SelectNonSmi(r9, rcx, rdx, exit);
14553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
145744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, rdx);
14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
14613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
14623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
14643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SelectNonSmi(r9, rcx, rdx, exit);
14653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
146744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, rcx);
14683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
14693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
14713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label fail_ok;
14723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
14733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
14743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rcx, Immediate(kSmiTagMask));
14753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rdx, Immediate(kSmiTagMask));
14763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
14773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ jmp(exit);
14783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&fail_ok);
14793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiSelectNonSmi) {
148344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
14843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
14853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
14863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
14873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
14883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
14893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
14903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
14913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
14928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
14938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
14948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
14953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);  // Avoid inline checks.
14988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
14993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
15003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
15023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
15033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
15043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
15063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
15093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
15103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
15123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
15138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
15143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
15153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
15173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
15183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
15203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
15253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = x & y;
15263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
15283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
15303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
15313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
15323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(r8, Smi::FromInt(result));
15333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAnd(r9, rcx, rdx);
153444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, r9);
15353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
15363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
153844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
15393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAnd(rcx, rcx, rdx);
154344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rcx);
15443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
15453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, r11);
15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, r9);
15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
155344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
15543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
15553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
155844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rcx);
15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
15603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiAnd) {
156444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
15653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
15663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
15673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
15713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
15723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
15738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
15748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
15758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
15783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
15798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x10, 0, 0);
15833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x20, 0, 1);
15843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x30, 1, 0);
15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x40, 0, -1);
15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x50, -1, 0);
15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x60, -1, -1);
15883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x70, 1, 1);
15893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
15903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
15913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
15968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
15973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
16013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
16033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
16083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = x | y;
16093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
16113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(r8, Smi::FromInt(result));
16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiOr(r9, rcx, rdx);
161744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, r9);
16183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
16193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
162144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
16223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
16233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
16253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiOr(rcx, rcx, rdx);
162644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rcx);
16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
16283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, r11);
16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, r9);
16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
16343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
163644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
16373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
16383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
16403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
164144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rcx);
16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiOr) {
164744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
16483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
16493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
16503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
16513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
16553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
16568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
16578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
16588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
16628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
16633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
16643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x10, 0, 0);
16663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x20, 0, 1);
16673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x30, 1, 0);
16683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x40, 0, -1);
16693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x50, -1, 0);
16703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x60, -1, -1);
16713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x70, 1, 1);
16723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
16733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
16743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
16753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
16763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
16773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
16783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
16803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
16818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
16833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
16863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = x ^ y;
16943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
16963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
16983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
16993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rdx, Smi::FromInt(y));
17003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(r8, Smi::FromInt(result));
17013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiXor(r9, rcx, rdx);
170244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, r9);
17033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
170644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
17073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
17103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiXor(rcx, rcx, rdx);
171144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rcx);
17123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(rcx, r11);
17153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
17163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
171744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, r9);
17183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
172144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
17223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
17253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
172644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r8, rcx);
17273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiXor) {
173244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
17333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
17343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
17353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
17363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
17373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
17383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
17393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
17403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
17418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
17428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
17438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
17443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
17463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
17478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
17483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
17493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x10, 0, 0);
17513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x20, 0, 1);
17523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x30, 1, 0);
17533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x40, 0, -1);
17543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x50, -1, 0);
17553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x60, -1, -1);
17563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x70, 1, 1);
17573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
17583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
17593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
17603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
17613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
17623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
17633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
17653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
17668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
17673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
17683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
17703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
17713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
17723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
17733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
17743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
17783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = ~x;
17793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
17803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(r8, Smi::FromInt(result));
17823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ Move(rcx, Smi::FromInt(x));
17833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movq(r11, rcx);
17843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiNot(r9, rcx);
178644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r9, r8);
17873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(r11, rcx);
17913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ incq(rax);
17943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ SmiNot(rcx, rcx);
179544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmpq(rcx, r8);
17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, exit);
17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiNot) {
180144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
18023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
18033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
18043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
18053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
18063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
18073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
18083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
18108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
18118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
18128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
18133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
18153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
18168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
18173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
18183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x10, 0);
18203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x20, 1);
18213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x30, -1);
18223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x40, 127);
18233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x50, 65535);
18243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
18253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiNot(masm, &exit, 0x80, 0x05555555);
18273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
18293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
18308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
18313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
18323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
18343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
18363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
18373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
18383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const int kNumShifts = 5;
18443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
18453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < kNumShifts; i++) {
18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // rax == id + i * 10.
18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int shift = shifts[i];
18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int result = x << shift;
184925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    CHECK(Smi::IsValid(result));
185025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(r8, Smi::FromInt(result));
185125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(rcx, Smi::FromInt(x));
185225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ SmiShiftLeftConstant(r9, rcx, shift);
185325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
185425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
185544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
185625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ j(not_equal, exit);
185725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
185825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
185925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(rcx, Smi::FromInt(x));
186025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ SmiShiftLeftConstant(rcx, rcx, shift);
186125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
186225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
186425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ j(not_equal, exit);
186525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
186625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
186725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(rdx, Smi::FromInt(x));
186825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(rcx, Smi::FromInt(shift));
186925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ SmiShiftLeft(r9, rdx, rcx);
187025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
187125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
187244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
187325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ j(not_equal, exit);
187425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
187525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
187625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(rdx, Smi::FromInt(x));
187725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(r11, Smi::FromInt(shift));
187825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ SmiShiftLeft(r9, rdx, r11);
187925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
188025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
188144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r9, r8);
188225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ j(not_equal, exit);
188325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
188425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
188525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(rdx, Smi::FromInt(x));
188625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ Move(r11, Smi::FromInt(shift));
188725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ SmiShiftLeft(rdx, rdx, r11);
188825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
188925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
189044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rdx, r8);
189125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ j(not_equal, exit);
189225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
189325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ incq(rax);
18943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiShiftLeft) {
189944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
19003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
19013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
19023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
19038defd9ff6930b4e24729971a61cf7469daf119beSteve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
19043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
19053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
19063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
19088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
19098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
19108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
19113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
19133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
19148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
19153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
19163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0x10, 0);
19183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0x50, 1);
19193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0x90, 127);
19203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
19213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
19223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
19233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLeft(masm, &exit, 0x190, -1);
19243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
19263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
19278defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
19283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
19293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
19313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
19323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
19333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
19343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
19353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
19363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiShiftLogicalRight(MacroAssembler* masm,
19393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              Label* exit,
19403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              int id,
19413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                              int x) {
19423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
19433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const int kNumShifts = 5;
19443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
19453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < kNumShifts; i++) {
19463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int shift = shifts[i];
19473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    intptr_t result = static_cast<unsigned int>(x) >> shift;
19483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (Smi::IsValid(result)) {
1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ Move(r8, Smi::FromInt(static_cast<int>(result)));
19503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(rcx, Smi::FromInt(x));
19513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
19523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
195444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(r9, r8);
19553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(not_equal, exit);
19563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
19583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(rdx, Smi::FromInt(x));
19593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(rcx, Smi::FromInt(shift));
19603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
19613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
196344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(r9, r8);
19643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(not_equal, exit);
19653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
19673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(rdx, Smi::FromInt(x));
19683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(r11, Smi::FromInt(shift));
19693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ SmiShiftLogicalRight(r9, rdx, r11, exit);
19703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(r9, r8);
19733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(not_equal, exit);
19743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
19763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
19773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Cannot happen with long smis.
19783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Label fail_ok;
19793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(rcx, Smi::FromInt(x));
19803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ movq(r11, rcx);
19813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
19823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ jmp(exit);
19833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ bind(&fail_ok);
19843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(rcx, r11);
19873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(not_equal, exit);
19883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
19903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ Move(r8, Smi::FromInt(shift));
19913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      Label fail_ok3;
19923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
19933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ jmp(exit);
19943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ bind(&fail_ok3);
19953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
19963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ incq(rax);
199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(rcx, r11);
19983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(not_equal, exit);
19993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ addq(rax, Immediate(3));
20013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
20023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
20033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
20043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiShiftLogicalRight) {
200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
20083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
20093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
20103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
20118defd9ff6930b4e24729971a61cf7469daf119beSteve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
20123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
20133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
20143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
20153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
20168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
20188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
20193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
20213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
20228defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
20233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
20243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
20263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
20273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
20283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
20293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
20303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
20313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
20323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
20343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
20358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
20363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
20373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
20393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
20403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
20413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
20423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
20433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
20443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestSmiShiftArithmeticRight(MacroAssembler* masm,
20473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                 Label* exit,
20483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                 int id,
20493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                 int x) {
20503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
20513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const int kNumShifts = 5;
20523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
20533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < kNumShifts; i++) {
20543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int shift = shifts[i];
20553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Guaranteed arithmetic shift.
20563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
20573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(r8, Smi::FromInt(result));
20583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, Smi::FromInt(x));
20593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
20603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rcx, r8);
20623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
20633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
20653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rdx, Smi::FromInt(x));
20663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(r11, Smi::FromInt(shift));
20673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ SmiShiftArithmeticRight(rdx, rdx, r11);
20683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rdx, r8);
20703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
20713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
20733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
20743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
20753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(SmiShiftArithmeticRight) {
207844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
20793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
20803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
20813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
20823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
20833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
20843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
20853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
20863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
20878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
20888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
20898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
20903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
20923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
20938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
20943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
20953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
20973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
20983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
20993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
21003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
21013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
21023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
21033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
21053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
21068defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
21073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
21083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
21103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
21113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
21123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
21133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
21143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
21153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
21183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(x >= 0);
21193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
21203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int power_count = 8;
21213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ movl(rax, Immediate(id));
21223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i  < power_count; i++) {
21233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int power = powers[i];
21243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    intptr_t result = static_cast<intptr_t>(x) << power;
21253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Set(r8, result);
21263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ Move(rcx, Smi::FromInt(x));
21273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ movq(r11, rcx);
21283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
212944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rdx, r8);
21303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
21313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(r11, rcx);  // rcx unchanged.
21333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
21343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
21353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmpq(rdx, r8);
21373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(not_equal, exit);
21383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ incq(rax);
21393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
21403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
21413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(PositiveSmiTimesPowerOfTwoToInteger64) {
214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
21453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate an executable page of memory.
21463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  size_t actual_size;
21473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte* buffer =
214844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
21493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      &actual_size,
21503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                      true));
21513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(buffer);
21523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  HandleScope handles;
21538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
21548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
21558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
21563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  MacroAssembler* masm = &assembler;
21583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->set_allow_stub_calls(false);
21598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
21603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label exit;
21613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
21633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
21643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
21653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
21663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
21673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
21683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
21693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
21703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
21713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ xor_(rax, rax);  // Success.
21733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&exit);
21748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
21753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
21763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CodeDesc desc;
21783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  masm->GetCode(&desc);
21793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the function from C++.
21803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int result = FUNCTION_CAST<F0>(buffer)();
21813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(0, result);
21823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
21833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
21843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTEST(OperandOffset) {
218644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int data[256];
2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Allocate an executable page of memory.
2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  size_t actual_size;
2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  byte* buffer =
2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                      &actual_size,
2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                      true));
2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(buffer);
2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  HandleScope handles;
21988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(Isolate::Current(),
21998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           buffer,
22008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           static_cast<int>(actual_size));
2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  MacroAssembler* masm = &assembler;
2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  masm->set_allow_stub_calls(false);
2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22068defd9ff6930b4e24729971a61cf7469daf119beSteve Block  EntryCode(masm);
2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(r13);
22088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ push(r14);
2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rbx);
2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(rbp);
2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x100));  // <-- rbp
2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbp, rsp);
2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x101));
2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x102));
2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x103));
2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x104));
2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x105));  // <-- rbx
2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x106));
2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x107));
2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x108));
2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(0x109));  // <-- rsp
2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rbp = rsp[9]
222344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r15 = rsp[3]
2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rbx = rsp[5]
2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r13 = rsp[7]
22268defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ lea(r14, Operand(rsp, 3 * kPointerSize));
2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ lea(r13, Operand(rbp, -3 * kPointerSize));
2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ lea(rbx, Operand(rbp, -5 * kPointerSize));
2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rcx, Immediate(2));
2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(r8, reinterpret_cast<uintptr_t>(&data[128]), RelocInfo::NONE);
2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rax, Immediate(1));
2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand sp0 = Operand(rsp, 0);
2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 1.
2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, sp0);  // Sanity check.
2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x109));
2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 2.
2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Zero to non-zero displacement.
2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(sp0, 2 * kPointerSize));
2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x107));
2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand sp2 = Operand(rsp, 2 * kPointerSize);
2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 3.
2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, sp2);  // Sanity check.
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x107));
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(sp2, 2 * kPointerSize));
2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x105));
2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-zero to zero displacement.
2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(sp2, -2 * kPointerSize));
2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x109));
2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 6.
2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, sp2c2);  // Sanity check.
2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x105));
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x103));
2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-zero to zero displacement.
2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x107));
2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand bp0 = Operand(rbp, 0);
2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 9.
2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, bp0);  // Sanity check.
2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x100));
2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Zero to non-zero displacement.
2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bp0, -2 * kPointerSize));
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x102));
2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand bp2 = Operand(rbp, -2 * kPointerSize);
2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 11.
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, bp2);  // Sanity check.
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x102));
2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-zero to zero displacement.
2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bp2, 2 * kPointerSize));
2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x100));
2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bp2, -2 * kPointerSize));
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x104));
2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 14:
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, bp2c4);  // Sanity check.
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x102));
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x100));
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x104));
2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand bx0 = Operand(rbx, 0);
2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 17.
2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, bx0);  // Sanity check.
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x105));
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bx0, 5 * kPointerSize));
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x100));
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bx0, -4 * kPointerSize));
2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x109));
2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand bx2 = Operand(rbx, 2 * kPointerSize);
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 20.
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, bx2);  // Sanity check.
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x103));
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bx2, 2 * kPointerSize));
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x101));
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-zero to zero displacement.
2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bx2, -2 * kPointerSize));
2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x105));
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 23.
2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, bx2c2);  // Sanity check.
2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x105));
2380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x103));
2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x107));
2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand r80 = Operand(r8, 0);
2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 26.
2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, r80);  // Sanity check.
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x80808080));
2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, -8 * kIntSize));
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x78787878));
2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, 8 * kIntSize));
2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x88888888));
2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, -64 * kIntSize));
2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x40404040));
2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, 64 * kIntSize));
2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xC0C0C0C0));
2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand r88 = Operand(r8, 8 * kIntSize);
2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 31.
2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, r88);  // Sanity check.
2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x88888888));
2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r88, -8 * kIntSize));
2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x80808080));
2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r88, 8 * kIntSize));
2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x90909090));
2436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r88, -64 * kIntSize));
2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x48484848));
2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r88, 64 * kIntSize));
2445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xC8C8C8C8));
2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand r864 = Operand(r8, 64 * kIntSize);
2451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 36.
2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, r864);  // Sanity check.
2454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xC0C0C0C0));
2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r864, -8 * kIntSize));
2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xB8B8B8B8));
2460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r864, 8 * kIntSize));
2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xC8C8C8C8));
2465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r864, -64 * kIntSize));
2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x80808080));
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r864, 32 * kIntSize));
2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xE0E0E0E0));
2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // 32-bit offset to 8-bit offset.
2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r864, -60 * kIntSize));
2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x84848484));
2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r864, 60 * kIntSize));
2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xFCFCFCFC));
2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test unaligned offsets.
2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Test 43.
2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, 2));
2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x81818080));
2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, -2));
2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x80807F7F));
2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, 126));
2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xA0A09F9F));
2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, -126));
2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x61616060));
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, 254));
2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0xC0C0BFBF));
2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rdx, Operand(r80, -254));
2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmpl(rdx, Immediate(0x41414040));
2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ incq(rax);
2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Success.
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movl(rax, Immediate(0));
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ lea(rsp, Operand(rbp, kPointerSize));
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rbp);
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(rbx);
25298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ pop(r14);
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(r13);
25318defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ExitCode(masm);
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ ret(0);
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CodeDesc desc;
2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  masm->GetCode(&desc);
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call the function from C++.
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int result = FUNCTION_CAST<F0>(buffer)();
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK_EQ(0, result);
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#undef __
2545