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