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