v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-macro-assembler-x64.cc
Go to the documentation of this file.
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 
43 using v8::internal::Immediate;
45 using v8::internal::Label;
47 using v8::internal::OS;
48 using v8::internal::Operand;
49 using v8::internal::RelocInfo;
50 using v8::internal::Smi;
52 using v8::internal::byte;
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;
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 
96 static void EntryCode(MacroAssembler* masm) {
97  // Smi constant register is callee save.
100  __ InitializeSmiConstantRegister();
101  __ InitializeRootRegister();
102 }
103 
104 
105 static void ExitCode(MacroAssembler* masm) {
106  // Return -1 if kSmiConstantRegister was clobbered during the test.
107  __ Move(rdx, Smi::FromInt(1));
109  __ movq(rdx, Immediate(-1));
110  __ cmovq(not_equal, rax, rdx);
113 }
114 
115 
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 
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.
152 TEST(SmiMove) {
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 
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).
241 TEST(SmiCompare) {
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 
294 TEST(Integer32ToSmi) {
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 
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 
424 TEST(Integer64PlusConstantToSmi) {
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 
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 
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 
719 TEST(SmiNeg) {
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 
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 
810 TEST(SmiAdd) {
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 
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 
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 
1001 TEST(SmiSub) {
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 
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 
1094 TEST(SmiMul) {
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 
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 
1201 TEST(SmiDiv) {
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 
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 
1313 TEST(SmiMod) {
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 
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 
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 
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 
1482 TEST(SmiSelectNonSmi) {
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 
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 
1563 TEST(SmiAnd) {
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 
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 
1646 TEST(SmiOr) {
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 
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 
1731 TEST(SmiXor) {
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 
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 
1800 TEST(SmiNot) {
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 
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 
1898 TEST(SmiShiftLeft) {
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 
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 
2006 TEST(SmiShiftLogicalRight) {
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 
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 
2077 TEST(SmiShiftArithmeticRight) {
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 
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 
2143 TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
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 
2185 TEST(OperandOffset) {
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 __
const Register rdx
void TestI64PlusConstantToSmi(MacroAssembler *masm, Label *exit, int id, int64_t x, int y)
static bool Initialize(Deserializer *des)
Definition: v8.cc:64
unsigned char byte
Definition: disasm.h:33
const intptr_t kSmiTagMask
Definition: v8.h:3855
#define CHECK_EQ(expected, value)
Definition: checks.h:219
const Register r14
SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift)
void TestSmiIndex(MacroAssembler *masm, Label *exit, int id, int x)
const Register r11
void TestSmiMod(MacroAssembler *masm, Label *exit, int id, int x, int y)
const Register rbp
const int kSmiValueSize
Definition: v8.h:3900
const Register rsi
void TestSmiNot(MacroAssembler *masm, Label *exit, int id, int x)
SmiIndex SmiToIndex(Register dst, Register src, int shift)
#define ASSERT(condition)
Definition: checks.h:270
Condition CheckIsMinSmi(Register src)
#define CHECK(condition)
Definition: checks.h:56
void TestSmiMul(MacroAssembler *masm, Label *exit, int id, int x, int y)
void TestSmiShiftLogicalRight(MacroAssembler *masm, Label *exit, int id, int x)
Condition CheckBothSmi(Register first, Register second)
int(* F0)()
const int kIntSize
Definition: globals.h:231
void TestSmiShiftArithmeticRight(MacroAssembler *masm, Label *exit, int id, int x)
const Register kRootRegister
uint8_t byte
Definition: globals.h:171
void TestSmiShiftLeft(MacroAssembler *masm, Label *exit, int id, int x)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
void GetCode(CodeDesc *desc)
const Register r9
const int kPointerSize
Definition: globals.h:234
const Register rbx
const Register rsp
Condition CheckInteger32ValidSmiValue(Register src)
const Register rax
const Register r13
const Register rdi
void TestSmiDiv(MacroAssembler *masm, Label *exit, int id, int x, int y)
void TestSmiXor(MacroAssembler *masm, Label *exit, int id, int x, int y)
void TestSmiAnd(MacroAssembler *masm, Label *exit, int id, int x, int y)
bool is(Register reg) const
void TestSmiCompare(MacroAssembler *masm, Label *exit, int id, int x, int y)
const Register r8
const Register rcx
Condition NegateCondition(Condition cond)
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
void TestSelectNonSmi(MacroAssembler *masm, Label *exit, int id, int x, int y)
void TestPositiveSmiPowerUp(MacroAssembler *masm, Label *exit, int id, int x)
Condition CheckNonNegativeSmi(Register src)
#define __
Condition CheckSmi(Register src)
const Register kSmiConstantRegister
const Register r15
void TestSmiOr(MacroAssembler *masm, Label *exit, int id, int x, int y)
void TestSmiNeg(MacroAssembler *masm, Label *exit, int id, int x)
F FUNCTION_CAST(Address addr)
Definition: globals.h:314