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 "test/cctest/cctest.h"
37 namespace i = v8::internal;
42 using i::FUNCTION_CAST;
47 using i::MacroAssembler;
50 using i::Representation;
56 using i::greater_equal;
58 using i::kPointerSize;
60 using i::kSmiValueSize;
82 using i::times_pointer_size;
84 // Test the x64 assembler by compiling some simple functions into
85 // a buffer and executing them. These tests do not initialize the
86 // V8 library, create a context, or use any V8 objects.
87 // The AMD64 calling convention is used, with the first five arguments
88 // in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
89 // the XMM registers. The return value is in RAX.
90 // This calling convention is used on Linux, with GCC, and on Mac OS,
91 // with GCC. A different convention is used on 64-bit windows.
98 static void EntryCode(MacroAssembler* masm) {
99 // Smi constant register is callee save.
100 __ pushq(i::kRootRegister);
101 __ InitializeRootRegister();
105 static void ExitCode(MacroAssembler* masm) {
106 __ popq(i::kRootRegister);
111 // Check that C++ Smi operations work as expected.
112 int64_t test_numbers[] = {
113 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
114 Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
115 Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
117 int test_number_count = 15;
118 for (int i = 0; i < test_number_count; i++) {
119 int64_t number = test_numbers[i];
120 bool is_valid = Smi::IsValid(number);
121 bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
122 CHECK_EQ(is_in_range, is_valid);
124 Smi* smi_from_intptr = Smi::FromIntptr(number);
125 if (static_cast<int>(number) == number) { // Is a 32-bit int.
126 Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
127 CHECK_EQ(smi_from_int, smi_from_intptr);
129 int64_t smi_value = smi_from_intptr->value();
130 CHECK_EQ(number, smi_value);
136 static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
137 __ movl(rax, Immediate(id));
139 __ Set(rdx, reinterpret_cast<intptr_t>(value));
141 __ j(not_equal, exit);
145 // Test that we can move a Smi value literally into a register.
147 // Allocate an executable page of memory.
149 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
150 Assembler::kMinimalBufferSize, &actual_size, true));
152 Isolate* isolate = CcTest::i_isolate();
153 HandleScope handles(isolate);
154 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
155 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
159 TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
160 TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
161 TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
162 TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
163 TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
164 TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
165 TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
166 TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
167 TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
168 TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
169 TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
170 TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
172 __ xorq(rax, rax); // Success.
178 masm->GetCode(&desc);
179 // Call the function from C++.
180 int result = FUNCTION_CAST<F0>(buffer)();
185 void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
186 __ Move(rcx, Smi::FromInt(x));
188 __ Move(rdx, Smi::FromInt(y));
190 __ SmiCompare(rcx, rdx);
192 __ movl(rax, Immediate(id + 1));
193 __ j(greater_equal, exit);
195 __ movl(rax, Immediate(id + 2));
196 __ j(less_equal, exit);
199 __ movl(rax, Immediate(id + 3));
200 __ j(not_equal, exit);
202 __ movl(rax, Immediate(id + 4));
204 __ j(not_equal, exit);
207 __ j(not_equal, exit);
210 __ SmiCompare(rdx, rcx);
212 __ movl(rax, Immediate(id + 9));
213 __ j(greater_equal, exit);
216 __ movl(rax, Immediate(id + 10));
217 __ j(less_equal, exit);
221 __ movl(rax, Immediate(id + 11));
222 __ j(not_equal, exit);
225 __ j(not_equal, exit);
230 // Test that we can compare smis for equality (and more).
232 // Allocate an executable page of memory.
234 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
235 Assembler::kMinimalBufferSize * 2, &actual_size, true));
237 Isolate* isolate = CcTest::i_isolate();
238 HandleScope handles(isolate);
239 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
241 MacroAssembler* masm = &assembler;
245 TestSmiCompare(masm, &exit, 0x10, 0, 0);
246 TestSmiCompare(masm, &exit, 0x20, 0, 1);
247 TestSmiCompare(masm, &exit, 0x30, 1, 0);
248 TestSmiCompare(masm, &exit, 0x40, 1, 1);
249 TestSmiCompare(masm, &exit, 0x50, 0, -1);
250 TestSmiCompare(masm, &exit, 0x60, -1, 0);
251 TestSmiCompare(masm, &exit, 0x70, -1, -1);
252 TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
253 TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
254 TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
255 TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
256 TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
257 TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
258 TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
259 TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
260 TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
261 TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
262 TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
263 TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
265 __ xorq(rax, rax); // Success.
271 masm->GetCode(&desc);
272 // Call the function from C++.
273 int result = FUNCTION_CAST<F0>(buffer)();
279 TEST(Integer32ToSmi) {
280 // Allocate an executable page of memory.
282 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
283 Assembler::kMinimalBufferSize, &actual_size, true));
285 Isolate* isolate = CcTest::i_isolate();
286 HandleScope handles(isolate);
287 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
289 MacroAssembler* masm = &assembler;
293 __ movq(rax, Immediate(1)); // Test number.
294 __ movl(rcx, Immediate(0));
295 __ Integer32ToSmi(rcx, rcx);
296 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
298 __ j(not_equal, &exit);
300 __ movq(rax, Immediate(2)); // Test number.
301 __ movl(rcx, Immediate(1024));
302 __ Integer32ToSmi(rcx, rcx);
303 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
305 __ j(not_equal, &exit);
307 __ movq(rax, Immediate(3)); // Test number.
308 __ movl(rcx, Immediate(-1));
309 __ Integer32ToSmi(rcx, rcx);
310 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
312 __ j(not_equal, &exit);
314 __ movq(rax, Immediate(4)); // Test number.
315 __ movl(rcx, Immediate(Smi::kMaxValue));
316 __ Integer32ToSmi(rcx, rcx);
317 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
319 __ j(not_equal, &exit);
321 __ movq(rax, Immediate(5)); // Test number.
322 __ movl(rcx, Immediate(Smi::kMinValue));
323 __ Integer32ToSmi(rcx, rcx);
324 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
326 __ j(not_equal, &exit);
328 // Different target register.
330 __ movq(rax, Immediate(6)); // Test number.
331 __ movl(rcx, Immediate(0));
332 __ Integer32ToSmi(r8, rcx);
333 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
335 __ j(not_equal, &exit);
337 __ movq(rax, Immediate(7)); // Test number.
338 __ movl(rcx, Immediate(1024));
339 __ Integer32ToSmi(r8, rcx);
340 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
342 __ j(not_equal, &exit);
344 __ movq(rax, Immediate(8)); // Test number.
345 __ movl(rcx, Immediate(-1));
346 __ Integer32ToSmi(r8, rcx);
347 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
349 __ j(not_equal, &exit);
351 __ movq(rax, Immediate(9)); // Test number.
352 __ movl(rcx, Immediate(Smi::kMaxValue));
353 __ Integer32ToSmi(r8, rcx);
354 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
356 __ j(not_equal, &exit);
358 __ movq(rax, Immediate(10)); // Test number.
359 __ movl(rcx, Immediate(Smi::kMinValue));
360 __ Integer32ToSmi(r8, rcx);
361 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
363 __ j(not_equal, &exit);
366 __ xorq(rax, rax); // Success.
372 masm->GetCode(&desc);
373 // Call the function from C++.
374 int result = FUNCTION_CAST<F0>(buffer)();
379 void TestI64PlusConstantToSmi(MacroAssembler* masm,
384 int64_t result = x + y;
385 DCHECK(Smi::IsValid(result));
386 __ movl(rax, Immediate(id));
387 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
390 __ Integer64PlusConstantToSmi(rdx, rcx, y);
392 __ j(not_equal, exit);
396 __ j(not_equal, exit);
399 __ Integer64PlusConstantToSmi(rcx, rcx, y);
401 __ j(not_equal, exit);
405 TEST(Integer64PlusConstantToSmi) {
406 // Allocate an executable page of memory.
408 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
409 Assembler::kMinimalBufferSize, &actual_size, true));
411 Isolate* isolate = CcTest::i_isolate();
412 HandleScope handles(isolate);
413 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
415 MacroAssembler* masm = &assembler;
419 int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
421 TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
422 TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
423 TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
424 TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
425 TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
426 TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
427 TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
428 TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
429 TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
430 TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
431 TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
432 TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
434 __ xorq(rax, rax); // Success.
440 masm->GetCode(&desc);
441 // Call the function from C++.
442 int result = FUNCTION_CAST<F0>(buffer)();
448 // Allocate an executable page of memory.
450 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
451 Assembler::kMinimalBufferSize, &actual_size, true));
453 Isolate* isolate = CcTest::i_isolate();
454 HandleScope handles(isolate);
455 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
457 MacroAssembler* masm = &assembler;
462 __ movl(rax, Immediate(1)); // Test number.
466 __ movl(rcx, Immediate(0));
467 __ Integer32ToSmi(rcx, rcx);
468 cond = masm->CheckSmi(rcx);
469 __ j(NegateCondition(cond), &exit);
472 __ xorq(rcx, Immediate(kSmiTagMask));
473 cond = masm->CheckSmi(rcx);
477 __ movl(rcx, Immediate(-1));
478 __ Integer32ToSmi(rcx, rcx);
479 cond = masm->CheckSmi(rcx);
480 __ j(NegateCondition(cond), &exit);
483 __ xorq(rcx, Immediate(kSmiTagMask));
484 cond = masm->CheckSmi(rcx);
488 __ movl(rcx, Immediate(Smi::kMaxValue));
489 __ Integer32ToSmi(rcx, rcx);
490 cond = masm->CheckSmi(rcx);
491 __ j(NegateCondition(cond), &exit);
494 __ xorq(rcx, Immediate(kSmiTagMask));
495 cond = masm->CheckSmi(rcx);
499 __ movl(rcx, Immediate(Smi::kMinValue));
500 __ Integer32ToSmi(rcx, rcx);
501 cond = masm->CheckSmi(rcx);
502 __ j(NegateCondition(cond), &exit);
505 __ xorq(rcx, Immediate(kSmiTagMask));
506 cond = masm->CheckSmi(rcx);
512 __ movl(rcx, Immediate(0));
513 __ Integer32ToSmi(rcx, rcx);
514 cond = masm->CheckNonNegativeSmi(rcx);
515 __ j(NegateCondition(cond), &exit);
518 __ xorq(rcx, Immediate(kSmiTagMask));
519 cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi.
523 __ movq(rcx, Immediate(-1));
524 __ Integer32ToSmi(rcx, rcx);
525 cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive.
529 __ movq(rcx, Immediate(Smi::kMinValue));
530 __ Integer32ToSmi(rcx, rcx);
531 cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive.
535 __ xorq(rcx, Immediate(kSmiTagMask));
536 cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi.
540 __ movq(rcx, Immediate(Smi::kMaxValue));
541 __ Integer32ToSmi(rcx, rcx);
542 cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive.
543 __ j(NegateCondition(cond), &exit);
546 __ xorq(rcx, Immediate(kSmiTagMask));
547 cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
553 __ movq(rcx, Immediate(Smi::kMaxValue));
554 __ Integer32ToSmi(rcx, rcx);
555 __ movq(rdx, Immediate(Smi::kMinValue));
556 __ Integer32ToSmi(rdx, rdx);
557 cond = masm->CheckBothSmi(rcx, rdx);
558 __ j(NegateCondition(cond), &exit);
561 __ xorq(rcx, Immediate(kSmiTagMask));
562 cond = masm->CheckBothSmi(rcx, rdx);
566 __ xorq(rdx, Immediate(kSmiTagMask));
567 cond = masm->CheckBothSmi(rcx, rdx);
571 __ xorq(rcx, Immediate(kSmiTagMask));
572 cond = masm->CheckBothSmi(rcx, rdx);
576 cond = masm->CheckBothSmi(rcx, rcx);
577 __ j(NegateCondition(cond), &exit);
580 cond = masm->CheckBothSmi(rdx, rdx);
583 // CheckInteger32ValidSmiValue
585 __ movq(rcx, Immediate(0));
586 cond = masm->CheckInteger32ValidSmiValue(rax);
587 __ j(NegateCondition(cond), &exit);
590 __ movq(rcx, Immediate(-1));
591 cond = masm->CheckInteger32ValidSmiValue(rax);
592 __ j(NegateCondition(cond), &exit);
595 __ movq(rcx, Immediate(Smi::kMaxValue));
596 cond = masm->CheckInteger32ValidSmiValue(rax);
597 __ j(NegateCondition(cond), &exit);
600 __ movq(rcx, Immediate(Smi::kMinValue));
601 cond = masm->CheckInteger32ValidSmiValue(rax);
602 __ j(NegateCondition(cond), &exit);
612 masm->GetCode(&desc);
613 // Call the function from C++.
614 int result = FUNCTION_CAST<F0>(buffer)();
620 void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
621 __ Move(rcx, Smi::FromInt(x));
623 if (x == Smi::kMinValue || x == 0) {
625 __ movl(rax, Immediate(id + 8));
626 __ SmiNeg(r9, rcx, exit);
630 __ j(not_equal, exit);
633 __ SmiNeg(rcx, rcx, exit);
637 __ j(not_equal, exit);
639 Label smi_ok, smi_ok2;
641 __ movl(rax, Immediate(id));
642 __ Move(r8, Smi::FromInt(result));
644 __ SmiNeg(r9, rcx, &smi_ok);
649 __ j(not_equal, exit);
653 __ j(not_equal, exit);
656 __ SmiNeg(rcx, rcx, &smi_ok2);
661 __ j(not_equal, exit);
667 // Allocate an executable page of memory.
669 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
670 Assembler::kMinimalBufferSize, &actual_size, true));
672 Isolate* isolate = CcTest::i_isolate();
673 HandleScope handles(isolate);
674 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
676 MacroAssembler* masm = &assembler;
680 TestSmiNeg(masm, &exit, 0x10, 0);
681 TestSmiNeg(masm, &exit, 0x20, 1);
682 TestSmiNeg(masm, &exit, 0x30, -1);
683 TestSmiNeg(masm, &exit, 0x40, 127);
684 TestSmiNeg(masm, &exit, 0x50, 65535);
685 TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
686 TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
687 TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
689 __ xorq(rax, rax); // Success.
695 masm->GetCode(&desc);
696 // Call the function from C++.
697 int result = FUNCTION_CAST<F0>(buffer)();
702 static void SmiAddTest(MacroAssembler* masm,
707 __ movl(rcx, Immediate(first));
708 __ Integer32ToSmi(rcx, rcx);
709 __ movl(rdx, Immediate(second));
710 __ Integer32ToSmi(rdx, rdx);
711 __ movl(r8, Immediate(first + second));
712 __ Integer32ToSmi(r8, r8);
714 __ movl(rax, Immediate(id)); // Test number.
715 __ SmiAdd(r9, rcx, rdx, exit);
717 __ j(not_equal, exit);
720 __ SmiAdd(rcx, rcx, rdx, exit);
722 __ j(not_equal, exit);
724 __ movl(rcx, Immediate(first));
725 __ Integer32ToSmi(rcx, rcx);
728 __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
730 __ j(not_equal, exit);
732 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
734 __ j(not_equal, exit);
736 __ movl(rcx, Immediate(first));
737 __ Integer32ToSmi(rcx, rcx);
739 i::SmiOperationExecutionMode mode;
740 mode.Add(i::PRESERVE_SOURCE_REGISTER);
741 mode.Add(i::BAILOUT_ON_OVERFLOW);
743 __ SmiAddConstant(r9, rcx, Smi::FromInt(second), mode, exit);
745 __ j(not_equal, exit);
748 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
750 __ j(not_equal, exit);
752 __ movl(rcx, Immediate(first));
753 __ Integer32ToSmi(rcx, rcx);
756 mode.Add(i::PRESERVE_SOURCE_REGISTER);
757 mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
760 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
764 __ j(not_equal, exit);
768 static void SmiAddOverflowTest(MacroAssembler* masm,
772 // Adds a Smi to x so that the addition overflows.
773 DCHECK(x != 0); // Can't overflow by adding a Smi.
774 int y_max = (x > 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue - x - 1);
775 int y_min = (x > 0) ? (Smi::kMaxValue - x + 1) : (Smi::kMinValue + 0);
777 __ movl(rax, Immediate(id));
778 __ Move(rcx, Smi::FromInt(x));
779 __ movq(r11, rcx); // Store original Smi value of x in r11.
780 __ Move(rdx, Smi::FromInt(y_min));
783 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
785 __ bind(&overflow_ok);
788 __ j(not_equal, exit);
794 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
796 __ bind(&overflow_ok);
799 __ j(not_equal, exit);
802 i::SmiOperationExecutionMode mode;
803 mode.Add(i::PRESERVE_SOURCE_REGISTER);
804 mode.Add(i::BAILOUT_ON_OVERFLOW);
809 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
811 __ bind(&overflow_ok);
814 __ j(not_equal, exit);
820 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
822 __ bind(&overflow_ok);
825 __ j(not_equal, exit);
828 __ Move(rdx, Smi::FromInt(y_max));
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);
856 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
858 __ bind(&overflow_ok);
861 __ j(not_equal, exit);
865 mode.Add(i::BAILOUT_ON_OVERFLOW);
869 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
871 __ bind(&overflow_ok);
880 // Allocate an executable page of memory.
882 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
883 Assembler::kMinimalBufferSize * 3, &actual_size, true));
885 Isolate* isolate = CcTest::i_isolate();
886 HandleScope handles(isolate);
887 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
889 MacroAssembler* masm = &assembler;
893 // No-overflow tests.
894 SmiAddTest(masm, &exit, 0x10, 1, 2);
895 SmiAddTest(masm, &exit, 0x20, 1, -2);
896 SmiAddTest(masm, &exit, 0x30, -1, 2);
897 SmiAddTest(masm, &exit, 0x40, -1, -2);
898 SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
899 SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
900 SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
901 SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
903 SmiAddOverflowTest(masm, &exit, 0x90, -1);
904 SmiAddOverflowTest(masm, &exit, 0xA0, 1);
905 SmiAddOverflowTest(masm, &exit, 0xB0, 1024);
906 SmiAddOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
907 SmiAddOverflowTest(masm, &exit, 0xD0, -2);
908 SmiAddOverflowTest(masm, &exit, 0xE0, -42000);
909 SmiAddOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
911 __ xorq(rax, rax); // Success.
917 masm->GetCode(&desc);
918 // Call the function from C++.
919 int result = FUNCTION_CAST<F0>(buffer)();
924 static void SmiSubTest(MacroAssembler* masm,
929 __ Move(rcx, Smi::FromInt(first));
930 __ Move(rdx, Smi::FromInt(second));
931 __ Move(r8, Smi::FromInt(first - second));
933 __ movl(rax, Immediate(id)); // Test 0.
934 __ SmiSub(r9, rcx, rdx, exit);
936 __ j(not_equal, exit);
938 __ incq(rax); // Test 1.
939 __ SmiSub(rcx, rcx, rdx, exit);
941 __ j(not_equal, exit);
943 __ Move(rcx, Smi::FromInt(first));
945 __ incq(rax); // Test 2.
946 __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
948 __ j(not_equal, exit);
950 __ incq(rax); // Test 3.
951 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
953 __ j(not_equal, exit);
955 i::SmiOperationExecutionMode mode;
956 mode.Add(i::PRESERVE_SOURCE_REGISTER);
957 mode.Add(i::BAILOUT_ON_OVERFLOW);
958 __ Move(rcx, Smi::FromInt(first));
959 __ incq(rax); // Test 4.
960 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
962 __ j(not_equal, exit);
964 __ Move(rcx, Smi::FromInt(first));
965 __ incq(rax); // Test 5.
966 __ SmiSubConstant(r9, rcx, Smi::FromInt(second), mode, exit);
968 __ j(not_equal, exit);
971 mode.Add(i::PRESERVE_SOURCE_REGISTER);
972 mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
973 __ Move(rcx, Smi::FromInt(first));
975 __ incq(rax); // Test 6.
976 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
980 __ j(not_equal, exit);
984 static void SmiSubOverflowTest(MacroAssembler* masm,
988 // Subtracts a Smi from x so that the subtraction overflows.
989 DCHECK(x != -1); // Can't overflow by subtracting a Smi.
990 int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
991 int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
993 __ movl(rax, Immediate(id));
994 __ Move(rcx, Smi::FromInt(x));
995 __ movq(r11, rcx); // Store original Smi value of x in r11.
996 __ Move(rdx, Smi::FromInt(y_min));
999 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1001 __ bind(&overflow_ok);
1004 __ j(not_equal, exit);
1010 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1012 __ bind(&overflow_ok);
1015 __ j(not_equal, exit);
1018 i::SmiOperationExecutionMode mode;
1019 mode.Add(i::PRESERVE_SOURCE_REGISTER);
1020 mode.Add(i::BAILOUT_ON_OVERFLOW);
1026 __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
1028 __ bind(&overflow_ok);
1031 __ j(not_equal, exit);
1037 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
1039 __ bind(&overflow_ok);
1042 __ j(not_equal, exit);
1045 __ Move(rdx, Smi::FromInt(y_max));
1050 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1052 __ bind(&overflow_ok);
1055 __ j(not_equal, exit);
1061 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1063 __ bind(&overflow_ok);
1066 __ j(not_equal, exit);
1073 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
1075 __ bind(&overflow_ok);
1078 __ j(not_equal, exit);
1082 mode.Add(i::BAILOUT_ON_OVERFLOW);
1087 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
1089 __ bind(&overflow_ok);
1098 // Allocate an executable page of memory.
1100 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1101 Assembler::kMinimalBufferSize * 4, &actual_size, true));
1103 Isolate* isolate = CcTest::i_isolate();
1104 HandleScope handles(isolate);
1105 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1107 MacroAssembler* masm = &assembler;
1111 SmiSubTest(masm, &exit, 0x10, 1, 2);
1112 SmiSubTest(masm, &exit, 0x20, 1, -2);
1113 SmiSubTest(masm, &exit, 0x30, -1, 2);
1114 SmiSubTest(masm, &exit, 0x40, -1, -2);
1115 SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
1116 SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
1117 SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
1118 SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
1119 SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
1121 SmiSubOverflowTest(masm, &exit, 0xA0, 1);
1122 SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
1123 SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
1124 SmiSubOverflowTest(masm, &exit, 0xD0, -2);
1125 SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
1126 SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
1127 SmiSubOverflowTest(masm, &exit, 0x100, 0);
1129 __ xorq(rax, rax); // Success.
1135 masm->GetCode(&desc);
1136 // Call the function from C++.
1137 int result = FUNCTION_CAST<F0>(buffer)();
1138 CHECK_EQ(0, result);
1143 void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1144 int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
1145 bool negative_zero = (result == 0) && (x < 0 || y < 0);
1146 __ Move(rcx, Smi::FromInt(x));
1148 __ Move(rdx, Smi::FromInt(y));
1149 if (Smi::IsValid(result) && !negative_zero) {
1150 __ movl(rax, Immediate(id));
1151 __ Move(r8, Smi::FromIntptr(result));
1152 __ SmiMul(r9, rcx, rdx, exit);
1155 __ j(not_equal, exit);
1158 __ j(not_equal, exit);
1161 __ SmiMul(rcx, rcx, rdx, exit);
1163 __ j(not_equal, exit);
1165 __ movl(rax, Immediate(id + 8));
1166 Label overflow_ok, overflow_ok2;
1167 __ SmiMul(r9, rcx, rdx, &overflow_ok);
1169 __ bind(&overflow_ok);
1172 __ j(not_equal, exit);
1174 __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
1176 __ bind(&overflow_ok2);
1177 // 31-bit version doesn't preserve rcx on failure.
1179 // __ cmpq(r11, rcx);
1180 // __ j(not_equal, exit);
1186 // Allocate an executable page of memory.
1188 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1189 Assembler::kMinimalBufferSize, &actual_size, true));
1191 Isolate* isolate = CcTest::i_isolate();
1192 HandleScope handles(isolate);
1193 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1195 MacroAssembler* masm = &assembler;
1199 TestSmiMul(masm, &exit, 0x10, 0, 0);
1200 TestSmiMul(masm, &exit, 0x20, -1, 0);
1201 TestSmiMul(masm, &exit, 0x30, 0, -1);
1202 TestSmiMul(masm, &exit, 0x40, -1, -1);
1203 TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
1204 TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
1205 TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
1206 TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
1207 TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
1208 TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
1209 TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
1210 TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
1211 TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
1212 TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
1214 __ xorq(rax, rax); // Success.
1220 masm->GetCode(&desc);
1221 // Call the function from C++.
1222 int result = FUNCTION_CAST<F0>(buffer)();
1223 CHECK_EQ(0, result);
1227 void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1228 bool division_by_zero = (y == 0);
1229 bool negative_zero = (x == 0 && y < 0);
1230 #if V8_TARGET_ARCH_X64
1231 bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
1233 bool overflow = (x == Smi::kMinValue && y == -1);
1235 bool fraction = !division_by_zero && !overflow && (x % y != 0);
1236 __ Move(r11, Smi::FromInt(x));
1237 __ Move(r14, Smi::FromInt(y));
1238 if (!fraction && !overflow && !negative_zero && !division_by_zero) {
1239 // Division succeeds
1241 __ movq(r15, Immediate(id));
1243 __ Move(r8, Smi::FromInt(result));
1244 __ SmiDiv(r9, rcx, r14, exit);
1245 // Might have destroyed rcx and r14.
1248 __ j(not_equal, exit);
1252 __ Move(r14, Smi::FromInt(y));
1254 __ j(not_equal, exit);
1257 __ SmiDiv(rcx, rcx, r14, exit);
1261 __ j(not_equal, exit);
1264 __ movq(r15, Immediate(id + 8));
1266 Label fail_ok, fail_ok2;
1268 __ SmiDiv(r9, rcx, r14, &fail_ok);
1274 __ j(not_equal, exit);
1277 __ SmiDiv(rcx, rcx, r14, &fail_ok2);
1283 __ j(not_equal, exit);
1289 // Allocate an executable page of memory.
1291 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1292 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1294 Isolate* isolate = CcTest::i_isolate();
1295 HandleScope handles(isolate);
1296 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1298 MacroAssembler* masm = &assembler;
1304 TestSmiDiv(masm, &exit, 0x10, 1, 1);
1305 TestSmiDiv(masm, &exit, 0x20, 1, 0);
1306 TestSmiDiv(masm, &exit, 0x30, -1, 0);
1307 TestSmiDiv(masm, &exit, 0x40, 0, 1);
1308 TestSmiDiv(masm, &exit, 0x50, 0, -1);
1309 TestSmiDiv(masm, &exit, 0x60, 4, 2);
1310 TestSmiDiv(masm, &exit, 0x70, -4, 2);
1311 TestSmiDiv(masm, &exit, 0x80, 4, -2);
1312 TestSmiDiv(masm, &exit, 0x90, -4, -2);
1313 TestSmiDiv(masm, &exit, 0xa0, 3, 2);
1314 TestSmiDiv(masm, &exit, 0xb0, 3, 4);
1315 TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1316 TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1317 TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1318 TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1319 TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1320 TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
1321 TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
1322 TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1323 TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
1325 __ xorq(r15, r15); // Success.
1334 masm->GetCode(&desc);
1335 // Call the function from C++.
1336 int result = FUNCTION_CAST<F0>(buffer)();
1337 CHECK_EQ(0, result);
1341 void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1342 bool division_by_zero = (y == 0);
1343 bool division_overflow = (x == Smi::kMinValue) && (y == -1);
1344 bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
1345 bool negative_zero = (!fraction && x < 0);
1346 __ Move(rcx, Smi::FromInt(x));
1348 __ Move(r14, Smi::FromInt(y));
1349 if (!division_overflow && !negative_zero && !division_by_zero) {
1351 __ movq(r15, Immediate(id));
1353 __ Move(r8, Smi::FromInt(result));
1354 __ SmiMod(r9, rcx, r14, exit);
1358 __ j(not_equal, exit);
1362 __ j(not_equal, exit);
1365 __ SmiMod(rcx, rcx, r14, exit);
1369 __ j(not_equal, exit);
1372 __ movq(r15, Immediate(id + 8));
1374 Label fail_ok, fail_ok2;
1375 __ SmiMod(r9, rcx, r14, &fail_ok);
1381 __ j(not_equal, exit);
1384 __ SmiMod(rcx, rcx, r14, &fail_ok2);
1390 __ j(not_equal, exit);
1396 // Allocate an executable page of memory.
1398 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1399 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1401 Isolate* isolate = CcTest::i_isolate();
1402 HandleScope handles(isolate);
1403 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1405 MacroAssembler* masm = &assembler;
1411 TestSmiMod(masm, &exit, 0x10, 1, 1);
1412 TestSmiMod(masm, &exit, 0x20, 1, 0);
1413 TestSmiMod(masm, &exit, 0x30, -1, 0);
1414 TestSmiMod(masm, &exit, 0x40, 0, 1);
1415 TestSmiMod(masm, &exit, 0x50, 0, -1);
1416 TestSmiMod(masm, &exit, 0x60, 4, 2);
1417 TestSmiMod(masm, &exit, 0x70, -4, 2);
1418 TestSmiMod(masm, &exit, 0x80, 4, -2);
1419 TestSmiMod(masm, &exit, 0x90, -4, -2);
1420 TestSmiMod(masm, &exit, 0xa0, 3, 2);
1421 TestSmiMod(masm, &exit, 0xb0, 3, 4);
1422 TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1423 TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1424 TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1425 TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1426 TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1427 TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
1428 TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
1429 TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1430 TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
1432 __ xorq(r15, r15); // Success.
1441 masm->GetCode(&desc);
1442 // Call the function from C++.
1443 int result = FUNCTION_CAST<F0>(buffer)();
1444 CHECK_EQ(0, result);
1448 void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
1449 __ movl(rax, Immediate(id));
1451 for (int i = 0; i < 8; i++) {
1452 __ Move(rcx, Smi::FromInt(x));
1453 SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
1454 DCHECK(index.reg.is(rcx) || index.reg.is(rdx));
1455 __ shlq(index.reg, Immediate(index.scale));
1456 __ Set(r8, static_cast<intptr_t>(x) << i);
1457 __ cmpq(index.reg, r8);
1458 __ j(not_equal, exit);
1460 __ Move(rcx, Smi::FromInt(x));
1461 index = masm->SmiToIndex(rcx, rcx, i);
1462 DCHECK(index.reg.is(rcx));
1463 __ shlq(rcx, Immediate(index.scale));
1464 __ Set(r8, static_cast<intptr_t>(x) << i);
1466 __ j(not_equal, exit);
1469 __ Move(rcx, Smi::FromInt(x));
1470 index = masm->SmiToNegativeIndex(rdx, rcx, i);
1471 DCHECK(index.reg.is(rcx) || index.reg.is(rdx));
1472 __ shlq(index.reg, Immediate(index.scale));
1473 __ Set(r8, static_cast<intptr_t>(-x) << i);
1474 __ cmpq(index.reg, r8);
1475 __ j(not_equal, exit);
1477 __ Move(rcx, Smi::FromInt(x));
1478 index = masm->SmiToNegativeIndex(rcx, rcx, i);
1479 DCHECK(index.reg.is(rcx));
1480 __ shlq(rcx, Immediate(index.scale));
1481 __ Set(r8, static_cast<intptr_t>(-x) << i);
1483 __ j(not_equal, exit);
1490 // Allocate an executable page of memory.
1492 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1493 Assembler::kMinimalBufferSize * 5, &actual_size, true));
1495 Isolate* isolate = CcTest::i_isolate();
1496 HandleScope handles(isolate);
1497 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1499 MacroAssembler* masm = &assembler;
1503 TestSmiIndex(masm, &exit, 0x10, 0);
1504 TestSmiIndex(masm, &exit, 0x20, 1);
1505 TestSmiIndex(masm, &exit, 0x30, 100);
1506 TestSmiIndex(masm, &exit, 0x40, 1000);
1507 TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
1509 __ xorq(rax, rax); // Success.
1515 masm->GetCode(&desc);
1516 // Call the function from C++.
1517 int result = FUNCTION_CAST<F0>(buffer)();
1518 CHECK_EQ(0, result);
1522 void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1523 __ movl(rax, Immediate(id));
1524 __ Move(rcx, Smi::FromInt(x));
1525 __ Move(rdx, Smi::FromInt(y));
1526 __ xorq(rdx, Immediate(kSmiTagMask));
1527 __ SelectNonSmi(r9, rcx, rdx, exit);
1531 __ j(not_equal, exit);
1534 __ Move(rcx, Smi::FromInt(x));
1535 __ Move(rdx, Smi::FromInt(y));
1536 __ xorq(rcx, Immediate(kSmiTagMask));
1537 __ SelectNonSmi(r9, rcx, rdx, exit);
1541 __ j(not_equal, exit);
1545 __ Move(rcx, Smi::FromInt(x));
1546 __ Move(rdx, Smi::FromInt(y));
1547 __ xorq(rcx, Immediate(kSmiTagMask));
1548 __ xorq(rdx, Immediate(kSmiTagMask));
1549 __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
1555 TEST(SmiSelectNonSmi) {
1556 // Allocate an executable page of memory.
1558 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1559 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1561 Isolate* isolate = CcTest::i_isolate();
1562 HandleScope handles(isolate);
1563 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1565 MacroAssembler* masm = &assembler;
1569 TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
1570 TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
1571 TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
1572 TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
1573 TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
1574 TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
1575 TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
1576 TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1577 TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1579 __ xorq(rax, rax); // Success.
1585 masm->GetCode(&desc);
1586 // Call the function from C++.
1587 int result = FUNCTION_CAST<F0>(buffer)();
1588 CHECK_EQ(0, result);
1592 void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1595 __ movl(rax, Immediate(id));
1597 __ Move(rcx, Smi::FromInt(x));
1599 __ Move(rdx, Smi::FromInt(y));
1600 __ Move(r8, Smi::FromInt(result));
1601 __ SmiAnd(r9, rcx, rdx);
1603 __ j(not_equal, exit);
1607 __ j(not_equal, exit);
1610 __ SmiAnd(rcx, rcx, rdx);
1612 __ j(not_equal, exit);
1616 __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
1618 __ j(not_equal, exit);
1622 __ j(not_equal, exit);
1625 __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
1627 __ j(not_equal, exit);
1632 // Allocate an executable page of memory.
1634 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1635 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1637 Isolate* isolate = CcTest::i_isolate();
1638 HandleScope handles(isolate);
1639 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1641 MacroAssembler* masm = &assembler;
1645 TestSmiAnd(masm, &exit, 0x10, 0, 0);
1646 TestSmiAnd(masm, &exit, 0x20, 0, 1);
1647 TestSmiAnd(masm, &exit, 0x30, 1, 0);
1648 TestSmiAnd(masm, &exit, 0x40, 0, -1);
1649 TestSmiAnd(masm, &exit, 0x50, -1, 0);
1650 TestSmiAnd(masm, &exit, 0x60, -1, -1);
1651 TestSmiAnd(masm, &exit, 0x70, 1, 1);
1652 TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1653 TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1654 TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
1655 TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
1657 __ xorq(rax, rax); // Success.
1663 masm->GetCode(&desc);
1664 // Call the function from C++.
1665 int result = FUNCTION_CAST<F0>(buffer)();
1666 CHECK_EQ(0, result);
1670 void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1673 __ movl(rax, Immediate(id));
1675 __ Move(rcx, Smi::FromInt(x));
1677 __ Move(rdx, Smi::FromInt(y));
1678 __ Move(r8, Smi::FromInt(result));
1679 __ SmiOr(r9, rcx, rdx);
1681 __ j(not_equal, exit);
1685 __ j(not_equal, exit);
1688 __ SmiOr(rcx, rcx, rdx);
1690 __ j(not_equal, exit);
1694 __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
1696 __ j(not_equal, exit);
1700 __ j(not_equal, exit);
1703 __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
1705 __ j(not_equal, exit);
1710 // Allocate an executable page of memory.
1712 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1713 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1715 Isolate* isolate = CcTest::i_isolate();
1716 HandleScope handles(isolate);
1717 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1719 MacroAssembler* masm = &assembler;
1723 TestSmiOr(masm, &exit, 0x10, 0, 0);
1724 TestSmiOr(masm, &exit, 0x20, 0, 1);
1725 TestSmiOr(masm, &exit, 0x30, 1, 0);
1726 TestSmiOr(masm, &exit, 0x40, 0, -1);
1727 TestSmiOr(masm, &exit, 0x50, -1, 0);
1728 TestSmiOr(masm, &exit, 0x60, -1, -1);
1729 TestSmiOr(masm, &exit, 0x70, 1, 1);
1730 TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1731 TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1732 TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
1733 TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
1734 TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
1735 TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
1737 __ xorq(rax, rax); // Success.
1743 masm->GetCode(&desc);
1744 // Call the function from C++.
1745 int result = FUNCTION_CAST<F0>(buffer)();
1746 CHECK_EQ(0, result);
1750 void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1753 __ movl(rax, Immediate(id));
1755 __ Move(rcx, Smi::FromInt(x));
1757 __ Move(rdx, Smi::FromInt(y));
1758 __ Move(r8, Smi::FromInt(result));
1759 __ SmiXor(r9, rcx, rdx);
1761 __ j(not_equal, exit);
1765 __ j(not_equal, exit);
1768 __ SmiXor(rcx, rcx, rdx);
1770 __ j(not_equal, exit);
1774 __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
1776 __ j(not_equal, exit);
1780 __ j(not_equal, exit);
1783 __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
1785 __ j(not_equal, exit);
1790 // Allocate an executable page of memory.
1792 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1793 Assembler::kMinimalBufferSize * 2, &actual_size, true));
1795 Isolate* isolate = CcTest::i_isolate();
1796 HandleScope handles(isolate);
1797 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1799 MacroAssembler* masm = &assembler;
1803 TestSmiXor(masm, &exit, 0x10, 0, 0);
1804 TestSmiXor(masm, &exit, 0x20, 0, 1);
1805 TestSmiXor(masm, &exit, 0x30, 1, 0);
1806 TestSmiXor(masm, &exit, 0x40, 0, -1);
1807 TestSmiXor(masm, &exit, 0x50, -1, 0);
1808 TestSmiXor(masm, &exit, 0x60, -1, -1);
1809 TestSmiXor(masm, &exit, 0x70, 1, 1);
1810 TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1811 TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1812 TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
1813 TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
1814 TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
1815 TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
1817 __ xorq(rax, rax); // Success.
1823 masm->GetCode(&desc);
1824 // Call the function from C++.
1825 int result = FUNCTION_CAST<F0>(buffer)();
1826 CHECK_EQ(0, result);
1830 void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
1832 __ movl(rax, Immediate(id));
1834 __ Move(r8, Smi::FromInt(result));
1835 __ Move(rcx, Smi::FromInt(x));
1840 __ j(not_equal, exit);
1844 __ j(not_equal, exit);
1847 __ SmiNot(rcx, rcx);
1849 __ j(not_equal, exit);
1854 // Allocate an executable page of memory.
1856 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1857 Assembler::kMinimalBufferSize, &actual_size, true));
1859 Isolate* isolate = CcTest::i_isolate();
1860 HandleScope handles(isolate);
1861 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1863 MacroAssembler* masm = &assembler;
1867 TestSmiNot(masm, &exit, 0x10, 0);
1868 TestSmiNot(masm, &exit, 0x20, 1);
1869 TestSmiNot(masm, &exit, 0x30, -1);
1870 TestSmiNot(masm, &exit, 0x40, 127);
1871 TestSmiNot(masm, &exit, 0x50, 65535);
1872 TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
1873 TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
1874 TestSmiNot(masm, &exit, 0x80, 0x05555555);
1876 __ xorq(rax, rax); // Success.
1882 masm->GetCode(&desc);
1883 // Call the function from C++.
1884 int result = FUNCTION_CAST<F0>(buffer)();
1885 CHECK_EQ(0, result);
1889 void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
1890 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1891 const int kNumShifts = 5;
1892 __ movl(rax, Immediate(id));
1893 for (int i = 0; i < kNumShifts; i++) {
1894 // rax == id + i * 10.
1895 int shift = shifts[i];
1896 int result = x << shift;
1897 CHECK(Smi::IsValid(result));
1898 __ Move(r8, Smi::FromInt(result));
1899 __ Move(rcx, Smi::FromInt(x));
1900 __ SmiShiftLeftConstant(r9, rcx, shift);
1904 __ j(not_equal, exit);
1907 __ Move(rcx, Smi::FromInt(x));
1908 __ SmiShiftLeftConstant(rcx, rcx, shift);
1912 __ j(not_equal, exit);
1915 __ Move(rdx, Smi::FromInt(x));
1916 __ Move(rcx, Smi::FromInt(shift));
1917 __ SmiShiftLeft(r9, rdx, rcx);
1921 __ j(not_equal, exit);
1924 __ Move(rdx, Smi::FromInt(x));
1925 __ Move(r11, Smi::FromInt(shift));
1926 __ SmiShiftLeft(r9, rdx, r11);
1930 __ j(not_equal, exit);
1933 __ Move(rdx, Smi::FromInt(x));
1934 __ Move(r11, Smi::FromInt(shift));
1935 __ SmiShiftLeft(rdx, rdx, r11);
1939 __ j(not_equal, exit);
1946 TEST(SmiShiftLeft) {
1947 // Allocate an executable page of memory.
1949 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1950 Assembler::kMinimalBufferSize * 7, &actual_size, true));
1952 Isolate* isolate = CcTest::i_isolate();
1953 HandleScope handles(isolate);
1954 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
1956 MacroAssembler* masm = &assembler;
1960 TestSmiShiftLeft(masm, &exit, 0x10, 0);
1961 TestSmiShiftLeft(masm, &exit, 0x50, 1);
1962 TestSmiShiftLeft(masm, &exit, 0x90, 127);
1963 TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
1964 TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
1965 TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
1966 TestSmiShiftLeft(masm, &exit, 0x190, -1);
1968 __ xorq(rax, rax); // Success.
1974 masm->GetCode(&desc);
1975 // Call the function from C++.
1976 int result = FUNCTION_CAST<F0>(buffer)();
1977 CHECK_EQ(0, result);
1981 void TestSmiShiftLogicalRight(MacroAssembler* masm,
1985 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1986 const int kNumShifts = 5;
1987 __ movl(rax, Immediate(id));
1988 for (int i = 0; i < kNumShifts; i++) {
1989 int shift = shifts[i];
1990 intptr_t result = static_cast<unsigned int>(x) >> shift;
1991 if (Smi::IsValid(result)) {
1992 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
1993 __ Move(rcx, Smi::FromInt(x));
1994 __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
1998 __ j(not_equal, exit);
2001 __ Move(rdx, Smi::FromInt(x));
2002 __ Move(rcx, Smi::FromInt(shift));
2003 __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
2007 __ j(not_equal, exit);
2010 __ Move(rdx, Smi::FromInt(x));
2011 __ Move(r11, Smi::FromInt(shift));
2012 __ SmiShiftLogicalRight(r9, rdx, r11, exit);
2016 __ j(not_equal, exit);
2020 // Cannot happen with long smis.
2022 __ Move(rcx, Smi::FromInt(x));
2024 __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
2030 __ j(not_equal, exit);
2033 __ Move(r8, Smi::FromInt(shift));
2035 __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
2041 __ j(not_equal, exit);
2043 __ addq(rax, Immediate(3));
2049 TEST(SmiShiftLogicalRight) {
2050 // Allocate an executable page of memory.
2052 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2053 Assembler::kMinimalBufferSize * 5, &actual_size, true));
2055 Isolate* isolate = CcTest::i_isolate();
2056 HandleScope handles(isolate);
2057 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2059 MacroAssembler* masm = &assembler;
2063 TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
2064 TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
2065 TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
2066 TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
2067 TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
2068 TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
2069 TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
2071 __ xorq(rax, rax); // Success.
2077 masm->GetCode(&desc);
2078 // Call the function from C++.
2079 int result = FUNCTION_CAST<F0>(buffer)();
2080 CHECK_EQ(0, result);
2084 void TestSmiShiftArithmeticRight(MacroAssembler* masm,
2088 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2089 const int kNumShifts = 5;
2090 __ movl(rax, Immediate(id));
2091 for (int i = 0; i < kNumShifts; i++) {
2092 int shift = shifts[i];
2093 // Guaranteed arithmetic shift.
2094 int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
2095 __ Move(r8, Smi::FromInt(result));
2096 __ Move(rcx, Smi::FromInt(x));
2097 __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
2100 __ j(not_equal, exit);
2103 __ Move(rdx, Smi::FromInt(x));
2104 __ Move(r11, Smi::FromInt(shift));
2105 __ SmiShiftArithmeticRight(rdx, rdx, r11);
2108 __ j(not_equal, exit);
2115 TEST(SmiShiftArithmeticRight) {
2116 // Allocate an executable page of memory.
2118 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2119 Assembler::kMinimalBufferSize * 3, &actual_size, true));
2121 Isolate* isolate = CcTest::i_isolate();
2122 HandleScope handles(isolate);
2123 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2125 MacroAssembler* masm = &assembler;
2129 TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
2130 TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
2131 TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
2132 TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
2133 TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
2134 TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
2135 TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
2137 __ xorq(rax, rax); // Success.
2143 masm->GetCode(&desc);
2144 // Call the function from C++.
2145 int result = FUNCTION_CAST<F0>(buffer)();
2146 CHECK_EQ(0, result);
2150 void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
2152 int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
2153 int power_count = 8;
2154 __ movl(rax, Immediate(id));
2155 for (int i = 0; i < power_count; i++) {
2156 int power = powers[i];
2157 intptr_t result = static_cast<intptr_t>(x) << power;
2159 __ Move(rcx, Smi::FromInt(x));
2161 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
2163 __ j(not_equal, exit);
2165 __ cmpq(r11, rcx); // rcx unchanged.
2166 __ j(not_equal, exit);
2168 __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
2170 __ j(not_equal, exit);
2176 TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
2177 // Allocate an executable page of memory.
2179 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2180 Assembler::kMinimalBufferSize * 4, &actual_size, true));
2182 Isolate* isolate = CcTest::i_isolate();
2183 HandleScope handles(isolate);
2184 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2186 MacroAssembler* masm = &assembler;
2190 TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
2191 TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
2192 TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
2193 TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
2194 TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
2195 TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
2196 TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
2197 TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
2198 TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
2200 __ xorq(rax, rax); // Success.
2206 masm->GetCode(&desc);
2207 // Call the function from C++.
2208 int result = FUNCTION_CAST<F0>(buffer)();
2209 CHECK_EQ(0, result);
2213 TEST(OperandOffset) {
2215 for (uint32_t i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
2217 // Allocate an executable page of memory.
2219 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2220 Assembler::kMinimalBufferSize * 2, &actual_size, true));
2222 Isolate* isolate = CcTest::i_isolate();
2223 HandleScope handles(isolate);
2224 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2226 MacroAssembler* masm = &assembler;
2234 __ pushq(Immediate(0x100)); // <-- rbp
2236 __ pushq(Immediate(0x101));
2237 __ pushq(Immediate(0x102));
2238 __ pushq(Immediate(0x103));
2239 __ pushq(Immediate(0x104));
2240 __ pushq(Immediate(0x105)); // <-- rbx
2241 __ pushq(Immediate(0x106));
2242 __ pushq(Immediate(0x107));
2243 __ pushq(Immediate(0x108));
2244 __ pushq(Immediate(0x109)); // <-- rsp
2249 __ leaq(r14, Operand(rsp, 3 * kPointerSize));
2250 __ leaq(r13, Operand(rbp, -3 * kPointerSize));
2251 __ leaq(rbx, Operand(rbp, -5 * kPointerSize));
2252 __ movl(rcx, Immediate(2));
2253 __ Move(r8, reinterpret_cast<Address>(&data[128]), RelocInfo::NONE64);
2254 __ movl(rax, Immediate(1));
2256 Operand sp0 = Operand(rsp, 0);
2259 __ movl(rdx, sp0); // Sanity check.
2260 __ cmpl(rdx, Immediate(0x109));
2261 __ j(not_equal, &exit);
2265 // Zero to non-zero displacement.
2266 __ movl(rdx, Operand(sp0, 2 * kPointerSize));
2267 __ cmpl(rdx, Immediate(0x107));
2268 __ j(not_equal, &exit);
2271 Operand sp2 = Operand(rsp, 2 * kPointerSize);
2274 __ movl(rdx, sp2); // Sanity check.
2275 __ cmpl(rdx, Immediate(0x107));
2276 __ j(not_equal, &exit);
2279 __ movl(rdx, Operand(sp2, 2 * kPointerSize));
2280 __ cmpl(rdx, Immediate(0x105));
2281 __ j(not_equal, &exit);
2284 // Non-zero to zero displacement.
2285 __ movl(rdx, Operand(sp2, -2 * kPointerSize));
2286 __ cmpl(rdx, Immediate(0x109));
2287 __ j(not_equal, &exit);
2290 Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
2293 __ movl(rdx, sp2c2); // Sanity check.
2294 __ cmpl(rdx, Immediate(0x105));
2295 __ j(not_equal, &exit);
2298 __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
2299 __ cmpl(rdx, Immediate(0x103));
2300 __ j(not_equal, &exit);
2303 // Non-zero to zero displacement.
2304 __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
2305 __ cmpl(rdx, Immediate(0x107));
2306 __ j(not_equal, &exit);
2310 Operand bp0 = Operand(rbp, 0);
2313 __ movl(rdx, bp0); // Sanity check.
2314 __ cmpl(rdx, Immediate(0x100));
2315 __ j(not_equal, &exit);
2318 // Zero to non-zero displacement.
2319 __ movl(rdx, Operand(bp0, -2 * kPointerSize));
2320 __ cmpl(rdx, Immediate(0x102));
2321 __ j(not_equal, &exit);
2324 Operand bp2 = Operand(rbp, -2 * kPointerSize);
2327 __ movl(rdx, bp2); // Sanity check.
2328 __ cmpl(rdx, Immediate(0x102));
2329 __ j(not_equal, &exit);
2332 // Non-zero to zero displacement.
2333 __ movl(rdx, Operand(bp2, 2 * kPointerSize));
2334 __ cmpl(rdx, Immediate(0x100));
2335 __ j(not_equal, &exit);
2338 __ movl(rdx, Operand(bp2, -2 * kPointerSize));
2339 __ cmpl(rdx, Immediate(0x104));
2340 __ j(not_equal, &exit);
2343 Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
2346 __ movl(rdx, bp2c4); // Sanity check.
2347 __ cmpl(rdx, Immediate(0x102));
2348 __ j(not_equal, &exit);
2351 __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
2352 __ cmpl(rdx, Immediate(0x100));
2353 __ j(not_equal, &exit);
2356 __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
2357 __ cmpl(rdx, Immediate(0x104));
2358 __ j(not_equal, &exit);
2361 Operand bx0 = Operand(rbx, 0);
2364 __ movl(rdx, bx0); // Sanity check.
2365 __ cmpl(rdx, Immediate(0x105));
2366 __ j(not_equal, &exit);
2369 __ movl(rdx, Operand(bx0, 5 * kPointerSize));
2370 __ cmpl(rdx, Immediate(0x100));
2371 __ j(not_equal, &exit);
2374 __ movl(rdx, Operand(bx0, -4 * kPointerSize));
2375 __ cmpl(rdx, Immediate(0x109));
2376 __ j(not_equal, &exit);
2379 Operand bx2 = Operand(rbx, 2 * kPointerSize);
2382 __ movl(rdx, bx2); // Sanity check.
2383 __ cmpl(rdx, Immediate(0x103));
2384 __ j(not_equal, &exit);
2387 __ movl(rdx, Operand(bx2, 2 * kPointerSize));
2388 __ cmpl(rdx, Immediate(0x101));
2389 __ j(not_equal, &exit);
2392 // Non-zero to zero displacement.
2393 __ movl(rdx, Operand(bx2, -2 * kPointerSize));
2394 __ cmpl(rdx, Immediate(0x105));
2395 __ j(not_equal, &exit);
2398 Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
2401 __ movl(rdx, bx2c2); // Sanity check.
2402 __ cmpl(rdx, Immediate(0x105));
2403 __ j(not_equal, &exit);
2406 __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
2407 __ cmpl(rdx, Immediate(0x103));
2408 __ j(not_equal, &exit);
2411 __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
2412 __ cmpl(rdx, Immediate(0x107));
2413 __ j(not_equal, &exit);
2416 Operand r80 = Operand(r8, 0);
2419 __ movl(rdx, r80); // Sanity check.
2420 __ cmpl(rdx, Immediate(0x80808080));
2421 __ j(not_equal, &exit);
2424 __ movl(rdx, Operand(r80, -8 * kIntSize));
2425 __ cmpl(rdx, Immediate(0x78787878));
2426 __ j(not_equal, &exit);
2429 __ movl(rdx, Operand(r80, 8 * kIntSize));
2430 __ cmpl(rdx, Immediate(0x88888888));
2431 __ j(not_equal, &exit);
2434 __ movl(rdx, Operand(r80, -64 * kIntSize));
2435 __ cmpl(rdx, Immediate(0x40404040));
2436 __ j(not_equal, &exit);
2439 __ movl(rdx, Operand(r80, 64 * kIntSize));
2440 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2441 __ j(not_equal, &exit);
2444 Operand r88 = Operand(r8, 8 * kIntSize);
2447 __ movl(rdx, r88); // Sanity check.
2448 __ cmpl(rdx, Immediate(0x88888888));
2449 __ j(not_equal, &exit);
2452 __ movl(rdx, Operand(r88, -8 * kIntSize));
2453 __ cmpl(rdx, Immediate(0x80808080));
2454 __ j(not_equal, &exit);
2457 __ movl(rdx, Operand(r88, 8 * kIntSize));
2458 __ cmpl(rdx, Immediate(0x90909090));
2459 __ j(not_equal, &exit);
2462 __ movl(rdx, Operand(r88, -64 * kIntSize));
2463 __ cmpl(rdx, Immediate(0x48484848));
2464 __ j(not_equal, &exit);
2467 __ movl(rdx, Operand(r88, 64 * kIntSize));
2468 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2469 __ j(not_equal, &exit);
2473 Operand r864 = Operand(r8, 64 * kIntSize);
2476 __ movl(rdx, r864); // Sanity check.
2477 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2478 __ j(not_equal, &exit);
2481 __ movl(rdx, Operand(r864, -8 * kIntSize));
2482 __ cmpl(rdx, Immediate(0xB8B8B8B8));
2483 __ j(not_equal, &exit);
2486 __ movl(rdx, Operand(r864, 8 * kIntSize));
2487 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2488 __ j(not_equal, &exit);
2491 __ movl(rdx, Operand(r864, -64 * kIntSize));
2492 __ cmpl(rdx, Immediate(0x80808080));
2493 __ j(not_equal, &exit);
2496 __ movl(rdx, Operand(r864, 32 * kIntSize));
2497 __ cmpl(rdx, Immediate(0xE0E0E0E0));
2498 __ j(not_equal, &exit);
2501 // 32-bit offset to 8-bit offset.
2502 __ movl(rdx, Operand(r864, -60 * kIntSize));
2503 __ cmpl(rdx, Immediate(0x84848484));
2504 __ j(not_equal, &exit);
2507 __ movl(rdx, Operand(r864, 60 * kIntSize));
2508 __ cmpl(rdx, Immediate(0xFCFCFCFC));
2509 __ j(not_equal, &exit);
2512 // Test unaligned offsets.
2515 __ movl(rdx, Operand(r80, 2));
2516 __ cmpl(rdx, Immediate(0x81818080));
2517 __ j(not_equal, &exit);
2520 __ movl(rdx, Operand(r80, -2));
2521 __ cmpl(rdx, Immediate(0x80807F7F));
2522 __ j(not_equal, &exit);
2525 __ movl(rdx, Operand(r80, 126));
2526 __ cmpl(rdx, Immediate(0xA0A09F9F));
2527 __ j(not_equal, &exit);
2530 __ movl(rdx, Operand(r80, -126));
2531 __ cmpl(rdx, Immediate(0x61616060));
2532 __ j(not_equal, &exit);
2535 __ movl(rdx, Operand(r80, 254));
2536 __ cmpl(rdx, Immediate(0xC0C0BFBF));
2537 __ j(not_equal, &exit);
2540 __ movl(rdx, Operand(r80, -254));
2541 __ cmpl(rdx, Immediate(0x41414040));
2542 __ j(not_equal, &exit);
2547 __ movl(rax, Immediate(0));
2549 __ leaq(rsp, Operand(rbp, kPointerSize));
2559 masm->GetCode(&desc);
2560 // Call the function from C++.
2561 int result = FUNCTION_CAST<F0>(buffer)();
2562 CHECK_EQ(0, result);
2566 TEST(LoadAndStoreWithRepresentation) {
2567 // Allocate an executable page of memory.
2569 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2570 Assembler::kMinimalBufferSize, &actual_size, true));
2572 Isolate* isolate = CcTest::i_isolate();
2573 HandleScope handles(isolate);
2574 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
2575 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
2577 __ subq(rsp, Immediate(1 * kPointerSize));
2581 __ movq(rax, Immediate(1)); // Test number.
2582 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2583 __ movq(rcx, Immediate(-1));
2584 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger8());
2585 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2586 __ movl(rdx, Immediate(255));
2588 __ j(not_equal, &exit);
2589 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger8());
2591 __ j(not_equal, &exit);
2594 __ movq(rax, Immediate(2)); // Test number.
2595 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2596 __ Set(rcx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2597 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Smi());
2598 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2599 __ Set(rdx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2601 __ j(not_equal, &exit);
2602 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Smi());
2604 __ j(not_equal, &exit);
2607 __ movq(rax, Immediate(3)); // Test number.
2608 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2609 __ movq(rcx, Immediate(-1));
2610 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer32());
2611 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2612 __ movl(rdx, Immediate(-1));
2614 __ j(not_equal, &exit);
2615 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer32());
2617 __ j(not_equal, &exit);
2620 __ movq(rax, Immediate(4)); // Test number.
2621 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2622 __ movl(rcx, Immediate(0x44332211));
2623 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::HeapObject());
2624 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2625 __ movl(rdx, Immediate(0x44332211));
2627 __ j(not_equal, &exit);
2628 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::HeapObject());
2630 __ j(not_equal, &exit);
2633 __ movq(rax, Immediate(5)); // Test number.
2634 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2635 __ Set(rcx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2636 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Tagged());
2637 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2638 __ Set(rdx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2640 __ j(not_equal, &exit);
2641 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Tagged());
2643 __ j(not_equal, &exit);
2646 __ movq(rax, Immediate(6)); // Test number.
2647 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2648 __ Set(rcx, V8_2PART_UINT64_C(0x11223344, 55667788));
2649 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::External());
2650 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2651 __ Set(rdx, V8_2PART_UINT64_C(0x11223344, 55667788));
2653 __ j(not_equal, &exit);
2654 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::External());
2656 __ j(not_equal, &exit);
2659 __ movq(rax, Immediate(7)); // Test number.
2660 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2661 __ movq(rcx, Immediate(-1));
2662 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer8());
2663 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2664 __ movl(rdx, Immediate(255));
2666 __ j(not_equal, &exit);
2667 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer8());
2668 __ movq(rcx, Immediate(-1));
2670 __ j(not_equal, &exit);
2673 __ movq(rax, Immediate(8)); // Test number.
2674 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2675 __ movq(rcx, Immediate(-1));
2676 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer16());
2677 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2678 __ movl(rdx, Immediate(65535));
2680 __ j(not_equal, &exit);
2681 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer16());
2682 __ movq(rcx, Immediate(-1));
2684 __ j(not_equal, &exit);
2687 __ movq(rax, Immediate(9)); // Test number.
2688 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2689 __ movq(rcx, Immediate(-1));
2690 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger16());
2691 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2692 __ movl(rdx, Immediate(65535));
2694 __ j(not_equal, &exit);
2695 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger16());
2697 __ j(not_equal, &exit);
2699 __ xorq(rax, rax); // Success.
2701 __ addq(rsp, Immediate(1 * kPointerSize));
2706 masm->GetCode(&desc);
2707 // Call the function from C++.
2708 int result = FUNCTION_CAST<F0>(buffer)();
2709 CHECK_EQ(0, result);