Home | History | Annotate | Download | only in cctest
      1 // Copyright 2009 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 
     30 #include "v8.h"
     31 
     32 #include "macro-assembler.h"
     33 #include "factory.h"
     34 #include "platform.h"
     35 #include "serialize.h"
     36 #include "cctest.h"
     37 
     38 using v8::internal::Assembler;
     39 using v8::internal::CodeDesc;
     40 using v8::internal::Condition;
     41 using v8::internal::FUNCTION_CAST;
     42 using v8::internal::HandleScope;
     43 using v8::internal::Immediate;
     44 using v8::internal::Isolate;
     45 using v8::internal::Label;
     46 using v8::internal::MacroAssembler;
     47 using v8::internal::OS;
     48 using v8::internal::Operand;
     49 using v8::internal::RelocInfo;
     50 using v8::internal::Smi;
     51 using v8::internal::SmiIndex;
     52 using v8::internal::byte;
     53 using v8::internal::carry;
     54 using v8::internal::greater;
     55 using v8::internal::greater_equal;
     56 using v8::internal::kIntSize;
     57 using v8::internal::kPointerSize;
     58 using v8::internal::kSmiTagMask;
     59 using v8::internal::kSmiValueSize;
     60 using v8::internal::less_equal;
     61 using v8::internal::negative;
     62 using v8::internal::not_carry;
     63 using v8::internal::not_equal;
     64 using v8::internal::not_zero;
     65 using v8::internal::positive;
     66 using v8::internal::r11;
     67 using v8::internal::r13;
     68 using v8::internal::r14;
     69 using v8::internal::r15;
     70 using v8::internal::r8;
     71 using v8::internal::r9;
     72 using v8::internal::rax;
     73 using v8::internal::rbp;
     74 using v8::internal::rbx;
     75 using v8::internal::rcx;
     76 using v8::internal::rdi;
     77 using v8::internal::rdx;
     78 using v8::internal::rsi;
     79 using v8::internal::rsp;
     80 using v8::internal::times_pointer_size;
     81 
     82 // Test the x64 assembler by compiling some simple functions into
     83 // a buffer and executing them.  These tests do not initialize the
     84 // V8 library, create a context, or use any V8 objects.
     85 // The AMD64 calling convention is used, with the first five arguments
     86 // in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
     87 // the XMM registers.  The return value is in RAX.
     88 // This calling convention is used on Linux, with GCC, and on Mac OS,
     89 // with GCC.  A different convention is used on 64-bit windows.
     90 
     91 typedef int (*F0)();
     92 
     93 #define __ masm->
     94 
     95 
     96 static void EntryCode(MacroAssembler* masm) {
     97   // Smi constant register is callee save.
     98   __ push(v8::internal::kSmiConstantRegister);
     99   __ push(v8::internal::kRootRegister);
    100   __ InitializeSmiConstantRegister();
    101   __ InitializeRootRegister();
    102 }
    103 
    104 
    105 static void ExitCode(MacroAssembler* masm) {
    106   // Return -1 if kSmiConstantRegister was clobbered during the test.
    107   __ Move(rdx, Smi::FromInt(1));
    108   __ cmpq(rdx, v8::internal::kSmiConstantRegister);
    109   __ movq(rdx, Immediate(-1));
    110   __ cmovq(not_equal, rax, rdx);
    111   __ pop(v8::internal::kRootRegister);
    112   __ pop(v8::internal::kSmiConstantRegister);
    113 }
    114 
    115 
    116 TEST(Smi) {
    117   // Check that C++ Smi operations work as expected.
    118   int64_t test_numbers[] = {
    119       0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
    120       Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
    121       Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
    122   };
    123   int test_number_count = 15;
    124   for (int i = 0; i < test_number_count; i++) {
    125     int64_t number = test_numbers[i];
    126     bool is_valid = Smi::IsValid(number);
    127     bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
    128     CHECK_EQ(is_in_range, is_valid);
    129     if (is_valid) {
    130       Smi* smi_from_intptr = Smi::FromIntptr(number);
    131       if (static_cast<int>(number) == number) {  // Is a 32-bit int.
    132         Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
    133         CHECK_EQ(smi_from_int, smi_from_intptr);
    134       }
    135       int64_t smi_value = smi_from_intptr->value();
    136       CHECK_EQ(number, smi_value);
    137     }
    138   }
    139 }
    140 
    141 
    142 static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
    143   __ movl(rax, Immediate(id));
    144   __ Move(rcx, Smi::FromInt(0));
    145   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
    146   __ cmpq(rcx, rdx);
    147   __ j(not_equal, exit);
    148 }
    149 
    150 
    151 // Test that we can move a Smi value literally into a register.
    152 TEST(SmiMove) {
    153   v8::internal::V8::Initialize(NULL);
    154   // Allocate an executable page of memory.
    155   size_t actual_size;
    156   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
    157                                                    &actual_size,
    158                                                    true));
    159   CHECK(buffer);
    160   Isolate* isolate = Isolate::Current();
    161   HandleScope handles(isolate);
    162   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    163   MacroAssembler* masm = &assembler;  // Create a pointer for the __ macro.
    164   masm->set_allow_stub_calls(false);
    165   EntryCode(masm);
    166   Label exit;
    167 
    168   TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
    169   TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
    170   TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
    171   TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
    172   TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
    173   TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
    174   TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
    175   TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
    176   TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
    177   TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
    178   TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
    179   TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
    180 
    181   __ xor_(rax, rax);  // Success.
    182   __ bind(&exit);
    183   ExitCode(masm);
    184   __ ret(0);
    185 
    186   CodeDesc desc;
    187   masm->GetCode(&desc);
    188   // Call the function from C++.
    189   int result = FUNCTION_CAST<F0>(buffer)();
    190   CHECK_EQ(0, result);
    191 }
    192 
    193 
    194 void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
    195   __ Move(rcx, Smi::FromInt(x));
    196   __ movq(r8, rcx);
    197   __ Move(rdx, Smi::FromInt(y));
    198   __ movq(r9, rdx);
    199   __ SmiCompare(rcx, rdx);
    200   if (x < y) {
    201     __ movl(rax, Immediate(id + 1));
    202     __ j(greater_equal, exit);
    203   } else if (x > y) {
    204     __ movl(rax, Immediate(id + 2));
    205     __ j(less_equal, exit);
    206   } else {
    207     ASSERT_EQ(x, y);
    208     __ movl(rax, Immediate(id + 3));
    209     __ j(not_equal, exit);
    210   }
    211   __ movl(rax, Immediate(id + 4));
    212   __ cmpq(rcx, r8);
    213   __ j(not_equal, exit);
    214   __ incq(rax);
    215   __ cmpq(rdx, r9);
    216   __ j(not_equal, exit);
    217 
    218   if (x != y) {
    219     __ SmiCompare(rdx, rcx);
    220     if (y < x) {
    221       __ movl(rax, Immediate(id + 9));
    222       __ j(greater_equal, exit);
    223     } else {
    224       ASSERT(y > x);
    225       __ movl(rax, Immediate(id + 10));
    226       __ j(less_equal, exit);
    227     }
    228   } else {
    229     __ cmpq(rcx, rcx);
    230     __ movl(rax, Immediate(id + 11));
    231     __ j(not_equal, exit);
    232     __ incq(rax);
    233     __ cmpq(rcx, r8);
    234     __ j(not_equal, exit);
    235   }
    236 }
    237 
    238 
    239 // Test that we can compare smis for equality (and more).
    240 TEST(SmiCompare) {
    241   v8::internal::V8::Initialize(NULL);
    242   // Allocate an executable page of memory.
    243   size_t actual_size;
    244   byte* buffer =
    245       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
    246                                       &actual_size,
    247                                       true));
    248   CHECK(buffer);
    249   Isolate* isolate = Isolate::Current();
    250   HandleScope handles(isolate);
    251   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    252 
    253   MacroAssembler* masm = &assembler;
    254   masm->set_allow_stub_calls(false);
    255   EntryCode(masm);
    256   Label exit;
    257 
    258   TestSmiCompare(masm, &exit, 0x10, 0, 0);
    259   TestSmiCompare(masm, &exit, 0x20, 0, 1);
    260   TestSmiCompare(masm, &exit, 0x30, 1, 0);
    261   TestSmiCompare(masm, &exit, 0x40, 1, 1);
    262   TestSmiCompare(masm, &exit, 0x50, 0, -1);
    263   TestSmiCompare(masm, &exit, 0x60, -1, 0);
    264   TestSmiCompare(masm, &exit, 0x70, -1, -1);
    265   TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
    266   TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
    267   TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
    268   TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
    269   TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
    270   TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
    271   TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
    272   TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
    273   TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
    274   TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
    275   TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
    276   TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
    277 
    278   __ xor_(rax, rax);  // Success.
    279   __ bind(&exit);
    280   ExitCode(masm);
    281   __ ret(0);
    282 
    283   CodeDesc desc;
    284   masm->GetCode(&desc);
    285   // Call the function from C++.
    286   int result = FUNCTION_CAST<F0>(buffer)();
    287   CHECK_EQ(0, result);
    288 }
    289 
    290 
    291 
    292 TEST(Integer32ToSmi) {
    293   v8::internal::V8::Initialize(NULL);
    294   // Allocate an executable page of memory.
    295   size_t actual_size;
    296   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
    297                                                  &actual_size,
    298                                                  true));
    299   CHECK(buffer);
    300   Isolate* isolate = Isolate::Current();
    301   HandleScope handles(isolate);
    302   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    303 
    304   MacroAssembler* masm = &assembler;
    305   masm->set_allow_stub_calls(false);
    306   EntryCode(masm);
    307   Label exit;
    308 
    309   __ movq(rax, Immediate(1));  // Test number.
    310   __ movl(rcx, Immediate(0));
    311   __ Integer32ToSmi(rcx, rcx);
    312   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
    313   __ cmpq(rcx, rdx);
    314   __ j(not_equal, &exit);
    315 
    316   __ movq(rax, Immediate(2));  // Test number.
    317   __ movl(rcx, Immediate(1024));
    318   __ Integer32ToSmi(rcx, rcx);
    319   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
    320   __ cmpq(rcx, rdx);
    321   __ j(not_equal, &exit);
    322 
    323   __ movq(rax, Immediate(3));  // Test number.
    324   __ movl(rcx, Immediate(-1));
    325   __ Integer32ToSmi(rcx, rcx);
    326   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
    327   __ cmpq(rcx, rdx);
    328   __ j(not_equal, &exit);
    329 
    330   __ movq(rax, Immediate(4));  // Test number.
    331   __ movl(rcx, Immediate(Smi::kMaxValue));
    332   __ Integer32ToSmi(rcx, rcx);
    333   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
    334   __ cmpq(rcx, rdx);
    335   __ j(not_equal, &exit);
    336 
    337   __ movq(rax, Immediate(5));  // Test number.
    338   __ movl(rcx, Immediate(Smi::kMinValue));
    339   __ Integer32ToSmi(rcx, rcx);
    340   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
    341   __ cmpq(rcx, rdx);
    342   __ j(not_equal, &exit);
    343 
    344   // Different target register.
    345 
    346   __ movq(rax, Immediate(6));  // Test number.
    347   __ movl(rcx, Immediate(0));
    348   __ Integer32ToSmi(r8, rcx);
    349   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
    350   __ cmpq(r8, rdx);
    351   __ j(not_equal, &exit);
    352 
    353   __ movq(rax, Immediate(7));  // Test number.
    354   __ movl(rcx, Immediate(1024));
    355   __ Integer32ToSmi(r8, rcx);
    356   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
    357   __ cmpq(r8, rdx);
    358   __ j(not_equal, &exit);
    359 
    360   __ movq(rax, Immediate(8));  // Test number.
    361   __ movl(rcx, Immediate(-1));
    362   __ Integer32ToSmi(r8, rcx);
    363   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
    364   __ cmpq(r8, rdx);
    365   __ j(not_equal, &exit);
    366 
    367   __ movq(rax, Immediate(9));  // Test number.
    368   __ movl(rcx, Immediate(Smi::kMaxValue));
    369   __ Integer32ToSmi(r8, rcx);
    370   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
    371   __ cmpq(r8, rdx);
    372   __ j(not_equal, &exit);
    373 
    374   __ movq(rax, Immediate(10));  // Test number.
    375   __ movl(rcx, Immediate(Smi::kMinValue));
    376   __ Integer32ToSmi(r8, rcx);
    377   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
    378   __ cmpq(r8, rdx);
    379   __ j(not_equal, &exit);
    380 
    381 
    382   __ xor_(rax, rax);  // Success.
    383   __ bind(&exit);
    384   ExitCode(masm);
    385   __ ret(0);
    386 
    387   CodeDesc desc;
    388   masm->GetCode(&desc);
    389   // Call the function from C++.
    390   int result = FUNCTION_CAST<F0>(buffer)();
    391   CHECK_EQ(0, result);
    392 }
    393 
    394 
    395 void TestI64PlusConstantToSmi(MacroAssembler* masm,
    396                               Label* exit,
    397                               int id,
    398                               int64_t x,
    399                               int y) {
    400   int64_t result = x + y;
    401   ASSERT(Smi::IsValid(result));
    402   __ movl(rax, Immediate(id));
    403   __ Move(r8, Smi::FromInt(static_cast<int>(result)));
    404   __ movq(rcx, x, RelocInfo::NONE64);
    405   __ movq(r11, rcx);
    406   __ Integer64PlusConstantToSmi(rdx, rcx, y);
    407   __ cmpq(rdx, r8);
    408   __ j(not_equal, exit);
    409 
    410   __ incq(rax);
    411   __ cmpq(r11, rcx);
    412   __ j(not_equal, exit);
    413 
    414   __ incq(rax);
    415   __ Integer64PlusConstantToSmi(rcx, rcx, y);
    416   __ cmpq(rcx, r8);
    417   __ j(not_equal, exit);
    418 }
    419 
    420 
    421 TEST(Integer64PlusConstantToSmi) {
    422   v8::internal::V8::Initialize(NULL);
    423   // Allocate an executable page of memory.
    424   size_t actual_size;
    425   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
    426                                                  &actual_size,
    427                                                  true));
    428   CHECK(buffer);
    429   Isolate* isolate = Isolate::Current();
    430   HandleScope handles(isolate);
    431   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    432 
    433   MacroAssembler* masm = &assembler;
    434   masm->set_allow_stub_calls(false);
    435   EntryCode(masm);
    436   Label exit;
    437 
    438   int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
    439 
    440   TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
    441   TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
    442   TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
    443   TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
    444   TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
    445   TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
    446   TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
    447   TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
    448   TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
    449   TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
    450   TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
    451   TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
    452 
    453   __ xor_(rax, rax);  // Success.
    454   __ bind(&exit);
    455   ExitCode(masm);
    456   __ ret(0);
    457 
    458   CodeDesc desc;
    459   masm->GetCode(&desc);
    460   // Call the function from C++.
    461   int result = FUNCTION_CAST<F0>(buffer)();
    462   CHECK_EQ(0, result);
    463 }
    464 
    465 
    466 TEST(SmiCheck) {
    467   v8::internal::V8::Initialize(NULL);
    468   // Allocate an executable page of memory.
    469   size_t actual_size;
    470   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
    471                                                    &actual_size,
    472                                                    true));
    473   CHECK(buffer);
    474   Isolate* isolate = Isolate::Current();
    475   HandleScope handles(isolate);
    476   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    477 
    478   MacroAssembler* masm = &assembler;
    479   masm->set_allow_stub_calls(false);
    480   EntryCode(masm);
    481   Label exit;
    482   Condition cond;
    483 
    484   __ movl(rax, Immediate(1));  // Test number.
    485 
    486   // CheckSmi
    487 
    488   __ movl(rcx, Immediate(0));
    489   __ Integer32ToSmi(rcx, rcx);
    490   cond = masm->CheckSmi(rcx);
    491   __ j(NegateCondition(cond), &exit);
    492 
    493   __ incq(rax);
    494   __ xor_(rcx, Immediate(kSmiTagMask));
    495   cond = masm->CheckSmi(rcx);
    496   __ j(cond, &exit);
    497 
    498   __ incq(rax);
    499   __ movl(rcx, Immediate(-1));
    500   __ Integer32ToSmi(rcx, rcx);
    501   cond = masm->CheckSmi(rcx);
    502   __ j(NegateCondition(cond), &exit);
    503 
    504   __ incq(rax);
    505   __ xor_(rcx, Immediate(kSmiTagMask));
    506   cond = masm->CheckSmi(rcx);
    507   __ j(cond, &exit);
    508 
    509   __ incq(rax);
    510   __ movl(rcx, Immediate(Smi::kMaxValue));
    511   __ Integer32ToSmi(rcx, rcx);
    512   cond = masm->CheckSmi(rcx);
    513   __ j(NegateCondition(cond), &exit);
    514 
    515   __ incq(rax);
    516   __ xor_(rcx, Immediate(kSmiTagMask));
    517   cond = masm->CheckSmi(rcx);
    518   __ j(cond, &exit);
    519 
    520   __ incq(rax);
    521   __ movl(rcx, Immediate(Smi::kMinValue));
    522   __ Integer32ToSmi(rcx, rcx);
    523   cond = masm->CheckSmi(rcx);
    524   __ j(NegateCondition(cond), &exit);
    525 
    526   __ incq(rax);
    527   __ xor_(rcx, Immediate(kSmiTagMask));
    528   cond = masm->CheckSmi(rcx);
    529   __ j(cond, &exit);
    530 
    531   // CheckPositiveSmi
    532 
    533   __ incq(rax);
    534   __ movl(rcx, Immediate(0));
    535   __ Integer32ToSmi(rcx, rcx);
    536   cond = masm->CheckNonNegativeSmi(rcx);
    537   __ j(NegateCondition(cond), &exit);
    538 
    539   __ incq(rax);
    540   __ xor_(rcx, Immediate(kSmiTagMask));
    541   cond = masm->CheckNonNegativeSmi(rcx);  // "zero" non-smi.
    542   __ j(cond, &exit);
    543 
    544   __ incq(rax);
    545   __ movq(rcx, Immediate(-1));
    546   __ Integer32ToSmi(rcx, rcx);
    547   cond = masm->CheckNonNegativeSmi(rcx);  // Negative smis are not positive.
    548   __ j(cond, &exit);
    549 
    550   __ incq(rax);
    551   __ movq(rcx, Immediate(Smi::kMinValue));
    552   __ Integer32ToSmi(rcx, rcx);
    553   cond = masm->CheckNonNegativeSmi(rcx);  // Most negative smi is not positive.
    554   __ j(cond, &exit);
    555 
    556   __ incq(rax);
    557   __ xor_(rcx, Immediate(kSmiTagMask));
    558   cond = masm->CheckNonNegativeSmi(rcx);  // "Negative" non-smi.
    559   __ j(cond, &exit);
    560 
    561   __ incq(rax);
    562   __ movq(rcx, Immediate(Smi::kMaxValue));
    563   __ Integer32ToSmi(rcx, rcx);
    564   cond = masm->CheckNonNegativeSmi(rcx);  // Most positive smi is positive.
    565   __ j(NegateCondition(cond), &exit);
    566 
    567   __ incq(rax);
    568   __ xor_(rcx, Immediate(kSmiTagMask));
    569   cond = masm->CheckNonNegativeSmi(rcx);  // "Positive" non-smi.
    570   __ j(cond, &exit);
    571 
    572   // CheckIsMinSmi
    573 
    574   __ incq(rax);
    575   __ movq(rcx, Immediate(Smi::kMaxValue));
    576   __ Integer32ToSmi(rcx, rcx);
    577   cond = masm->CheckIsMinSmi(rcx);
    578   __ j(cond, &exit);
    579 
    580   __ incq(rax);
    581   __ movq(rcx, Immediate(0));
    582   __ Integer32ToSmi(rcx, rcx);
    583   cond = masm->CheckIsMinSmi(rcx);
    584   __ j(cond, &exit);
    585 
    586   __ incq(rax);
    587   __ movq(rcx, Immediate(Smi::kMinValue));
    588   __ Integer32ToSmi(rcx, rcx);
    589   cond = masm->CheckIsMinSmi(rcx);
    590   __ j(NegateCondition(cond), &exit);
    591 
    592   __ incq(rax);
    593   __ movq(rcx, Immediate(Smi::kMinValue + 1));
    594   __ Integer32ToSmi(rcx, rcx);
    595   cond = masm->CheckIsMinSmi(rcx);
    596   __ j(cond, &exit);
    597 
    598   // CheckBothSmi
    599 
    600   __ incq(rax);
    601   __ movq(rcx, Immediate(Smi::kMaxValue));
    602   __ Integer32ToSmi(rcx, rcx);
    603   __ movq(rdx, Immediate(Smi::kMinValue));
    604   __ Integer32ToSmi(rdx, rdx);
    605   cond = masm->CheckBothSmi(rcx, rdx);
    606   __ j(NegateCondition(cond), &exit);
    607 
    608   __ incq(rax);
    609   __ xor_(rcx, Immediate(kSmiTagMask));
    610   cond = masm->CheckBothSmi(rcx, rdx);
    611   __ j(cond, &exit);
    612 
    613   __ incq(rax);
    614   __ xor_(rdx, Immediate(kSmiTagMask));
    615   cond = masm->CheckBothSmi(rcx, rdx);
    616   __ j(cond, &exit);
    617 
    618   __ incq(rax);
    619   __ xor_(rcx, Immediate(kSmiTagMask));
    620   cond = masm->CheckBothSmi(rcx, rdx);
    621   __ j(cond, &exit);
    622 
    623   __ incq(rax);
    624   cond = masm->CheckBothSmi(rcx, rcx);
    625   __ j(NegateCondition(cond), &exit);
    626 
    627   __ incq(rax);
    628   cond = masm->CheckBothSmi(rdx, rdx);
    629   __ j(cond, &exit);
    630 
    631   // CheckInteger32ValidSmiValue
    632   __ incq(rax);
    633   __ movq(rcx, Immediate(0));
    634   cond = masm->CheckInteger32ValidSmiValue(rax);
    635   __ j(NegateCondition(cond), &exit);
    636 
    637   __ incq(rax);
    638   __ movq(rcx, Immediate(-1));
    639   cond = masm->CheckInteger32ValidSmiValue(rax);
    640   __ j(NegateCondition(cond), &exit);
    641 
    642   __ incq(rax);
    643   __ movq(rcx, Immediate(Smi::kMaxValue));
    644   cond = masm->CheckInteger32ValidSmiValue(rax);
    645   __ j(NegateCondition(cond), &exit);
    646 
    647   __ incq(rax);
    648   __ movq(rcx, Immediate(Smi::kMinValue));
    649   cond = masm->CheckInteger32ValidSmiValue(rax);
    650   __ j(NegateCondition(cond), &exit);
    651 
    652   // Success
    653   __ xor_(rax, rax);
    654 
    655   __ bind(&exit);
    656   ExitCode(masm);
    657   __ ret(0);
    658 
    659   CodeDesc desc;
    660   masm->GetCode(&desc);
    661   // Call the function from C++.
    662   int result = FUNCTION_CAST<F0>(buffer)();
    663   CHECK_EQ(0, result);
    664 }
    665 
    666 
    667 
    668 void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
    669   __ Move(rcx, Smi::FromInt(x));
    670   __ movq(r11, rcx);
    671   if (x == Smi::kMinValue || x == 0) {
    672     // Negation fails.
    673     __ movl(rax, Immediate(id + 8));
    674     __ SmiNeg(r9, rcx, exit);
    675 
    676     __ incq(rax);
    677     __ cmpq(r11, rcx);
    678     __ j(not_equal, exit);
    679 
    680     __ incq(rax);
    681     __ SmiNeg(rcx, rcx, exit);
    682 
    683     __ incq(rax);
    684     __ cmpq(r11, rcx);
    685     __ j(not_equal, exit);
    686   } else {
    687     Label smi_ok, smi_ok2;
    688     int result = -x;
    689     __ movl(rax, Immediate(id));
    690     __ Move(r8, Smi::FromInt(result));
    691 
    692     __ SmiNeg(r9, rcx, &smi_ok);
    693     __ jmp(exit);
    694     __ bind(&smi_ok);
    695     __ incq(rax);
    696     __ cmpq(r9, r8);
    697     __ j(not_equal, exit);
    698 
    699     __ incq(rax);
    700     __ cmpq(r11, rcx);
    701     __ j(not_equal, exit);
    702 
    703     __ incq(rax);
    704     __ SmiNeg(rcx, rcx, &smi_ok2);
    705     __ jmp(exit);
    706     __ bind(&smi_ok2);
    707     __ incq(rax);
    708     __ cmpq(rcx, r8);
    709     __ j(not_equal, exit);
    710   }
    711 }
    712 
    713 
    714 TEST(SmiNeg) {
    715   v8::internal::V8::Initialize(NULL);
    716   // Allocate an executable page of memory.
    717   size_t actual_size;
    718   byte* buffer =
    719       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
    720                                       &actual_size,
    721                                       true));
    722   CHECK(buffer);
    723   Isolate* isolate = Isolate::Current();
    724   HandleScope handles(isolate);
    725   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    726 
    727   MacroAssembler* masm = &assembler;
    728   masm->set_allow_stub_calls(false);
    729   EntryCode(masm);
    730   Label exit;
    731 
    732   TestSmiNeg(masm, &exit, 0x10, 0);
    733   TestSmiNeg(masm, &exit, 0x20, 1);
    734   TestSmiNeg(masm, &exit, 0x30, -1);
    735   TestSmiNeg(masm, &exit, 0x40, 127);
    736   TestSmiNeg(masm, &exit, 0x50, 65535);
    737   TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
    738   TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
    739   TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
    740 
    741   __ xor_(rax, rax);  // Success.
    742   __ bind(&exit);
    743   ExitCode(masm);
    744   __ ret(0);
    745 
    746   CodeDesc desc;
    747   masm->GetCode(&desc);
    748   // Call the function from C++.
    749   int result = FUNCTION_CAST<F0>(buffer)();
    750   CHECK_EQ(0, result);
    751 }
    752 
    753 
    754 
    755 
    756 static void SmiAddTest(MacroAssembler* masm,
    757                        Label* exit,
    758                        int id,
    759                        int first,
    760                        int second) {
    761   __ movl(rcx, Immediate(first));
    762   __ Integer32ToSmi(rcx, rcx);
    763   __ movl(rdx, Immediate(second));
    764   __ Integer32ToSmi(rdx, rdx);
    765   __ movl(r8, Immediate(first + second));
    766   __ Integer32ToSmi(r8, r8);
    767 
    768   __ movl(rax, Immediate(id));  // Test number.
    769   __ SmiAdd(r9, rcx, rdx, exit);
    770   __ cmpq(r9, r8);
    771   __ j(not_equal, exit);
    772 
    773   __ incq(rax);
    774   __ SmiAdd(rcx, rcx, rdx, exit);                              \
    775   __ cmpq(rcx, r8);
    776   __ j(not_equal, exit);
    777 
    778   __ movl(rcx, Immediate(first));
    779   __ Integer32ToSmi(rcx, rcx);
    780 
    781   __ incq(rax);
    782   __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
    783   __ cmpq(r9, r8);
    784   __ j(not_equal, exit);
    785 
    786   __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
    787   __ cmpq(rcx, r8);
    788   __ j(not_equal, exit);
    789 
    790   __ movl(rcx, Immediate(first));
    791   __ Integer32ToSmi(rcx, rcx);
    792 
    793   __ incq(rax);
    794   __ SmiAddConstant(r9, rcx, Smi::FromInt(second), exit);
    795   __ cmpq(r9, r8);
    796   __ j(not_equal, exit);
    797 
    798   __ incq(rax);
    799   __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), exit);
    800   __ cmpq(rcx, r8);
    801   __ j(not_equal, exit);
    802 }
    803 
    804 
    805 TEST(SmiAdd) {
    806   v8::internal::V8::Initialize(NULL);
    807   // Allocate an executable page of memory.
    808   size_t actual_size;
    809   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
    810                                                  &actual_size,
    811                                                  true));
    812   CHECK(buffer);
    813   Isolate* isolate = Isolate::Current();
    814   HandleScope handles(isolate);
    815   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
    816 
    817   MacroAssembler* masm = &assembler;
    818   masm->set_allow_stub_calls(false);
    819   EntryCode(masm);
    820   Label exit;
    821 
    822   // No-overflow tests.
    823   SmiAddTest(masm, &exit, 0x10, 1, 2);
    824   SmiAddTest(masm, &exit, 0x20, 1, -2);
    825   SmiAddTest(masm, &exit, 0x30, -1, 2);
    826   SmiAddTest(masm, &exit, 0x40, -1, -2);
    827   SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
    828   SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
    829   SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
    830   SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
    831 
    832   __ xor_(rax, rax);  // Success.
    833   __ bind(&exit);
    834   ExitCode(masm);
    835   __ ret(0);
    836 
    837   CodeDesc desc;
    838   masm->GetCode(&desc);
    839   // Call the function from C++.
    840   int result = FUNCTION_CAST<F0>(buffer)();
    841   CHECK_EQ(0, result);
    842 }
    843 
    844 
    845 static void SmiSubTest(MacroAssembler* masm,
    846                       Label* exit,
    847                       int id,
    848                       int first,
    849                       int second) {
    850   __ Move(rcx, Smi::FromInt(first));
    851   __ Move(rdx, Smi::FromInt(second));
    852   __ Move(r8, Smi::FromInt(first - second));
    853 
    854   __ movl(rax, Immediate(id));  // Test 0.
    855   __ SmiSub(r9, rcx, rdx, exit);
    856   __ cmpq(r9, r8);
    857   __ j(not_equal, exit);
    858 
    859   __ incq(rax);  // Test 1.
    860   __ SmiSub(rcx, rcx, rdx, exit);
    861   __ cmpq(rcx, r8);
    862   __ j(not_equal, exit);
    863 
    864   __ Move(rcx, Smi::FromInt(first));
    865 
    866   __ incq(rax);  // Test 2.
    867   __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
    868   __ cmpq(r9, r8);
    869   __ j(not_equal, exit);
    870 
    871   __ incq(rax);  // Test 3.
    872   __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
    873   __ cmpq(rcx, r8);
    874   __ j(not_equal, exit);
    875 
    876   __ Move(rcx, Smi::FromInt(first));
    877 
    878   __ incq(rax);  // Test 4.
    879   __ SmiSubConstant(r9, rcx, Smi::FromInt(second), exit);
    880   __ cmpq(r9, r8);
    881   __ j(not_equal, exit);
    882 
    883   __ incq(rax);  // Test 5.
    884   __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), exit);
    885   __ cmpq(rcx, r8);
    886   __ j(not_equal, exit);
    887 }
    888 
    889 static void SmiSubOverflowTest(MacroAssembler* masm,
    890                                Label* exit,
    891                                int id,
    892                                int x) {
    893   // Subtracts a Smi from x so that the subtraction overflows.
    894   ASSERT(x != -1);  // Can't overflow by subtracting a Smi.
    895   int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
    896   int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
    897 
    898   __ movl(rax, Immediate(id));
    899   __ Move(rcx, Smi::FromInt(x));
    900   __ movq(r11, rcx);  // Store original Smi value of x in r11.
    901   __ Move(rdx, Smi::FromInt(y_min));
    902   {
    903     Label overflow_ok;
    904     __ SmiSub(r9, rcx, rdx, &overflow_ok);
    905     __ jmp(exit);
    906     __ bind(&overflow_ok);
    907     __ incq(rax);
    908     __ cmpq(rcx, r11);
    909     __ j(not_equal, exit);
    910   }
    911 
    912   {
    913     Label overflow_ok;
    914     __ incq(rax);
    915     __ SmiSub(rcx, rcx, rdx, &overflow_ok);
    916     __ jmp(exit);
    917     __ bind(&overflow_ok);
    918     __ incq(rax);
    919     __ cmpq(rcx, r11);
    920     __ j(not_equal, exit);
    921   }
    922 
    923   __ movq(rcx, r11);
    924   {
    925     Label overflow_ok;
    926     __ incq(rax);
    927     __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), &overflow_ok);
    928     __ jmp(exit);
    929     __ bind(&overflow_ok);
    930     __ incq(rax);
    931     __ cmpq(rcx, r11);
    932     __ j(not_equal, exit);
    933   }
    934 
    935   {
    936     Label overflow_ok;
    937     __ incq(rax);
    938     __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), &overflow_ok);
    939     __ jmp(exit);
    940     __ bind(&overflow_ok);
    941     __ incq(rax);
    942     __ cmpq(rcx, r11);
    943     __ j(not_equal, exit);
    944   }
    945 
    946   __ Move(rdx, Smi::FromInt(y_max));
    947 
    948   {
    949     Label overflow_ok;
    950     __ incq(rax);
    951     __ SmiSub(r9, rcx, rdx, &overflow_ok);
    952     __ jmp(exit);
    953     __ bind(&overflow_ok);
    954     __ incq(rax);
    955     __ cmpq(rcx, r11);
    956     __ j(not_equal, exit);
    957   }
    958 
    959   {
    960     Label overflow_ok;
    961     __ incq(rax);
    962     __ SmiSub(rcx, rcx, rdx, &overflow_ok);
    963     __ jmp(exit);
    964     __ bind(&overflow_ok);
    965     __ incq(rax);
    966     __ cmpq(rcx, r11);
    967     __ j(not_equal, exit);
    968   }
    969 
    970   __ movq(rcx, r11);
    971   {
    972     Label overflow_ok;
    973     __ incq(rax);
    974     __ SmiSubConstant(r9, rcx, Smi::FromInt(y_max), &overflow_ok);
    975     __ jmp(exit);
    976     __ bind(&overflow_ok);
    977     __ incq(rax);
    978     __ cmpq(rcx, r11);
    979     __ j(not_equal, exit);
    980   }
    981 
    982   {
    983     Label overflow_ok;
    984     __ incq(rax);
    985     __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), &overflow_ok);
    986     __ jmp(exit);
    987     __ bind(&overflow_ok);
    988     __ incq(rax);
    989     __ cmpq(rcx, r11);
    990     __ j(not_equal, exit);
    991   }
    992 }
    993 
    994 
    995 TEST(SmiSub) {
    996   v8::internal::V8::Initialize(NULL);
    997   // Allocate an executable page of memory.
    998   size_t actual_size;
    999   byte* buffer =
   1000       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
   1001                                       &actual_size,
   1002                                       true));
   1003   CHECK(buffer);
   1004   Isolate* isolate = Isolate::Current();
   1005   HandleScope handles(isolate);
   1006   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1007 
   1008   MacroAssembler* masm = &assembler;
   1009   masm->set_allow_stub_calls(false);
   1010   EntryCode(masm);
   1011   Label exit;
   1012 
   1013   SmiSubTest(masm, &exit, 0x10, 1, 2);
   1014   SmiSubTest(masm, &exit, 0x20, 1, -2);
   1015   SmiSubTest(masm, &exit, 0x30, -1, 2);
   1016   SmiSubTest(masm, &exit, 0x40, -1, -2);
   1017   SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
   1018   SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
   1019   SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
   1020   SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
   1021   SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
   1022 
   1023   SmiSubOverflowTest(masm, &exit, 0xA0, 1);
   1024   SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
   1025   SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
   1026   SmiSubOverflowTest(masm, &exit, 0xD0, -2);
   1027   SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
   1028   SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
   1029   SmiSubOverflowTest(masm, &exit, 0x100, 0);
   1030 
   1031   __ xor_(rax, rax);  // Success.
   1032   __ bind(&exit);
   1033   ExitCode(masm);
   1034   __ ret(0);
   1035 
   1036   CodeDesc desc;
   1037   masm->GetCode(&desc);
   1038   // Call the function from C++.
   1039   int result = FUNCTION_CAST<F0>(buffer)();
   1040   CHECK_EQ(0, result);
   1041 }
   1042 
   1043 
   1044 
   1045 void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1046   int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
   1047   bool negative_zero = (result == 0) && (x < 0 || y < 0);
   1048   __ Move(rcx, Smi::FromInt(x));
   1049   __ movq(r11, rcx);
   1050   __ Move(rdx, Smi::FromInt(y));
   1051   if (Smi::IsValid(result) && !negative_zero) {
   1052     __ movl(rax, Immediate(id));
   1053     __ Move(r8, Smi::FromIntptr(result));
   1054     __ SmiMul(r9, rcx, rdx, exit);
   1055     __ incq(rax);
   1056     __ cmpq(r11, rcx);
   1057     __ j(not_equal, exit);
   1058     __ incq(rax);
   1059     __ cmpq(r9, r8);
   1060     __ j(not_equal, exit);
   1061 
   1062     __ incq(rax);
   1063     __ SmiMul(rcx, rcx, rdx, exit);
   1064     __ cmpq(rcx, r8);
   1065     __ j(not_equal, exit);
   1066   } else {
   1067     __ movl(rax, Immediate(id + 8));
   1068     Label overflow_ok, overflow_ok2;
   1069     __ SmiMul(r9, rcx, rdx, &overflow_ok);
   1070     __ jmp(exit);
   1071     __ bind(&overflow_ok);
   1072     __ incq(rax);
   1073     __ cmpq(r11, rcx);
   1074     __ j(not_equal, exit);
   1075     __ incq(rax);
   1076     __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
   1077     __ jmp(exit);
   1078     __ bind(&overflow_ok2);
   1079     // 31-bit version doesn't preserve rcx on failure.
   1080     // __ incq(rax);
   1081     // __ cmpq(r11, rcx);
   1082     // __ j(not_equal, exit);
   1083   }
   1084 }
   1085 
   1086 
   1087 TEST(SmiMul) {
   1088   v8::internal::V8::Initialize(NULL);
   1089   // Allocate an executable page of memory.
   1090   size_t actual_size;
   1091   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
   1092                                                  &actual_size,
   1093                                                  true));
   1094   CHECK(buffer);
   1095   Isolate* isolate = Isolate::Current();
   1096   HandleScope handles(isolate);
   1097   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1098 
   1099   MacroAssembler* masm = &assembler;
   1100   masm->set_allow_stub_calls(false);
   1101   EntryCode(masm);
   1102   Label exit;
   1103 
   1104   TestSmiMul(masm, &exit, 0x10, 0, 0);
   1105   TestSmiMul(masm, &exit, 0x20, -1, 0);
   1106   TestSmiMul(masm, &exit, 0x30, 0, -1);
   1107   TestSmiMul(masm, &exit, 0x40, -1, -1);
   1108   TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
   1109   TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
   1110   TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
   1111   TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
   1112   TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
   1113   TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
   1114   TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
   1115   TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
   1116   TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
   1117   TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
   1118 
   1119   __ xor_(rax, rax);  // Success.
   1120   __ bind(&exit);
   1121   ExitCode(masm);
   1122   __ ret(0);
   1123 
   1124   CodeDesc desc;
   1125   masm->GetCode(&desc);
   1126   // Call the function from C++.
   1127   int result = FUNCTION_CAST<F0>(buffer)();
   1128   CHECK_EQ(0, result);
   1129 }
   1130 
   1131 
   1132 void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1133   bool division_by_zero = (y == 0);
   1134   bool negative_zero = (x == 0 && y < 0);
   1135 #if V8_TARGET_ARCH_X64
   1136   bool overflow = (x == Smi::kMinValue && y < 0);  // Safe approx. used.
   1137 #else
   1138   bool overflow = (x == Smi::kMinValue && y == -1);
   1139 #endif
   1140   bool fraction = !division_by_zero && !overflow && (x % y != 0);
   1141   __ Move(r11, Smi::FromInt(x));
   1142   __ Move(r14, Smi::FromInt(y));
   1143   if (!fraction && !overflow && !negative_zero && !division_by_zero) {
   1144     // Division succeeds
   1145     __ movq(rcx, r11);
   1146     __ movq(r15, Immediate(id));
   1147     int result = x / y;
   1148     __ Move(r8, Smi::FromInt(result));
   1149     __ SmiDiv(r9, rcx, r14, exit);
   1150     // Might have destroyed rcx and r14.
   1151     __ incq(r15);
   1152     __ cmpq(r9, r8);
   1153     __ j(not_equal, exit);
   1154 
   1155     __ incq(r15);
   1156     __ movq(rcx, r11);
   1157     __ Move(r14, Smi::FromInt(y));
   1158     __ cmpq(rcx, r11);
   1159     __ j(not_equal, exit);
   1160 
   1161     __ incq(r15);
   1162     __ SmiDiv(rcx, rcx, r14, exit);
   1163 
   1164     __ incq(r15);
   1165     __ cmpq(rcx, r8);
   1166     __ j(not_equal, exit);
   1167   } else {
   1168     // Division fails.
   1169     __ movq(r15, Immediate(id + 8));
   1170 
   1171     Label fail_ok, fail_ok2;
   1172     __ movq(rcx, r11);
   1173     __ SmiDiv(r9, rcx, r14, &fail_ok);
   1174     __ jmp(exit);
   1175     __ bind(&fail_ok);
   1176 
   1177     __ incq(r15);
   1178     __ cmpq(rcx, r11);
   1179     __ j(not_equal, exit);
   1180 
   1181     __ incq(r15);
   1182     __ SmiDiv(rcx, rcx, r14, &fail_ok2);
   1183     __ jmp(exit);
   1184     __ bind(&fail_ok2);
   1185 
   1186     __ incq(r15);
   1187     __ cmpq(rcx, r11);
   1188     __ j(not_equal, exit);
   1189   }
   1190 }
   1191 
   1192 
   1193 TEST(SmiDiv) {
   1194   v8::internal::V8::Initialize(NULL);
   1195   // Allocate an executable page of memory.
   1196   size_t actual_size;
   1197   byte* buffer =
   1198       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
   1199                                       &actual_size,
   1200                                       true));
   1201   CHECK(buffer);
   1202   Isolate* isolate = Isolate::Current();
   1203   HandleScope handles(isolate);
   1204   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1205 
   1206   MacroAssembler* masm = &assembler;
   1207   masm->set_allow_stub_calls(false);
   1208   EntryCode(masm);
   1209   Label exit;
   1210 
   1211   __ push(r14);
   1212   __ push(r15);
   1213   TestSmiDiv(masm, &exit, 0x10, 1, 1);
   1214   TestSmiDiv(masm, &exit, 0x20, 1, 0);
   1215   TestSmiDiv(masm, &exit, 0x30, -1, 0);
   1216   TestSmiDiv(masm, &exit, 0x40, 0, 1);
   1217   TestSmiDiv(masm, &exit, 0x50, 0, -1);
   1218   TestSmiDiv(masm, &exit, 0x60, 4, 2);
   1219   TestSmiDiv(masm, &exit, 0x70, -4, 2);
   1220   TestSmiDiv(masm, &exit, 0x80, 4, -2);
   1221   TestSmiDiv(masm, &exit, 0x90, -4, -2);
   1222   TestSmiDiv(masm, &exit, 0xa0, 3, 2);
   1223   TestSmiDiv(masm, &exit, 0xb0, 3, 4);
   1224   TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
   1225   TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
   1226   TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
   1227   TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
   1228   TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
   1229   TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
   1230   TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
   1231   TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
   1232   TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
   1233 
   1234   __ xor_(r15, r15);  // Success.
   1235   __ bind(&exit);
   1236   __ movq(rax, r15);
   1237   __ pop(r15);
   1238   __ pop(r14);
   1239   ExitCode(masm);
   1240   __ ret(0);
   1241 
   1242   CodeDesc desc;
   1243   masm->GetCode(&desc);
   1244   // Call the function from C++.
   1245   int result = FUNCTION_CAST<F0>(buffer)();
   1246   CHECK_EQ(0, result);
   1247 }
   1248 
   1249 
   1250 void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1251   bool division_by_zero = (y == 0);
   1252   bool division_overflow = (x == Smi::kMinValue) && (y == -1);
   1253   bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
   1254   bool negative_zero = (!fraction && x < 0);
   1255   __ Move(rcx, Smi::FromInt(x));
   1256   __ movq(r11, rcx);
   1257   __ Move(r14, Smi::FromInt(y));
   1258   if (!division_overflow && !negative_zero && !division_by_zero) {
   1259     // Modulo succeeds
   1260     __ movq(r15, Immediate(id));
   1261     int result = x % y;
   1262     __ Move(r8, Smi::FromInt(result));
   1263     __ SmiMod(r9, rcx, r14, exit);
   1264 
   1265     __ incq(r15);
   1266     __ cmpq(r9, r8);
   1267     __ j(not_equal, exit);
   1268 
   1269     __ incq(r15);
   1270     __ cmpq(rcx, r11);
   1271     __ j(not_equal, exit);
   1272 
   1273     __ incq(r15);
   1274     __ SmiMod(rcx, rcx, r14, exit);
   1275 
   1276     __ incq(r15);
   1277     __ cmpq(rcx, r8);
   1278     __ j(not_equal, exit);
   1279   } else {
   1280     // Modulo fails.
   1281     __ movq(r15, Immediate(id + 8));
   1282 
   1283     Label fail_ok, fail_ok2;
   1284     __ SmiMod(r9, rcx, r14, &fail_ok);
   1285     __ jmp(exit);
   1286     __ bind(&fail_ok);
   1287 
   1288     __ incq(r15);
   1289     __ cmpq(rcx, r11);
   1290     __ j(not_equal, exit);
   1291 
   1292     __ incq(r15);
   1293     __ SmiMod(rcx, rcx, r14, &fail_ok2);
   1294     __ jmp(exit);
   1295     __ bind(&fail_ok2);
   1296 
   1297     __ incq(r15);
   1298     __ cmpq(rcx, r11);
   1299     __ j(not_equal, exit);
   1300   }
   1301 }
   1302 
   1303 
   1304 TEST(SmiMod) {
   1305   v8::internal::V8::Initialize(NULL);
   1306   // Allocate an executable page of memory.
   1307   size_t actual_size;
   1308   byte* buffer =
   1309       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
   1310                                       &actual_size,
   1311                                       true));
   1312   CHECK(buffer);
   1313   Isolate* isolate = Isolate::Current();
   1314   HandleScope handles(isolate);
   1315   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1316 
   1317   MacroAssembler* masm = &assembler;
   1318   masm->set_allow_stub_calls(false);
   1319   EntryCode(masm);
   1320   Label exit;
   1321 
   1322   __ push(r14);
   1323   __ push(r15);
   1324   TestSmiMod(masm, &exit, 0x10, 1, 1);
   1325   TestSmiMod(masm, &exit, 0x20, 1, 0);
   1326   TestSmiMod(masm, &exit, 0x30, -1, 0);
   1327   TestSmiMod(masm, &exit, 0x40, 0, 1);
   1328   TestSmiMod(masm, &exit, 0x50, 0, -1);
   1329   TestSmiMod(masm, &exit, 0x60, 4, 2);
   1330   TestSmiMod(masm, &exit, 0x70, -4, 2);
   1331   TestSmiMod(masm, &exit, 0x80, 4, -2);
   1332   TestSmiMod(masm, &exit, 0x90, -4, -2);
   1333   TestSmiMod(masm, &exit, 0xa0, 3, 2);
   1334   TestSmiMod(masm, &exit, 0xb0, 3, 4);
   1335   TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
   1336   TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
   1337   TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
   1338   TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
   1339   TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
   1340   TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
   1341   TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
   1342   TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
   1343   TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
   1344 
   1345   __ xor_(r15, r15);  // Success.
   1346   __ bind(&exit);
   1347   __ movq(rax, r15);
   1348   __ pop(r15);
   1349   __ pop(r14);
   1350   ExitCode(masm);
   1351   __ ret(0);
   1352 
   1353   CodeDesc desc;
   1354   masm->GetCode(&desc);
   1355   // Call the function from C++.
   1356   int result = FUNCTION_CAST<F0>(buffer)();
   1357   CHECK_EQ(0, result);
   1358 }
   1359 
   1360 
   1361 void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
   1362   __ movl(rax, Immediate(id));
   1363 
   1364   for (int i = 0; i < 8; i++) {
   1365     __ Move(rcx, Smi::FromInt(x));
   1366     SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
   1367     ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
   1368     __ shl(index.reg, Immediate(index.scale));
   1369     __ Set(r8, static_cast<intptr_t>(x) << i);
   1370     __ cmpq(index.reg, r8);
   1371     __ j(not_equal, exit);
   1372     __ incq(rax);
   1373     __ Move(rcx, Smi::FromInt(x));
   1374     index = masm->SmiToIndex(rcx, rcx, i);
   1375     ASSERT(index.reg.is(rcx));
   1376     __ shl(rcx, Immediate(index.scale));
   1377     __ Set(r8, static_cast<intptr_t>(x) << i);
   1378     __ cmpq(rcx, r8);
   1379     __ j(not_equal, exit);
   1380     __ incq(rax);
   1381 
   1382     __ Move(rcx, Smi::FromInt(x));
   1383     index = masm->SmiToNegativeIndex(rdx, rcx, i);
   1384     ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
   1385     __ shl(index.reg, Immediate(index.scale));
   1386     __ Set(r8, static_cast<intptr_t>(-x) << i);
   1387     __ cmpq(index.reg, r8);
   1388     __ j(not_equal, exit);
   1389     __ incq(rax);
   1390     __ Move(rcx, Smi::FromInt(x));
   1391     index = masm->SmiToNegativeIndex(rcx, rcx, i);
   1392     ASSERT(index.reg.is(rcx));
   1393     __ shl(rcx, Immediate(index.scale));
   1394     __ Set(r8, static_cast<intptr_t>(-x) << i);
   1395     __ cmpq(rcx, r8);
   1396     __ j(not_equal, exit);
   1397     __ incq(rax);
   1398   }
   1399 }
   1400 
   1401 
   1402 TEST(SmiIndex) {
   1403   v8::internal::V8::Initialize(NULL);
   1404   // Allocate an executable page of memory.
   1405   size_t actual_size;
   1406   byte* buffer =
   1407       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
   1408                                       &actual_size,
   1409                                       true));
   1410   CHECK(buffer);
   1411   Isolate* isolate = Isolate::Current();
   1412   HandleScope handles(isolate);
   1413   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1414 
   1415   MacroAssembler* masm = &assembler;
   1416   masm->set_allow_stub_calls(false);
   1417   EntryCode(masm);
   1418   Label exit;
   1419 
   1420   TestSmiIndex(masm, &exit, 0x10, 0);
   1421   TestSmiIndex(masm, &exit, 0x20, 1);
   1422   TestSmiIndex(masm, &exit, 0x30, 100);
   1423   TestSmiIndex(masm, &exit, 0x40, 1000);
   1424   TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
   1425 
   1426   __ xor_(rax, rax);  // Success.
   1427   __ bind(&exit);
   1428   ExitCode(masm);
   1429   __ ret(0);
   1430 
   1431   CodeDesc desc;
   1432   masm->GetCode(&desc);
   1433   // Call the function from C++.
   1434   int result = FUNCTION_CAST<F0>(buffer)();
   1435   CHECK_EQ(0, result);
   1436 }
   1437 
   1438 
   1439 void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1440   __ movl(rax, Immediate(id));
   1441   __ Move(rcx, Smi::FromInt(x));
   1442   __ Move(rdx, Smi::FromInt(y));
   1443   __ xor_(rdx, Immediate(kSmiTagMask));
   1444   __ SelectNonSmi(r9, rcx, rdx, exit);
   1445 
   1446   __ incq(rax);
   1447   __ cmpq(r9, rdx);
   1448   __ j(not_equal, exit);
   1449 
   1450   __ incq(rax);
   1451   __ Move(rcx, Smi::FromInt(x));
   1452   __ Move(rdx, Smi::FromInt(y));
   1453   __ xor_(rcx, Immediate(kSmiTagMask));
   1454   __ SelectNonSmi(r9, rcx, rdx, exit);
   1455 
   1456   __ incq(rax);
   1457   __ cmpq(r9, rcx);
   1458   __ j(not_equal, exit);
   1459 
   1460   __ incq(rax);
   1461   Label fail_ok;
   1462   __ Move(rcx, Smi::FromInt(x));
   1463   __ Move(rdx, Smi::FromInt(y));
   1464   __ xor_(rcx, Immediate(kSmiTagMask));
   1465   __ xor_(rdx, Immediate(kSmiTagMask));
   1466   __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
   1467   __ jmp(exit);
   1468   __ bind(&fail_ok);
   1469 }
   1470 
   1471 
   1472 TEST(SmiSelectNonSmi) {
   1473   v8::internal::V8::Initialize(NULL);
   1474   // Allocate an executable page of memory.
   1475   size_t actual_size;
   1476   byte* buffer =
   1477       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
   1478                                       &actual_size,
   1479                                       true));
   1480   CHECK(buffer);
   1481   Isolate* isolate = Isolate::Current();
   1482   HandleScope handles(isolate);
   1483   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1484 
   1485   MacroAssembler* masm = &assembler;
   1486   masm->set_allow_stub_calls(false);  // Avoid inline checks.
   1487   EntryCode(masm);
   1488   Label exit;
   1489 
   1490   TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
   1491   TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
   1492   TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
   1493   TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
   1494   TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
   1495   TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
   1496   TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
   1497   TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
   1498   TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
   1499 
   1500   __ xor_(rax, rax);  // Success.
   1501   __ bind(&exit);
   1502   ExitCode(masm);
   1503   __ ret(0);
   1504 
   1505   CodeDesc desc;
   1506   masm->GetCode(&desc);
   1507   // Call the function from C++.
   1508   int result = FUNCTION_CAST<F0>(buffer)();
   1509   CHECK_EQ(0, result);
   1510 }
   1511 
   1512 
   1513 void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1514   int result = x & y;
   1515 
   1516   __ movl(rax, Immediate(id));
   1517 
   1518   __ Move(rcx, Smi::FromInt(x));
   1519   __ movq(r11, rcx);
   1520   __ Move(rdx, Smi::FromInt(y));
   1521   __ Move(r8, Smi::FromInt(result));
   1522   __ SmiAnd(r9, rcx, rdx);
   1523   __ cmpq(r8, r9);
   1524   __ j(not_equal, exit);
   1525 
   1526   __ incq(rax);
   1527   __ cmpq(r11, rcx);
   1528   __ j(not_equal, exit);
   1529 
   1530   __ incq(rax);
   1531   __ SmiAnd(rcx, rcx, rdx);
   1532   __ cmpq(r8, rcx);
   1533   __ j(not_equal, exit);
   1534 
   1535   __ movq(rcx, r11);
   1536   __ incq(rax);
   1537   __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
   1538   __ cmpq(r8, r9);
   1539   __ j(not_equal, exit);
   1540 
   1541   __ incq(rax);
   1542   __ cmpq(r11, rcx);
   1543   __ j(not_equal, exit);
   1544 
   1545   __ incq(rax);
   1546   __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
   1547   __ cmpq(r8, rcx);
   1548   __ j(not_equal, exit);
   1549 }
   1550 
   1551 
   1552 TEST(SmiAnd) {
   1553   v8::internal::V8::Initialize(NULL);
   1554   // Allocate an executable page of memory.
   1555   size_t actual_size;
   1556   byte* buffer =
   1557       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
   1558                                       &actual_size,
   1559                                       true));
   1560   CHECK(buffer);
   1561   Isolate* isolate = Isolate::Current();
   1562   HandleScope handles(isolate);
   1563   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1564 
   1565   MacroAssembler* masm = &assembler;
   1566   masm->set_allow_stub_calls(false);
   1567   EntryCode(masm);
   1568   Label exit;
   1569 
   1570   TestSmiAnd(masm, &exit, 0x10, 0, 0);
   1571   TestSmiAnd(masm, &exit, 0x20, 0, 1);
   1572   TestSmiAnd(masm, &exit, 0x30, 1, 0);
   1573   TestSmiAnd(masm, &exit, 0x40, 0, -1);
   1574   TestSmiAnd(masm, &exit, 0x50, -1, 0);
   1575   TestSmiAnd(masm, &exit, 0x60, -1, -1);
   1576   TestSmiAnd(masm, &exit, 0x70, 1, 1);
   1577   TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
   1578   TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
   1579   TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
   1580   TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
   1581 
   1582   __ xor_(rax, rax);  // Success.
   1583   __ bind(&exit);
   1584   ExitCode(masm);
   1585   __ ret(0);
   1586 
   1587   CodeDesc desc;
   1588   masm->GetCode(&desc);
   1589   // Call the function from C++.
   1590   int result = FUNCTION_CAST<F0>(buffer)();
   1591   CHECK_EQ(0, result);
   1592 }
   1593 
   1594 
   1595 void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1596   int result = x | y;
   1597 
   1598   __ movl(rax, Immediate(id));
   1599 
   1600   __ Move(rcx, Smi::FromInt(x));
   1601   __ movq(r11, rcx);
   1602   __ Move(rdx, Smi::FromInt(y));
   1603   __ Move(r8, Smi::FromInt(result));
   1604   __ SmiOr(r9, rcx, rdx);
   1605   __ cmpq(r8, r9);
   1606   __ j(not_equal, exit);
   1607 
   1608   __ incq(rax);
   1609   __ cmpq(r11, rcx);
   1610   __ j(not_equal, exit);
   1611 
   1612   __ incq(rax);
   1613   __ SmiOr(rcx, rcx, rdx);
   1614   __ cmpq(r8, rcx);
   1615   __ j(not_equal, exit);
   1616 
   1617   __ movq(rcx, r11);
   1618   __ incq(rax);
   1619   __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
   1620   __ cmpq(r8, r9);
   1621   __ j(not_equal, exit);
   1622 
   1623   __ incq(rax);
   1624   __ cmpq(r11, rcx);
   1625   __ j(not_equal, exit);
   1626 
   1627   __ incq(rax);
   1628   __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
   1629   __ cmpq(r8, rcx);
   1630   __ j(not_equal, exit);
   1631 }
   1632 
   1633 
   1634 TEST(SmiOr) {
   1635   v8::internal::V8::Initialize(NULL);
   1636   // Allocate an executable page of memory.
   1637   size_t actual_size;
   1638   byte* buffer =
   1639       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
   1640                                       &actual_size,
   1641                                       true));
   1642   CHECK(buffer);
   1643   Isolate* isolate = Isolate::Current();
   1644   HandleScope handles(isolate);
   1645   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1646 
   1647   MacroAssembler* masm = &assembler;
   1648   masm->set_allow_stub_calls(false);
   1649   EntryCode(masm);
   1650   Label exit;
   1651 
   1652   TestSmiOr(masm, &exit, 0x10, 0, 0);
   1653   TestSmiOr(masm, &exit, 0x20, 0, 1);
   1654   TestSmiOr(masm, &exit, 0x30, 1, 0);
   1655   TestSmiOr(masm, &exit, 0x40, 0, -1);
   1656   TestSmiOr(masm, &exit, 0x50, -1, 0);
   1657   TestSmiOr(masm, &exit, 0x60, -1, -1);
   1658   TestSmiOr(masm, &exit, 0x70, 1, 1);
   1659   TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
   1660   TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
   1661   TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
   1662   TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
   1663   TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
   1664   TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
   1665 
   1666   __ xor_(rax, rax);  // Success.
   1667   __ bind(&exit);
   1668   ExitCode(masm);
   1669   __ ret(0);
   1670 
   1671   CodeDesc desc;
   1672   masm->GetCode(&desc);
   1673   // Call the function from C++.
   1674   int result = FUNCTION_CAST<F0>(buffer)();
   1675   CHECK_EQ(0, result);
   1676 }
   1677 
   1678 
   1679 void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
   1680   int result = x ^ y;
   1681 
   1682   __ movl(rax, Immediate(id));
   1683 
   1684   __ Move(rcx, Smi::FromInt(x));
   1685   __ movq(r11, rcx);
   1686   __ Move(rdx, Smi::FromInt(y));
   1687   __ Move(r8, Smi::FromInt(result));
   1688   __ SmiXor(r9, rcx, rdx);
   1689   __ cmpq(r8, r9);
   1690   __ j(not_equal, exit);
   1691 
   1692   __ incq(rax);
   1693   __ cmpq(r11, rcx);
   1694   __ j(not_equal, exit);
   1695 
   1696   __ incq(rax);
   1697   __ SmiXor(rcx, rcx, rdx);
   1698   __ cmpq(r8, rcx);
   1699   __ j(not_equal, exit);
   1700 
   1701   __ movq(rcx, r11);
   1702   __ incq(rax);
   1703   __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
   1704   __ cmpq(r8, r9);
   1705   __ j(not_equal, exit);
   1706 
   1707   __ incq(rax);
   1708   __ cmpq(r11, rcx);
   1709   __ j(not_equal, exit);
   1710 
   1711   __ incq(rax);
   1712   __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
   1713   __ cmpq(r8, rcx);
   1714   __ j(not_equal, exit);
   1715 }
   1716 
   1717 
   1718 TEST(SmiXor) {
   1719   v8::internal::V8::Initialize(NULL);
   1720   // Allocate an executable page of memory.
   1721   size_t actual_size;
   1722   byte* buffer =
   1723       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
   1724                                       &actual_size,
   1725                                       true));
   1726   CHECK(buffer);
   1727   Isolate* isolate = Isolate::Current();
   1728   HandleScope handles(isolate);
   1729   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1730 
   1731   MacroAssembler* masm = &assembler;
   1732   masm->set_allow_stub_calls(false);
   1733   EntryCode(masm);
   1734   Label exit;
   1735 
   1736   TestSmiXor(masm, &exit, 0x10, 0, 0);
   1737   TestSmiXor(masm, &exit, 0x20, 0, 1);
   1738   TestSmiXor(masm, &exit, 0x30, 1, 0);
   1739   TestSmiXor(masm, &exit, 0x40, 0, -1);
   1740   TestSmiXor(masm, &exit, 0x50, -1, 0);
   1741   TestSmiXor(masm, &exit, 0x60, -1, -1);
   1742   TestSmiXor(masm, &exit, 0x70, 1, 1);
   1743   TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
   1744   TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
   1745   TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
   1746   TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
   1747   TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
   1748   TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
   1749 
   1750   __ xor_(rax, rax);  // Success.
   1751   __ bind(&exit);
   1752   ExitCode(masm);
   1753   __ ret(0);
   1754 
   1755   CodeDesc desc;
   1756   masm->GetCode(&desc);
   1757   // Call the function from C++.
   1758   int result = FUNCTION_CAST<F0>(buffer)();
   1759   CHECK_EQ(0, result);
   1760 }
   1761 
   1762 
   1763 void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
   1764   int result = ~x;
   1765   __ movl(rax, Immediate(id));
   1766 
   1767   __ Move(r8, Smi::FromInt(result));
   1768   __ Move(rcx, Smi::FromInt(x));
   1769   __ movq(r11, rcx);
   1770 
   1771   __ SmiNot(r9, rcx);
   1772   __ cmpq(r9, r8);
   1773   __ j(not_equal, exit);
   1774 
   1775   __ incq(rax);
   1776   __ cmpq(r11, rcx);
   1777   __ j(not_equal, exit);
   1778 
   1779   __ incq(rax);
   1780   __ SmiNot(rcx, rcx);
   1781   __ cmpq(rcx, r8);
   1782   __ j(not_equal, exit);
   1783 }
   1784 
   1785 
   1786 TEST(SmiNot) {
   1787   v8::internal::V8::Initialize(NULL);
   1788   // Allocate an executable page of memory.
   1789   size_t actual_size;
   1790   byte* buffer =
   1791       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
   1792                                       &actual_size,
   1793                                       true));
   1794   CHECK(buffer);
   1795   Isolate* isolate = Isolate::Current();
   1796   HandleScope handles(isolate);
   1797   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1798 
   1799   MacroAssembler* masm = &assembler;
   1800   masm->set_allow_stub_calls(false);
   1801   EntryCode(masm);
   1802   Label exit;
   1803 
   1804   TestSmiNot(masm, &exit, 0x10, 0);
   1805   TestSmiNot(masm, &exit, 0x20, 1);
   1806   TestSmiNot(masm, &exit, 0x30, -1);
   1807   TestSmiNot(masm, &exit, 0x40, 127);
   1808   TestSmiNot(masm, &exit, 0x50, 65535);
   1809   TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
   1810   TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
   1811   TestSmiNot(masm, &exit, 0x80, 0x05555555);
   1812 
   1813   __ xor_(rax, rax);  // Success.
   1814   __ bind(&exit);
   1815   ExitCode(masm);
   1816   __ ret(0);
   1817 
   1818   CodeDesc desc;
   1819   masm->GetCode(&desc);
   1820   // Call the function from C++.
   1821   int result = FUNCTION_CAST<F0>(buffer)();
   1822   CHECK_EQ(0, result);
   1823 }
   1824 
   1825 
   1826 void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
   1827   const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
   1828   const int kNumShifts = 5;
   1829   __ movl(rax, Immediate(id));
   1830   for (int i = 0; i < kNumShifts; i++) {
   1831     // rax == id + i * 10.
   1832     int shift = shifts[i];
   1833     int result = x << shift;
   1834     CHECK(Smi::IsValid(result));
   1835     __ Move(r8, Smi::FromInt(result));
   1836     __ Move(rcx, Smi::FromInt(x));
   1837     __ SmiShiftLeftConstant(r9, rcx, shift);
   1838 
   1839     __ incq(rax);
   1840     __ cmpq(r9, r8);
   1841     __ j(not_equal, exit);
   1842 
   1843     __ incq(rax);
   1844     __ Move(rcx, Smi::FromInt(x));
   1845     __ SmiShiftLeftConstant(rcx, rcx, shift);
   1846 
   1847     __ incq(rax);
   1848     __ cmpq(rcx, r8);
   1849     __ j(not_equal, exit);
   1850 
   1851     __ incq(rax);
   1852     __ Move(rdx, Smi::FromInt(x));
   1853     __ Move(rcx, Smi::FromInt(shift));
   1854     __ SmiShiftLeft(r9, rdx, rcx);
   1855 
   1856     __ incq(rax);
   1857     __ cmpq(r9, r8);
   1858     __ j(not_equal, exit);
   1859 
   1860     __ incq(rax);
   1861     __ Move(rdx, Smi::FromInt(x));
   1862     __ Move(r11, Smi::FromInt(shift));
   1863     __ SmiShiftLeft(r9, rdx, r11);
   1864 
   1865     __ incq(rax);
   1866     __ cmpq(r9, r8);
   1867     __ j(not_equal, exit);
   1868 
   1869     __ incq(rax);
   1870     __ Move(rdx, Smi::FromInt(x));
   1871     __ Move(r11, Smi::FromInt(shift));
   1872     __ SmiShiftLeft(rdx, rdx, r11);
   1873 
   1874     __ incq(rax);
   1875     __ cmpq(rdx, r8);
   1876     __ j(not_equal, exit);
   1877 
   1878     __ incq(rax);
   1879   }
   1880 }
   1881 
   1882 
   1883 TEST(SmiShiftLeft) {
   1884   v8::internal::V8::Initialize(NULL);
   1885   // Allocate an executable page of memory.
   1886   size_t actual_size;
   1887   byte* buffer =
   1888       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
   1889                                       &actual_size,
   1890                                       true));
   1891   CHECK(buffer);
   1892   Isolate* isolate = Isolate::Current();
   1893   HandleScope handles(isolate);
   1894   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   1895 
   1896   MacroAssembler* masm = &assembler;
   1897   masm->set_allow_stub_calls(false);
   1898   EntryCode(masm);
   1899   Label exit;
   1900 
   1901   TestSmiShiftLeft(masm, &exit, 0x10, 0);
   1902   TestSmiShiftLeft(masm, &exit, 0x50, 1);
   1903   TestSmiShiftLeft(masm, &exit, 0x90, 127);
   1904   TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
   1905   TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
   1906   TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
   1907   TestSmiShiftLeft(masm, &exit, 0x190, -1);
   1908 
   1909   __ xor_(rax, rax);  // Success.
   1910   __ bind(&exit);
   1911   ExitCode(masm);
   1912   __ ret(0);
   1913 
   1914   CodeDesc desc;
   1915   masm->GetCode(&desc);
   1916   // Call the function from C++.
   1917   int result = FUNCTION_CAST<F0>(buffer)();
   1918   CHECK_EQ(0, result);
   1919 }
   1920 
   1921 
   1922 void TestSmiShiftLogicalRight(MacroAssembler* masm,
   1923                               Label* exit,
   1924                               int id,
   1925                               int x) {
   1926   const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
   1927   const int kNumShifts = 5;
   1928   __ movl(rax, Immediate(id));
   1929   for (int i = 0; i < kNumShifts; i++) {
   1930     int shift = shifts[i];
   1931     intptr_t result = static_cast<unsigned int>(x) >> shift;
   1932     if (Smi::IsValid(result)) {
   1933       __ Move(r8, Smi::FromInt(static_cast<int>(result)));
   1934       __ Move(rcx, Smi::FromInt(x));
   1935       __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
   1936 
   1937       __ incq(rax);
   1938       __ cmpq(r9, r8);
   1939       __ j(not_equal, exit);
   1940 
   1941       __ incq(rax);
   1942       __ Move(rdx, Smi::FromInt(x));
   1943       __ Move(rcx, Smi::FromInt(shift));
   1944       __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
   1945 
   1946       __ incq(rax);
   1947       __ cmpq(r9, r8);
   1948       __ j(not_equal, exit);
   1949 
   1950       __ incq(rax);
   1951       __ Move(rdx, Smi::FromInt(x));
   1952       __ Move(r11, Smi::FromInt(shift));
   1953       __ SmiShiftLogicalRight(r9, rdx, r11, exit);
   1954 
   1955       __ incq(rax);
   1956       __ cmpq(r9, r8);
   1957       __ j(not_equal, exit);
   1958 
   1959       __ incq(rax);
   1960     } else {
   1961       // Cannot happen with long smis.
   1962       Label fail_ok;
   1963       __ Move(rcx, Smi::FromInt(x));
   1964       __ movq(r11, rcx);
   1965       __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
   1966       __ jmp(exit);
   1967       __ bind(&fail_ok);
   1968 
   1969       __ incq(rax);
   1970       __ cmpq(rcx, r11);
   1971       __ j(not_equal, exit);
   1972 
   1973       __ incq(rax);
   1974       __ Move(r8, Smi::FromInt(shift));
   1975       Label fail_ok3;
   1976       __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
   1977       __ jmp(exit);
   1978       __ bind(&fail_ok3);
   1979 
   1980       __ incq(rax);
   1981       __ cmpq(rcx, r11);
   1982       __ j(not_equal, exit);
   1983 
   1984       __ addq(rax, Immediate(3));
   1985     }
   1986   }
   1987 }
   1988 
   1989 
   1990 TEST(SmiShiftLogicalRight) {
   1991   v8::internal::V8::Initialize(NULL);
   1992   // Allocate an executable page of memory.
   1993   size_t actual_size;
   1994   byte* buffer =
   1995       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
   1996                                       &actual_size,
   1997                                       true));
   1998   CHECK(buffer);
   1999   Isolate* isolate = Isolate::Current();
   2000   HandleScope handles(isolate);
   2001   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   2002 
   2003   MacroAssembler* masm = &assembler;
   2004   masm->set_allow_stub_calls(false);
   2005   EntryCode(masm);
   2006   Label exit;
   2007 
   2008   TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
   2009   TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
   2010   TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
   2011   TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
   2012   TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
   2013   TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
   2014   TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
   2015 
   2016   __ xor_(rax, rax);  // Success.
   2017   __ bind(&exit);
   2018   ExitCode(masm);
   2019   __ ret(0);
   2020 
   2021   CodeDesc desc;
   2022   masm->GetCode(&desc);
   2023   // Call the function from C++.
   2024   int result = FUNCTION_CAST<F0>(buffer)();
   2025   CHECK_EQ(0, result);
   2026 }
   2027 
   2028 
   2029 void TestSmiShiftArithmeticRight(MacroAssembler* masm,
   2030                                  Label* exit,
   2031                                  int id,
   2032                                  int x) {
   2033   const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
   2034   const int kNumShifts = 5;
   2035   __ movl(rax, Immediate(id));
   2036   for (int i = 0; i < kNumShifts; i++) {
   2037     int shift = shifts[i];
   2038     // Guaranteed arithmetic shift.
   2039     int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
   2040     __ Move(r8, Smi::FromInt(result));
   2041     __ Move(rcx, Smi::FromInt(x));
   2042     __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
   2043 
   2044     __ cmpq(rcx, r8);
   2045     __ j(not_equal, exit);
   2046 
   2047     __ incq(rax);
   2048     __ Move(rdx, Smi::FromInt(x));
   2049     __ Move(r11, Smi::FromInt(shift));
   2050     __ SmiShiftArithmeticRight(rdx, rdx, r11);
   2051 
   2052     __ cmpq(rdx, r8);
   2053     __ j(not_equal, exit);
   2054 
   2055     __ incq(rax);
   2056   }
   2057 }
   2058 
   2059 
   2060 TEST(SmiShiftArithmeticRight) {
   2061   v8::internal::V8::Initialize(NULL);
   2062   // Allocate an executable page of memory.
   2063   size_t actual_size;
   2064   byte* buffer =
   2065       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
   2066                                       &actual_size,
   2067                                       true));
   2068   CHECK(buffer);
   2069   Isolate* isolate = Isolate::Current();
   2070   HandleScope handles(isolate);
   2071   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   2072 
   2073   MacroAssembler* masm = &assembler;
   2074   masm->set_allow_stub_calls(false);
   2075   EntryCode(masm);
   2076   Label exit;
   2077 
   2078   TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
   2079   TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
   2080   TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
   2081   TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
   2082   TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
   2083   TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
   2084   TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
   2085 
   2086   __ xor_(rax, rax);  // Success.
   2087   __ bind(&exit);
   2088   ExitCode(masm);
   2089   __ ret(0);
   2090 
   2091   CodeDesc desc;
   2092   masm->GetCode(&desc);
   2093   // Call the function from C++.
   2094   int result = FUNCTION_CAST<F0>(buffer)();
   2095   CHECK_EQ(0, result);
   2096 }
   2097 
   2098 
   2099 void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
   2100   ASSERT(x >= 0);
   2101   int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
   2102   int power_count = 8;
   2103   __ movl(rax, Immediate(id));
   2104   for (int i = 0; i  < power_count; i++) {
   2105     int power = powers[i];
   2106     intptr_t result = static_cast<intptr_t>(x) << power;
   2107     __ Set(r8, result);
   2108     __ Move(rcx, Smi::FromInt(x));
   2109     __ movq(r11, rcx);
   2110     __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
   2111     __ cmpq(rdx, r8);
   2112     __ j(not_equal, exit);
   2113     __ incq(rax);
   2114     __ cmpq(r11, rcx);  // rcx unchanged.
   2115     __ j(not_equal, exit);
   2116     __ incq(rax);
   2117     __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
   2118     __ cmpq(rdx, r8);
   2119     __ j(not_equal, exit);
   2120     __ incq(rax);
   2121   }
   2122 }
   2123 
   2124 
   2125 TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
   2126   v8::internal::V8::Initialize(NULL);
   2127   // Allocate an executable page of memory.
   2128   size_t actual_size;
   2129   byte* buffer =
   2130       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
   2131                                       &actual_size,
   2132                                       true));
   2133   CHECK(buffer);
   2134   Isolate* isolate = Isolate::Current();
   2135   HandleScope handles(isolate);
   2136   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   2137 
   2138   MacroAssembler* masm = &assembler;
   2139   masm->set_allow_stub_calls(false);
   2140   EntryCode(masm);
   2141   Label exit;
   2142 
   2143   TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
   2144   TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
   2145   TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
   2146   TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
   2147   TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
   2148   TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
   2149   TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
   2150   TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
   2151   TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
   2152 
   2153   __ xor_(rax, rax);  // Success.
   2154   __ bind(&exit);
   2155   ExitCode(masm);
   2156   __ ret(0);
   2157 
   2158   CodeDesc desc;
   2159   masm->GetCode(&desc);
   2160   // Call the function from C++.
   2161   int result = FUNCTION_CAST<F0>(buffer)();
   2162   CHECK_EQ(0, result);
   2163 }
   2164 
   2165 
   2166 TEST(OperandOffset) {
   2167   v8::internal::V8::Initialize(NULL);
   2168   int data[256];
   2169   for (int i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
   2170 
   2171   // Allocate an executable page of memory.
   2172   size_t actual_size;
   2173   byte* buffer =
   2174       static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
   2175                                       &actual_size,
   2176                                       true));
   2177   CHECK(buffer);
   2178   Isolate* isolate = Isolate::Current();
   2179   HandleScope handles(isolate);
   2180   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
   2181 
   2182   MacroAssembler* masm = &assembler;
   2183   masm->set_allow_stub_calls(false);
   2184   Label exit;
   2185 
   2186   EntryCode(masm);
   2187   __ push(r13);
   2188   __ push(r14);
   2189   __ push(rbx);
   2190   __ push(rbp);
   2191   __ push(Immediate(0x100));  // <-- rbp
   2192   __ movq(rbp, rsp);
   2193   __ push(Immediate(0x101));
   2194   __ push(Immediate(0x102));
   2195   __ push(Immediate(0x103));
   2196   __ push(Immediate(0x104));
   2197   __ push(Immediate(0x105));  // <-- rbx
   2198   __ push(Immediate(0x106));
   2199   __ push(Immediate(0x107));
   2200   __ push(Immediate(0x108));
   2201   __ push(Immediate(0x109));  // <-- rsp
   2202   // rbp = rsp[9]
   2203   // r15 = rsp[3]
   2204   // rbx = rsp[5]
   2205   // r13 = rsp[7]
   2206   __ lea(r14, Operand(rsp, 3 * kPointerSize));
   2207   __ lea(r13, Operand(rbp, -3 * kPointerSize));
   2208   __ lea(rbx, Operand(rbp, -5 * kPointerSize));
   2209   __ movl(rcx, Immediate(2));
   2210   __ movq(r8, reinterpret_cast<uintptr_t>(&data[128]), RelocInfo::NONE64);
   2211   __ movl(rax, Immediate(1));
   2212 
   2213   Operand sp0 = Operand(rsp, 0);
   2214 
   2215   // Test 1.
   2216   __ movl(rdx, sp0);  // Sanity check.
   2217   __ cmpl(rdx, Immediate(0x109));
   2218   __ j(not_equal, &exit);
   2219   __ incq(rax);
   2220 
   2221   // Test 2.
   2222   // Zero to non-zero displacement.
   2223   __ movl(rdx, Operand(sp0, 2 * kPointerSize));
   2224   __ cmpl(rdx, Immediate(0x107));
   2225   __ j(not_equal, &exit);
   2226   __ incq(rax);
   2227 
   2228   Operand sp2 = Operand(rsp, 2 * kPointerSize);
   2229 
   2230   // Test 3.
   2231   __ movl(rdx, sp2);  // Sanity check.
   2232   __ cmpl(rdx, Immediate(0x107));
   2233   __ j(not_equal, &exit);
   2234   __ incq(rax);
   2235 
   2236   __ movl(rdx, Operand(sp2, 2 * kPointerSize));
   2237   __ cmpl(rdx, Immediate(0x105));
   2238   __ j(not_equal, &exit);
   2239   __ incq(rax);
   2240 
   2241   // Non-zero to zero displacement.
   2242   __ movl(rdx, Operand(sp2, -2 * kPointerSize));
   2243   __ cmpl(rdx, Immediate(0x109));
   2244   __ j(not_equal, &exit);
   2245   __ incq(rax);
   2246 
   2247   Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
   2248 
   2249   // Test 6.
   2250   __ movl(rdx, sp2c2);  // Sanity check.
   2251   __ cmpl(rdx, Immediate(0x105));
   2252   __ j(not_equal, &exit);
   2253   __ incq(rax);
   2254 
   2255   __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
   2256   __ cmpl(rdx, Immediate(0x103));
   2257   __ j(not_equal, &exit);
   2258   __ incq(rax);
   2259 
   2260   // Non-zero to zero displacement.
   2261   __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
   2262   __ cmpl(rdx, Immediate(0x107));
   2263   __ j(not_equal, &exit);
   2264   __ incq(rax);
   2265 
   2266 
   2267   Operand bp0 = Operand(rbp, 0);
   2268 
   2269   // Test 9.
   2270   __ movl(rdx, bp0);  // Sanity check.
   2271   __ cmpl(rdx, Immediate(0x100));
   2272   __ j(not_equal, &exit);
   2273   __ incq(rax);
   2274 
   2275   // Zero to non-zero displacement.
   2276   __ movl(rdx, Operand(bp0, -2 * kPointerSize));
   2277   __ cmpl(rdx, Immediate(0x102));
   2278   __ j(not_equal, &exit);
   2279   __ incq(rax);
   2280 
   2281   Operand bp2 = Operand(rbp, -2 * kPointerSize);
   2282 
   2283   // Test 11.
   2284   __ movl(rdx, bp2);  // Sanity check.
   2285   __ cmpl(rdx, Immediate(0x102));
   2286   __ j(not_equal, &exit);
   2287   __ incq(rax);
   2288 
   2289   // Non-zero to zero displacement.
   2290   __ movl(rdx, Operand(bp2, 2 * kPointerSize));
   2291   __ cmpl(rdx, Immediate(0x100));
   2292   __ j(not_equal, &exit);
   2293   __ incq(rax);
   2294 
   2295   __ movl(rdx, Operand(bp2, -2 * kPointerSize));
   2296   __ cmpl(rdx, Immediate(0x104));
   2297   __ j(not_equal, &exit);
   2298   __ incq(rax);
   2299 
   2300   Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
   2301 
   2302   // Test 14:
   2303   __ movl(rdx, bp2c4);  // Sanity check.
   2304   __ cmpl(rdx, Immediate(0x102));
   2305   __ j(not_equal, &exit);
   2306   __ incq(rax);
   2307 
   2308   __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
   2309   __ cmpl(rdx, Immediate(0x100));
   2310   __ j(not_equal, &exit);
   2311   __ incq(rax);
   2312 
   2313   __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
   2314   __ cmpl(rdx, Immediate(0x104));
   2315   __ j(not_equal, &exit);
   2316   __ incq(rax);
   2317 
   2318   Operand bx0 = Operand(rbx, 0);
   2319 
   2320   // Test 17.
   2321   __ movl(rdx, bx0);  // Sanity check.
   2322   __ cmpl(rdx, Immediate(0x105));
   2323   __ j(not_equal, &exit);
   2324   __ incq(rax);
   2325 
   2326   __ movl(rdx, Operand(bx0, 5 * kPointerSize));
   2327   __ cmpl(rdx, Immediate(0x100));
   2328   __ j(not_equal, &exit);
   2329   __ incq(rax);
   2330 
   2331   __ movl(rdx, Operand(bx0, -4 * kPointerSize));
   2332   __ cmpl(rdx, Immediate(0x109));
   2333   __ j(not_equal, &exit);
   2334   __ incq(rax);
   2335 
   2336   Operand bx2 = Operand(rbx, 2 * kPointerSize);
   2337 
   2338   // Test 20.
   2339   __ movl(rdx, bx2);  // Sanity check.
   2340   __ cmpl(rdx, Immediate(0x103));
   2341   __ j(not_equal, &exit);
   2342   __ incq(rax);
   2343 
   2344   __ movl(rdx, Operand(bx2, 2 * kPointerSize));
   2345   __ cmpl(rdx, Immediate(0x101));
   2346   __ j(not_equal, &exit);
   2347   __ incq(rax);
   2348 
   2349   // Non-zero to zero displacement.
   2350   __ movl(rdx, Operand(bx2, -2 * kPointerSize));
   2351   __ cmpl(rdx, Immediate(0x105));
   2352   __ j(not_equal, &exit);
   2353   __ incq(rax);
   2354 
   2355   Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
   2356 
   2357   // Test 23.
   2358   __ movl(rdx, bx2c2);  // Sanity check.
   2359   __ cmpl(rdx, Immediate(0x105));
   2360   __ j(not_equal, &exit);
   2361   __ incq(rax);
   2362 
   2363   __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
   2364   __ cmpl(rdx, Immediate(0x103));
   2365   __ j(not_equal, &exit);
   2366   __ incq(rax);
   2367 
   2368   __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
   2369   __ cmpl(rdx, Immediate(0x107));
   2370   __ j(not_equal, &exit);
   2371   __ incq(rax);
   2372 
   2373   Operand r80 = Operand(r8, 0);
   2374 
   2375   // Test 26.
   2376   __ movl(rdx, r80);  // Sanity check.
   2377   __ cmpl(rdx, Immediate(0x80808080));
   2378   __ j(not_equal, &exit);
   2379   __ incq(rax);
   2380 
   2381   __ movl(rdx, Operand(r80, -8 * kIntSize));
   2382   __ cmpl(rdx, Immediate(0x78787878));
   2383   __ j(not_equal, &exit);
   2384   __ incq(rax);
   2385 
   2386   __ movl(rdx, Operand(r80, 8 * kIntSize));
   2387   __ cmpl(rdx, Immediate(0x88888888));
   2388   __ j(not_equal, &exit);
   2389   __ incq(rax);
   2390 
   2391   __ movl(rdx, Operand(r80, -64 * kIntSize));
   2392   __ cmpl(rdx, Immediate(0x40404040));
   2393   __ j(not_equal, &exit);
   2394   __ incq(rax);
   2395 
   2396   __ movl(rdx, Operand(r80, 64 * kIntSize));
   2397   __ cmpl(rdx, Immediate(0xC0C0C0C0));
   2398   __ j(not_equal, &exit);
   2399   __ incq(rax);
   2400 
   2401   Operand r88 = Operand(r8, 8 * kIntSize);
   2402 
   2403   // Test 31.
   2404   __ movl(rdx, r88);  // Sanity check.
   2405   __ cmpl(rdx, Immediate(0x88888888));
   2406   __ j(not_equal, &exit);
   2407   __ incq(rax);
   2408 
   2409   __ movl(rdx, Operand(r88, -8 * kIntSize));
   2410   __ cmpl(rdx, Immediate(0x80808080));
   2411   __ j(not_equal, &exit);
   2412   __ incq(rax);
   2413 
   2414   __ movl(rdx, Operand(r88, 8 * kIntSize));
   2415   __ cmpl(rdx, Immediate(0x90909090));
   2416   __ j(not_equal, &exit);
   2417   __ incq(rax);
   2418 
   2419   __ movl(rdx, Operand(r88, -64 * kIntSize));
   2420   __ cmpl(rdx, Immediate(0x48484848));
   2421   __ j(not_equal, &exit);
   2422   __ incq(rax);
   2423 
   2424   __ movl(rdx, Operand(r88, 64 * kIntSize));
   2425   __ cmpl(rdx, Immediate(0xC8C8C8C8));
   2426   __ j(not_equal, &exit);
   2427   __ incq(rax);
   2428 
   2429 
   2430   Operand r864 = Operand(r8, 64 * kIntSize);
   2431 
   2432   // Test 36.
   2433   __ movl(rdx, r864);  // Sanity check.
   2434   __ cmpl(rdx, Immediate(0xC0C0C0C0));
   2435   __ j(not_equal, &exit);
   2436   __ incq(rax);
   2437 
   2438   __ movl(rdx, Operand(r864, -8 * kIntSize));
   2439   __ cmpl(rdx, Immediate(0xB8B8B8B8));
   2440   __ j(not_equal, &exit);
   2441   __ incq(rax);
   2442 
   2443   __ movl(rdx, Operand(r864, 8 * kIntSize));
   2444   __ cmpl(rdx, Immediate(0xC8C8C8C8));
   2445   __ j(not_equal, &exit);
   2446   __ incq(rax);
   2447 
   2448   __ movl(rdx, Operand(r864, -64 * kIntSize));
   2449   __ cmpl(rdx, Immediate(0x80808080));
   2450   __ j(not_equal, &exit);
   2451   __ incq(rax);
   2452 
   2453   __ movl(rdx, Operand(r864, 32 * kIntSize));
   2454   __ cmpl(rdx, Immediate(0xE0E0E0E0));
   2455   __ j(not_equal, &exit);
   2456   __ incq(rax);
   2457 
   2458   // 32-bit offset to 8-bit offset.
   2459   __ movl(rdx, Operand(r864, -60 * kIntSize));
   2460   __ cmpl(rdx, Immediate(0x84848484));
   2461   __ j(not_equal, &exit);
   2462   __ incq(rax);
   2463 
   2464   __ movl(rdx, Operand(r864, 60 * kIntSize));
   2465   __ cmpl(rdx, Immediate(0xFCFCFCFC));
   2466   __ j(not_equal, &exit);
   2467   __ incq(rax);
   2468 
   2469   // Test unaligned offsets.
   2470 
   2471   // Test 43.
   2472   __ movl(rdx, Operand(r80, 2));
   2473   __ cmpl(rdx, Immediate(0x81818080));
   2474   __ j(not_equal, &exit);
   2475   __ incq(rax);
   2476 
   2477   __ movl(rdx, Operand(r80, -2));
   2478   __ cmpl(rdx, Immediate(0x80807F7F));
   2479   __ j(not_equal, &exit);
   2480   __ incq(rax);
   2481 
   2482   __ movl(rdx, Operand(r80, 126));
   2483   __ cmpl(rdx, Immediate(0xA0A09F9F));
   2484   __ j(not_equal, &exit);
   2485   __ incq(rax);
   2486 
   2487   __ movl(rdx, Operand(r80, -126));
   2488   __ cmpl(rdx, Immediate(0x61616060));
   2489   __ j(not_equal, &exit);
   2490   __ incq(rax);
   2491 
   2492   __ movl(rdx, Operand(r80, 254));
   2493   __ cmpl(rdx, Immediate(0xC0C0BFBF));
   2494   __ j(not_equal, &exit);
   2495   __ incq(rax);
   2496 
   2497   __ movl(rdx, Operand(r80, -254));
   2498   __ cmpl(rdx, Immediate(0x41414040));
   2499   __ j(not_equal, &exit);
   2500   __ incq(rax);
   2501 
   2502   // Success.
   2503 
   2504   __ movl(rax, Immediate(0));
   2505   __ bind(&exit);
   2506   __ lea(rsp, Operand(rbp, kPointerSize));
   2507   __ pop(rbp);
   2508   __ pop(rbx);
   2509   __ pop(r14);
   2510   __ pop(r13);
   2511   ExitCode(masm);
   2512   __ ret(0);
   2513 
   2514 
   2515   CodeDesc desc;
   2516   masm->GetCode(&desc);
   2517   // Call the function from C++.
   2518   int result = FUNCTION_CAST<F0>(buffer)();
   2519   CHECK_EQ(0, result);
   2520 }
   2521 
   2522 
   2523 
   2524 #undef __
   2525