1 // Copyright 2011 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/disassembler.h"
34 #include "src/factory.h"
35 #include "src/macro-assembler.h"
36 #include "src/ostreams.h"
37 #include "test/cctest/cctest.h"
39 using namespace v8::internal;
43 typedef int (*F1)(int x);
44 typedef int (*F2)(int x, int y);
49 TEST(AssemblerIa320) {
50 CcTest::InitializeVM();
51 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
52 HandleScope scope(isolate);
54 v8::internal::byte buffer[256];
55 Assembler assm(isolate, buffer, sizeof buffer);
57 __ mov(eax, Operand(esp, 4));
58 __ add(eax, Operand(esp, 8));
63 Handle<Code> code = isolate->factory()->NewCode(
64 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
69 F2 f = FUNCTION_CAST<F2>(code->entry());
71 ::printf("f() = %d\n", res);
76 TEST(AssemblerIa321) {
77 CcTest::InitializeVM();
78 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
79 HandleScope scope(isolate);
81 v8::internal::byte buffer[256];
82 Assembler assm(isolate, buffer, sizeof buffer);
85 __ mov(edx, Operand(esp, 4));
86 __ xor_(eax, eax); // clear eax
91 __ sub(edx, Immediate(1));
100 Handle<Code> code = isolate->factory()->NewCode(
101 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
106 F1 f = FUNCTION_CAST<F1>(code->entry());
108 ::printf("f() = %d\n", res);
113 TEST(AssemblerIa322) {
114 CcTest::InitializeVM();
115 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
116 HandleScope scope(isolate);
118 v8::internal::byte buffer[256];
119 Assembler assm(isolate, buffer, sizeof buffer);
122 __ mov(edx, Operand(esp, 4));
128 __ sub(edx, Immediate(1));
135 // some relocated stuff here, not executed
136 __ mov(eax, isolate->factory()->true_value());
137 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
141 Handle<Code> code = isolate->factory()->NewCode(
142 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
147 F1 f = FUNCTION_CAST<F1>(code->entry());
149 ::printf("f() = %d\n", res);
150 CHECK_EQ(3628800, res);
154 typedef int (*F3)(float x);
156 TEST(AssemblerIa323) {
157 CcTest::InitializeVM();
159 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
160 HandleScope scope(isolate);
162 v8::internal::byte buffer[256];
163 Assembler assm(isolate, buffer, sizeof buffer);
165 __ cvttss2si(eax, Operand(esp, 4));
170 Handle<Code> code = isolate->factory()->NewCode(
171 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
176 F3 f = FUNCTION_CAST<F3>(code->entry());
177 int res = f(static_cast<float>(-3.1415));
178 ::printf("f() = %d\n", res);
183 typedef int (*F4)(double x);
185 TEST(AssemblerIa324) {
186 CcTest::InitializeVM();
188 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
189 HandleScope scope(isolate);
191 v8::internal::byte buffer[256];
192 Assembler assm(isolate, buffer, sizeof buffer);
194 __ cvttsd2si(eax, Operand(esp, 4));
199 Handle<Code> code = isolate->factory()->NewCode(
200 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
205 F4 f = FUNCTION_CAST<F4>(code->entry());
206 int res = f(2.718281828);
207 ::printf("f() = %d\n", res);
213 TEST(AssemblerIa325) {
214 CcTest::InitializeVM();
215 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
216 HandleScope scope(isolate);
218 v8::internal::byte buffer[256];
219 Assembler assm(isolate, buffer, sizeof buffer);
221 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
226 Handle<Code> code = isolate->factory()->NewCode(
227 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
228 F0 f = FUNCTION_CAST<F0>(code->entry());
234 typedef double (*F5)(double x, double y);
236 TEST(AssemblerIa326) {
237 CcTest::InitializeVM();
239 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
240 HandleScope scope(isolate);
241 v8::internal::byte buffer[256];
242 Assembler assm(isolate, buffer, sizeof buffer);
244 __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
245 __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
246 __ addsd(xmm0, xmm1);
247 __ mulsd(xmm0, xmm1);
248 __ subsd(xmm0, xmm1);
249 __ divsd(xmm0, xmm1);
250 // Copy xmm0 to st(0) using eight bytes of stack.
251 __ sub(esp, Immediate(8));
252 __ movsd(Operand(esp, 0), xmm0);
253 __ fld_d(Operand(esp, 0));
254 __ add(esp, Immediate(8));
259 Handle<Code> code = isolate->factory()->NewCode(
260 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
265 F5 f = FUNCTION_CAST<F5>(code->entry());
266 double res = f(2.2, 1.1);
267 ::printf("f() = %f\n", res);
268 CHECK(2.29 < res && res < 2.31);
272 typedef double (*F6)(int x);
274 TEST(AssemblerIa328) {
275 CcTest::InitializeVM();
277 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
278 HandleScope scope(isolate);
279 v8::internal::byte buffer[256];
280 Assembler assm(isolate, buffer, sizeof buffer);
281 __ mov(eax, Operand(esp, 4));
282 __ cvtsi2sd(xmm0, eax);
283 // Copy xmm0 to st(0) using eight bytes of stack.
284 __ sub(esp, Immediate(8));
285 __ movsd(Operand(esp, 0), xmm0);
286 __ fld_d(Operand(esp, 0));
287 __ add(esp, Immediate(8));
291 Handle<Code> code = isolate->factory()->NewCode(
292 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
297 F6 f = FUNCTION_CAST<F6>(code->entry());
300 ::printf("f() = %f\n", res);
301 CHECK(11.99 < res && res < 12.001);
305 typedef int (*F7)(double x, double y);
307 TEST(AssemblerIa329) {
308 CcTest::InitializeVM();
309 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
310 HandleScope scope(isolate);
311 v8::internal::byte buffer[256];
312 MacroAssembler assm(isolate, buffer, sizeof buffer);
313 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
314 Label equal_l, less_l, greater_l, nan_l;
315 __ fld_d(Operand(esp, 3 * kPointerSize));
316 __ fld_d(Operand(esp, 1 * kPointerSize));
318 __ j(parity_even, &nan_l);
319 __ j(equal, &equal_l);
320 __ j(below, &less_l);
321 __ j(above, &greater_l);
323 __ mov(eax, kUndefined);
331 __ mov(eax, kGreater);
345 Handle<Code> code = isolate->factory()->NewCode(
346 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
352 F7 f = FUNCTION_CAST<F7>(code->entry());
353 CHECK_EQ(kLess, f(1.1, 2.2));
354 CHECK_EQ(kEqual, f(2.2, 2.2));
355 CHECK_EQ(kGreater, f(3.3, 2.2));
356 CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
360 TEST(AssemblerIa3210) {
361 // Test chaining of label usages within instructions (issue 1644).
362 CcTest::InitializeVM();
363 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
364 HandleScope scope(isolate);
365 Assembler assm(isolate, NULL, 0);
368 __ j(equal, &target);
369 __ j(not_equal, &target);
375 TEST(AssemblerMultiByteNop) {
376 CcTest::InitializeVM();
377 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
378 HandleScope scope(isolate);
379 v8::internal::byte buffer[1024];
380 Assembler assm(isolate, buffer, sizeof(buffer));
392 for (int i = 0; i < 16; i++) {
393 int before = assm.pc_offset();
395 CHECK_EQ(assm.pc_offset() - before, i);
400 __ j(not_equal, &fail);
402 __ j(not_equal, &fail);
404 __ j(not_equal, &fail);
406 __ j(not_equal, &fail);
408 __ j(not_equal, &fail);
410 __ j(not_equal, &fail);
429 Handle<Code> code = isolate->factory()->NewCode(
430 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
431 CHECK(code->IsCode());
433 F0 f = FUNCTION_CAST<F0>(code->entry());
440 #define ELEMENT_COUNT 4u
442 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
443 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
444 HandleScope scope(isolate);
446 CHECK(args[0]->IsArray());
447 v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
448 CHECK_EQ(ELEMENT_COUNT, vec->Length());
450 v8::internal::byte buffer[256];
451 Assembler assm(isolate, buffer, sizeof buffer);
453 // Remove return address from the stack for fix stack frame alignment.
456 // Store input vector on the stack.
457 for (unsigned i = 0; i < ELEMENT_COUNT; ++i) {
458 __ push(Immediate(vec->Get(i)->Int32Value()));
461 // Read vector into a xmm register.
463 __ movdqa(xmm0, Operand(esp, 0));
464 // Create mask and store it in the return register.
465 __ movmskps(eax, xmm0);
467 // Remove unused data from the stack.
468 __ add(esp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
469 // Restore return address.
477 Handle<Code> code = isolate->factory()->NewCode(
478 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
480 F0 f = FUNCTION_CAST<F0>(code->entry());
482 args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
486 TEST(StackAlignmentForSSE2) {
487 CcTest::InitializeVM();
488 CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
490 v8::Isolate* isolate = CcTest::isolate();
491 v8::HandleScope handle_scope(isolate);
492 v8::Handle<v8::ObjectTemplate> global_template =
493 v8::ObjectTemplate::New(isolate);
494 global_template->Set(v8_str("do_sse2"),
495 v8::FunctionTemplate::New(isolate, DoSSE2));
497 LocalContext env(NULL, global_template);
499 "function foo(vec) {"
500 " return do_sse2(vec);"
503 v8::Local<v8::Object> global_object = env->Global();
504 v8::Local<v8::Function> foo =
505 v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
507 int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
508 v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
509 for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
510 v8_vec->Set(i, v8_num(vec[i]));
513 v8::Local<v8::Value> args[] = { v8_vec };
514 v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
516 // The mask should be 0b1000.
517 CHECK_EQ(8, result->Int32Value());
524 TEST(AssemblerIa32Extractps) {
525 CcTest::InitializeVM();
526 if (!CpuFeatures::IsSupported(SSE4_1)) return;
528 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
529 HandleScope scope(isolate);
530 v8::internal::byte buffer[256];
531 MacroAssembler assm(isolate, buffer, sizeof buffer);
532 { CpuFeatureScope fscope41(&assm, SSE4_1);
533 __ movsd(xmm1, Operand(esp, 4));
534 __ extractps(eax, xmm1, 0x1);
540 Handle<Code> code = isolate->factory()->NewCode(
541 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
547 F4 f = FUNCTION_CAST<F4>(code->entry());
548 uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
549 CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
550 uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
551 CHECK_EQ(static_cast<int>(0x87654321), f(uint64_to_double(value2)));
555 typedef int (*F8)(float x, float y);
556 TEST(AssemblerIa32SSE) {
557 CcTest::InitializeVM();
559 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
560 HandleScope scope(isolate);
561 v8::internal::byte buffer[256];
562 MacroAssembler assm(isolate, buffer, sizeof buffer);
564 __ movss(xmm0, Operand(esp, kPointerSize));
565 __ movss(xmm1, Operand(esp, 2 * kPointerSize));
566 __ shufps(xmm0, xmm0, 0x0);
567 __ shufps(xmm1, xmm1, 0x0);
568 __ movaps(xmm2, xmm1);
569 __ addps(xmm2, xmm0);
570 __ mulps(xmm2, xmm1);
571 __ subps(xmm2, xmm0);
572 __ divps(xmm2, xmm1);
573 __ cvttss2si(eax, xmm2);
579 Handle<Code> code = isolate->factory()->NewCode(
580 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
586 F8 f = FUNCTION_CAST<F8>(code->entry());
587 CHECK_EQ(2, f(1.0, 2.0));
591 typedef int (*F9)(double x, double y, double z);
592 TEST(AssemblerX64FMA_sd) {
593 CcTest::InitializeVM();
594 if (!CpuFeatures::IsSupported(FMA3)) return;
596 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
597 HandleScope scope(isolate);
598 v8::internal::byte buffer[1024];
599 MacroAssembler assm(isolate, buffer, sizeof buffer);
601 CpuFeatureScope fscope(&assm, FMA3);
603 __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
604 __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
605 __ movsd(xmm2, Operand(esp, 5 * kPointerSize));
606 // argument in xmm0, xmm1 and xmm2
607 // xmm0 * xmm1 + xmm2
608 __ movaps(xmm3, xmm0);
609 __ mulsd(xmm3, xmm1);
610 __ addsd(xmm3, xmm2); // Expected result in xmm3
612 __ sub(esp, Immediate(kDoubleSize)); // For memory operand
614 __ mov(eax, Immediate(1)); // Test number
615 __ movaps(xmm4, xmm0);
616 __ vfmadd132sd(xmm4, xmm2, xmm1);
617 __ ucomisd(xmm4, xmm3);
618 __ j(not_equal, &exit);
621 __ movaps(xmm4, xmm1);
622 __ vfmadd213sd(xmm4, xmm0, xmm2);
623 __ ucomisd(xmm4, xmm3);
624 __ j(not_equal, &exit);
627 __ movaps(xmm4, xmm2);
628 __ vfmadd231sd(xmm4, xmm0, xmm1);
629 __ ucomisd(xmm4, xmm3);
630 __ j(not_equal, &exit);
634 __ movaps(xmm4, xmm0);
635 __ movsd(Operand(esp, 0), xmm1);
636 __ vfmadd132sd(xmm4, xmm2, Operand(esp, 0));
637 __ ucomisd(xmm4, xmm3);
638 __ j(not_equal, &exit);
641 __ movaps(xmm4, xmm1);
642 __ movsd(Operand(esp, 0), xmm2);
643 __ vfmadd213sd(xmm4, xmm0, Operand(esp, 0));
644 __ ucomisd(xmm4, xmm3);
645 __ j(not_equal, &exit);
648 __ movaps(xmm4, xmm2);
649 __ movsd(Operand(esp, 0), xmm1);
650 __ vfmadd231sd(xmm4, xmm0, Operand(esp, 0));
651 __ ucomisd(xmm4, xmm3);
652 __ j(not_equal, &exit);
654 // xmm0 * xmm1 - xmm2
655 __ movaps(xmm3, xmm0);
656 __ mulsd(xmm3, xmm1);
657 __ subsd(xmm3, xmm2); // Expected result in xmm3
661 __ movaps(xmm4, xmm0);
662 __ vfmsub132sd(xmm4, xmm2, xmm1);
663 __ ucomisd(xmm4, xmm3);
664 __ j(not_equal, &exit);
667 __ movaps(xmm4, xmm1);
668 __ vfmsub213sd(xmm4, xmm0, xmm2);
669 __ ucomisd(xmm4, xmm3);
670 __ j(not_equal, &exit);
673 __ movaps(xmm4, xmm2);
674 __ vfmsub231sd(xmm4, xmm0, xmm1);
675 __ ucomisd(xmm4, xmm3);
676 __ j(not_equal, &exit);
680 __ movaps(xmm4, xmm0);
681 __ movsd(Operand(esp, 0), xmm1);
682 __ vfmsub132sd(xmm4, xmm2, Operand(esp, 0));
683 __ ucomisd(xmm4, xmm3);
684 __ j(not_equal, &exit);
687 __ movaps(xmm4, xmm1);
688 __ movsd(Operand(esp, 0), xmm2);
689 __ vfmsub213sd(xmm4, xmm0, Operand(esp, 0));
690 __ ucomisd(xmm4, xmm3);
691 __ j(not_equal, &exit);
694 __ movaps(xmm4, xmm2);
695 __ movsd(Operand(esp, 0), xmm1);
696 __ vfmsub231sd(xmm4, xmm0, Operand(esp, 0));
697 __ ucomisd(xmm4, xmm3);
698 __ j(not_equal, &exit);
701 // - xmm0 * xmm1 + xmm2
702 __ movaps(xmm3, xmm0);
703 __ mulsd(xmm3, xmm1);
704 __ Move(xmm4, (uint64_t)1 << 63);
705 __ xorpd(xmm3, xmm4);
706 __ addsd(xmm3, xmm2); // Expected result in xmm3
710 __ movaps(xmm4, xmm0);
711 __ vfnmadd132sd(xmm4, xmm2, xmm1);
712 __ ucomisd(xmm4, xmm3);
713 __ j(not_equal, &exit);
716 __ movaps(xmm4, xmm1);
717 __ vfnmadd213sd(xmm4, xmm0, xmm2);
718 __ ucomisd(xmm4, xmm3);
719 __ j(not_equal, &exit);
722 __ movaps(xmm4, xmm2);
723 __ vfnmadd231sd(xmm4, xmm0, xmm1);
724 __ ucomisd(xmm4, xmm3);
725 __ j(not_equal, &exit);
729 __ movaps(xmm4, xmm0);
730 __ movsd(Operand(esp, 0), xmm1);
731 __ vfnmadd132sd(xmm4, xmm2, Operand(esp, 0));
732 __ ucomisd(xmm4, xmm3);
733 __ j(not_equal, &exit);
736 __ movaps(xmm4, xmm1);
737 __ movsd(Operand(esp, 0), xmm2);
738 __ vfnmadd213sd(xmm4, xmm0, Operand(esp, 0));
739 __ ucomisd(xmm4, xmm3);
740 __ j(not_equal, &exit);
743 __ movaps(xmm4, xmm2);
744 __ movsd(Operand(esp, 0), xmm1);
745 __ vfnmadd231sd(xmm4, xmm0, Operand(esp, 0));
746 __ ucomisd(xmm4, xmm3);
747 __ j(not_equal, &exit);
750 // - xmm0 * xmm1 - xmm2
751 __ movaps(xmm3, xmm0);
752 __ mulsd(xmm3, xmm1);
753 __ Move(xmm4, (uint64_t)1 << 63);
754 __ xorpd(xmm3, xmm4);
755 __ subsd(xmm3, xmm2); // Expected result in xmm3
759 __ movaps(xmm4, xmm0);
760 __ vfnmsub132sd(xmm4, xmm2, xmm1);
761 __ ucomisd(xmm4, xmm3);
762 __ j(not_equal, &exit);
765 __ movaps(xmm4, xmm1);
766 __ vfnmsub213sd(xmm4, xmm0, xmm2);
767 __ ucomisd(xmm4, xmm3);
768 __ j(not_equal, &exit);
771 __ movaps(xmm4, xmm2);
772 __ vfnmsub231sd(xmm4, xmm0, xmm1);
773 __ ucomisd(xmm4, xmm3);
774 __ j(not_equal, &exit);
778 __ movaps(xmm4, xmm0);
779 __ movsd(Operand(esp, 0), xmm1);
780 __ vfnmsub132sd(xmm4, xmm2, Operand(esp, 0));
781 __ ucomisd(xmm4, xmm3);
782 __ j(not_equal, &exit);
785 __ movaps(xmm4, xmm1);
786 __ movsd(Operand(esp, 0), xmm2);
787 __ vfnmsub213sd(xmm4, xmm0, Operand(esp, 0));
788 __ ucomisd(xmm4, xmm3);
789 __ j(not_equal, &exit);
792 __ movaps(xmm4, xmm2);
793 __ movsd(Operand(esp, 0), xmm1);
794 __ vfnmsub231sd(xmm4, xmm0, Operand(esp, 0));
795 __ ucomisd(xmm4, xmm3);
796 __ j(not_equal, &exit);
801 __ add(esp, Immediate(kDoubleSize));
807 Handle<Code> code = isolate->factory()->NewCode(
808 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
814 F9 f = FUNCTION_CAST<F9>(code->entry());
815 CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
819 typedef int (*F10)(float x, float y, float z);
820 TEST(AssemblerX64FMA_ss) {
821 CcTest::InitializeVM();
822 if (!CpuFeatures::IsSupported(FMA3)) return;
824 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
825 HandleScope scope(isolate);
826 v8::internal::byte buffer[1024];
827 MacroAssembler assm(isolate, buffer, sizeof buffer);
829 CpuFeatureScope fscope(&assm, FMA3);
831 __ movss(xmm0, Operand(esp, 1 * kPointerSize));
832 __ movss(xmm1, Operand(esp, 2 * kPointerSize));
833 __ movss(xmm2, Operand(esp, 3 * kPointerSize));
834 // arguments in xmm0, xmm1 and xmm2
835 // xmm0 * xmm1 + xmm2
836 __ movaps(xmm3, xmm0);
837 __ mulss(xmm3, xmm1);
838 __ addss(xmm3, xmm2); // Expected result in xmm3
840 __ sub(esp, Immediate(kDoubleSize)); // For memory operand
842 __ mov(eax, Immediate(1)); // Test number
843 __ movaps(xmm4, xmm0);
844 __ vfmadd132ss(xmm4, xmm2, xmm1);
845 __ ucomiss(xmm4, xmm3);
846 __ j(not_equal, &exit);
849 __ movaps(xmm4, xmm1);
850 __ vfmadd213ss(xmm4, xmm0, xmm2);
851 __ ucomiss(xmm4, xmm3);
852 __ j(not_equal, &exit);
855 __ movaps(xmm4, xmm2);
856 __ vfmadd231ss(xmm4, xmm0, xmm1);
857 __ ucomiss(xmm4, xmm3);
858 __ j(not_equal, &exit);
862 __ movaps(xmm4, xmm0);
863 __ movss(Operand(esp, 0), xmm1);
864 __ vfmadd132ss(xmm4, xmm2, Operand(esp, 0));
865 __ ucomiss(xmm4, xmm3);
866 __ j(not_equal, &exit);
869 __ movaps(xmm4, xmm1);
870 __ movss(Operand(esp, 0), xmm2);
871 __ vfmadd213ss(xmm4, xmm0, Operand(esp, 0));
872 __ ucomiss(xmm4, xmm3);
873 __ j(not_equal, &exit);
876 __ movaps(xmm4, xmm2);
877 __ movss(Operand(esp, 0), xmm1);
878 __ vfmadd231ss(xmm4, xmm0, Operand(esp, 0));
879 __ ucomiss(xmm4, xmm3);
880 __ j(not_equal, &exit);
882 // xmm0 * xmm1 - xmm2
883 __ movaps(xmm3, xmm0);
884 __ mulss(xmm3, xmm1);
885 __ subss(xmm3, xmm2); // Expected result in xmm3
889 __ movaps(xmm4, xmm0);
890 __ vfmsub132ss(xmm4, xmm2, xmm1);
891 __ ucomiss(xmm4, xmm3);
892 __ j(not_equal, &exit);
895 __ movaps(xmm4, xmm1);
896 __ vfmsub213ss(xmm4, xmm0, xmm2);
897 __ ucomiss(xmm4, xmm3);
898 __ j(not_equal, &exit);
901 __ movaps(xmm4, xmm2);
902 __ vfmsub231ss(xmm4, xmm0, xmm1);
903 __ ucomiss(xmm4, xmm3);
904 __ j(not_equal, &exit);
908 __ movaps(xmm4, xmm0);
909 __ movss(Operand(esp, 0), xmm1);
910 __ vfmsub132ss(xmm4, xmm2, Operand(esp, 0));
911 __ ucomiss(xmm4, xmm3);
912 __ j(not_equal, &exit);
915 __ movaps(xmm4, xmm1);
916 __ movss(Operand(esp, 0), xmm2);
917 __ vfmsub213ss(xmm4, xmm0, Operand(esp, 0));
918 __ ucomiss(xmm4, xmm3);
919 __ j(not_equal, &exit);
922 __ movaps(xmm4, xmm2);
923 __ movss(Operand(esp, 0), xmm1);
924 __ vfmsub231ss(xmm4, xmm0, Operand(esp, 0));
925 __ ucomiss(xmm4, xmm3);
926 __ j(not_equal, &exit);
929 // - xmm0 * xmm1 + xmm2
930 __ movaps(xmm3, xmm0);
931 __ mulss(xmm3, xmm1);
932 __ Move(xmm4, (uint32_t)1 << 31);
933 __ xorps(xmm3, xmm4);
934 __ addss(xmm3, xmm2); // Expected result in xmm3
938 __ movaps(xmm4, xmm0);
939 __ vfnmadd132ss(xmm4, xmm2, xmm1);
940 __ ucomiss(xmm4, xmm3);
941 __ j(not_equal, &exit);
944 __ movaps(xmm4, xmm1);
945 __ vfnmadd213ss(xmm4, xmm0, xmm2);
946 __ ucomiss(xmm4, xmm3);
947 __ j(not_equal, &exit);
950 __ movaps(xmm4, xmm2);
951 __ vfnmadd231ss(xmm4, xmm0, xmm1);
952 __ ucomiss(xmm4, xmm3);
953 __ j(not_equal, &exit);
957 __ movaps(xmm4, xmm0);
958 __ movss(Operand(esp, 0), xmm1);
959 __ vfnmadd132ss(xmm4, xmm2, Operand(esp, 0));
960 __ ucomiss(xmm4, xmm3);
961 __ j(not_equal, &exit);
964 __ movaps(xmm4, xmm1);
965 __ movss(Operand(esp, 0), xmm2);
966 __ vfnmadd213ss(xmm4, xmm0, Operand(esp, 0));
967 __ ucomiss(xmm4, xmm3);
968 __ j(not_equal, &exit);
971 __ movaps(xmm4, xmm2);
972 __ movss(Operand(esp, 0), xmm1);
973 __ vfnmadd231ss(xmm4, xmm0, Operand(esp, 0));
974 __ ucomiss(xmm4, xmm3);
975 __ j(not_equal, &exit);
978 // - xmm0 * xmm1 - xmm2
979 __ movaps(xmm3, xmm0);
980 __ mulss(xmm3, xmm1);
981 __ Move(xmm4, (uint32_t)1 << 31);
982 __ xorps(xmm3, xmm4);
983 __ subss(xmm3, xmm2); // Expected result in xmm3
987 __ movaps(xmm4, xmm0);
988 __ vfnmsub132ss(xmm4, xmm2, xmm1);
989 __ ucomiss(xmm4, xmm3);
990 __ j(not_equal, &exit);
993 __ movaps(xmm4, xmm1);
994 __ vfnmsub213ss(xmm4, xmm0, xmm2);
995 __ ucomiss(xmm4, xmm3);
996 __ j(not_equal, &exit);
999 __ movaps(xmm4, xmm2);
1000 __ vfnmsub231ss(xmm4, xmm0, xmm1);
1001 __ ucomiss(xmm4, xmm3);
1002 __ j(not_equal, &exit);
1006 __ movaps(xmm4, xmm0);
1007 __ movss(Operand(esp, 0), xmm1);
1008 __ vfnmsub132ss(xmm4, xmm2, Operand(esp, 0));
1009 __ ucomiss(xmm4, xmm3);
1010 __ j(not_equal, &exit);
1013 __ movaps(xmm4, xmm1);
1014 __ movss(Operand(esp, 0), xmm2);
1015 __ vfnmsub213ss(xmm4, xmm0, Operand(esp, 0));
1016 __ ucomiss(xmm4, xmm3);
1017 __ j(not_equal, &exit);
1020 __ movaps(xmm4, xmm2);
1021 __ movss(Operand(esp, 0), xmm1);
1022 __ vfnmsub231ss(xmm4, xmm0, Operand(esp, 0));
1023 __ ucomiss(xmm4, xmm3);
1024 __ j(not_equal, &exit);
1029 __ add(esp, Immediate(kDoubleSize));
1034 assm.GetCode(&desc);
1035 Handle<Code> code = isolate->factory()->NewCode(
1036 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1038 OFStream os(stdout);
1042 F10 f = FUNCTION_CAST<F10>(code->entry());
1043 CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1047 TEST(AssemblerIa32JumpTables1) {
1048 // Test jump tables with forward jumps.
1049 CcTest::InitializeVM();
1050 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1051 HandleScope scope(isolate);
1052 Assembler assm(isolate, nullptr, 0);
1054 const int kNumCases = 512;
1055 int values[kNumCases];
1056 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1057 Label labels[kNumCases];
1060 __ mov(eax, Operand(esp, 4));
1061 __ jmp(Operand::JumpTable(eax, times_4, &table));
1064 for (int i = 0; i < kNumCases; ++i) {
1068 for (int i = 0; i < kNumCases; ++i) {
1069 __ bind(&labels[i]);
1070 __ mov(eax, Immediate(values[i]));
1078 assm.GetCode(&desc);
1079 Handle<Code> code = isolate->factory()->NewCode(
1080 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1082 OFStream os(stdout);
1085 F1 f = FUNCTION_CAST<F1>(code->entry());
1086 for (int i = 0; i < kNumCases; ++i) {
1088 ::printf("f(%d) = %d\n", i, res);
1089 CHECK_EQ(values[i], res);
1094 TEST(AssemblerIa32JumpTables2) {
1095 // Test jump tables with backward jumps.
1096 CcTest::InitializeVM();
1097 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1098 HandleScope scope(isolate);
1099 Assembler assm(isolate, nullptr, 0);
1101 const int kNumCases = 512;
1102 int values[kNumCases];
1103 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1104 Label labels[kNumCases];
1107 __ mov(eax, Operand(esp, 4));
1108 __ jmp(Operand::JumpTable(eax, times_4, &table));
1111 for (int i = 0; i < kNumCases; ++i) {
1112 __ bind(&labels[i]);
1113 __ mov(eax, Immediate(values[i]));
1118 for (int i = 0; i < kNumCases; ++i) {
1126 assm.GetCode(&desc);
1127 Handle<Code> code = isolate->factory()->NewCode(
1128 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1130 OFStream os(stdout);
1133 F1 f = FUNCTION_CAST<F1>(code->entry());
1134 for (int i = 0; i < kNumCases; ++i) {
1136 ::printf("f(%d) = %d\n", i, res);
1137 CHECK_EQ(values[i], res);