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
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.
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.
32 #include "src/base/platform/platform.h"
33 #include "src/factory.h"
34 #include "src/macro-assembler.h"
35 #include "src/serialize.h"
36 #include "test/cctest/cctest.h"
38 namespace i = v8::internal;
43 using i::FUNCTION_CAST;
48 using i::MacroAssembler;
51 using i::Representation;
57 using i::greater_equal;
59 using i::kPointerSize;
61 using i::kSmiValueSize;
83 using i::times_pointer_size;
85 // Test the x64 assembler by compiling some simple functions into
86 // a buffer and executing them. These tests do not initialize the
87 // V8 library, create a context, or use any V8 objects.
88 // The AMD64 calling convention is used, with the first five arguments
89 // in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
90 // the XMM registers. The return value is in RAX.
91 // This calling convention is used on Linux, with GCC, and on Mac OS,
92 // with GCC. A different convention is used on 64-bit windows.
99 static void EntryCode(MacroAssembler* masm) {
100 // Smi constant register is callee save.
101 __ pushq(i::kSmiConstantRegister);
102 __ pushq(i::kRootRegister);
103 __ InitializeSmiConstantRegister();
104 __ InitializeRootRegister();
108 static void ExitCode(MacroAssembler* masm) {
109 // Return -1 if kSmiConstantRegister was clobbered during the test.
110 __ Move(rdx, Smi::FromInt(1));
111 __ cmpq(rdx, i::kSmiConstantRegister);
112 __ movq(rdx, Immediate(-1));
113 __ cmovq(not_equal, rax, rdx);
114 __ popq(i::kRootRegister);
115 __ popq(i::kSmiConstantRegister);
120 // Check that C++ Smi operations work as expected.
121 int64_t test_numbers[] = {
122 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
123 Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
124 Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
126 int test_number_count = 15;
127 for (int i = 0; i < test_number_count; i++) {
128 int64_t number = test_numbers[i];
129 bool is_valid = Smi::IsValid(number);
130 bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
131 CHECK_EQ(is_in_range, is_valid);
133 Smi* smi_from_intptr = Smi::FromIntptr(number);
134 if (static_cast<int>(number) == number) { // Is a 32-bit int.
135 Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
136 CHECK_EQ(smi_from_int, smi_from_intptr);
138 int64_t smi_value = smi_from_intptr->value();
139 CHECK_EQ(number, smi_value);
145 static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
146 __ movl(rax, Immediate(id));
148 __ Set(rdx, reinterpret_cast<intptr_t>(value));
150 __ j(not_equal, exit);
154 // Test that we can move a Smi value literally into a register.
156 // Allocate an executable page of memory.
158 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
159 Assembler::kMinimalBufferSize, &actual_size, true));
161 Isolate* isolate = CcTest::i_isolate();
162 HandleScope handles(isolate);
163 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
164 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
168 TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
169 TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
170 TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
171 TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
172 TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
173 TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
174 TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
175 TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
176 TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
177 TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
178 TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
179 TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
181 __ xorq(rax, rax); // Success.
187 masm->GetCode(&desc);
188 // Call the function from C++.
189 int result = FUNCTION_CAST<F0>(buffer)();
194 void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
195 __ Move(rcx, Smi::FromInt(x));
197 __ Move(rdx, Smi::FromInt(y));
199 __ SmiCompare(rcx, rdx);
201 __ movl(rax, Immediate(id + 1));
202 __ j(greater_equal, exit);
204 __ movl(rax, Immediate(id + 2));
205 __ j(less_equal, exit);
208 __ movl(rax, Immediate(id + 3));
209 __ j(not_equal, exit);
211 __ movl(rax, Immediate(id + 4));
213 __ j(not_equal, exit);
216 __ j(not_equal, exit);
219 __ SmiCompare(rdx, rcx);
221 __ movl(rax, Immediate(id + 9));
222 __ j(greater_equal, exit);
225 __ movl(rax, Immediate(id + 10));
226 __ j(less_equal, exit);
230 __ movl(rax, Immediate(id + 11));
231 __ j(not_equal, exit);
234 __ j(not_equal, exit);
239 // Test that we can compare smis for equality (and more).
241 // Allocate an executable page of memory.
243 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
244 Assembler::kMinimalBufferSize * 2, &actual_size, true));
246 Isolate* isolate = CcTest::i_isolate();
247 HandleScope handles(isolate);
248 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
250 MacroAssembler* masm = &assembler;
254 TestSmiCompare(masm, &exit, 0x10, 0, 0);
255 TestSmiCompare(masm, &exit, 0x20, 0, 1);
256 TestSmiCompare(masm, &exit, 0x30, 1, 0);
257 TestSmiCompare(masm, &exit, 0x40, 1, 1);
258 TestSmiCompare(masm, &exit, 0x50, 0, -1);
259 TestSmiCompare(masm, &exit, 0x60, -1, 0);
260 TestSmiCompare(masm, &exit, 0x70, -1, -1);
261 TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
262 TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
263 TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
264 TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
265 TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
266 TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
267 TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
268 TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
269 TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
270 TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
271 TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
272 TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
274 __ xorq(rax, rax); // Success.
280 masm->GetCode(&desc);
281 // Call the function from C++.
282 int result = FUNCTION_CAST<F0>(buffer)();
288 TEST(Integer32ToSmi) {
289 // Allocate an executable page of memory.
291 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
292 Assembler::kMinimalBufferSize, &actual_size, true));
294 Isolate* isolate = CcTest::i_isolate();
295 HandleScope handles(isolate);
296 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
298 MacroAssembler* masm = &assembler;
302 __ movq(rax, Immediate(1)); // Test number.
303 __ movl(rcx, Immediate(0));
304 __ Integer32ToSmi(rcx, rcx);
305 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
307 __ j(not_equal, &exit);
309 __ movq(rax, Immediate(2)); // Test number.
310 __ movl(rcx, Immediate(1024));
311 __ Integer32ToSmi(rcx, rcx);
312 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
314 __ j(not_equal, &exit);
316 __ movq(rax, Immediate(3)); // Test number.
317 __ movl(rcx, Immediate(-1));
318 __ Integer32ToSmi(rcx, rcx);
319 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
321 __ j(not_equal, &exit);
323 __ movq(rax, Immediate(4)); // Test number.
324 __ movl(rcx, Immediate(Smi::kMaxValue));
325 __ Integer32ToSmi(rcx, rcx);
326 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
328 __ j(not_equal, &exit);
330 __ movq(rax, Immediate(5)); // Test number.
331 __ movl(rcx, Immediate(Smi::kMinValue));
332 __ Integer32ToSmi(rcx, rcx);
333 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
335 __ j(not_equal, &exit);
337 // Different target register.
339 __ movq(rax, Immediate(6)); // Test number.
340 __ movl(rcx, Immediate(0));
341 __ Integer32ToSmi(r8, rcx);
342 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
344 __ j(not_equal, &exit);
346 __ movq(rax, Immediate(7)); // Test number.
347 __ movl(rcx, Immediate(1024));
348 __ Integer32ToSmi(r8, rcx);
349 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
351 __ j(not_equal, &exit);
353 __ movq(rax, Immediate(8)); // Test number.
354 __ movl(rcx, Immediate(-1));
355 __ Integer32ToSmi(r8, rcx);
356 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
358 __ j(not_equal, &exit);
360 __ movq(rax, Immediate(9)); // Test number.
361 __ movl(rcx, Immediate(Smi::kMaxValue));
362 __ Integer32ToSmi(r8, rcx);
363 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
365 __ j(not_equal, &exit);
367 __ movq(rax, Immediate(10)); // Test number.
368 __ movl(rcx, Immediate(Smi::kMinValue));
369 __ Integer32ToSmi(r8, rcx);
370 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
372 __ j(not_equal, &exit);
375 __ xorq(rax, rax); // Success.
381 masm->GetCode(&desc);
382 // Call the function from C++.
383 int result = FUNCTION_CAST<F0>(buffer)();
388 void TestI64PlusConstantToSmi(MacroAssembler* masm,
393 int64_t result = x + y;
394 DCHECK(Smi::IsValid(result));
395 __ movl(rax, Immediate(id));
396 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
399 __ Integer64PlusConstantToSmi(rdx, rcx, y);
401 __ j(not_equal, exit);
405 __ j(not_equal, exit);
408 __ Integer64PlusConstantToSmi(rcx, rcx, y);
410 __ j(not_equal, exit);
414 TEST(Integer64PlusConstantToSmi) {
415 // Allocate an executable page of memory.
417 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
418 Assembler::kMinimalBufferSize, &actual_size, true));
420 Isolate* isolate = CcTest::i_isolate();
421 HandleScope handles(isolate);
422 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
424 MacroAssembler* masm = &assembler;
428 int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
430 TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
431 TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
432 TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
433 TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
434 TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
435 TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
436 TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
437 TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
438 TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
439 TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
440 TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
441 TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
443 __ xorq(rax, rax); // Success.
449 masm->GetCode(&desc);
450 // Call the function from C++.
451 int result = FUNCTION_CAST<F0>(buffer)();
457 // Allocate an executable page of memory.
459 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
460 Assembler::kMinimalBufferSize, &actual_size, true));
462 Isolate* isolate = CcTest::i_isolate();
463 HandleScope handles(isolate);
464 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
466 MacroAssembler* masm = &assembler;
471 __ movl(rax, Immediate(1)); // Test number.
475 __ movl(rcx, Immediate(0));
476 __ Integer32ToSmi(rcx, rcx);
477 cond = masm->CheckSmi(rcx);
478 __ j(NegateCondition(cond), &exit);
481 __ xorq(rcx, Immediate(kSmiTagMask));
482 cond = masm->CheckSmi(rcx);
486 __ movl(rcx, Immediate(-1));
487 __ Integer32ToSmi(rcx, rcx);
488 cond = masm->CheckSmi(rcx);
489 __ j(NegateCondition(cond), &exit);
492 __ xorq(rcx, Immediate(kSmiTagMask));
493 cond = masm->CheckSmi(rcx);
497 __ movl(rcx, Immediate(Smi::kMaxValue));
498 __ Integer32ToSmi(rcx, rcx);
499 cond = masm->CheckSmi(rcx);
500 __ j(NegateCondition(cond), &exit);
503 __ xorq(rcx, Immediate(kSmiTagMask));
504 cond = masm->CheckSmi(rcx);
508 __ movl(rcx, Immediate(Smi::kMinValue));
509 __ Integer32ToSmi(rcx, rcx);
510 cond = masm->CheckSmi(rcx);
511 __ j(NegateCondition(cond), &exit);
514 __ xorq(rcx, Immediate(kSmiTagMask));
515 cond = masm->CheckSmi(rcx);
521 __ movl(rcx, Immediate(0));
522 __ Integer32ToSmi(rcx, rcx);
523 cond = masm->CheckNonNegativeSmi(rcx);
524 __ j(NegateCondition(cond), &exit);
527 __ xorq(rcx, Immediate(kSmiTagMask));
528 cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi.
532 __ movq(rcx, Immediate(-1));
533 __ Integer32ToSmi(rcx, rcx);
534 cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive.
538 __ movq(rcx, Immediate(Smi::kMinValue));
539 __ Integer32ToSmi(rcx, rcx);
540 cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive.
544 __ xorq(rcx, Immediate(kSmiTagMask));
545 cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi.
549 __ movq(rcx, Immediate(Smi::kMaxValue));
550 __ Integer32ToSmi(rcx, rcx);
551 cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive.
552 __ j(NegateCondition(cond), &exit);
555 __ xorq(rcx, Immediate(kSmiTagMask));
556 cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
562 __ movq(rcx, Immediate(Smi::kMaxValue));
563 __ Integer32ToSmi(rcx, rcx);
564 cond = masm->CheckIsMinSmi(rcx);
568 __ movq(rcx, Immediate(0));
569 __ Integer32ToSmi(rcx, rcx);
570 cond = masm->CheckIsMinSmi(rcx);
574 __ movq(rcx, Immediate(Smi::kMinValue));
575 __ Integer32ToSmi(rcx, rcx);
576 cond = masm->CheckIsMinSmi(rcx);
577 __ j(NegateCondition(cond), &exit);
580 __ movq(rcx, Immediate(Smi::kMinValue + 1));
581 __ Integer32ToSmi(rcx, rcx);
582 cond = masm->CheckIsMinSmi(rcx);
588 __ movq(rcx, Immediate(Smi::kMaxValue));
589 __ Integer32ToSmi(rcx, rcx);
590 __ movq(rdx, Immediate(Smi::kMinValue));
591 __ Integer32ToSmi(rdx, rdx);
592 cond = masm->CheckBothSmi(rcx, rdx);
593 __ j(NegateCondition(cond), &exit);
596 __ xorq(rcx, Immediate(kSmiTagMask));
597 cond = masm->CheckBothSmi(rcx, rdx);
601 __ xorq(rdx, Immediate(kSmiTagMask));
602 cond = masm->CheckBothSmi(rcx, rdx);
606 __ xorq(rcx, Immediate(kSmiTagMask));
607 cond = masm->CheckBothSmi(rcx, rdx);
611 cond = masm->CheckBothSmi(rcx, rcx);
612 __ j(NegateCondition(cond), &exit);
615 cond = masm->CheckBothSmi(rdx, rdx);
618 // CheckInteger32ValidSmiValue
620 __ movq(rcx, Immediate(0));
621 cond = masm->CheckInteger32ValidSmiValue(rax);
622 __ j(NegateCondition(cond), &exit);
625 __ movq(rcx, Immediate(-1));
626 cond = masm->CheckInteger32ValidSmiValue(rax);
627 __ j(NegateCondition(cond), &exit);
630 __ movq(rcx, Immediate(Smi::kMaxValue));
631 cond = masm->CheckInteger32ValidSmiValue(rax);
632 __ j(NegateCondition(cond), &exit);
635 __ movq(rcx, Immediate(Smi::kMinValue));
636 cond = masm->CheckInteger32ValidSmiValue(rax);
637 __ j(NegateCondition(cond), &exit);
647 masm->GetCode(&desc);
648 // Call the function from C++.
649 int result = FUNCTION_CAST<F0>(buffer)();
655 void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
656 __ Move(rcx, Smi::FromInt(x));
658 if (x == Smi::kMinValue || x == 0) {
660 __ movl(rax, Immediate(id + 8));
661 __ SmiNeg(r9, rcx, exit);
665 __ j(not_equal, exit);
668 __ SmiNeg(rcx, rcx, exit);
672 __ j(not_equal, exit);
674 Label smi_ok, smi_ok2;
676 __ movl(rax, Immediate(id));
677 __ Move(r8, Smi::FromInt(result));
679 __ SmiNeg(r9, rcx, &smi_ok);
684 __ j(not_equal, exit);
688 __ j(not_equal, exit);
691 __ SmiNeg(rcx, rcx, &smi_ok2);
696 __ j(not_equal, exit);
702 // Allocate an executable page of memory.
704 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
705 Assembler::kMinimalBufferSize, &actual_size, true));
707 Isolate* isolate = CcTest::i_isolate();
708 HandleScope handles(isolate);
709 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
711 MacroAssembler* masm = &assembler;
715 TestSmiNeg(masm, &exit, 0x10, 0);
716 TestSmiNeg(masm, &exit, 0x20, 1);
717 TestSmiNeg(masm, &exit, 0x30, -1);
718 TestSmiNeg(masm, &exit, 0x40, 127);
719 TestSmiNeg(masm, &exit, 0x50, 65535);
720 TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
721 TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
722 TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
724 __ xorq(rax, rax); // Success.
730 masm->GetCode(&desc);
731 // Call the function from C++.
732 int result = FUNCTION_CAST<F0>(buffer)();
737 static void SmiAddTest(MacroAssembler* masm,
742 __ movl(rcx, Immediate(first));
743 __ Integer32ToSmi(rcx, rcx);
744 __ movl(rdx, Immediate(second));
745 __ Integer32ToSmi(rdx, rdx);
746 __ movl(r8, Immediate(first + second));
747 __ Integer32ToSmi(r8, r8);
749 __ movl(rax, Immediate(id)); // Test number.
750 __ SmiAdd(r9, rcx, rdx, exit);
752 __ j(not_equal, exit);
755 __ SmiAdd(rcx, rcx, rdx, exit);
757 __ j(not_equal, exit);
759 __ movl(rcx, Immediate(first));
760 __ Integer32ToSmi(rcx, rcx);
763 __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
765 __ j(not_equal, exit);
767 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
769 __ j(not_equal, exit);
771 __ movl(rcx, Immediate(first));
772 __ Integer32ToSmi(rcx, rcx);
774 i::SmiOperationExecutionMode mode;
775 mode.Add(i::PRESERVE_SOURCE_REGISTER);
776 mode.Add(i::BAILOUT_ON_OVERFLOW);
778 __ SmiAddConstant(r9, rcx, Smi::FromInt(second), mode, exit);
780 __ j(not_equal, exit);
783 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
785 __ j(not_equal, exit);
787 __ movl(rcx, Immediate(first));
788 __ Integer32ToSmi(rcx, rcx);
791 mode.Add(i::PRESERVE_SOURCE_REGISTER);
792 mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
795 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
799 __ j(not_equal, exit);
803 static void SmiAddOverflowTest(MacroAssembler* masm,
807 // Adds a Smi to x so that the addition overflows.
808 DCHECK(x != 0); // Can't overflow by adding a Smi.
809 int y_max = (x > 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue - x - 1);
810 int y_min = (x > 0) ? (Smi::kMaxValue - x + 1) : (Smi::kMinValue + 0);
812 __ movl(rax, Immediate(id));
813 __ Move(rcx, Smi::FromInt(x));
814 __ movq(r11, rcx); // Store original Smi value of x in r11.
815 __ Move(rdx, Smi::FromInt(y_min));
818 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
820 __ bind(&overflow_ok);
823 __ j(not_equal, exit);
829 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
831 __ bind(&overflow_ok);
834 __ j(not_equal, exit);
837 i::SmiOperationExecutionMode mode;
838 mode.Add(i::PRESERVE_SOURCE_REGISTER);
839 mode.Add(i::BAILOUT_ON_OVERFLOW);
844 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
846 __ bind(&overflow_ok);
849 __ j(not_equal, exit);
855 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
857 __ bind(&overflow_ok);
860 __ j(not_equal, exit);
863 __ Move(rdx, Smi::FromInt(y_max));
868 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
870 __ bind(&overflow_ok);
873 __ j(not_equal, exit);
879 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
881 __ bind(&overflow_ok);
884 __ j(not_equal, exit);
891 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
893 __ bind(&overflow_ok);
896 __ j(not_equal, exit);
900 mode.Add(i::BAILOUT_ON_OVERFLOW);
904 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
906 __ bind(&overflow_ok);
915 // Allocate an executable page of memory.
917 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
918 Assembler::kMinimalBufferSize * 3, &actual_size, true));
920 Isolate* isolate = CcTest::i_isolate();
921 HandleScope handles(isolate);
922 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
924 MacroAssembler* masm = &assembler;
928 // No-overflow tests.
929 SmiAddTest(masm, &exit, 0x10, 1, 2);
930 SmiAddTest(masm, &exit, 0x20, 1, -2);
931 SmiAddTest(masm, &exit, 0x30, -1, 2);
932 SmiAddTest(masm, &exit, 0x40, -1, -2);
933 SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
934 SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
935 SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
936 SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
938 SmiAddOverflowTest(masm, &exit, 0x90, -1);
939 SmiAddOverflowTest(masm, &exit, 0xA0, 1);
940 SmiAddOverflowTest(masm, &exit, 0xB0, 1024);
941 SmiAddOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
942 SmiAddOverflowTest(masm, &exit, 0xD0, -2);
943 SmiAddOverflowTest(masm, &exit, 0xE0, -42000);
944 SmiAddOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
946 __ xorq(rax, rax); // Success.
952 masm->GetCode(&desc);
953 // Call the function from C++.
954 int result = FUNCTION_CAST<F0>(buffer)();
959 static void SmiSubTest(MacroAssembler* masm,
964 __ Move(rcx, Smi::FromInt(first));
965 __ Move(rdx, Smi::FromInt(second));
966 __ Move(r8, Smi::FromInt(first - second));
968 __ movl(rax, Immediate(id)); // Test 0.
969 __ SmiSub(r9, rcx, rdx, exit);
971 __ j(not_equal, exit);
973 __ incq(rax); // Test 1.
974 __ SmiSub(rcx, rcx, rdx, exit);
976 __ j(not_equal, exit);
978 __ Move(rcx, Smi::FromInt(first));
980 __ incq(rax); // Test 2.
981 __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
983 __ j(not_equal, exit);
985 __ incq(rax); // Test 3.
986 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
988 __ j(not_equal, exit);
990 i::SmiOperationExecutionMode mode;
991 mode.Add(i::PRESERVE_SOURCE_REGISTER);
992 mode.Add(i::BAILOUT_ON_OVERFLOW);
993 __ Move(rcx, Smi::FromInt(first));
994 __ incq(rax); // Test 4.
995 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
997 __ j(not_equal, exit);
999 __ Move(rcx, Smi::FromInt(first));
1000 __ incq(rax); // Test 5.
1001 __ SmiSubConstant(r9, rcx, Smi::FromInt(second), mode, exit);
1003 __ j(not_equal, exit);
1006 mode.Add(i::PRESERVE_SOURCE_REGISTER);
1007 mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
1008 __ Move(rcx, Smi::FromInt(first));
1010 __ incq(rax); // Test 6.
1011 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
1015 __ j(not_equal, exit);
1019 static void SmiSubOverflowTest(MacroAssembler* masm,
1023 // Subtracts a Smi from x so that the subtraction overflows.
1024 DCHECK(x != -1); // Can't overflow by subtracting a Smi.
1025 int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
1026 int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
1028 __ movl(rax, Immediate(id));
1029 __ Move(rcx, Smi::FromInt(x));
1030 __ movq(r11, rcx); // Store original Smi value of x in r11.
1031 __ Move(rdx, Smi::FromInt(y_min));
1034 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1036 __ bind(&overflow_ok);
1039 __ j(not_equal, exit);
1045 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1047 __ bind(&overflow_ok);
1050 __ j(not_equal, exit);
1053 i::SmiOperationExecutionMode mode;
1054 mode.Add(i::PRESERVE_SOURCE_REGISTER);
1055 mode.Add(i::BAILOUT_ON_OVERFLOW);
1061 __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
1063 __ bind(&overflow_ok);
1066 __ j(not_equal, exit);
1072 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
1074 __ bind(&overflow_ok);
1077 __ j(not_equal, exit);
1080 __ Move(rdx, Smi::FromInt(y_max));
1085 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1087 __ bind(&overflow_ok);
1090 __ j(not_equal, exit);
1096 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1098 __ bind(&overflow_ok);
1101 __ j(not_equal, exit);
1108 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
1110 __ bind(&overflow_ok);
1113 __ j(not_equal, exit);
1117 mode.Add(i::BAILOUT_ON_OVERFLOW);
1122 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
1124 __ bind(&overflow_ok);
1133 // Allocate an executable page of memory.
1135 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1136 Assembler::kMinimalBufferSize * 4, &actual_size, true));
1138 Isolate* isolate = CcTest::i_isolate();
1139 HandleScope handles(isolate);
1140 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1142 MacroAssembler* masm = &assembler;
1146 SmiSubTest(masm, &exit, 0x10, 1, 2);
1147 SmiSubTest(masm, &exit, 0x20, 1, -2);
1148 SmiSubTest(masm, &exit, 0x30, -1, 2);
1149 SmiSubTest(masm, &exit, 0x40, -1, -2);
1150 SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
1151 SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
1152 SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
1153 SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
1154 SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
1156 SmiSubOverflowTest(masm, &exit, 0xA0, 1);
1157 SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
1158 SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
1159 SmiSubOverflowTest(masm, &exit, 0xD0, -2);
1160 SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
1161 SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
1162 SmiSubOverflowTest(masm, &exit, 0x100, 0);
1164 __ xorq(rax, rax); // Success.
1170 masm->GetCode(&desc);
1171 // Call the function from C++.
1172 int result = FUNCTION_CAST<F0>(buffer)();
1173 CHECK_EQ(0, result);
1178 void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1179 int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
1180 bool negative_zero = (result == 0) && (x < 0 || y < 0);
1181 __ Move(rcx, Smi::FromInt(x));
1183 __ Move(rdx, Smi::FromInt(y));
1184 if (Smi::IsValid(result) && !negative_zero) {
1185 __ movl(rax, Immediate(id));
1186 __ Move(r8, Smi::FromIntptr(result));
1187 __ SmiMul(r9, rcx, rdx, exit);
1190 __ j(not_equal, exit);
1193 __ j(not_equal, exit);
1196 __ SmiMul(rcx, rcx, rdx, exit);
1198 __ j(not_equal, exit);
1200 __ movl(rax, Immediate(id + 8));
1201 Label overflow_ok, overflow_ok2;
1202 __ SmiMul(r9, rcx, rdx, &overflow_ok);
1204 __ bind(&overflow_ok);
1207 __ j(not_equal, exit);
1209 __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
1211 __ bind(&overflow_ok2);
1212 // 31-bit version doesn't preserve rcx on failure.
1214 // __ cmpq(r11, rcx);
1215 // __ j(not_equal, exit);
1221 // Allocate an executable page of memory.
1223 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1224 Assembler::kMinimalBufferSize, &actual_size, true));
1226 Isolate* isolate = CcTest::i_isolate();
1227 HandleScope handles(isolate);
1228 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1230 MacroAssembler* masm = &assembler;
1234 TestSmiMul(masm, &exit, 0x10, 0, 0);
1235 TestSmiMul(masm, &exit, 0x20, -1, 0);
1236 TestSmiMul(masm, &exit, 0x30, 0, -1);
1237 TestSmiMul(masm, &exit, 0x40, -1, -1);
1238 TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
1239 TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
1240 TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
1241 TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
1242 TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
1243 TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
1244 TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
1245 TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
1246 TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
1247 TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
1249 __ xorq(rax, rax); // Success.
1255 masm->GetCode(&desc);
1256 // Call the function from C++.
1257 int result = FUNCTION_CAST<F0>(buffer)();
1258 CHECK_EQ(0, result);
1262 void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1263 bool division_by_zero = (y == 0);
1264 bool negative_zero = (x == 0 && y < 0);
1265 #if V8_TARGET_ARCH_X64
1266 bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
1268 bool overflow = (x == Smi::kMinValue && y == -1);
1270 bool fraction = !division_by_zero && !overflow && (x % y != 0);
1271 __ Move(r11, Smi::FromInt(x));
1272 __ Move(r14, Smi::FromInt(y));
1273 if (!fraction && !overflow && !negative_zero && !division_by_zero) {
1274 // Division succeeds
1276 __ movq(r15, Immediate(id));
1278 __ Move(r8, Smi::FromInt(result));
1279 __ SmiDiv(r9, rcx, r14, exit);
1280 // Might have destroyed rcx and r14.
1283 __ j(not_equal, exit);
1287 __ Move(r14, Smi::FromInt(y));
1289 __ j(not_equal, exit);
1292 __ SmiDiv(rcx, rcx, r14, exit);
1296 __ j(not_equal, exit);
1299 __ movq(r15, Immediate(id + 8));
1301 Label fail_ok, fail_ok2;
1303 __ SmiDiv(r9, rcx, r14, &fail_ok);
1309 __ j(not_equal, exit);
1312 __ SmiDiv(rcx, rcx, r14, &fail_ok2);
1318 __ j(not_equal, exit);
1324 // Allocate an executable page of memory.
1326 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1327 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1329 Isolate* isolate = CcTest::i_isolate();
1330 HandleScope handles(isolate);
1331 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1333 MacroAssembler* masm = &assembler;
1339 TestSmiDiv(masm, &exit, 0x10, 1, 1);
1340 TestSmiDiv(masm, &exit, 0x20, 1, 0);
1341 TestSmiDiv(masm, &exit, 0x30, -1, 0);
1342 TestSmiDiv(masm, &exit, 0x40, 0, 1);
1343 TestSmiDiv(masm, &exit, 0x50, 0, -1);
1344 TestSmiDiv(masm, &exit, 0x60, 4, 2);
1345 TestSmiDiv(masm, &exit, 0x70, -4, 2);
1346 TestSmiDiv(masm, &exit, 0x80, 4, -2);
1347 TestSmiDiv(masm, &exit, 0x90, -4, -2);
1348 TestSmiDiv(masm, &exit, 0xa0, 3, 2);
1349 TestSmiDiv(masm, &exit, 0xb0, 3, 4);
1350 TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1351 TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1352 TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1353 TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1354 TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1355 TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
1356 TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
1357 TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1358 TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
1360 __ xorq(r15, r15); // Success.
1369 masm->GetCode(&desc);
1370 // Call the function from C++.
1371 int result = FUNCTION_CAST<F0>(buffer)();
1372 CHECK_EQ(0, result);
1376 void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1377 bool division_by_zero = (y == 0);
1378 bool division_overflow = (x == Smi::kMinValue) && (y == -1);
1379 bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
1380 bool negative_zero = (!fraction && x < 0);
1381 __ Move(rcx, Smi::FromInt(x));
1383 __ Move(r14, Smi::FromInt(y));
1384 if (!division_overflow && !negative_zero && !division_by_zero) {
1386 __ movq(r15, Immediate(id));
1388 __ Move(r8, Smi::FromInt(result));
1389 __ SmiMod(r9, rcx, r14, exit);
1393 __ j(not_equal, exit);
1397 __ j(not_equal, exit);
1400 __ SmiMod(rcx, rcx, r14, exit);
1404 __ j(not_equal, exit);
1407 __ movq(r15, Immediate(id + 8));
1409 Label fail_ok, fail_ok2;
1410 __ SmiMod(r9, rcx, r14, &fail_ok);
1416 __ j(not_equal, exit);
1419 __ SmiMod(rcx, rcx, r14, &fail_ok2);
1425 __ j(not_equal, exit);
1431 // Allocate an executable page of memory.
1433 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1434 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1436 Isolate* isolate = CcTest::i_isolate();
1437 HandleScope handles(isolate);
1438 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1440 MacroAssembler* masm = &assembler;
1446 TestSmiMod(masm, &exit, 0x10, 1, 1);
1447 TestSmiMod(masm, &exit, 0x20, 1, 0);
1448 TestSmiMod(masm, &exit, 0x30, -1, 0);
1449 TestSmiMod(masm, &exit, 0x40, 0, 1);
1450 TestSmiMod(masm, &exit, 0x50, 0, -1);
1451 TestSmiMod(masm, &exit, 0x60, 4, 2);
1452 TestSmiMod(masm, &exit, 0x70, -4, 2);
1453 TestSmiMod(masm, &exit, 0x80, 4, -2);
1454 TestSmiMod(masm, &exit, 0x90, -4, -2);
1455 TestSmiMod(masm, &exit, 0xa0, 3, 2);
1456 TestSmiMod(masm, &exit, 0xb0, 3, 4);
1457 TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1458 TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1459 TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1460 TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1461 TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1462 TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
1463 TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
1464 TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1465 TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
1467 __ xorq(r15, r15); // Success.
1476 masm->GetCode(&desc);
1477 // Call the function from C++.
1478 int result = FUNCTION_CAST<F0>(buffer)();
1479 CHECK_EQ(0, result);
1483 void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
1484 __ movl(rax, Immediate(id));
1486 for (int i = 0; i < 8; i++) {
1487 __ Move(rcx, Smi::FromInt(x));
1488 SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
1489 DCHECK(index.reg.is(rcx) || index.reg.is(rdx));
1490 __ shlq(index.reg, Immediate(index.scale));
1491 __ Set(r8, static_cast<intptr_t>(x) << i);
1492 __ cmpq(index.reg, r8);
1493 __ j(not_equal, exit);
1495 __ Move(rcx, Smi::FromInt(x));
1496 index = masm->SmiToIndex(rcx, rcx, i);
1497 DCHECK(index.reg.is(rcx));
1498 __ shlq(rcx, Immediate(index.scale));
1499 __ Set(r8, static_cast<intptr_t>(x) << i);
1501 __ j(not_equal, exit);
1504 __ Move(rcx, Smi::FromInt(x));
1505 index = masm->SmiToNegativeIndex(rdx, rcx, i);
1506 DCHECK(index.reg.is(rcx) || index.reg.is(rdx));
1507 __ shlq(index.reg, Immediate(index.scale));
1508 __ Set(r8, static_cast<intptr_t>(-x) << i);
1509 __ cmpq(index.reg, r8);
1510 __ j(not_equal, exit);
1512 __ Move(rcx, Smi::FromInt(x));
1513 index = masm->SmiToNegativeIndex(rcx, rcx, i);
1514 DCHECK(index.reg.is(rcx));
1515 __ shlq(rcx, Immediate(index.scale));
1516 __ Set(r8, static_cast<intptr_t>(-x) << i);
1518 __ j(not_equal, exit);
1525 // Allocate an executable page of memory.
1527 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1528 Assembler::kMinimalBufferSize * 5, &actual_size, true));
1530 Isolate* isolate = CcTest::i_isolate();
1531 HandleScope handles(isolate);
1532 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1534 MacroAssembler* masm = &assembler;
1538 TestSmiIndex(masm, &exit, 0x10, 0);
1539 TestSmiIndex(masm, &exit, 0x20, 1);
1540 TestSmiIndex(masm, &exit, 0x30, 100);
1541 TestSmiIndex(masm, &exit, 0x40, 1000);
1542 TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
1544 __ xorq(rax, rax); // Success.
1550 masm->GetCode(&desc);
1551 // Call the function from C++.
1552 int result = FUNCTION_CAST<F0>(buffer)();
1553 CHECK_EQ(0, result);
1557 void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1558 __ movl(rax, Immediate(id));
1559 __ Move(rcx, Smi::FromInt(x));
1560 __ Move(rdx, Smi::FromInt(y));
1561 __ xorq(rdx, Immediate(kSmiTagMask));
1562 __ SelectNonSmi(r9, rcx, rdx, exit);
1566 __ j(not_equal, exit);
1569 __ Move(rcx, Smi::FromInt(x));
1570 __ Move(rdx, Smi::FromInt(y));
1571 __ xorq(rcx, Immediate(kSmiTagMask));
1572 __ SelectNonSmi(r9, rcx, rdx, exit);
1576 __ j(not_equal, exit);
1580 __ Move(rcx, Smi::FromInt(x));
1581 __ Move(rdx, Smi::FromInt(y));
1582 __ xorq(rcx, Immediate(kSmiTagMask));
1583 __ xorq(rdx, Immediate(kSmiTagMask));
1584 __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
1590 TEST(SmiSelectNonSmi) {
1591 // Allocate an executable page of memory.
1593 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1594 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1596 Isolate* isolate = CcTest::i_isolate();
1597 HandleScope handles(isolate);
1598 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1600 MacroAssembler* masm = &assembler;
1604 TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
1605 TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
1606 TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
1607 TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
1608 TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
1609 TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
1610 TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
1611 TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1612 TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1614 __ xorq(rax, rax); // Success.
1620 masm->GetCode(&desc);
1621 // Call the function from C++.
1622 int result = FUNCTION_CAST<F0>(buffer)();
1623 CHECK_EQ(0, result);
1627 void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1630 __ movl(rax, Immediate(id));
1632 __ Move(rcx, Smi::FromInt(x));
1634 __ Move(rdx, Smi::FromInt(y));
1635 __ Move(r8, Smi::FromInt(result));
1636 __ SmiAnd(r9, rcx, rdx);
1638 __ j(not_equal, exit);
1642 __ j(not_equal, exit);
1645 __ SmiAnd(rcx, rcx, rdx);
1647 __ j(not_equal, exit);
1651 __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
1653 __ j(not_equal, exit);
1657 __ j(not_equal, exit);
1660 __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
1662 __ j(not_equal, exit);
1667 // Allocate an executable page of memory.
1669 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1670 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1672 Isolate* isolate = CcTest::i_isolate();
1673 HandleScope handles(isolate);
1674 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1676 MacroAssembler* masm = &assembler;
1680 TestSmiAnd(masm, &exit, 0x10, 0, 0);
1681 TestSmiAnd(masm, &exit, 0x20, 0, 1);
1682 TestSmiAnd(masm, &exit, 0x30, 1, 0);
1683 TestSmiAnd(masm, &exit, 0x40, 0, -1);
1684 TestSmiAnd(masm, &exit, 0x50, -1, 0);
1685 TestSmiAnd(masm, &exit, 0x60, -1, -1);
1686 TestSmiAnd(masm, &exit, 0x70, 1, 1);
1687 TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1688 TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1689 TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
1690 TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
1692 __ xorq(rax, rax); // Success.
1698 masm->GetCode(&desc);
1699 // Call the function from C++.
1700 int result = FUNCTION_CAST<F0>(buffer)();
1701 CHECK_EQ(0, result);
1705 void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1708 __ movl(rax, Immediate(id));
1710 __ Move(rcx, Smi::FromInt(x));
1712 __ Move(rdx, Smi::FromInt(y));
1713 __ Move(r8, Smi::FromInt(result));
1714 __ SmiOr(r9, rcx, rdx);
1716 __ j(not_equal, exit);
1720 __ j(not_equal, exit);
1723 __ SmiOr(rcx, rcx, rdx);
1725 __ j(not_equal, exit);
1729 __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
1731 __ j(not_equal, exit);
1735 __ j(not_equal, exit);
1738 __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
1740 __ j(not_equal, exit);
1745 // Allocate an executable page of memory.
1747 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1748 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1750 Isolate* isolate = CcTest::i_isolate();
1751 HandleScope handles(isolate);
1752 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1754 MacroAssembler* masm = &assembler;
1758 TestSmiOr(masm, &exit, 0x10, 0, 0);
1759 TestSmiOr(masm, &exit, 0x20, 0, 1);
1760 TestSmiOr(masm, &exit, 0x30, 1, 0);
1761 TestSmiOr(masm, &exit, 0x40, 0, -1);
1762 TestSmiOr(masm, &exit, 0x50, -1, 0);
1763 TestSmiOr(masm, &exit, 0x60, -1, -1);
1764 TestSmiOr(masm, &exit, 0x70, 1, 1);
1765 TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1766 TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1767 TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
1768 TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
1769 TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
1770 TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
1772 __ xorq(rax, rax); // Success.
1778 masm->GetCode(&desc);
1779 // Call the function from C++.
1780 int result = FUNCTION_CAST<F0>(buffer)();
1781 CHECK_EQ(0, result);
1785 void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1788 __ movl(rax, Immediate(id));
1790 __ Move(rcx, Smi::FromInt(x));
1792 __ Move(rdx, Smi::FromInt(y));
1793 __ Move(r8, Smi::FromInt(result));
1794 __ SmiXor(r9, rcx, rdx);
1796 __ j(not_equal, exit);
1800 __ j(not_equal, exit);
1803 __ SmiXor(rcx, rcx, rdx);
1805 __ j(not_equal, exit);
1809 __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
1811 __ j(not_equal, exit);
1815 __ j(not_equal, exit);
1818 __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
1820 __ j(not_equal, exit);
1825 // Allocate an executable page of memory.
1827 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1828 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1830 Isolate* isolate = CcTest::i_isolate();
1831 HandleScope handles(isolate);
1832 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1834 MacroAssembler* masm = &assembler;
1838 TestSmiXor(masm, &exit, 0x10, 0, 0);
1839 TestSmiXor(masm, &exit, 0x20, 0, 1);
1840 TestSmiXor(masm, &exit, 0x30, 1, 0);
1841 TestSmiXor(masm, &exit, 0x40, 0, -1);
1842 TestSmiXor(masm, &exit, 0x50, -1, 0);
1843 TestSmiXor(masm, &exit, 0x60, -1, -1);
1844 TestSmiXor(masm, &exit, 0x70, 1, 1);
1845 TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1846 TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1847 TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
1848 TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
1849 TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
1850 TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
1852 __ xorq(rax, rax); // Success.
1858 masm->GetCode(&desc);
1859 // Call the function from C++.
1860 int result = FUNCTION_CAST<F0>(buffer)();
1861 CHECK_EQ(0, result);
1865 void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
1867 __ movl(rax, Immediate(id));
1869 __ Move(r8, Smi::FromInt(result));
1870 __ Move(rcx, Smi::FromInt(x));
1875 __ j(not_equal, exit);
1879 __ j(not_equal, exit);
1882 __ SmiNot(rcx, rcx);
1884 __ j(not_equal, exit);
1889 // Allocate an executable page of memory.
1891 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1892 Assembler::kMinimalBufferSize, &actual_size, true));
1894 Isolate* isolate = CcTest::i_isolate();
1895 HandleScope handles(isolate);
1896 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1898 MacroAssembler* masm = &assembler;
1902 TestSmiNot(masm, &exit, 0x10, 0);
1903 TestSmiNot(masm, &exit, 0x20, 1);
1904 TestSmiNot(masm, &exit, 0x30, -1);
1905 TestSmiNot(masm, &exit, 0x40, 127);
1906 TestSmiNot(masm, &exit, 0x50, 65535);
1907 TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
1908 TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
1909 TestSmiNot(masm, &exit, 0x80, 0x05555555);
1911 __ xorq(rax, rax); // Success.
1917 masm->GetCode(&desc);
1918 // Call the function from C++.
1919 int result = FUNCTION_CAST<F0>(buffer)();
1920 CHECK_EQ(0, result);
1924 void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
1925 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1926 const int kNumShifts = 5;
1927 __ movl(rax, Immediate(id));
1928 for (int i = 0; i < kNumShifts; i++) {
1929 // rax == id + i * 10.
1930 int shift = shifts[i];
1931 int result = x << shift;
1932 CHECK(Smi::IsValid(result));
1933 __ Move(r8, Smi::FromInt(result));
1934 __ Move(rcx, Smi::FromInt(x));
1935 __ SmiShiftLeftConstant(r9, rcx, shift);
1939 __ j(not_equal, exit);
1942 __ Move(rcx, Smi::FromInt(x));
1943 __ SmiShiftLeftConstant(rcx, rcx, shift);
1947 __ j(not_equal, exit);
1950 __ Move(rdx, Smi::FromInt(x));
1951 __ Move(rcx, Smi::FromInt(shift));
1952 __ SmiShiftLeft(r9, rdx, rcx);
1956 __ j(not_equal, exit);
1959 __ Move(rdx, Smi::FromInt(x));
1960 __ Move(r11, Smi::FromInt(shift));
1961 __ SmiShiftLeft(r9, rdx, r11);
1965 __ j(not_equal, exit);
1968 __ Move(rdx, Smi::FromInt(x));
1969 __ Move(r11, Smi::FromInt(shift));
1970 __ SmiShiftLeft(rdx, rdx, r11);
1974 __ j(not_equal, exit);
1981 TEST(SmiShiftLeft) {
1982 // Allocate an executable page of memory.
1984 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1985 Assembler::kMinimalBufferSize * 7, &actual_size, true));
1987 Isolate* isolate = CcTest::i_isolate();
1988 HandleScope handles(isolate);
1989 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1991 MacroAssembler* masm = &assembler;
1995 TestSmiShiftLeft(masm, &exit, 0x10, 0);
1996 TestSmiShiftLeft(masm, &exit, 0x50, 1);
1997 TestSmiShiftLeft(masm, &exit, 0x90, 127);
1998 TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
1999 TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
2000 TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
2001 TestSmiShiftLeft(masm, &exit, 0x190, -1);
2003 __ xorq(rax, rax); // Success.
2009 masm->GetCode(&desc);
2010 // Call the function from C++.
2011 int result = FUNCTION_CAST<F0>(buffer)();
2012 CHECK_EQ(0, result);
2016 void TestSmiShiftLogicalRight(MacroAssembler* masm,
2020 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2021 const int kNumShifts = 5;
2022 __ movl(rax, Immediate(id));
2023 for (int i = 0; i < kNumShifts; i++) {
2024 int shift = shifts[i];
2025 intptr_t result = static_cast<unsigned int>(x) >> shift;
2026 if (Smi::IsValid(result)) {
2027 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
2028 __ Move(rcx, Smi::FromInt(x));
2029 __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
2033 __ j(not_equal, exit);
2036 __ Move(rdx, Smi::FromInt(x));
2037 __ Move(rcx, Smi::FromInt(shift));
2038 __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
2042 __ j(not_equal, exit);
2045 __ Move(rdx, Smi::FromInt(x));
2046 __ Move(r11, Smi::FromInt(shift));
2047 __ SmiShiftLogicalRight(r9, rdx, r11, exit);
2051 __ j(not_equal, exit);
2055 // Cannot happen with long smis.
2057 __ Move(rcx, Smi::FromInt(x));
2059 __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
2065 __ j(not_equal, exit);
2068 __ Move(r8, Smi::FromInt(shift));
2070 __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
2076 __ j(not_equal, exit);
2078 __ addq(rax, Immediate(3));
2084 TEST(SmiShiftLogicalRight) {
2085 // Allocate an executable page of memory.
2087 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2088 Assembler::kMinimalBufferSize * 5, &actual_size, true));
2090 Isolate* isolate = CcTest::i_isolate();
2091 HandleScope handles(isolate);
2092 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2094 MacroAssembler* masm = &assembler;
2098 TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
2099 TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
2100 TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
2101 TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
2102 TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
2103 TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
2104 TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
2106 __ xorq(rax, rax); // Success.
2112 masm->GetCode(&desc);
2113 // Call the function from C++.
2114 int result = FUNCTION_CAST<F0>(buffer)();
2115 CHECK_EQ(0, result);
2119 void TestSmiShiftArithmeticRight(MacroAssembler* masm,
2123 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2124 const int kNumShifts = 5;
2125 __ movl(rax, Immediate(id));
2126 for (int i = 0; i < kNumShifts; i++) {
2127 int shift = shifts[i];
2128 // Guaranteed arithmetic shift.
2129 int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
2130 __ Move(r8, Smi::FromInt(result));
2131 __ Move(rcx, Smi::FromInt(x));
2132 __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
2135 __ j(not_equal, exit);
2138 __ Move(rdx, Smi::FromInt(x));
2139 __ Move(r11, Smi::FromInt(shift));
2140 __ SmiShiftArithmeticRight(rdx, rdx, r11);
2143 __ j(not_equal, exit);
2150 TEST(SmiShiftArithmeticRight) {
2151 // Allocate an executable page of memory.
2153 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2154 Assembler::kMinimalBufferSize * 3, &actual_size, true));
2156 Isolate* isolate = CcTest::i_isolate();
2157 HandleScope handles(isolate);
2158 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2160 MacroAssembler* masm = &assembler;
2164 TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
2165 TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
2166 TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
2167 TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
2168 TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
2169 TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
2170 TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
2172 __ xorq(rax, rax); // Success.
2178 masm->GetCode(&desc);
2179 // Call the function from C++.
2180 int result = FUNCTION_CAST<F0>(buffer)();
2181 CHECK_EQ(0, result);
2185 void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
2187 int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
2188 int power_count = 8;
2189 __ movl(rax, Immediate(id));
2190 for (int i = 0; i < power_count; i++) {
2191 int power = powers[i];
2192 intptr_t result = static_cast<intptr_t>(x) << power;
2194 __ Move(rcx, Smi::FromInt(x));
2196 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
2198 __ j(not_equal, exit);
2200 __ cmpq(r11, rcx); // rcx unchanged.
2201 __ j(not_equal, exit);
2203 __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
2205 __ j(not_equal, exit);
2211 TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
2212 // Allocate an executable page of memory.
2214 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2215 Assembler::kMinimalBufferSize * 4, &actual_size, true));
2217 Isolate* isolate = CcTest::i_isolate();
2218 HandleScope handles(isolate);
2219 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2221 MacroAssembler* masm = &assembler;
2225 TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
2226 TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
2227 TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
2228 TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
2229 TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
2230 TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
2231 TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
2232 TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
2233 TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
2235 __ xorq(rax, rax); // Success.
2241 masm->GetCode(&desc);
2242 // Call the function from C++.
2243 int result = FUNCTION_CAST<F0>(buffer)();
2244 CHECK_EQ(0, result);
2248 TEST(OperandOffset) {
2250 for (uint32_t i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
2252 // Allocate an executable page of memory.
2254 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2255 Assembler::kMinimalBufferSize * 2, &actual_size, true));
2257 Isolate* isolate = CcTest::i_isolate();
2258 HandleScope handles(isolate);
2259 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2261 MacroAssembler* masm = &assembler;
2269 __ pushq(Immediate(0x100)); // <-- rbp
2271 __ pushq(Immediate(0x101));
2272 __ pushq(Immediate(0x102));
2273 __ pushq(Immediate(0x103));
2274 __ pushq(Immediate(0x104));
2275 __ pushq(Immediate(0x105)); // <-- rbx
2276 __ pushq(Immediate(0x106));
2277 __ pushq(Immediate(0x107));
2278 __ pushq(Immediate(0x108));
2279 __ pushq(Immediate(0x109)); // <-- rsp
2284 __ leaq(r14, Operand(rsp, 3 * kPointerSize));
2285 __ leaq(r13, Operand(rbp, -3 * kPointerSize));
2286 __ leaq(rbx, Operand(rbp, -5 * kPointerSize));
2287 __ movl(rcx, Immediate(2));
2288 __ Move(r8, reinterpret_cast<Address>(&data[128]), RelocInfo::NONE64);
2289 __ movl(rax, Immediate(1));
2291 Operand sp0 = Operand(rsp, 0);
2294 __ movl(rdx, sp0); // Sanity check.
2295 __ cmpl(rdx, Immediate(0x109));
2296 __ j(not_equal, &exit);
2300 // Zero to non-zero displacement.
2301 __ movl(rdx, Operand(sp0, 2 * kPointerSize));
2302 __ cmpl(rdx, Immediate(0x107));
2303 __ j(not_equal, &exit);
2306 Operand sp2 = Operand(rsp, 2 * kPointerSize);
2309 __ movl(rdx, sp2); // Sanity check.
2310 __ cmpl(rdx, Immediate(0x107));
2311 __ j(not_equal, &exit);
2314 __ movl(rdx, Operand(sp2, 2 * kPointerSize));
2315 __ cmpl(rdx, Immediate(0x105));
2316 __ j(not_equal, &exit);
2319 // Non-zero to zero displacement.
2320 __ movl(rdx, Operand(sp2, -2 * kPointerSize));
2321 __ cmpl(rdx, Immediate(0x109));
2322 __ j(not_equal, &exit);
2325 Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
2328 __ movl(rdx, sp2c2); // Sanity check.
2329 __ cmpl(rdx, Immediate(0x105));
2330 __ j(not_equal, &exit);
2333 __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
2334 __ cmpl(rdx, Immediate(0x103));
2335 __ j(not_equal, &exit);
2338 // Non-zero to zero displacement.
2339 __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
2340 __ cmpl(rdx, Immediate(0x107));
2341 __ j(not_equal, &exit);
2345 Operand bp0 = Operand(rbp, 0);
2348 __ movl(rdx, bp0); // Sanity check.
2349 __ cmpl(rdx, Immediate(0x100));
2350 __ j(not_equal, &exit);
2353 // Zero to non-zero displacement.
2354 __ movl(rdx, Operand(bp0, -2 * kPointerSize));
2355 __ cmpl(rdx, Immediate(0x102));
2356 __ j(not_equal, &exit);
2359 Operand bp2 = Operand(rbp, -2 * kPointerSize);
2362 __ movl(rdx, bp2); // Sanity check.
2363 __ cmpl(rdx, Immediate(0x102));
2364 __ j(not_equal, &exit);
2367 // Non-zero to zero displacement.
2368 __ movl(rdx, Operand(bp2, 2 * kPointerSize));
2369 __ cmpl(rdx, Immediate(0x100));
2370 __ j(not_equal, &exit);
2373 __ movl(rdx, Operand(bp2, -2 * kPointerSize));
2374 __ cmpl(rdx, Immediate(0x104));
2375 __ j(not_equal, &exit);
2378 Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
2381 __ movl(rdx, bp2c4); // Sanity check.
2382 __ cmpl(rdx, Immediate(0x102));
2383 __ j(not_equal, &exit);
2386 __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
2387 __ cmpl(rdx, Immediate(0x100));
2388 __ j(not_equal, &exit);
2391 __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
2392 __ cmpl(rdx, Immediate(0x104));
2393 __ j(not_equal, &exit);
2396 Operand bx0 = Operand(rbx, 0);
2399 __ movl(rdx, bx0); // Sanity check.
2400 __ cmpl(rdx, Immediate(0x105));
2401 __ j(not_equal, &exit);
2404 __ movl(rdx, Operand(bx0, 5 * kPointerSize));
2405 __ cmpl(rdx, Immediate(0x100));
2406 __ j(not_equal, &exit);
2409 __ movl(rdx, Operand(bx0, -4 * kPointerSize));
2410 __ cmpl(rdx, Immediate(0x109));
2411 __ j(not_equal, &exit);
2414 Operand bx2 = Operand(rbx, 2 * kPointerSize);
2417 __ movl(rdx, bx2); // Sanity check.
2418 __ cmpl(rdx, Immediate(0x103));
2419 __ j(not_equal, &exit);
2422 __ movl(rdx, Operand(bx2, 2 * kPointerSize));
2423 __ cmpl(rdx, Immediate(0x101));
2424 __ j(not_equal, &exit);
2427 // Non-zero to zero displacement.
2428 __ movl(rdx, Operand(bx2, -2 * kPointerSize));
2429 __ cmpl(rdx, Immediate(0x105));
2430 __ j(not_equal, &exit);
2433 Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
2436 __ movl(rdx, bx2c2); // Sanity check.
2437 __ cmpl(rdx, Immediate(0x105));
2438 __ j(not_equal, &exit);
2441 __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
2442 __ cmpl(rdx, Immediate(0x103));
2443 __ j(not_equal, &exit);
2446 __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
2447 __ cmpl(rdx, Immediate(0x107));
2448 __ j(not_equal, &exit);
2451 Operand r80 = Operand(r8, 0);
2454 __ movl(rdx, r80); // Sanity check.
2455 __ cmpl(rdx, Immediate(0x80808080));
2456 __ j(not_equal, &exit);
2459 __ movl(rdx, Operand(r80, -8 * kIntSize));
2460 __ cmpl(rdx, Immediate(0x78787878));
2461 __ j(not_equal, &exit);
2464 __ movl(rdx, Operand(r80, 8 * kIntSize));
2465 __ cmpl(rdx, Immediate(0x88888888));
2466 __ j(not_equal, &exit);
2469 __ movl(rdx, Operand(r80, -64 * kIntSize));
2470 __ cmpl(rdx, Immediate(0x40404040));
2471 __ j(not_equal, &exit);
2474 __ movl(rdx, Operand(r80, 64 * kIntSize));
2475 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2476 __ j(not_equal, &exit);
2479 Operand r88 = Operand(r8, 8 * kIntSize);
2482 __ movl(rdx, r88); // Sanity check.
2483 __ cmpl(rdx, Immediate(0x88888888));
2484 __ j(not_equal, &exit);
2487 __ movl(rdx, Operand(r88, -8 * kIntSize));
2488 __ cmpl(rdx, Immediate(0x80808080));
2489 __ j(not_equal, &exit);
2492 __ movl(rdx, Operand(r88, 8 * kIntSize));
2493 __ cmpl(rdx, Immediate(0x90909090));
2494 __ j(not_equal, &exit);
2497 __ movl(rdx, Operand(r88, -64 * kIntSize));
2498 __ cmpl(rdx, Immediate(0x48484848));
2499 __ j(not_equal, &exit);
2502 __ movl(rdx, Operand(r88, 64 * kIntSize));
2503 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2504 __ j(not_equal, &exit);
2508 Operand r864 = Operand(r8, 64 * kIntSize);
2511 __ movl(rdx, r864); // Sanity check.
2512 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2513 __ j(not_equal, &exit);
2516 __ movl(rdx, Operand(r864, -8 * kIntSize));
2517 __ cmpl(rdx, Immediate(0xB8B8B8B8));
2518 __ j(not_equal, &exit);
2521 __ movl(rdx, Operand(r864, 8 * kIntSize));
2522 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2523 __ j(not_equal, &exit);
2526 __ movl(rdx, Operand(r864, -64 * kIntSize));
2527 __ cmpl(rdx, Immediate(0x80808080));
2528 __ j(not_equal, &exit);
2531 __ movl(rdx, Operand(r864, 32 * kIntSize));
2532 __ cmpl(rdx, Immediate(0xE0E0E0E0));
2533 __ j(not_equal, &exit);
2536 // 32-bit offset to 8-bit offset.
2537 __ movl(rdx, Operand(r864, -60 * kIntSize));
2538 __ cmpl(rdx, Immediate(0x84848484));
2539 __ j(not_equal, &exit);
2542 __ movl(rdx, Operand(r864, 60 * kIntSize));
2543 __ cmpl(rdx, Immediate(0xFCFCFCFC));
2544 __ j(not_equal, &exit);
2547 // Test unaligned offsets.
2550 __ movl(rdx, Operand(r80, 2));
2551 __ cmpl(rdx, Immediate(0x81818080));
2552 __ j(not_equal, &exit);
2555 __ movl(rdx, Operand(r80, -2));
2556 __ cmpl(rdx, Immediate(0x80807F7F));
2557 __ j(not_equal, &exit);
2560 __ movl(rdx, Operand(r80, 126));
2561 __ cmpl(rdx, Immediate(0xA0A09F9F));
2562 __ j(not_equal, &exit);
2565 __ movl(rdx, Operand(r80, -126));
2566 __ cmpl(rdx, Immediate(0x61616060));
2567 __ j(not_equal, &exit);
2570 __ movl(rdx, Operand(r80, 254));
2571 __ cmpl(rdx, Immediate(0xC0C0BFBF));
2572 __ j(not_equal, &exit);
2575 __ movl(rdx, Operand(r80, -254));
2576 __ cmpl(rdx, Immediate(0x41414040));
2577 __ j(not_equal, &exit);
2582 __ movl(rax, Immediate(0));
2584 __ leaq(rsp, Operand(rbp, kPointerSize));
2594 masm->GetCode(&desc);
2595 // Call the function from C++.
2596 int result = FUNCTION_CAST<F0>(buffer)();
2597 CHECK_EQ(0, result);
2601 TEST(LoadAndStoreWithRepresentation) {
2602 // Allocate an executable page of memory.
2604 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2605 Assembler::kMinimalBufferSize, &actual_size, true));
2607 Isolate* isolate = CcTest::i_isolate();
2608 HandleScope handles(isolate);
2609 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2610 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
2612 __ subq(rsp, Immediate(1 * kPointerSize));
2616 __ movq(rax, Immediate(1)); // Test number.
2617 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2618 __ movq(rcx, Immediate(-1));
2619 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger8());
2620 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2621 __ movl(rdx, Immediate(255));
2623 __ j(not_equal, &exit);
2624 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger8());
2626 __ j(not_equal, &exit);
2629 __ movq(rax, Immediate(2)); // Test number.
2630 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2631 __ Set(rcx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2632 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Smi());
2633 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2634 __ Set(rdx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2636 __ j(not_equal, &exit);
2637 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Smi());
2639 __ j(not_equal, &exit);
2642 __ movq(rax, Immediate(3)); // Test number.
2643 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2644 __ movq(rcx, Immediate(-1));
2645 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer32());
2646 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2647 __ movl(rdx, Immediate(-1));
2649 __ j(not_equal, &exit);
2650 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer32());
2652 __ j(not_equal, &exit);
2655 __ movq(rax, Immediate(4)); // Test number.
2656 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2657 __ movl(rcx, Immediate(0x44332211));
2658 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::HeapObject());
2659 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2660 __ movl(rdx, Immediate(0x44332211));
2662 __ j(not_equal, &exit);
2663 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::HeapObject());
2665 __ j(not_equal, &exit);
2668 __ movq(rax, Immediate(5)); // Test number.
2669 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2670 __ Set(rcx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2671 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Tagged());
2672 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2673 __ Set(rdx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2675 __ j(not_equal, &exit);
2676 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Tagged());
2678 __ j(not_equal, &exit);
2681 __ movq(rax, Immediate(6)); // Test number.
2682 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2683 __ Set(rcx, V8_2PART_UINT64_C(0x11223344, 55667788));
2684 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::External());
2685 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2686 __ Set(rdx, V8_2PART_UINT64_C(0x11223344, 55667788));
2688 __ j(not_equal, &exit);
2689 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::External());
2691 __ j(not_equal, &exit);
2694 __ movq(rax, Immediate(7)); // Test number.
2695 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2696 __ movq(rcx, Immediate(-1));
2697 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer8());
2698 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2699 __ movl(rdx, Immediate(255));
2701 __ j(not_equal, &exit);
2702 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer8());
2703 __ movq(rcx, Immediate(-1));
2705 __ j(not_equal, &exit);
2708 __ movq(rax, Immediate(8)); // Test number.
2709 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2710 __ movq(rcx, Immediate(-1));
2711 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer16());
2712 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2713 __ movl(rdx, Immediate(65535));
2715 __ j(not_equal, &exit);
2716 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer16());
2717 __ movq(rcx, Immediate(-1));
2719 __ j(not_equal, &exit);
2722 __ movq(rax, Immediate(9)); // Test number.
2723 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2724 __ movq(rcx, Immediate(-1));
2725 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger16());
2726 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2727 __ movl(rdx, Immediate(65535));
2729 __ j(not_equal, &exit);
2730 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger16());
2732 __ j(not_equal, &exit);
2734 __ xorq(rax, rax); // Success.
2736 __ addq(rsp, Immediate(1 * kPointerSize));
2741 masm->GetCode(&desc);
2742 // Call the function from C++.
2743 int result = FUNCTION_CAST<F0>(buffer)();
2744 CHECK_EQ(0, result);