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