7f20a8dd4bbe448feac41195801c1a46d06c25f1
[platform/upstream/nodejs.git] / deps / 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 "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 __