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