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