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