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 "src/serialize.h"
38 #include "test/cctest/cctest.h"
40 using namespace v8::internal;
44 typedef int (*F1)(int x);
45 typedef int (*F2)(int x, int y);
50 TEST(AssemblerIa320) {
51 CcTest::InitializeVM();
52 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
53 HandleScope scope(isolate);
55 v8::internal::byte buffer[256];
56 Assembler assm(isolate, buffer, sizeof buffer);
58 __ mov(eax, Operand(esp, 4));
59 __ add(eax, Operand(esp, 8));
64 Handle<Code> code = isolate->factory()->NewCode(
65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
70 F2 f = FUNCTION_CAST<F2>(code->entry());
72 ::printf("f() = %d\n", res);
77 TEST(AssemblerIa321) {
78 CcTest::InitializeVM();
79 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
80 HandleScope scope(isolate);
82 v8::internal::byte buffer[256];
83 Assembler assm(isolate, buffer, sizeof buffer);
86 __ mov(edx, Operand(esp, 4));
87 __ xor_(eax, eax); // clear eax
92 __ sub(edx, Immediate(1));
101 Handle<Code> code = isolate->factory()->NewCode(
102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
107 F1 f = FUNCTION_CAST<F1>(code->entry());
109 ::printf("f() = %d\n", res);
114 TEST(AssemblerIa322) {
115 CcTest::InitializeVM();
116 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
117 HandleScope scope(isolate);
119 v8::internal::byte buffer[256];
120 Assembler assm(isolate, buffer, sizeof buffer);
123 __ mov(edx, Operand(esp, 4));
129 __ sub(edx, Immediate(1));
136 // some relocated stuff here, not executed
137 __ mov(eax, isolate->factory()->true_value());
138 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
142 Handle<Code> code = isolate->factory()->NewCode(
143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
148 F1 f = FUNCTION_CAST<F1>(code->entry());
150 ::printf("f() = %d\n", res);
151 CHECK_EQ(3628800, res);
155 typedef int (*F3)(float x);
157 TEST(AssemblerIa323) {
158 CcTest::InitializeVM();
160 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
161 HandleScope scope(isolate);
163 v8::internal::byte buffer[256];
164 Assembler assm(isolate, buffer, sizeof buffer);
166 __ cvttss2si(eax, Operand(esp, 4));
171 Handle<Code> code = isolate->factory()->NewCode(
172 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
177 F3 f = FUNCTION_CAST<F3>(code->entry());
178 int res = f(static_cast<float>(-3.1415));
179 ::printf("f() = %d\n", res);
184 typedef int (*F4)(double x);
186 TEST(AssemblerIa324) {
187 CcTest::InitializeVM();
189 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
190 HandleScope scope(isolate);
192 v8::internal::byte buffer[256];
193 Assembler assm(isolate, buffer, sizeof buffer);
195 __ cvttsd2si(eax, Operand(esp, 4));
200 Handle<Code> code = isolate->factory()->NewCode(
201 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
206 F4 f = FUNCTION_CAST<F4>(code->entry());
207 int res = f(2.718281828);
208 ::printf("f() = %d\n", res);
214 TEST(AssemblerIa325) {
215 CcTest::InitializeVM();
216 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
217 HandleScope scope(isolate);
219 v8::internal::byte buffer[256];
220 Assembler assm(isolate, buffer, sizeof buffer);
222 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
227 Handle<Code> code = isolate->factory()->NewCode(
228 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
229 F0 f = FUNCTION_CAST<F0>(code->entry());
235 typedef double (*F5)(double x, double y);
237 TEST(AssemblerIa326) {
238 CcTest::InitializeVM();
240 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
241 HandleScope scope(isolate);
242 v8::internal::byte buffer[256];
243 Assembler assm(isolate, buffer, sizeof buffer);
245 __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
246 __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
247 __ addsd(xmm0, xmm1);
248 __ mulsd(xmm0, xmm1);
249 __ subsd(xmm0, xmm1);
250 __ divsd(xmm0, xmm1);
251 // Copy xmm0 to st(0) using eight bytes of stack.
252 __ sub(esp, Immediate(8));
253 __ movsd(Operand(esp, 0), xmm0);
254 __ fld_d(Operand(esp, 0));
255 __ add(esp, Immediate(8));
260 Handle<Code> code = isolate->factory()->NewCode(
261 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
266 F5 f = FUNCTION_CAST<F5>(code->entry());
267 double res = f(2.2, 1.1);
268 ::printf("f() = %f\n", res);
269 CHECK(2.29 < res && res < 2.31);
273 typedef double (*F6)(int x);
275 TEST(AssemblerIa328) {
276 CcTest::InitializeVM();
278 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
279 HandleScope scope(isolate);
280 v8::internal::byte buffer[256];
281 Assembler assm(isolate, buffer, sizeof buffer);
282 __ mov(eax, Operand(esp, 4));
283 __ cvtsi2sd(xmm0, eax);
284 // Copy xmm0 to st(0) using eight bytes of stack.
285 __ sub(esp, Immediate(8));
286 __ movsd(Operand(esp, 0), xmm0);
287 __ fld_d(Operand(esp, 0));
288 __ add(esp, Immediate(8));
292 Handle<Code> code = isolate->factory()->NewCode(
293 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
298 F6 f = FUNCTION_CAST<F6>(code->entry());
301 ::printf("f() = %f\n", res);
302 CHECK(11.99 < res && res < 12.001);
306 typedef int (*F7)(double x, double y);
308 TEST(AssemblerIa329) {
309 CcTest::InitializeVM();
310 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
311 HandleScope scope(isolate);
312 v8::internal::byte buffer[256];
313 MacroAssembler assm(isolate, buffer, sizeof buffer);
314 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
315 Label equal_l, less_l, greater_l, nan_l;
316 __ fld_d(Operand(esp, 3 * kPointerSize));
317 __ fld_d(Operand(esp, 1 * kPointerSize));
319 __ j(parity_even, &nan_l);
320 __ j(equal, &equal_l);
321 __ j(below, &less_l);
322 __ j(above, &greater_l);
324 __ mov(eax, kUndefined);
332 __ mov(eax, kGreater);
346 Handle<Code> code = isolate->factory()->NewCode(
347 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
353 F7 f = FUNCTION_CAST<F7>(code->entry());
354 CHECK_EQ(kLess, f(1.1, 2.2));
355 CHECK_EQ(kEqual, f(2.2, 2.2));
356 CHECK_EQ(kGreater, f(3.3, 2.2));
357 CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
361 TEST(AssemblerIa3210) {
362 // Test chaining of label usages within instructions (issue 1644).
363 CcTest::InitializeVM();
364 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
365 HandleScope scope(isolate);
366 Assembler assm(isolate, NULL, 0);
369 __ j(equal, &target);
370 __ j(not_equal, &target);
376 TEST(AssemblerMultiByteNop) {
377 CcTest::InitializeVM();
378 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
379 HandleScope scope(isolate);
380 v8::internal::byte buffer[1024];
381 Assembler assm(isolate, buffer, sizeof(buffer));
393 for (int i = 0; i < 16; i++) {
394 int before = assm.pc_offset();
396 CHECK_EQ(assm.pc_offset() - before, i);
401 __ j(not_equal, &fail);
403 __ j(not_equal, &fail);
405 __ j(not_equal, &fail);
407 __ j(not_equal, &fail);
409 __ j(not_equal, &fail);
411 __ j(not_equal, &fail);
430 Handle<Code> code = isolate->factory()->NewCode(
431 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
432 CHECK(code->IsCode());
434 F0 f = FUNCTION_CAST<F0>(code->entry());
441 #define ELEMENT_COUNT 4u
443 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
444 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
445 HandleScope scope(isolate);
447 CHECK(args[0]->IsArray());
448 v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
449 CHECK_EQ(ELEMENT_COUNT, vec->Length());
451 v8::internal::byte buffer[256];
452 Assembler assm(isolate, buffer, sizeof buffer);
454 // Remove return address from the stack for fix stack frame alignment.
457 // Store input vector on the stack.
458 for (unsigned i = 0; i < ELEMENT_COUNT; ++i) {
459 __ push(Immediate(vec->Get(i)->Int32Value()));
462 // Read vector into a xmm register.
464 __ movdqa(xmm0, Operand(esp, 0));
465 // Create mask and store it in the return register.
466 __ movmskps(eax, xmm0);
468 // Remove unused data from the stack.
469 __ add(esp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
470 // Restore return address.
478 Handle<Code> code = isolate->factory()->NewCode(
479 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
481 F0 f = FUNCTION_CAST<F0>(code->entry());
483 args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
487 TEST(StackAlignmentForSSE2) {
488 CcTest::InitializeVM();
489 CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
491 v8::Isolate* isolate = CcTest::isolate();
492 v8::HandleScope handle_scope(isolate);
493 v8::Handle<v8::ObjectTemplate> global_template =
494 v8::ObjectTemplate::New(isolate);
495 global_template->Set(v8_str("do_sse2"),
496 v8::FunctionTemplate::New(isolate, DoSSE2));
498 LocalContext env(NULL, global_template);
500 "function foo(vec) {"
501 " return do_sse2(vec);"
504 v8::Local<v8::Object> global_object = env->Global();
505 v8::Local<v8::Function> foo =
506 v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
508 int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
509 v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
510 for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
511 v8_vec->Set(i, v8_num(vec[i]));
514 v8::Local<v8::Value> args[] = { v8_vec };
515 v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
517 // The mask should be 0b1000.
518 CHECK_EQ(8, result->Int32Value());
525 TEST(AssemblerIa32Extractps) {
526 CcTest::InitializeVM();
527 if (!CpuFeatures::IsSupported(SSE4_1)) return;
529 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
530 HandleScope scope(isolate);
531 v8::internal::byte buffer[256];
532 MacroAssembler assm(isolate, buffer, sizeof buffer);
533 { CpuFeatureScope fscope41(&assm, SSE4_1);
534 __ movsd(xmm1, Operand(esp, 4));
535 __ extractps(eax, xmm1, 0x1);
541 Handle<Code> code = isolate->factory()->NewCode(
542 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
548 F4 f = FUNCTION_CAST<F4>(code->entry());
549 uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
550 CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
551 uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
552 CHECK_EQ(static_cast<int>(0x87654321), f(uint64_to_double(value2)));
556 typedef int (*F8)(float x, float y);
557 TEST(AssemblerIa32SSE) {
558 CcTest::InitializeVM();
560 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
561 HandleScope scope(isolate);
562 v8::internal::byte buffer[256];
563 MacroAssembler assm(isolate, buffer, sizeof buffer);
565 __ movss(xmm0, Operand(esp, kPointerSize));
566 __ movss(xmm1, Operand(esp, 2 * kPointerSize));
567 __ shufps(xmm0, xmm0, 0x0);
568 __ shufps(xmm1, xmm1, 0x0);
569 __ movaps(xmm2, xmm1);
570 __ addps(xmm2, xmm0);
571 __ mulps(xmm2, xmm1);
572 __ subps(xmm2, xmm0);
573 __ divps(xmm2, xmm1);
574 __ cvttss2si(eax, xmm2);
580 Handle<Code> code = isolate->factory()->NewCode(
581 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
587 F8 f = FUNCTION_CAST<F8>(code->entry());
588 CHECK_EQ(2, f(1.0, 2.0));
592 typedef int (*F9)(double x, double y, double z);
593 TEST(AssemblerX64FMA_sd) {
594 CcTest::InitializeVM();
595 if (!CpuFeatures::IsSupported(FMA3)) return;
597 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
598 HandleScope scope(isolate);
599 v8::internal::byte buffer[1024];
600 MacroAssembler assm(isolate, buffer, sizeof buffer);
602 CpuFeatureScope fscope(&assm, FMA3);
604 __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
605 __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
606 __ movsd(xmm2, Operand(esp, 5 * kPointerSize));
607 // argument in xmm0, xmm1 and xmm2
608 // xmm0 * xmm1 + xmm2
609 __ movaps(xmm3, xmm0);
610 __ mulsd(xmm3, xmm1);
611 __ addsd(xmm3, xmm2); // Expected result in xmm3
613 __ sub(esp, Immediate(kDoubleSize)); // For memory operand
615 __ mov(eax, Immediate(1)); // Test number
616 __ movaps(xmm4, xmm0);
617 __ vfmadd132sd(xmm4, xmm2, xmm1);
618 __ ucomisd(xmm4, xmm3);
619 __ j(not_equal, &exit);
622 __ movaps(xmm4, xmm1);
623 __ vfmadd213sd(xmm4, xmm0, xmm2);
624 __ ucomisd(xmm4, xmm3);
625 __ j(not_equal, &exit);
628 __ movaps(xmm4, xmm2);
629 __ vfmadd231sd(xmm4, xmm0, xmm1);
630 __ ucomisd(xmm4, xmm3);
631 __ j(not_equal, &exit);
635 __ movaps(xmm4, xmm0);
636 __ movsd(Operand(esp, 0), xmm1);
637 __ vfmadd132sd(xmm4, xmm2, Operand(esp, 0));
638 __ ucomisd(xmm4, xmm3);
639 __ j(not_equal, &exit);
642 __ movaps(xmm4, xmm1);
643 __ movsd(Operand(esp, 0), xmm2);
644 __ vfmadd213sd(xmm4, xmm0, Operand(esp, 0));
645 __ ucomisd(xmm4, xmm3);
646 __ j(not_equal, &exit);
649 __ movaps(xmm4, xmm2);
650 __ movsd(Operand(esp, 0), xmm1);
651 __ vfmadd231sd(xmm4, xmm0, Operand(esp, 0));
652 __ ucomisd(xmm4, xmm3);
653 __ j(not_equal, &exit);
655 // xmm0 * xmm1 - xmm2
656 __ movaps(xmm3, xmm0);
657 __ mulsd(xmm3, xmm1);
658 __ subsd(xmm3, xmm2); // Expected result in xmm3
662 __ movaps(xmm4, xmm0);
663 __ vfmsub132sd(xmm4, xmm2, xmm1);
664 __ ucomisd(xmm4, xmm3);
665 __ j(not_equal, &exit);
668 __ movaps(xmm4, xmm1);
669 __ vfmsub213sd(xmm4, xmm0, xmm2);
670 __ ucomisd(xmm4, xmm3);
671 __ j(not_equal, &exit);
674 __ movaps(xmm4, xmm2);
675 __ vfmsub231sd(xmm4, xmm0, xmm1);
676 __ ucomisd(xmm4, xmm3);
677 __ j(not_equal, &exit);
681 __ movaps(xmm4, xmm0);
682 __ movsd(Operand(esp, 0), xmm1);
683 __ vfmsub132sd(xmm4, xmm2, Operand(esp, 0));
684 __ ucomisd(xmm4, xmm3);
685 __ j(not_equal, &exit);
688 __ movaps(xmm4, xmm1);
689 __ movsd(Operand(esp, 0), xmm2);
690 __ vfmsub213sd(xmm4, xmm0, Operand(esp, 0));
691 __ ucomisd(xmm4, xmm3);
692 __ j(not_equal, &exit);
695 __ movaps(xmm4, xmm2);
696 __ movsd(Operand(esp, 0), xmm1);
697 __ vfmsub231sd(xmm4, xmm0, Operand(esp, 0));
698 __ ucomisd(xmm4, xmm3);
699 __ j(not_equal, &exit);
702 // - xmm0 * xmm1 + xmm2
703 __ movaps(xmm3, xmm0);
704 __ mulsd(xmm3, xmm1);
705 __ Move(xmm4, (uint64_t)1 << 63);
706 __ xorpd(xmm3, xmm4);
707 __ addsd(xmm3, xmm2); // Expected result in xmm3
711 __ movaps(xmm4, xmm0);
712 __ vfnmadd132sd(xmm4, xmm2, xmm1);
713 __ ucomisd(xmm4, xmm3);
714 __ j(not_equal, &exit);
717 __ movaps(xmm4, xmm1);
718 __ vfnmadd213sd(xmm4, xmm0, xmm2);
719 __ ucomisd(xmm4, xmm3);
720 __ j(not_equal, &exit);
723 __ movaps(xmm4, xmm2);
724 __ vfnmadd231sd(xmm4, xmm0, xmm1);
725 __ ucomisd(xmm4, xmm3);
726 __ j(not_equal, &exit);
730 __ movaps(xmm4, xmm0);
731 __ movsd(Operand(esp, 0), xmm1);
732 __ vfnmadd132sd(xmm4, xmm2, Operand(esp, 0));
733 __ ucomisd(xmm4, xmm3);
734 __ j(not_equal, &exit);
737 __ movaps(xmm4, xmm1);
738 __ movsd(Operand(esp, 0), xmm2);
739 __ vfnmadd213sd(xmm4, xmm0, Operand(esp, 0));
740 __ ucomisd(xmm4, xmm3);
741 __ j(not_equal, &exit);
744 __ movaps(xmm4, xmm2);
745 __ movsd(Operand(esp, 0), xmm1);
746 __ vfnmadd231sd(xmm4, xmm0, Operand(esp, 0));
747 __ ucomisd(xmm4, xmm3);
748 __ j(not_equal, &exit);
751 // - xmm0 * xmm1 - xmm2
752 __ movaps(xmm3, xmm0);
753 __ mulsd(xmm3, xmm1);
754 __ Move(xmm4, (uint64_t)1 << 63);
755 __ xorpd(xmm3, xmm4);
756 __ subsd(xmm3, xmm2); // Expected result in xmm3
760 __ movaps(xmm4, xmm0);
761 __ vfnmsub132sd(xmm4, xmm2, xmm1);
762 __ ucomisd(xmm4, xmm3);
763 __ j(not_equal, &exit);
766 __ movaps(xmm4, xmm1);
767 __ vfnmsub213sd(xmm4, xmm0, xmm2);
768 __ ucomisd(xmm4, xmm3);
769 __ j(not_equal, &exit);
772 __ movaps(xmm4, xmm2);
773 __ vfnmsub231sd(xmm4, xmm0, xmm1);
774 __ ucomisd(xmm4, xmm3);
775 __ j(not_equal, &exit);
779 __ movaps(xmm4, xmm0);
780 __ movsd(Operand(esp, 0), xmm1);
781 __ vfnmsub132sd(xmm4, xmm2, Operand(esp, 0));
782 __ ucomisd(xmm4, xmm3);
783 __ j(not_equal, &exit);
786 __ movaps(xmm4, xmm1);
787 __ movsd(Operand(esp, 0), xmm2);
788 __ vfnmsub213sd(xmm4, xmm0, Operand(esp, 0));
789 __ ucomisd(xmm4, xmm3);
790 __ j(not_equal, &exit);
793 __ movaps(xmm4, xmm2);
794 __ movsd(Operand(esp, 0), xmm1);
795 __ vfnmsub231sd(xmm4, xmm0, Operand(esp, 0));
796 __ ucomisd(xmm4, xmm3);
797 __ j(not_equal, &exit);
802 __ add(esp, Immediate(kDoubleSize));
808 Handle<Code> code = isolate->factory()->NewCode(
809 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
815 F9 f = FUNCTION_CAST<F9>(code->entry());
816 CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
820 typedef int (*F10)(float x, float y, float z);
821 TEST(AssemblerX64FMA_ss) {
822 CcTest::InitializeVM();
823 if (!CpuFeatures::IsSupported(FMA3)) return;
825 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
826 HandleScope scope(isolate);
827 v8::internal::byte buffer[1024];
828 MacroAssembler assm(isolate, buffer, sizeof buffer);
830 CpuFeatureScope fscope(&assm, FMA3);
832 __ movss(xmm0, Operand(esp, 1 * kPointerSize));
833 __ movss(xmm1, Operand(esp, 2 * kPointerSize));
834 __ movss(xmm2, Operand(esp, 3 * kPointerSize));
835 // arguments in xmm0, xmm1 and xmm2
836 // xmm0 * xmm1 + xmm2
837 __ movaps(xmm3, xmm0);
838 __ mulss(xmm3, xmm1);
839 __ addss(xmm3, xmm2); // Expected result in xmm3
841 __ sub(esp, Immediate(kDoubleSize)); // For memory operand
843 __ mov(eax, Immediate(1)); // Test number
844 __ movaps(xmm4, xmm0);
845 __ vfmadd132ss(xmm4, xmm2, xmm1);
846 __ ucomiss(xmm4, xmm3);
847 __ j(not_equal, &exit);
850 __ movaps(xmm4, xmm1);
851 __ vfmadd213ss(xmm4, xmm0, xmm2);
852 __ ucomiss(xmm4, xmm3);
853 __ j(not_equal, &exit);
856 __ movaps(xmm4, xmm2);
857 __ vfmadd231ss(xmm4, xmm0, xmm1);
858 __ ucomiss(xmm4, xmm3);
859 __ j(not_equal, &exit);
863 __ movaps(xmm4, xmm0);
864 __ movss(Operand(esp, 0), xmm1);
865 __ vfmadd132ss(xmm4, xmm2, Operand(esp, 0));
866 __ ucomiss(xmm4, xmm3);
867 __ j(not_equal, &exit);
870 __ movaps(xmm4, xmm1);
871 __ movss(Operand(esp, 0), xmm2);
872 __ vfmadd213ss(xmm4, xmm0, Operand(esp, 0));
873 __ ucomiss(xmm4, xmm3);
874 __ j(not_equal, &exit);
877 __ movaps(xmm4, xmm2);
878 __ movss(Operand(esp, 0), xmm1);
879 __ vfmadd231ss(xmm4, xmm0, Operand(esp, 0));
880 __ ucomiss(xmm4, xmm3);
881 __ j(not_equal, &exit);
883 // xmm0 * xmm1 - xmm2
884 __ movaps(xmm3, xmm0);
885 __ mulss(xmm3, xmm1);
886 __ subss(xmm3, xmm2); // Expected result in xmm3
890 __ movaps(xmm4, xmm0);
891 __ vfmsub132ss(xmm4, xmm2, xmm1);
892 __ ucomiss(xmm4, xmm3);
893 __ j(not_equal, &exit);
896 __ movaps(xmm4, xmm1);
897 __ vfmsub213ss(xmm4, xmm0, xmm2);
898 __ ucomiss(xmm4, xmm3);
899 __ j(not_equal, &exit);
902 __ movaps(xmm4, xmm2);
903 __ vfmsub231ss(xmm4, xmm0, xmm1);
904 __ ucomiss(xmm4, xmm3);
905 __ j(not_equal, &exit);
909 __ movaps(xmm4, xmm0);
910 __ movss(Operand(esp, 0), xmm1);
911 __ vfmsub132ss(xmm4, xmm2, Operand(esp, 0));
912 __ ucomiss(xmm4, xmm3);
913 __ j(not_equal, &exit);
916 __ movaps(xmm4, xmm1);
917 __ movss(Operand(esp, 0), xmm2);
918 __ vfmsub213ss(xmm4, xmm0, Operand(esp, 0));
919 __ ucomiss(xmm4, xmm3);
920 __ j(not_equal, &exit);
923 __ movaps(xmm4, xmm2);
924 __ movss(Operand(esp, 0), xmm1);
925 __ vfmsub231ss(xmm4, xmm0, Operand(esp, 0));
926 __ ucomiss(xmm4, xmm3);
927 __ j(not_equal, &exit);
930 // - xmm0 * xmm1 + xmm2
931 __ movaps(xmm3, xmm0);
932 __ mulss(xmm3, xmm1);
933 __ Move(xmm4, (uint32_t)1 << 31);
934 __ xorps(xmm3, xmm4);
935 __ addss(xmm3, xmm2); // Expected result in xmm3
939 __ movaps(xmm4, xmm0);
940 __ vfnmadd132ss(xmm4, xmm2, xmm1);
941 __ ucomiss(xmm4, xmm3);
942 __ j(not_equal, &exit);
945 __ movaps(xmm4, xmm1);
946 __ vfnmadd213ss(xmm4, xmm0, xmm2);
947 __ ucomiss(xmm4, xmm3);
948 __ j(not_equal, &exit);
951 __ movaps(xmm4, xmm2);
952 __ vfnmadd231ss(xmm4, xmm0, xmm1);
953 __ ucomiss(xmm4, xmm3);
954 __ j(not_equal, &exit);
958 __ movaps(xmm4, xmm0);
959 __ movss(Operand(esp, 0), xmm1);
960 __ vfnmadd132ss(xmm4, xmm2, Operand(esp, 0));
961 __ ucomiss(xmm4, xmm3);
962 __ j(not_equal, &exit);
965 __ movaps(xmm4, xmm1);
966 __ movss(Operand(esp, 0), xmm2);
967 __ vfnmadd213ss(xmm4, xmm0, Operand(esp, 0));
968 __ ucomiss(xmm4, xmm3);
969 __ j(not_equal, &exit);
972 __ movaps(xmm4, xmm2);
973 __ movss(Operand(esp, 0), xmm1);
974 __ vfnmadd231ss(xmm4, xmm0, Operand(esp, 0));
975 __ ucomiss(xmm4, xmm3);
976 __ j(not_equal, &exit);
979 // - xmm0 * xmm1 - xmm2
980 __ movaps(xmm3, xmm0);
981 __ mulss(xmm3, xmm1);
982 __ Move(xmm4, (uint32_t)1 << 31);
983 __ xorps(xmm3, xmm4);
984 __ subss(xmm3, xmm2); // Expected result in xmm3
988 __ movaps(xmm4, xmm0);
989 __ vfnmsub132ss(xmm4, xmm2, xmm1);
990 __ ucomiss(xmm4, xmm3);
991 __ j(not_equal, &exit);
994 __ movaps(xmm4, xmm1);
995 __ vfnmsub213ss(xmm4, xmm0, xmm2);
996 __ ucomiss(xmm4, xmm3);
997 __ j(not_equal, &exit);
1000 __ movaps(xmm4, xmm2);
1001 __ vfnmsub231ss(xmm4, xmm0, xmm1);
1002 __ ucomiss(xmm4, xmm3);
1003 __ j(not_equal, &exit);
1007 __ movaps(xmm4, xmm0);
1008 __ movss(Operand(esp, 0), xmm1);
1009 __ vfnmsub132ss(xmm4, xmm2, Operand(esp, 0));
1010 __ ucomiss(xmm4, xmm3);
1011 __ j(not_equal, &exit);
1014 __ movaps(xmm4, xmm1);
1015 __ movss(Operand(esp, 0), xmm2);
1016 __ vfnmsub213ss(xmm4, xmm0, Operand(esp, 0));
1017 __ ucomiss(xmm4, xmm3);
1018 __ j(not_equal, &exit);
1021 __ movaps(xmm4, xmm2);
1022 __ movss(Operand(esp, 0), xmm1);
1023 __ vfnmsub231ss(xmm4, xmm0, Operand(esp, 0));
1024 __ ucomiss(xmm4, xmm3);
1025 __ j(not_equal, &exit);
1030 __ add(esp, Immediate(kDoubleSize));
1035 assm.GetCode(&desc);
1036 Handle<Code> code = isolate->factory()->NewCode(
1037 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1039 OFStream os(stdout);
1043 F10 f = FUNCTION_CAST<F10>(code->entry());
1044 CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1048 TEST(AssemblerIa32JumpTables1) {
1049 // Test jump tables with forward jumps.
1050 CcTest::InitializeVM();
1051 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1052 HandleScope scope(isolate);
1053 Assembler assm(isolate, nullptr, 0);
1055 const int kNumCases = 512;
1056 int values[kNumCases];
1057 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1058 Label labels[kNumCases];
1061 __ mov(eax, Operand(esp, 4));
1062 __ jmp(Operand::JumpTable(eax, times_4, &table));
1065 for (int i = 0; i < kNumCases; ++i) {
1069 for (int i = 0; i < kNumCases; ++i) {
1070 __ bind(&labels[i]);
1071 __ mov(eax, Immediate(values[i]));
1079 assm.GetCode(&desc);
1080 Handle<Code> code = isolate->factory()->NewCode(
1081 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1083 OFStream os(stdout);
1086 F1 f = FUNCTION_CAST<F1>(code->entry());
1087 for (int i = 0; i < kNumCases; ++i) {
1089 ::printf("f(%d) = %d\n", i, res);
1090 CHECK_EQ(values[i], res);
1095 TEST(AssemblerIa32JumpTables2) {
1096 // Test jump tables with backward jumps.
1097 CcTest::InitializeVM();
1098 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1099 HandleScope scope(isolate);
1100 Assembler assm(isolate, nullptr, 0);
1102 const int kNumCases = 512;
1103 int values[kNumCases];
1104 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1105 Label labels[kNumCases];
1108 __ mov(eax, Operand(esp, 4));
1109 __ jmp(Operand::JumpTable(eax, times_4, &table));
1112 for (int i = 0; i < kNumCases; ++i) {
1113 __ bind(&labels[i]);
1114 __ mov(eax, Immediate(values[i]));
1119 for (int i = 0; i < kNumCases; ++i) {
1127 assm.GetCode(&desc);
1128 Handle<Code> code = isolate->factory()->NewCode(
1129 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1131 OFStream os(stdout);
1134 F1 f = FUNCTION_CAST<F1>(code->entry());
1135 for (int i = 0; i < kNumCases; ++i) {
1137 ::printf("f(%d) = %d\n", i, res);
1138 CHECK_EQ(values[i], res);