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 "macro-assembler.h"
35 #include "serialize.h"
38 namespace i = v8::internal;
43 using i::FUNCTION_CAST;
48 using i::MacroAssembler;
52 using i::Representation;
58 using i::greater_equal;
60 using i::kPointerSize;
62 using i::kSmiValueSize;
84 using i::times_pointer_size;
86 // Test the x64 assembler by compiling some simple functions into
87 // a buffer and executing them. These tests do not initialize the
88 // V8 library, create a context, or use any V8 objects.
89 // The AMD64 calling convention is used, with the first five arguments
90 // in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
91 // the XMM registers. The return value is in RAX.
92 // This calling convention is used on Linux, with GCC, and on Mac OS,
93 // with GCC. A different convention is used on 64-bit windows.
100 static void EntryCode(MacroAssembler* masm) {
101 // Smi constant register is callee save.
102 __ push(i::kSmiConstantRegister);
103 __ push(i::kRootRegister);
104 __ InitializeSmiConstantRegister();
105 __ InitializeRootRegister();
109 static void ExitCode(MacroAssembler* masm) {
110 // Return -1 if kSmiConstantRegister was clobbered during the test.
111 __ Move(rdx, Smi::FromInt(1));
112 __ cmpq(rdx, i::kSmiConstantRegister);
113 __ movq(rdx, Immediate(-1));
114 __ cmovq(not_equal, rax, rdx);
115 __ pop(i::kRootRegister);
116 __ pop(i::kSmiConstantRegister);
121 // Check that C++ Smi operations work as expected.
122 int64_t test_numbers[] = {
123 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
124 Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
125 Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
127 int test_number_count = 15;
128 for (int i = 0; i < test_number_count; i++) {
129 int64_t number = test_numbers[i];
130 bool is_valid = Smi::IsValid(number);
131 bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
132 CHECK_EQ(is_in_range, is_valid);
134 Smi* smi_from_intptr = Smi::FromIntptr(number);
135 if (static_cast<int>(number) == number) { // Is a 32-bit int.
136 Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
137 CHECK_EQ(smi_from_int, smi_from_intptr);
139 int64_t smi_value = smi_from_intptr->value();
140 CHECK_EQ(number, smi_value);
146 static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
147 __ movl(rax, Immediate(id));
149 __ Set(rdx, reinterpret_cast<intptr_t>(value));
151 __ j(not_equal, exit);
155 // Test that we can move a Smi value literally into a register.
157 i::V8::Initialize(NULL);
158 // Allocate an executable page of memory.
160 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
164 Isolate* isolate = CcTest::i_isolate();
165 HandleScope handles(isolate);
166 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
167 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
171 TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
172 TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
173 TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
174 TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
175 TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
176 TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
177 TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
178 TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
179 TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
180 TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
181 TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
182 TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
184 __ xor_(rax, rax); // Success.
190 masm->GetCode(&desc);
191 // Call the function from C++.
192 int result = FUNCTION_CAST<F0>(buffer)();
197 void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
198 __ Move(rcx, Smi::FromInt(x));
200 __ Move(rdx, Smi::FromInt(y));
202 __ SmiCompare(rcx, rdx);
204 __ movl(rax, Immediate(id + 1));
205 __ j(greater_equal, exit);
207 __ movl(rax, Immediate(id + 2));
208 __ j(less_equal, exit);
211 __ movl(rax, Immediate(id + 3));
212 __ j(not_equal, exit);
214 __ movl(rax, Immediate(id + 4));
216 __ j(not_equal, exit);
219 __ j(not_equal, exit);
222 __ SmiCompare(rdx, rcx);
224 __ movl(rax, Immediate(id + 9));
225 __ j(greater_equal, exit);
228 __ movl(rax, Immediate(id + 10));
229 __ j(less_equal, exit);
233 __ movl(rax, Immediate(id + 11));
234 __ j(not_equal, exit);
237 __ j(not_equal, exit);
242 // Test that we can compare smis for equality (and more).
244 i::V8::Initialize(NULL);
245 // Allocate an executable page of memory.
248 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
252 Isolate* isolate = CcTest::i_isolate();
253 HandleScope handles(isolate);
254 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
256 MacroAssembler* masm = &assembler;
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);
280 __ xor_(rax, rax); // Success.
286 masm->GetCode(&desc);
287 // Call the function from C++.
288 int result = FUNCTION_CAST<F0>(buffer)();
294 TEST(Integer32ToSmi) {
295 i::V8::Initialize(NULL);
296 // Allocate an executable page of memory.
298 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
302 Isolate* isolate = CcTest::i_isolate();
303 HandleScope handles(isolate);
304 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
306 MacroAssembler* masm = &assembler;
310 __ movq(rax, Immediate(1)); // Test number.
311 __ movl(rcx, Immediate(0));
312 __ Integer32ToSmi(rcx, rcx);
313 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
315 __ j(not_equal, &exit);
317 __ movq(rax, Immediate(2)); // Test number.
318 __ movl(rcx, Immediate(1024));
319 __ Integer32ToSmi(rcx, rcx);
320 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
322 __ j(not_equal, &exit);
324 __ movq(rax, Immediate(3)); // Test number.
325 __ movl(rcx, Immediate(-1));
326 __ Integer32ToSmi(rcx, rcx);
327 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
329 __ j(not_equal, &exit);
331 __ movq(rax, Immediate(4)); // Test number.
332 __ movl(rcx, Immediate(Smi::kMaxValue));
333 __ Integer32ToSmi(rcx, rcx);
334 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
336 __ j(not_equal, &exit);
338 __ movq(rax, Immediate(5)); // Test number.
339 __ movl(rcx, Immediate(Smi::kMinValue));
340 __ Integer32ToSmi(rcx, rcx);
341 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
343 __ j(not_equal, &exit);
345 // Different target register.
347 __ movq(rax, Immediate(6)); // Test number.
348 __ movl(rcx, Immediate(0));
349 __ Integer32ToSmi(r8, rcx);
350 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
352 __ j(not_equal, &exit);
354 __ movq(rax, Immediate(7)); // Test number.
355 __ movl(rcx, Immediate(1024));
356 __ Integer32ToSmi(r8, rcx);
357 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
359 __ j(not_equal, &exit);
361 __ movq(rax, Immediate(8)); // Test number.
362 __ movl(rcx, Immediate(-1));
363 __ Integer32ToSmi(r8, rcx);
364 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
366 __ j(not_equal, &exit);
368 __ movq(rax, Immediate(9)); // Test number.
369 __ movl(rcx, Immediate(Smi::kMaxValue));
370 __ Integer32ToSmi(r8, rcx);
371 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
373 __ j(not_equal, &exit);
375 __ movq(rax, Immediate(10)); // Test number.
376 __ movl(rcx, Immediate(Smi::kMinValue));
377 __ Integer32ToSmi(r8, rcx);
378 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
380 __ j(not_equal, &exit);
383 __ xor_(rax, rax); // Success.
389 masm->GetCode(&desc);
390 // Call the function from C++.
391 int result = FUNCTION_CAST<F0>(buffer)();
396 void TestI64PlusConstantToSmi(MacroAssembler* masm,
401 int64_t result = x + y;
402 ASSERT(Smi::IsValid(result));
403 __ movl(rax, Immediate(id));
404 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
407 __ Integer64PlusConstantToSmi(rdx, rcx, y);
409 __ j(not_equal, exit);
413 __ j(not_equal, exit);
416 __ Integer64PlusConstantToSmi(rcx, rcx, y);
418 __ j(not_equal, exit);
422 TEST(Integer64PlusConstantToSmi) {
423 i::V8::Initialize(NULL);
424 // Allocate an executable page of memory.
426 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
430 Isolate* isolate = CcTest::i_isolate();
431 HandleScope handles(isolate);
432 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
434 MacroAssembler* masm = &assembler;
438 int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
440 TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
441 TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
442 TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
443 TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
444 TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
445 TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
446 TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
447 TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
448 TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
449 TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
450 TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
451 TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
453 __ xor_(rax, rax); // Success.
459 masm->GetCode(&desc);
460 // Call the function from C++.
461 int result = FUNCTION_CAST<F0>(buffer)();
467 i::V8::Initialize(NULL);
468 // Allocate an executable page of memory.
470 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
474 Isolate* isolate = CcTest::i_isolate();
475 HandleScope handles(isolate);
476 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
478 MacroAssembler* masm = &assembler;
483 __ movl(rax, Immediate(1)); // Test number.
487 __ movl(rcx, Immediate(0));
488 __ Integer32ToSmi(rcx, rcx);
489 cond = masm->CheckSmi(rcx);
490 __ j(NegateCondition(cond), &exit);
493 __ xor_(rcx, Immediate(kSmiTagMask));
494 cond = masm->CheckSmi(rcx);
498 __ movl(rcx, Immediate(-1));
499 __ Integer32ToSmi(rcx, rcx);
500 cond = masm->CheckSmi(rcx);
501 __ j(NegateCondition(cond), &exit);
504 __ xor_(rcx, Immediate(kSmiTagMask));
505 cond = masm->CheckSmi(rcx);
509 __ movl(rcx, Immediate(Smi::kMaxValue));
510 __ Integer32ToSmi(rcx, rcx);
511 cond = masm->CheckSmi(rcx);
512 __ j(NegateCondition(cond), &exit);
515 __ xor_(rcx, Immediate(kSmiTagMask));
516 cond = masm->CheckSmi(rcx);
520 __ movl(rcx, Immediate(Smi::kMinValue));
521 __ Integer32ToSmi(rcx, rcx);
522 cond = masm->CheckSmi(rcx);
523 __ j(NegateCondition(cond), &exit);
526 __ xor_(rcx, Immediate(kSmiTagMask));
527 cond = masm->CheckSmi(rcx);
533 __ movl(rcx, Immediate(0));
534 __ Integer32ToSmi(rcx, rcx);
535 cond = masm->CheckNonNegativeSmi(rcx);
536 __ j(NegateCondition(cond), &exit);
539 __ xor_(rcx, Immediate(kSmiTagMask));
540 cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi.
544 __ movq(rcx, Immediate(-1));
545 __ Integer32ToSmi(rcx, rcx);
546 cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive.
550 __ movq(rcx, Immediate(Smi::kMinValue));
551 __ Integer32ToSmi(rcx, rcx);
552 cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive.
556 __ xor_(rcx, Immediate(kSmiTagMask));
557 cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi.
561 __ movq(rcx, Immediate(Smi::kMaxValue));
562 __ Integer32ToSmi(rcx, rcx);
563 cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive.
564 __ j(NegateCondition(cond), &exit);
567 __ xor_(rcx, Immediate(kSmiTagMask));
568 cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
574 __ movq(rcx, Immediate(Smi::kMaxValue));
575 __ Integer32ToSmi(rcx, rcx);
576 cond = masm->CheckIsMinSmi(rcx);
580 __ movq(rcx, Immediate(0));
581 __ Integer32ToSmi(rcx, rcx);
582 cond = masm->CheckIsMinSmi(rcx);
586 __ movq(rcx, Immediate(Smi::kMinValue));
587 __ Integer32ToSmi(rcx, rcx);
588 cond = masm->CheckIsMinSmi(rcx);
589 __ j(NegateCondition(cond), &exit);
592 __ movq(rcx, Immediate(Smi::kMinValue + 1));
593 __ Integer32ToSmi(rcx, rcx);
594 cond = masm->CheckIsMinSmi(rcx);
600 __ movq(rcx, Immediate(Smi::kMaxValue));
601 __ Integer32ToSmi(rcx, rcx);
602 __ movq(rdx, Immediate(Smi::kMinValue));
603 __ Integer32ToSmi(rdx, rdx);
604 cond = masm->CheckBothSmi(rcx, rdx);
605 __ j(NegateCondition(cond), &exit);
608 __ xor_(rcx, Immediate(kSmiTagMask));
609 cond = masm->CheckBothSmi(rcx, rdx);
613 __ xor_(rdx, Immediate(kSmiTagMask));
614 cond = masm->CheckBothSmi(rcx, rdx);
618 __ xor_(rcx, Immediate(kSmiTagMask));
619 cond = masm->CheckBothSmi(rcx, rdx);
623 cond = masm->CheckBothSmi(rcx, rcx);
624 __ j(NegateCondition(cond), &exit);
627 cond = masm->CheckBothSmi(rdx, rdx);
630 // CheckInteger32ValidSmiValue
632 __ movq(rcx, Immediate(0));
633 cond = masm->CheckInteger32ValidSmiValue(rax);
634 __ j(NegateCondition(cond), &exit);
637 __ movq(rcx, Immediate(-1));
638 cond = masm->CheckInteger32ValidSmiValue(rax);
639 __ j(NegateCondition(cond), &exit);
642 __ movq(rcx, Immediate(Smi::kMaxValue));
643 cond = masm->CheckInteger32ValidSmiValue(rax);
644 __ j(NegateCondition(cond), &exit);
647 __ movq(rcx, Immediate(Smi::kMinValue));
648 cond = masm->CheckInteger32ValidSmiValue(rax);
649 __ j(NegateCondition(cond), &exit);
659 masm->GetCode(&desc);
660 // Call the function from C++.
661 int result = FUNCTION_CAST<F0>(buffer)();
667 void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
668 __ Move(rcx, Smi::FromInt(x));
670 if (x == Smi::kMinValue || x == 0) {
672 __ movl(rax, Immediate(id + 8));
673 __ SmiNeg(r9, rcx, exit);
677 __ j(not_equal, exit);
680 __ SmiNeg(rcx, rcx, exit);
684 __ j(not_equal, exit);
686 Label smi_ok, smi_ok2;
688 __ movl(rax, Immediate(id));
689 __ Move(r8, Smi::FromInt(result));
691 __ SmiNeg(r9, rcx, &smi_ok);
696 __ j(not_equal, exit);
700 __ j(not_equal, exit);
703 __ SmiNeg(rcx, rcx, &smi_ok2);
708 __ j(not_equal, exit);
714 i::V8::Initialize(NULL);
715 // Allocate an executable page of memory.
718 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
722 Isolate* isolate = CcTest::i_isolate();
723 HandleScope handles(isolate);
724 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
726 MacroAssembler* masm = &assembler;
730 TestSmiNeg(masm, &exit, 0x10, 0);
731 TestSmiNeg(masm, &exit, 0x20, 1);
732 TestSmiNeg(masm, &exit, 0x30, -1);
733 TestSmiNeg(masm, &exit, 0x40, 127);
734 TestSmiNeg(masm, &exit, 0x50, 65535);
735 TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
736 TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
737 TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
739 __ xor_(rax, rax); // Success.
745 masm->GetCode(&desc);
746 // Call the function from C++.
747 int result = FUNCTION_CAST<F0>(buffer)();
752 static void SmiAddTest(MacroAssembler* masm,
757 __ movl(rcx, Immediate(first));
758 __ Integer32ToSmi(rcx, rcx);
759 __ movl(rdx, Immediate(second));
760 __ Integer32ToSmi(rdx, rdx);
761 __ movl(r8, Immediate(first + second));
762 __ Integer32ToSmi(r8, r8);
764 __ movl(rax, Immediate(id)); // Test number.
765 __ SmiAdd(r9, rcx, rdx, exit);
767 __ j(not_equal, exit);
770 __ SmiAdd(rcx, rcx, rdx, exit);
772 __ j(not_equal, exit);
774 __ movl(rcx, Immediate(first));
775 __ Integer32ToSmi(rcx, rcx);
778 __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
780 __ j(not_equal, exit);
782 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
784 __ j(not_equal, exit);
786 __ movl(rcx, Immediate(first));
787 __ Integer32ToSmi(rcx, rcx);
789 i::SmiOperationExecutionMode mode;
790 mode.Add(i::PRESERVE_SOURCE_REGISTER);
791 mode.Add(i::BAILOUT_ON_OVERFLOW);
793 __ SmiAddConstant(r9, rcx, Smi::FromInt(second), mode, exit);
795 __ j(not_equal, exit);
798 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
800 __ j(not_equal, exit);
802 __ movl(rcx, Immediate(first));
803 __ Integer32ToSmi(rcx, rcx);
806 mode.Add(i::PRESERVE_SOURCE_REGISTER);
807 mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
810 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
814 __ j(not_equal, exit);
818 static void SmiAddOverflowTest(MacroAssembler* masm,
822 // Adds a Smi to x so that the addition overflows.
823 ASSERT(x != 0); // Can't overflow by adding a Smi.
824 int y_max = (x > 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue - x - 1);
825 int y_min = (x > 0) ? (Smi::kMaxValue - x + 1) : (Smi::kMinValue + 0);
827 __ movl(rax, Immediate(id));
828 __ Move(rcx, Smi::FromInt(x));
829 __ movq(r11, rcx); // Store original Smi value of x in r11.
830 __ Move(rdx, Smi::FromInt(y_min));
833 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
835 __ bind(&overflow_ok);
838 __ j(not_equal, exit);
844 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
846 __ bind(&overflow_ok);
849 __ j(not_equal, exit);
852 i::SmiOperationExecutionMode mode;
853 mode.Add(i::PRESERVE_SOURCE_REGISTER);
854 mode.Add(i::BAILOUT_ON_OVERFLOW);
859 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
861 __ bind(&overflow_ok);
864 __ j(not_equal, exit);
870 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
872 __ bind(&overflow_ok);
875 __ j(not_equal, exit);
878 __ Move(rdx, Smi::FromInt(y_max));
883 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
885 __ bind(&overflow_ok);
888 __ j(not_equal, exit);
894 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
896 __ bind(&overflow_ok);
899 __ j(not_equal, exit);
906 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
908 __ bind(&overflow_ok);
911 __ j(not_equal, exit);
915 mode.Add(i::BAILOUT_ON_OVERFLOW);
919 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
921 __ bind(&overflow_ok);
930 i::V8::Initialize(NULL);
931 // Allocate an executable page of memory.
934 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
938 Isolate* isolate = CcTest::i_isolate();
939 HandleScope handles(isolate);
940 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
942 MacroAssembler* masm = &assembler;
946 // No-overflow tests.
947 SmiAddTest(masm, &exit, 0x10, 1, 2);
948 SmiAddTest(masm, &exit, 0x20, 1, -2);
949 SmiAddTest(masm, &exit, 0x30, -1, 2);
950 SmiAddTest(masm, &exit, 0x40, -1, -2);
951 SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
952 SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
953 SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
954 SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
956 SmiAddOverflowTest(masm, &exit, 0x90, -1);
957 SmiAddOverflowTest(masm, &exit, 0xA0, 1);
958 SmiAddOverflowTest(masm, &exit, 0xB0, 1024);
959 SmiAddOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
960 SmiAddOverflowTest(masm, &exit, 0xD0, -2);
961 SmiAddOverflowTest(masm, &exit, 0xE0, -42000);
962 SmiAddOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
964 __ xor_(rax, rax); // Success.
970 masm->GetCode(&desc);
971 // Call the function from C++.
972 int result = FUNCTION_CAST<F0>(buffer)();
977 static void SmiSubTest(MacroAssembler* masm,
982 __ Move(rcx, Smi::FromInt(first));
983 __ Move(rdx, Smi::FromInt(second));
984 __ Move(r8, Smi::FromInt(first - second));
986 __ movl(rax, Immediate(id)); // Test 0.
987 __ SmiSub(r9, rcx, rdx, exit);
989 __ j(not_equal, exit);
991 __ incq(rax); // Test 1.
992 __ SmiSub(rcx, rcx, rdx, exit);
994 __ j(not_equal, exit);
996 __ Move(rcx, Smi::FromInt(first));
998 __ incq(rax); // Test 2.
999 __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
1001 __ j(not_equal, exit);
1003 __ incq(rax); // Test 3.
1004 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
1006 __ j(not_equal, exit);
1008 i::SmiOperationExecutionMode mode;
1009 mode.Add(i::PRESERVE_SOURCE_REGISTER);
1010 mode.Add(i::BAILOUT_ON_OVERFLOW);
1011 __ Move(rcx, Smi::FromInt(first));
1012 __ incq(rax); // Test 4.
1013 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
1015 __ j(not_equal, exit);
1017 __ Move(rcx, Smi::FromInt(first));
1018 __ incq(rax); // Test 5.
1019 __ SmiSubConstant(r9, rcx, Smi::FromInt(second), mode, exit);
1021 __ j(not_equal, exit);
1024 mode.Add(i::PRESERVE_SOURCE_REGISTER);
1025 mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
1026 __ Move(rcx, Smi::FromInt(first));
1028 __ incq(rax); // Test 6.
1029 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
1033 __ j(not_equal, exit);
1037 static void SmiSubOverflowTest(MacroAssembler* masm,
1041 // Subtracts a Smi from x so that the subtraction overflows.
1042 ASSERT(x != -1); // Can't overflow by subtracting a Smi.
1043 int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
1044 int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
1046 __ movl(rax, Immediate(id));
1047 __ Move(rcx, Smi::FromInt(x));
1048 __ movq(r11, rcx); // Store original Smi value of x in r11.
1049 __ Move(rdx, Smi::FromInt(y_min));
1052 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1054 __ bind(&overflow_ok);
1057 __ j(not_equal, exit);
1063 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1065 __ bind(&overflow_ok);
1068 __ j(not_equal, exit);
1071 i::SmiOperationExecutionMode mode;
1072 mode.Add(i::PRESERVE_SOURCE_REGISTER);
1073 mode.Add(i::BAILOUT_ON_OVERFLOW);
1079 __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
1081 __ bind(&overflow_ok);
1084 __ j(not_equal, exit);
1090 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
1092 __ bind(&overflow_ok);
1095 __ j(not_equal, exit);
1098 __ Move(rdx, Smi::FromInt(y_max));
1103 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1105 __ bind(&overflow_ok);
1108 __ j(not_equal, exit);
1114 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1116 __ bind(&overflow_ok);
1119 __ j(not_equal, exit);
1126 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
1128 __ bind(&overflow_ok);
1131 __ j(not_equal, exit);
1135 mode.Add(i::BAILOUT_ON_OVERFLOW);
1140 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
1142 __ bind(&overflow_ok);
1151 i::V8::Initialize(NULL);
1152 // Allocate an executable page of memory.
1155 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
1159 Isolate* isolate = CcTest::i_isolate();
1160 HandleScope handles(isolate);
1161 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1163 MacroAssembler* masm = &assembler;
1167 SmiSubTest(masm, &exit, 0x10, 1, 2);
1168 SmiSubTest(masm, &exit, 0x20, 1, -2);
1169 SmiSubTest(masm, &exit, 0x30, -1, 2);
1170 SmiSubTest(masm, &exit, 0x40, -1, -2);
1171 SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
1172 SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
1173 SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
1174 SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
1175 SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
1177 SmiSubOverflowTest(masm, &exit, 0xA0, 1);
1178 SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
1179 SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
1180 SmiSubOverflowTest(masm, &exit, 0xD0, -2);
1181 SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
1182 SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
1183 SmiSubOverflowTest(masm, &exit, 0x100, 0);
1185 __ xor_(rax, rax); // Success.
1191 masm->GetCode(&desc);
1192 // Call the function from C++.
1193 int result = FUNCTION_CAST<F0>(buffer)();
1194 CHECK_EQ(0, result);
1199 void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1200 int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
1201 bool negative_zero = (result == 0) && (x < 0 || y < 0);
1202 __ Move(rcx, Smi::FromInt(x));
1204 __ Move(rdx, Smi::FromInt(y));
1205 if (Smi::IsValid(result) && !negative_zero) {
1206 __ movl(rax, Immediate(id));
1207 __ Move(r8, Smi::FromIntptr(result));
1208 __ SmiMul(r9, rcx, rdx, exit);
1211 __ j(not_equal, exit);
1214 __ j(not_equal, exit);
1217 __ SmiMul(rcx, rcx, rdx, exit);
1219 __ j(not_equal, exit);
1221 __ movl(rax, Immediate(id + 8));
1222 Label overflow_ok, overflow_ok2;
1223 __ SmiMul(r9, rcx, rdx, &overflow_ok);
1225 __ bind(&overflow_ok);
1228 __ j(not_equal, exit);
1230 __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
1232 __ bind(&overflow_ok2);
1233 // 31-bit version doesn't preserve rcx on failure.
1235 // __ cmpq(r11, rcx);
1236 // __ j(not_equal, exit);
1242 i::V8::Initialize(NULL);
1243 // Allocate an executable page of memory.
1245 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1249 Isolate* isolate = CcTest::i_isolate();
1250 HandleScope handles(isolate);
1251 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1253 MacroAssembler* masm = &assembler;
1257 TestSmiMul(masm, &exit, 0x10, 0, 0);
1258 TestSmiMul(masm, &exit, 0x20, -1, 0);
1259 TestSmiMul(masm, &exit, 0x30, 0, -1);
1260 TestSmiMul(masm, &exit, 0x40, -1, -1);
1261 TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
1262 TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
1263 TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
1264 TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
1265 TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
1266 TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
1267 TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
1268 TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
1269 TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
1270 TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
1272 __ xor_(rax, rax); // Success.
1278 masm->GetCode(&desc);
1279 // Call the function from C++.
1280 int result = FUNCTION_CAST<F0>(buffer)();
1281 CHECK_EQ(0, result);
1285 void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1286 bool division_by_zero = (y == 0);
1287 bool negative_zero = (x == 0 && y < 0);
1288 #if V8_TARGET_ARCH_X64
1289 bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
1291 bool overflow = (x == Smi::kMinValue && y == -1);
1293 bool fraction = !division_by_zero && !overflow && (x % y != 0);
1294 __ Move(r11, Smi::FromInt(x));
1295 __ Move(r14, Smi::FromInt(y));
1296 if (!fraction && !overflow && !negative_zero && !division_by_zero) {
1297 // Division succeeds
1299 __ movq(r15, Immediate(id));
1301 __ Move(r8, Smi::FromInt(result));
1302 __ SmiDiv(r9, rcx, r14, exit);
1303 // Might have destroyed rcx and r14.
1306 __ j(not_equal, exit);
1310 __ Move(r14, Smi::FromInt(y));
1312 __ j(not_equal, exit);
1315 __ SmiDiv(rcx, rcx, r14, exit);
1319 __ j(not_equal, exit);
1322 __ movq(r15, Immediate(id + 8));
1324 Label fail_ok, fail_ok2;
1326 __ SmiDiv(r9, rcx, r14, &fail_ok);
1332 __ j(not_equal, exit);
1335 __ SmiDiv(rcx, rcx, r14, &fail_ok2);
1341 __ j(not_equal, exit);
1347 i::V8::Initialize(NULL);
1348 // Allocate an executable page of memory.
1351 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1355 Isolate* isolate = CcTest::i_isolate();
1356 HandleScope handles(isolate);
1357 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1359 MacroAssembler* masm = &assembler;
1365 TestSmiDiv(masm, &exit, 0x10, 1, 1);
1366 TestSmiDiv(masm, &exit, 0x20, 1, 0);
1367 TestSmiDiv(masm, &exit, 0x30, -1, 0);
1368 TestSmiDiv(masm, &exit, 0x40, 0, 1);
1369 TestSmiDiv(masm, &exit, 0x50, 0, -1);
1370 TestSmiDiv(masm, &exit, 0x60, 4, 2);
1371 TestSmiDiv(masm, &exit, 0x70, -4, 2);
1372 TestSmiDiv(masm, &exit, 0x80, 4, -2);
1373 TestSmiDiv(masm, &exit, 0x90, -4, -2);
1374 TestSmiDiv(masm, &exit, 0xa0, 3, 2);
1375 TestSmiDiv(masm, &exit, 0xb0, 3, 4);
1376 TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1377 TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1378 TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1379 TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1380 TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1381 TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
1382 TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
1383 TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1384 TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
1386 __ xor_(r15, r15); // Success.
1395 masm->GetCode(&desc);
1396 // Call the function from C++.
1397 int result = FUNCTION_CAST<F0>(buffer)();
1398 CHECK_EQ(0, result);
1402 void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1403 bool division_by_zero = (y == 0);
1404 bool division_overflow = (x == Smi::kMinValue) && (y == -1);
1405 bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
1406 bool negative_zero = (!fraction && x < 0);
1407 __ Move(rcx, Smi::FromInt(x));
1409 __ Move(r14, Smi::FromInt(y));
1410 if (!division_overflow && !negative_zero && !division_by_zero) {
1412 __ movq(r15, Immediate(id));
1414 __ Move(r8, Smi::FromInt(result));
1415 __ SmiMod(r9, rcx, r14, exit);
1419 __ j(not_equal, exit);
1423 __ j(not_equal, exit);
1426 __ SmiMod(rcx, rcx, r14, exit);
1430 __ j(not_equal, exit);
1433 __ movq(r15, Immediate(id + 8));
1435 Label fail_ok, fail_ok2;
1436 __ SmiMod(r9, rcx, r14, &fail_ok);
1442 __ j(not_equal, exit);
1445 __ SmiMod(rcx, rcx, r14, &fail_ok2);
1451 __ j(not_equal, exit);
1457 i::V8::Initialize(NULL);
1458 // Allocate an executable page of memory.
1461 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1465 Isolate* isolate = CcTest::i_isolate();
1466 HandleScope handles(isolate);
1467 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1469 MacroAssembler* masm = &assembler;
1475 TestSmiMod(masm, &exit, 0x10, 1, 1);
1476 TestSmiMod(masm, &exit, 0x20, 1, 0);
1477 TestSmiMod(masm, &exit, 0x30, -1, 0);
1478 TestSmiMod(masm, &exit, 0x40, 0, 1);
1479 TestSmiMod(masm, &exit, 0x50, 0, -1);
1480 TestSmiMod(masm, &exit, 0x60, 4, 2);
1481 TestSmiMod(masm, &exit, 0x70, -4, 2);
1482 TestSmiMod(masm, &exit, 0x80, 4, -2);
1483 TestSmiMod(masm, &exit, 0x90, -4, -2);
1484 TestSmiMod(masm, &exit, 0xa0, 3, 2);
1485 TestSmiMod(masm, &exit, 0xb0, 3, 4);
1486 TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1487 TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1488 TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1489 TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1490 TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1491 TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
1492 TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
1493 TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1494 TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
1496 __ xor_(r15, r15); // Success.
1505 masm->GetCode(&desc);
1506 // Call the function from C++.
1507 int result = FUNCTION_CAST<F0>(buffer)();
1508 CHECK_EQ(0, result);
1512 void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
1513 __ movl(rax, Immediate(id));
1515 for (int i = 0; i < 8; i++) {
1516 __ Move(rcx, Smi::FromInt(x));
1517 SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
1518 ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
1519 __ shl(index.reg, Immediate(index.scale));
1520 __ Set(r8, static_cast<intptr_t>(x) << i);
1521 __ cmpq(index.reg, r8);
1522 __ j(not_equal, exit);
1524 __ Move(rcx, Smi::FromInt(x));
1525 index = masm->SmiToIndex(rcx, rcx, i);
1526 ASSERT(index.reg.is(rcx));
1527 __ shl(rcx, Immediate(index.scale));
1528 __ Set(r8, static_cast<intptr_t>(x) << i);
1530 __ j(not_equal, exit);
1533 __ Move(rcx, Smi::FromInt(x));
1534 index = masm->SmiToNegativeIndex(rdx, rcx, i);
1535 ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
1536 __ shl(index.reg, Immediate(index.scale));
1537 __ Set(r8, static_cast<intptr_t>(-x) << i);
1538 __ cmpq(index.reg, r8);
1539 __ j(not_equal, exit);
1541 __ Move(rcx, Smi::FromInt(x));
1542 index = masm->SmiToNegativeIndex(rcx, rcx, i);
1543 ASSERT(index.reg.is(rcx));
1544 __ shl(rcx, Immediate(index.scale));
1545 __ Set(r8, static_cast<intptr_t>(-x) << i);
1547 __ j(not_equal, exit);
1554 i::V8::Initialize(NULL);
1555 // Allocate an executable page of memory.
1558 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
1562 Isolate* isolate = CcTest::i_isolate();
1563 HandleScope handles(isolate);
1564 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1566 MacroAssembler* masm = &assembler;
1570 TestSmiIndex(masm, &exit, 0x10, 0);
1571 TestSmiIndex(masm, &exit, 0x20, 1);
1572 TestSmiIndex(masm, &exit, 0x30, 100);
1573 TestSmiIndex(masm, &exit, 0x40, 1000);
1574 TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
1576 __ xor_(rax, rax); // Success.
1582 masm->GetCode(&desc);
1583 // Call the function from C++.
1584 int result = FUNCTION_CAST<F0>(buffer)();
1585 CHECK_EQ(0, result);
1589 void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1590 __ movl(rax, Immediate(id));
1591 __ Move(rcx, Smi::FromInt(x));
1592 __ Move(rdx, Smi::FromInt(y));
1593 __ xor_(rdx, Immediate(kSmiTagMask));
1594 __ SelectNonSmi(r9, rcx, rdx, exit);
1598 __ j(not_equal, exit);
1601 __ Move(rcx, Smi::FromInt(x));
1602 __ Move(rdx, Smi::FromInt(y));
1603 __ xor_(rcx, Immediate(kSmiTagMask));
1604 __ SelectNonSmi(r9, rcx, rdx, exit);
1608 __ j(not_equal, exit);
1612 __ Move(rcx, Smi::FromInt(x));
1613 __ Move(rdx, Smi::FromInt(y));
1614 __ xor_(rcx, Immediate(kSmiTagMask));
1615 __ xor_(rdx, Immediate(kSmiTagMask));
1616 __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
1622 TEST(SmiSelectNonSmi) {
1623 i::V8::Initialize(NULL);
1624 // Allocate an executable page of memory.
1627 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1631 Isolate* isolate = CcTest::i_isolate();
1632 HandleScope handles(isolate);
1633 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1635 MacroAssembler* masm = &assembler;
1639 TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
1640 TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
1641 TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
1642 TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
1643 TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
1644 TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
1645 TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
1646 TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1647 TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1649 __ xor_(rax, rax); // Success.
1655 masm->GetCode(&desc);
1656 // Call the function from C++.
1657 int result = FUNCTION_CAST<F0>(buffer)();
1658 CHECK_EQ(0, result);
1662 void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1665 __ movl(rax, Immediate(id));
1667 __ Move(rcx, Smi::FromInt(x));
1669 __ Move(rdx, Smi::FromInt(y));
1670 __ Move(r8, Smi::FromInt(result));
1671 __ SmiAnd(r9, rcx, rdx);
1673 __ j(not_equal, exit);
1677 __ j(not_equal, exit);
1680 __ SmiAnd(rcx, rcx, rdx);
1682 __ j(not_equal, exit);
1686 __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
1688 __ j(not_equal, exit);
1692 __ j(not_equal, exit);
1695 __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
1697 __ j(not_equal, exit);
1702 i::V8::Initialize(NULL);
1703 // Allocate an executable page of memory.
1706 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1710 Isolate* isolate = CcTest::i_isolate();
1711 HandleScope handles(isolate);
1712 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1714 MacroAssembler* masm = &assembler;
1718 TestSmiAnd(masm, &exit, 0x10, 0, 0);
1719 TestSmiAnd(masm, &exit, 0x20, 0, 1);
1720 TestSmiAnd(masm, &exit, 0x30, 1, 0);
1721 TestSmiAnd(masm, &exit, 0x40, 0, -1);
1722 TestSmiAnd(masm, &exit, 0x50, -1, 0);
1723 TestSmiAnd(masm, &exit, 0x60, -1, -1);
1724 TestSmiAnd(masm, &exit, 0x70, 1, 1);
1725 TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1726 TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1727 TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
1728 TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
1730 __ xor_(rax, rax); // Success.
1736 masm->GetCode(&desc);
1737 // Call the function from C++.
1738 int result = FUNCTION_CAST<F0>(buffer)();
1739 CHECK_EQ(0, result);
1743 void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1746 __ movl(rax, Immediate(id));
1748 __ Move(rcx, Smi::FromInt(x));
1750 __ Move(rdx, Smi::FromInt(y));
1751 __ Move(r8, Smi::FromInt(result));
1752 __ SmiOr(r9, rcx, rdx);
1754 __ j(not_equal, exit);
1758 __ j(not_equal, exit);
1761 __ SmiOr(rcx, rcx, rdx);
1763 __ j(not_equal, exit);
1767 __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
1769 __ j(not_equal, exit);
1773 __ j(not_equal, exit);
1776 __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
1778 __ j(not_equal, exit);
1783 i::V8::Initialize(NULL);
1784 // Allocate an executable page of memory.
1787 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1791 Isolate* isolate = CcTest::i_isolate();
1792 HandleScope handles(isolate);
1793 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1795 MacroAssembler* masm = &assembler;
1799 TestSmiOr(masm, &exit, 0x10, 0, 0);
1800 TestSmiOr(masm, &exit, 0x20, 0, 1);
1801 TestSmiOr(masm, &exit, 0x30, 1, 0);
1802 TestSmiOr(masm, &exit, 0x40, 0, -1);
1803 TestSmiOr(masm, &exit, 0x50, -1, 0);
1804 TestSmiOr(masm, &exit, 0x60, -1, -1);
1805 TestSmiOr(masm, &exit, 0x70, 1, 1);
1806 TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1807 TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1808 TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
1809 TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
1810 TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
1811 TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
1813 __ xor_(rax, rax); // Success.
1819 masm->GetCode(&desc);
1820 // Call the function from C++.
1821 int result = FUNCTION_CAST<F0>(buffer)();
1822 CHECK_EQ(0, result);
1826 void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1829 __ movl(rax, Immediate(id));
1831 __ Move(rcx, Smi::FromInt(x));
1833 __ Move(rdx, Smi::FromInt(y));
1834 __ Move(r8, Smi::FromInt(result));
1835 __ SmiXor(r9, rcx, rdx);
1837 __ j(not_equal, exit);
1841 __ j(not_equal, exit);
1844 __ SmiXor(rcx, rcx, rdx);
1846 __ j(not_equal, exit);
1850 __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
1852 __ j(not_equal, exit);
1856 __ j(not_equal, exit);
1859 __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
1861 __ j(not_equal, exit);
1866 i::V8::Initialize(NULL);
1867 // Allocate an executable page of memory.
1870 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1874 Isolate* isolate = CcTest::i_isolate();
1875 HandleScope handles(isolate);
1876 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1878 MacroAssembler* masm = &assembler;
1882 TestSmiXor(masm, &exit, 0x10, 0, 0);
1883 TestSmiXor(masm, &exit, 0x20, 0, 1);
1884 TestSmiXor(masm, &exit, 0x30, 1, 0);
1885 TestSmiXor(masm, &exit, 0x40, 0, -1);
1886 TestSmiXor(masm, &exit, 0x50, -1, 0);
1887 TestSmiXor(masm, &exit, 0x60, -1, -1);
1888 TestSmiXor(masm, &exit, 0x70, 1, 1);
1889 TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1890 TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1891 TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
1892 TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
1893 TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
1894 TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
1896 __ xor_(rax, rax); // Success.
1902 masm->GetCode(&desc);
1903 // Call the function from C++.
1904 int result = FUNCTION_CAST<F0>(buffer)();
1905 CHECK_EQ(0, result);
1909 void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
1911 __ movl(rax, Immediate(id));
1913 __ Move(r8, Smi::FromInt(result));
1914 __ Move(rcx, Smi::FromInt(x));
1919 __ j(not_equal, exit);
1923 __ j(not_equal, exit);
1926 __ SmiNot(rcx, rcx);
1928 __ j(not_equal, exit);
1933 i::V8::Initialize(NULL);
1934 // Allocate an executable page of memory.
1937 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1941 Isolate* isolate = CcTest::i_isolate();
1942 HandleScope handles(isolate);
1943 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1945 MacroAssembler* masm = &assembler;
1949 TestSmiNot(masm, &exit, 0x10, 0);
1950 TestSmiNot(masm, &exit, 0x20, 1);
1951 TestSmiNot(masm, &exit, 0x30, -1);
1952 TestSmiNot(masm, &exit, 0x40, 127);
1953 TestSmiNot(masm, &exit, 0x50, 65535);
1954 TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
1955 TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
1956 TestSmiNot(masm, &exit, 0x80, 0x05555555);
1958 __ xor_(rax, rax); // Success.
1964 masm->GetCode(&desc);
1965 // Call the function from C++.
1966 int result = FUNCTION_CAST<F0>(buffer)();
1967 CHECK_EQ(0, result);
1971 void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
1972 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1973 const int kNumShifts = 5;
1974 __ movl(rax, Immediate(id));
1975 for (int i = 0; i < kNumShifts; i++) {
1976 // rax == id + i * 10.
1977 int shift = shifts[i];
1978 int result = x << shift;
1979 CHECK(Smi::IsValid(result));
1980 __ Move(r8, Smi::FromInt(result));
1981 __ Move(rcx, Smi::FromInt(x));
1982 __ SmiShiftLeftConstant(r9, rcx, shift);
1986 __ j(not_equal, exit);
1989 __ Move(rcx, Smi::FromInt(x));
1990 __ SmiShiftLeftConstant(rcx, rcx, shift);
1994 __ j(not_equal, exit);
1997 __ Move(rdx, Smi::FromInt(x));
1998 __ Move(rcx, Smi::FromInt(shift));
1999 __ SmiShiftLeft(r9, rdx, rcx);
2003 __ j(not_equal, exit);
2006 __ Move(rdx, Smi::FromInt(x));
2007 __ Move(r11, Smi::FromInt(shift));
2008 __ SmiShiftLeft(r9, rdx, r11);
2012 __ j(not_equal, exit);
2015 __ Move(rdx, Smi::FromInt(x));
2016 __ Move(r11, Smi::FromInt(shift));
2017 __ SmiShiftLeft(rdx, rdx, r11);
2021 __ j(not_equal, exit);
2028 TEST(SmiShiftLeft) {
2029 i::V8::Initialize(NULL);
2030 // Allocate an executable page of memory.
2033 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 7,
2037 Isolate* isolate = CcTest::i_isolate();
2038 HandleScope handles(isolate);
2039 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2041 MacroAssembler* masm = &assembler;
2045 TestSmiShiftLeft(masm, &exit, 0x10, 0);
2046 TestSmiShiftLeft(masm, &exit, 0x50, 1);
2047 TestSmiShiftLeft(masm, &exit, 0x90, 127);
2048 TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
2049 TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
2050 TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
2051 TestSmiShiftLeft(masm, &exit, 0x190, -1);
2053 __ xor_(rax, rax); // Success.
2059 masm->GetCode(&desc);
2060 // Call the function from C++.
2061 int result = FUNCTION_CAST<F0>(buffer)();
2062 CHECK_EQ(0, result);
2066 void TestSmiShiftLogicalRight(MacroAssembler* masm,
2070 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2071 const int kNumShifts = 5;
2072 __ movl(rax, Immediate(id));
2073 for (int i = 0; i < kNumShifts; i++) {
2074 int shift = shifts[i];
2075 intptr_t result = static_cast<unsigned int>(x) >> shift;
2076 if (Smi::IsValid(result)) {
2077 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
2078 __ Move(rcx, Smi::FromInt(x));
2079 __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
2083 __ j(not_equal, exit);
2086 __ Move(rdx, Smi::FromInt(x));
2087 __ Move(rcx, Smi::FromInt(shift));
2088 __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
2092 __ j(not_equal, exit);
2095 __ Move(rdx, Smi::FromInt(x));
2096 __ Move(r11, Smi::FromInt(shift));
2097 __ SmiShiftLogicalRight(r9, rdx, r11, exit);
2101 __ j(not_equal, exit);
2105 // Cannot happen with long smis.
2107 __ Move(rcx, Smi::FromInt(x));
2109 __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
2115 __ j(not_equal, exit);
2118 __ Move(r8, Smi::FromInt(shift));
2120 __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
2126 __ j(not_equal, exit);
2128 __ addq(rax, Immediate(3));
2134 TEST(SmiShiftLogicalRight) {
2135 i::V8::Initialize(NULL);
2136 // Allocate an executable page of memory.
2139 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 5,
2143 Isolate* isolate = CcTest::i_isolate();
2144 HandleScope handles(isolate);
2145 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2147 MacroAssembler* masm = &assembler;
2151 TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
2152 TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
2153 TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
2154 TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
2155 TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
2156 TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
2157 TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
2159 __ xor_(rax, rax); // Success.
2165 masm->GetCode(&desc);
2166 // Call the function from C++.
2167 int result = FUNCTION_CAST<F0>(buffer)();
2168 CHECK_EQ(0, result);
2172 void TestSmiShiftArithmeticRight(MacroAssembler* masm,
2176 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2177 const int kNumShifts = 5;
2178 __ movl(rax, Immediate(id));
2179 for (int i = 0; i < kNumShifts; i++) {
2180 int shift = shifts[i];
2181 // Guaranteed arithmetic shift.
2182 int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
2183 __ Move(r8, Smi::FromInt(result));
2184 __ Move(rcx, Smi::FromInt(x));
2185 __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
2188 __ j(not_equal, exit);
2191 __ Move(rdx, Smi::FromInt(x));
2192 __ Move(r11, Smi::FromInt(shift));
2193 __ SmiShiftArithmeticRight(rdx, rdx, r11);
2196 __ j(not_equal, exit);
2203 TEST(SmiShiftArithmeticRight) {
2204 i::V8::Initialize(NULL);
2205 // Allocate an executable page of memory.
2208 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
2212 Isolate* isolate = CcTest::i_isolate();
2213 HandleScope handles(isolate);
2214 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2216 MacroAssembler* masm = &assembler;
2220 TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
2221 TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
2222 TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
2223 TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
2224 TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
2225 TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
2226 TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
2228 __ xor_(rax, rax); // Success.
2234 masm->GetCode(&desc);
2235 // Call the function from C++.
2236 int result = FUNCTION_CAST<F0>(buffer)();
2237 CHECK_EQ(0, result);
2241 void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
2243 int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
2244 int power_count = 8;
2245 __ movl(rax, Immediate(id));
2246 for (int i = 0; i < power_count; i++) {
2247 int power = powers[i];
2248 intptr_t result = static_cast<intptr_t>(x) << power;
2250 __ Move(rcx, Smi::FromInt(x));
2252 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
2254 __ j(not_equal, exit);
2256 __ cmpq(r11, rcx); // rcx unchanged.
2257 __ j(not_equal, exit);
2259 __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
2261 __ j(not_equal, exit);
2267 TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
2268 i::V8::Initialize(NULL);
2269 // Allocate an executable page of memory.
2272 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
2276 Isolate* isolate = CcTest::i_isolate();
2277 HandleScope handles(isolate);
2278 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2280 MacroAssembler* masm = &assembler;
2284 TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
2285 TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
2286 TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
2287 TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
2288 TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
2289 TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
2290 TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
2291 TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
2292 TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
2294 __ xor_(rax, rax); // Success.
2300 masm->GetCode(&desc);
2301 // Call the function from C++.
2302 int result = FUNCTION_CAST<F0>(buffer)();
2303 CHECK_EQ(0, result);
2307 TEST(OperandOffset) {
2308 i::V8::Initialize(NULL);
2310 for (uint32_t i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
2312 // Allocate an executable page of memory.
2315 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
2319 Isolate* isolate = CcTest::i_isolate();
2320 HandleScope handles(isolate);
2321 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2323 MacroAssembler* masm = &assembler;
2331 __ push(Immediate(0x100)); // <-- rbp
2333 __ push(Immediate(0x101));
2334 __ push(Immediate(0x102));
2335 __ push(Immediate(0x103));
2336 __ push(Immediate(0x104));
2337 __ push(Immediate(0x105)); // <-- rbx
2338 __ push(Immediate(0x106));
2339 __ push(Immediate(0x107));
2340 __ push(Immediate(0x108));
2341 __ push(Immediate(0x109)); // <-- rsp
2346 __ lea(r14, Operand(rsp, 3 * kPointerSize));
2347 __ lea(r13, Operand(rbp, -3 * kPointerSize));
2348 __ lea(rbx, Operand(rbp, -5 * kPointerSize));
2349 __ movl(rcx, Immediate(2));
2350 __ Move(r8, reinterpret_cast<Address>(&data[128]), RelocInfo::NONE64);
2351 __ movl(rax, Immediate(1));
2353 Operand sp0 = Operand(rsp, 0);
2356 __ movl(rdx, sp0); // Sanity check.
2357 __ cmpl(rdx, Immediate(0x109));
2358 __ j(not_equal, &exit);
2362 // Zero to non-zero displacement.
2363 __ movl(rdx, Operand(sp0, 2 * kPointerSize));
2364 __ cmpl(rdx, Immediate(0x107));
2365 __ j(not_equal, &exit);
2368 Operand sp2 = Operand(rsp, 2 * kPointerSize);
2371 __ movl(rdx, sp2); // Sanity check.
2372 __ cmpl(rdx, Immediate(0x107));
2373 __ j(not_equal, &exit);
2376 __ movl(rdx, Operand(sp2, 2 * kPointerSize));
2377 __ cmpl(rdx, Immediate(0x105));
2378 __ j(not_equal, &exit);
2381 // Non-zero to zero displacement.
2382 __ movl(rdx, Operand(sp2, -2 * kPointerSize));
2383 __ cmpl(rdx, Immediate(0x109));
2384 __ j(not_equal, &exit);
2387 Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
2390 __ movl(rdx, sp2c2); // Sanity check.
2391 __ cmpl(rdx, Immediate(0x105));
2392 __ j(not_equal, &exit);
2395 __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
2396 __ cmpl(rdx, Immediate(0x103));
2397 __ j(not_equal, &exit);
2400 // Non-zero to zero displacement.
2401 __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
2402 __ cmpl(rdx, Immediate(0x107));
2403 __ j(not_equal, &exit);
2407 Operand bp0 = Operand(rbp, 0);
2410 __ movl(rdx, bp0); // Sanity check.
2411 __ cmpl(rdx, Immediate(0x100));
2412 __ j(not_equal, &exit);
2415 // Zero to non-zero displacement.
2416 __ movl(rdx, Operand(bp0, -2 * kPointerSize));
2417 __ cmpl(rdx, Immediate(0x102));
2418 __ j(not_equal, &exit);
2421 Operand bp2 = Operand(rbp, -2 * kPointerSize);
2424 __ movl(rdx, bp2); // Sanity check.
2425 __ cmpl(rdx, Immediate(0x102));
2426 __ j(not_equal, &exit);
2429 // Non-zero to zero displacement.
2430 __ movl(rdx, Operand(bp2, 2 * kPointerSize));
2431 __ cmpl(rdx, Immediate(0x100));
2432 __ j(not_equal, &exit);
2435 __ movl(rdx, Operand(bp2, -2 * kPointerSize));
2436 __ cmpl(rdx, Immediate(0x104));
2437 __ j(not_equal, &exit);
2440 Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
2443 __ movl(rdx, bp2c4); // Sanity check.
2444 __ cmpl(rdx, Immediate(0x102));
2445 __ j(not_equal, &exit);
2448 __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
2449 __ cmpl(rdx, Immediate(0x100));
2450 __ j(not_equal, &exit);
2453 __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
2454 __ cmpl(rdx, Immediate(0x104));
2455 __ j(not_equal, &exit);
2458 Operand bx0 = Operand(rbx, 0);
2461 __ movl(rdx, bx0); // Sanity check.
2462 __ cmpl(rdx, Immediate(0x105));
2463 __ j(not_equal, &exit);
2466 __ movl(rdx, Operand(bx0, 5 * kPointerSize));
2467 __ cmpl(rdx, Immediate(0x100));
2468 __ j(not_equal, &exit);
2471 __ movl(rdx, Operand(bx0, -4 * kPointerSize));
2472 __ cmpl(rdx, Immediate(0x109));
2473 __ j(not_equal, &exit);
2476 Operand bx2 = Operand(rbx, 2 * kPointerSize);
2479 __ movl(rdx, bx2); // Sanity check.
2480 __ cmpl(rdx, Immediate(0x103));
2481 __ j(not_equal, &exit);
2484 __ movl(rdx, Operand(bx2, 2 * kPointerSize));
2485 __ cmpl(rdx, Immediate(0x101));
2486 __ j(not_equal, &exit);
2489 // Non-zero to zero displacement.
2490 __ movl(rdx, Operand(bx2, -2 * kPointerSize));
2491 __ cmpl(rdx, Immediate(0x105));
2492 __ j(not_equal, &exit);
2495 Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
2498 __ movl(rdx, bx2c2); // Sanity check.
2499 __ cmpl(rdx, Immediate(0x105));
2500 __ j(not_equal, &exit);
2503 __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
2504 __ cmpl(rdx, Immediate(0x103));
2505 __ j(not_equal, &exit);
2508 __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
2509 __ cmpl(rdx, Immediate(0x107));
2510 __ j(not_equal, &exit);
2513 Operand r80 = Operand(r8, 0);
2516 __ movl(rdx, r80); // Sanity check.
2517 __ cmpl(rdx, Immediate(0x80808080));
2518 __ j(not_equal, &exit);
2521 __ movl(rdx, Operand(r80, -8 * kIntSize));
2522 __ cmpl(rdx, Immediate(0x78787878));
2523 __ j(not_equal, &exit);
2526 __ movl(rdx, Operand(r80, 8 * kIntSize));
2527 __ cmpl(rdx, Immediate(0x88888888));
2528 __ j(not_equal, &exit);
2531 __ movl(rdx, Operand(r80, -64 * kIntSize));
2532 __ cmpl(rdx, Immediate(0x40404040));
2533 __ j(not_equal, &exit);
2536 __ movl(rdx, Operand(r80, 64 * kIntSize));
2537 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2538 __ j(not_equal, &exit);
2541 Operand r88 = Operand(r8, 8 * kIntSize);
2544 __ movl(rdx, r88); // Sanity check.
2545 __ cmpl(rdx, Immediate(0x88888888));
2546 __ j(not_equal, &exit);
2549 __ movl(rdx, Operand(r88, -8 * kIntSize));
2550 __ cmpl(rdx, Immediate(0x80808080));
2551 __ j(not_equal, &exit);
2554 __ movl(rdx, Operand(r88, 8 * kIntSize));
2555 __ cmpl(rdx, Immediate(0x90909090));
2556 __ j(not_equal, &exit);
2559 __ movl(rdx, Operand(r88, -64 * kIntSize));
2560 __ cmpl(rdx, Immediate(0x48484848));
2561 __ j(not_equal, &exit);
2564 __ movl(rdx, Operand(r88, 64 * kIntSize));
2565 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2566 __ j(not_equal, &exit);
2570 Operand r864 = Operand(r8, 64 * kIntSize);
2573 __ movl(rdx, r864); // Sanity check.
2574 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2575 __ j(not_equal, &exit);
2578 __ movl(rdx, Operand(r864, -8 * kIntSize));
2579 __ cmpl(rdx, Immediate(0xB8B8B8B8));
2580 __ j(not_equal, &exit);
2583 __ movl(rdx, Operand(r864, 8 * kIntSize));
2584 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2585 __ j(not_equal, &exit);
2588 __ movl(rdx, Operand(r864, -64 * kIntSize));
2589 __ cmpl(rdx, Immediate(0x80808080));
2590 __ j(not_equal, &exit);
2593 __ movl(rdx, Operand(r864, 32 * kIntSize));
2594 __ cmpl(rdx, Immediate(0xE0E0E0E0));
2595 __ j(not_equal, &exit);
2598 // 32-bit offset to 8-bit offset.
2599 __ movl(rdx, Operand(r864, -60 * kIntSize));
2600 __ cmpl(rdx, Immediate(0x84848484));
2601 __ j(not_equal, &exit);
2604 __ movl(rdx, Operand(r864, 60 * kIntSize));
2605 __ cmpl(rdx, Immediate(0xFCFCFCFC));
2606 __ j(not_equal, &exit);
2609 // Test unaligned offsets.
2612 __ movl(rdx, Operand(r80, 2));
2613 __ cmpl(rdx, Immediate(0x81818080));
2614 __ j(not_equal, &exit);
2617 __ movl(rdx, Operand(r80, -2));
2618 __ cmpl(rdx, Immediate(0x80807F7F));
2619 __ j(not_equal, &exit);
2622 __ movl(rdx, Operand(r80, 126));
2623 __ cmpl(rdx, Immediate(0xA0A09F9F));
2624 __ j(not_equal, &exit);
2627 __ movl(rdx, Operand(r80, -126));
2628 __ cmpl(rdx, Immediate(0x61616060));
2629 __ j(not_equal, &exit);
2632 __ movl(rdx, Operand(r80, 254));
2633 __ cmpl(rdx, Immediate(0xC0C0BFBF));
2634 __ j(not_equal, &exit);
2637 __ movl(rdx, Operand(r80, -254));
2638 __ cmpl(rdx, Immediate(0x41414040));
2639 __ j(not_equal, &exit);
2644 __ movl(rax, Immediate(0));
2646 __ lea(rsp, Operand(rbp, kPointerSize));
2656 masm->GetCode(&desc);
2657 // Call the function from C++.
2658 int result = FUNCTION_CAST<F0>(buffer)();
2659 CHECK_EQ(0, result);
2663 TEST(LoadAndStoreWithRepresentation) {
2664 v8::internal::V8::Initialize(NULL);
2666 // Allocate an executable page of memory.
2668 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
2672 Isolate* isolate = CcTest::i_isolate();
2673 HandleScope handles(isolate);
2674 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2675 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
2677 __ subq(rsp, Immediate(1 * kPointerSize));
2681 __ movq(rax, Immediate(1)); // Test number.
2682 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2683 __ movq(rcx, Immediate(-1));
2684 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger8());
2685 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2686 __ movl(rdx, Immediate(255));
2688 __ j(not_equal, &exit);
2689 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger8());
2691 __ j(not_equal, &exit);
2694 __ movq(rax, Immediate(2)); // Test number.
2695 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2696 __ Set(rcx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2697 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Smi());
2698 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2699 __ Set(rdx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2701 __ j(not_equal, &exit);
2702 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Smi());
2704 __ j(not_equal, &exit);
2707 __ movq(rax, Immediate(3)); // Test number.
2708 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2709 __ movq(rcx, Immediate(-1));
2710 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer32());
2711 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2712 __ movl(rdx, Immediate(-1));
2714 __ j(not_equal, &exit);
2715 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer32());
2717 __ j(not_equal, &exit);
2720 __ movq(rax, Immediate(4)); // Test number.
2721 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2722 __ movl(rcx, Immediate(0x44332211));
2723 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::HeapObject());
2724 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2725 __ movl(rdx, Immediate(0x44332211));
2727 __ j(not_equal, &exit);
2728 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::HeapObject());
2730 __ j(not_equal, &exit);
2733 __ movq(rax, Immediate(5)); // Test number.
2734 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2735 __ Set(rcx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2736 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Tagged());
2737 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2738 __ Set(rdx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2740 __ j(not_equal, &exit);
2741 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Tagged());
2743 __ j(not_equal, &exit);
2746 __ movq(rax, Immediate(6)); // Test number.
2747 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2748 __ Set(rcx, V8_2PART_UINT64_C(0x11223344, 55667788));
2749 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::External());
2750 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2751 __ Set(rdx, V8_2PART_UINT64_C(0x11223344, 55667788));
2753 __ j(not_equal, &exit);
2754 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::External());
2756 __ j(not_equal, &exit);
2759 __ movq(rax, Immediate(7)); // Test number.
2760 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2761 __ movq(rcx, Immediate(-1));
2762 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer8());
2763 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2764 __ movl(rdx, Immediate(255));
2766 __ j(not_equal, &exit);
2767 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer8());
2768 __ movq(rcx, Immediate(-1));
2770 __ j(not_equal, &exit);
2773 __ movq(rax, Immediate(8)); // Test number.
2774 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2775 __ movq(rcx, Immediate(-1));
2776 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer16());
2777 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2778 __ movl(rdx, Immediate(65535));
2780 __ j(not_equal, &exit);
2781 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer16());
2782 __ movq(rcx, Immediate(-1));
2784 __ j(not_equal, &exit);
2787 __ movq(rax, Immediate(9)); // Test number.
2788 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2789 __ movq(rcx, Immediate(-1));
2790 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger16());
2791 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2792 __ movl(rdx, Immediate(65535));
2794 __ j(not_equal, &exit);
2795 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger16());
2797 __ j(not_equal, &exit);
2799 __ xor_(rax, rax); // Success.
2801 __ addq(rsp, Immediate(1 * kPointerSize));
2806 masm->GetCode(&desc);
2807 // Call the function from C++.
2808 int result = FUNCTION_CAST<F0>(buffer)();
2809 CHECK_EQ(0, result);