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
4 // met:
5 //
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.
15 //
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.
27
28 #include <stdlib.h>
29
30 #include "include/v8-function.h"
31 #include "src/base/platform/platform.h"
32 #include "src/base/utils/random-number-generator.h"
33 #include "src/codegen/assembler-inl.h"
34 #include "src/codegen/macro-assembler.h"
35 #include "src/deoptimizer/deoptimizer.h"
36 #include "src/diagnostics/disassembler.h"
37 #include "src/heap/factory.h"
38 #include "src/init/v8.h"
39 #include "src/utils/ostreams.h"
40 #include "test/cctest/cctest.h"
41
42 namespace v8 {
43 namespace internal {
44
45 using F0 = int (*)();
46 using F1 = int (*)(int x);
47 using F2 = int (*)(int x, int y);
48
49 #define __ assm.
50
TEST(AssemblerIa320)51 TEST(AssemblerIa320) {
52 CcTest::InitializeVM();
53 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
54 HandleScope scope(isolate);
55
56 v8::internal::byte buffer[256];
57 Assembler assm(AssemblerOptions{},
58 ExternalAssemblerBuffer(buffer, sizeof buffer));
59
60 __ mov(eax, Operand(esp, 4));
61 __ add(eax, Operand(esp, 8));
62 __ ret(0);
63
64 CodeDesc desc;
65 assm.GetCode(isolate, &desc);
66 Handle<Code> code =
67 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
68 #ifdef OBJECT_PRINT
69 StdoutStream os;
70 code->Print(os);
71 #endif
72 F2 f = FUNCTION_CAST<F2>(code->entry());
73 int res = f(3, 4);
74 ::printf("f() = %d\n", res);
75 CHECK_EQ(7, res);
76 }
77
78
TEST(AssemblerIa321)79 TEST(AssemblerIa321) {
80 CcTest::InitializeVM();
81 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
82 HandleScope scope(isolate);
83
84 v8::internal::byte buffer[256];
85 Assembler assm(AssemblerOptions{},
86 ExternalAssemblerBuffer(buffer, sizeof buffer));
87 Label L, C;
88
89 __ mov(edx, Operand(esp, 4));
90 __ xor_(eax, eax); // clear eax
91 __ jmp(&C);
92
93 __ bind(&L);
94 __ add(eax, edx);
95 __ sub(edx, Immediate(1));
96
97 __ bind(&C);
98 __ test(edx, edx);
99 __ j(not_zero, &L);
100 __ ret(0);
101
102 CodeDesc desc;
103 assm.GetCode(isolate, &desc);
104 Handle<Code> code =
105 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
106 #ifdef OBJECT_PRINT
107 StdoutStream os;
108 code->Print(os);
109 #endif
110 F1 f = FUNCTION_CAST<F1>(code->entry());
111 int res = f(100);
112 ::printf("f() = %d\n", res);
113 CHECK_EQ(5050, res);
114 }
115
116
TEST(AssemblerIa322)117 TEST(AssemblerIa322) {
118 CcTest::InitializeVM();
119 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
120 HandleScope scope(isolate);
121
122 v8::internal::byte buffer[256];
123 Assembler assm(AssemblerOptions{},
124 ExternalAssemblerBuffer(buffer, sizeof buffer));
125 Label L, C;
126
127 __ mov(edx, Operand(esp, 4));
128 __ mov(eax, 1);
129 __ jmp(&C);
130
131 __ bind(&L);
132 __ imul(eax, edx);
133 __ sub(edx, Immediate(1));
134
135 __ bind(&C);
136 __ test(edx, edx);
137 __ j(not_zero, &L);
138 __ ret(0);
139
140 // some relocated stuff here, not executed
141 __ mov(eax, isolate->factory()->true_value());
142 __ jmp(kNullAddress, RelocInfo::RUNTIME_ENTRY);
143
144 CodeDesc desc;
145 assm.GetCode(isolate, &desc);
146 Handle<Code> code =
147 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
148 #ifdef OBJECT_PRINT
149 StdoutStream os;
150 code->Print(os);
151 #endif
152 F1 f = FUNCTION_CAST<F1>(code->entry());
153 int res = f(10);
154 ::printf("f() = %d\n", res);
155 CHECK_EQ(3628800, res);
156 }
157
158 using F3 = int (*)(float x);
159
TEST(AssemblerIa323)160 TEST(AssemblerIa323) {
161 CcTest::InitializeVM();
162
163 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
164 HandleScope scope(isolate);
165
166 v8::internal::byte buffer[256];
167 Assembler assm(AssemblerOptions{},
168 ExternalAssemblerBuffer(buffer, sizeof buffer));
169
170 __ cvttss2si(eax, Operand(esp, 4));
171 __ ret(0);
172
173 CodeDesc desc;
174 assm.GetCode(isolate, &desc);
175 Handle<Code> code =
176 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
177 #ifdef OBJECT_PRINT
178 StdoutStream os;
179 code->Print(os);
180 #endif
181 F3 f = FUNCTION_CAST<F3>(code->entry());
182 int res = f(static_cast<float>(-3.1415));
183 ::printf("f() = %d\n", res);
184 CHECK_EQ(-3, res);
185 }
186
187 using F4 = int (*)(double x);
188
TEST(AssemblerIa324)189 TEST(AssemblerIa324) {
190 CcTest::InitializeVM();
191
192 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
193 HandleScope scope(isolate);
194
195 v8::internal::byte buffer[256];
196 Assembler assm(AssemblerOptions{},
197 ExternalAssemblerBuffer(buffer, sizeof buffer));
198
199 __ cvttsd2si(eax, Operand(esp, 4));
200 __ ret(0);
201
202 CodeDesc desc;
203 assm.GetCode(isolate, &desc);
204 Handle<Code> code =
205 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
206 #ifdef OBJECT_PRINT
207 StdoutStream os;
208 code->Print(os);
209 #endif
210 F4 f = FUNCTION_CAST<F4>(code->entry());
211 int res = f(2.718281828);
212 ::printf("f() = %d\n", res);
213 CHECK_EQ(2, res);
214 }
215
216
217 static int baz = 42;
TEST(AssemblerIa325)218 TEST(AssemblerIa325) {
219 CcTest::InitializeVM();
220 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
221 HandleScope scope(isolate);
222
223 v8::internal::byte buffer[256];
224 Assembler assm(AssemblerOptions{},
225 ExternalAssemblerBuffer(buffer, sizeof buffer));
226
227 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
228 __ ret(0);
229
230 CodeDesc desc;
231 assm.GetCode(isolate, &desc);
232 Handle<Code> code =
233 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
234 F0 f = FUNCTION_CAST<F0>(code->entry());
235 int res = f();
236 CHECK_EQ(42, res);
237 }
238
239 using F5 = double (*)(double x, double y);
240
TEST(AssemblerIa326)241 TEST(AssemblerIa326) {
242 CcTest::InitializeVM();
243
244 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
245 HandleScope scope(isolate);
246 v8::internal::byte buffer[256];
247 Assembler assm(AssemblerOptions{},
248 ExternalAssemblerBuffer(buffer, sizeof buffer));
249
250 __ movsd(xmm0, Operand(esp, 1 * kSystemPointerSize));
251 __ movsd(xmm1, Operand(esp, 3 * kSystemPointerSize));
252 __ addsd(xmm0, xmm1);
253 __ mulsd(xmm0, xmm1);
254 __ subsd(xmm0, xmm1);
255 __ divsd(xmm0, xmm1);
256 // Copy xmm0 to st(0) using eight bytes of stack.
257 __ sub(esp, Immediate(8));
258 __ movsd(Operand(esp, 0), xmm0);
259 __ fld_d(Operand(esp, 0));
260 __ add(esp, Immediate(8));
261 __ ret(0);
262
263 CodeDesc desc;
264 assm.GetCode(isolate, &desc);
265 Handle<Code> code =
266 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
267 #ifdef OBJECT_PRINT
268 StdoutStream os;
269 code->Print(os);
270 #endif
271 F5 f = FUNCTION_CAST<F5>(code->entry());
272 double res = f(2.2, 1.1);
273 ::printf("f() = %f\n", res);
274 CHECK(2.29 < res && res < 2.31);
275 }
276
277 using F6 = double (*)(int x);
278
TEST(AssemblerIa328)279 TEST(AssemblerIa328) {
280 CcTest::InitializeVM();
281
282 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
283 HandleScope scope(isolate);
284 v8::internal::byte buffer[256];
285 Assembler assm(AssemblerOptions{},
286 ExternalAssemblerBuffer(buffer, sizeof buffer));
287 __ mov(eax, Operand(esp, 4));
288 __ cvtsi2sd(xmm0, eax);
289 // Copy xmm0 to st(0) using eight bytes of stack.
290 __ sub(esp, Immediate(8));
291 __ movsd(Operand(esp, 0), xmm0);
292 __ fld_d(Operand(esp, 0));
293 __ add(esp, Immediate(8));
294 __ ret(0);
295 CodeDesc desc;
296 assm.GetCode(isolate, &desc);
297 Handle<Code> code =
298 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
299 #ifdef OBJECT_PRINT
300 StdoutStream os;
301 code->Print(os);
302 #endif
303 F6 f = FUNCTION_CAST<F6>(code->entry());
304 double res = f(12);
305
306 ::printf("f() = %f\n", res);
307 CHECK(11.99 < res && res < 12.001);
308 }
309
TEST(AssemblerIa3210)310 TEST(AssemblerIa3210) {
311 // Test chaining of label usages within instructions (issue 1644).
312 CcTest::InitializeVM();
313 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
314 HandleScope scope(isolate);
315 Assembler assm(AssemblerOptions{});
316
317 Label target;
318 __ j(equal, &target);
319 __ j(not_equal, &target);
320 __ bind(&target);
321 __ nop();
322 }
323
324
TEST(AssemblerMultiByteNop)325 TEST(AssemblerMultiByteNop) {
326 CcTest::InitializeVM();
327 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
328 HandleScope scope(isolate);
329 v8::internal::byte buffer[1024];
330 Assembler assm(AssemblerOptions{},
331 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
332 __ push(ebx);
333 __ push(ecx);
334 __ push(edx);
335 __ push(edi);
336 __ push(esi);
337 __ mov(eax, 1);
338 __ mov(ebx, 2);
339 __ mov(ecx, 3);
340 __ mov(edx, 4);
341 __ mov(edi, 5);
342 __ mov(esi, 6);
343 for (int i = 0; i < 16; i++) {
344 int before = assm.pc_offset();
345 __ Nop(i);
346 CHECK_EQ(assm.pc_offset() - before, i);
347 }
348
349 Label fail;
350 __ cmp(eax, 1);
351 __ j(not_equal, &fail);
352 __ cmp(ebx, 2);
353 __ j(not_equal, &fail);
354 __ cmp(ecx, 3);
355 __ j(not_equal, &fail);
356 __ cmp(edx, 4);
357 __ j(not_equal, &fail);
358 __ cmp(edi, 5);
359 __ j(not_equal, &fail);
360 __ cmp(esi, 6);
361 __ j(not_equal, &fail);
362 __ mov(eax, 42);
363 __ pop(esi);
364 __ pop(edi);
365 __ pop(edx);
366 __ pop(ecx);
367 __ pop(ebx);
368 __ ret(0);
369 __ bind(&fail);
370 __ mov(eax, 13);
371 __ pop(esi);
372 __ pop(edi);
373 __ pop(edx);
374 __ pop(ecx);
375 __ pop(ebx);
376 __ ret(0);
377
378 CodeDesc desc;
379 assm.GetCode(isolate, &desc);
380 Handle<Code> code =
381 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
382 CHECK(code->IsCode());
383
384 F0 f = FUNCTION_CAST<F0>(code->entry());
385 int res = f();
386 CHECK_EQ(42, res);
387 }
388
389
390 #ifdef __GNUC__
391 #define ELEMENT_COUNT 4u
392
DoSSE2(const v8::FunctionCallbackInfo<v8::Value> & args)393 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
394 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
395 HandleScope scope(isolate);
396 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
397
398 CHECK(args[0]->IsArray());
399 v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
400 CHECK_EQ(ELEMENT_COUNT, vec->Length());
401
402 v8::internal::byte buffer[256];
403 Assembler assm(AssemblerOptions{},
404 ExternalAssemblerBuffer(buffer, sizeof buffer));
405
406 // Remove return address from the stack for fix stack frame alignment.
407 __ pop(ecx);
408
409 // Store input vector on the stack.
410 for (unsigned i = 0; i < ELEMENT_COUNT; ++i) {
411 __ push(Immediate(
412 vec->Get(context, i).ToLocalChecked()->Int32Value(context).FromJust()));
413 }
414
415 // Read vector into a xmm register.
416 __ pxor(xmm0, xmm0);
417 __ movdqa(xmm0, Operand(esp, 0));
418 // Create mask and store it in the return register.
419 __ movmskps(eax, xmm0);
420
421 // Remove unused data from the stack.
422 __ add(esp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
423 // Restore return address.
424 __ push(ecx);
425
426 __ ret(0);
427
428 CodeDesc desc;
429 assm.GetCode(isolate, &desc);
430
431 Handle<Code> code =
432 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
433
434 F0 f = FUNCTION_CAST<F0>(code->entry());
435 int res = f();
436 args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
437 }
438
439
TEST(StackAlignmentForSSE2)440 TEST(StackAlignmentForSSE2) {
441 CcTest::InitializeVM();
442 CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
443
444 v8::Isolate* isolate = CcTest::isolate();
445 v8::HandleScope handle_scope(isolate);
446 v8::Local<v8::ObjectTemplate> global_template =
447 v8::ObjectTemplate::New(isolate);
448 global_template->Set(v8_str("do_sse2"),
449 v8::FunctionTemplate::New(isolate, DoSSE2));
450
451 LocalContext env(nullptr, global_template);
452 CompileRun(
453 "function foo(vec) {"
454 " return do_sse2(vec);"
455 "}");
456
457 v8::Local<v8::Object> global_object = env->Global();
458 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
459 global_object->Get(env.local(), v8_str("foo")).ToLocalChecked());
460
461 int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
462 v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
463 for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
464 v8_vec->Set(env.local(), i, v8_num(vec[i])).FromJust();
465 }
466
467 v8::Local<v8::Value> args[] = { v8_vec };
468 v8::Local<v8::Value> result =
469 foo->Call(env.local(), global_object, 1, args).ToLocalChecked();
470
471 // The mask should be 0b1000.
472 CHECK_EQ(8, result->Int32Value(env.local()).FromJust());
473 }
474
475 #undef ELEMENT_COUNT
476 #endif // __GNUC__
477
478
TEST(AssemblerIa32Extractps)479 TEST(AssemblerIa32Extractps) {
480 CcTest::InitializeVM();
481 if (!CpuFeatures::IsSupported(SSE4_1)) return;
482
483 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
484 HandleScope scope(isolate);
485 v8::internal::byte buffer[256];
486 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
487 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
488 { CpuFeatureScope fscope41(&assm, SSE4_1);
489 __ movsd(xmm1, Operand(esp, 4));
490 __ extractps(eax, xmm1, 0x1);
491 __ ret(0);
492 }
493
494 CodeDesc desc;
495 assm.GetCode(isolate, &desc);
496 Handle<Code> code =
497 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
498 #ifdef OBJECT_PRINT
499 StdoutStream os;
500 code->Print(os);
501 #endif
502
503 F4 f = FUNCTION_CAST<F4>(code->entry());
504 uint64_t value1 = 0x1234'5678'8765'4321;
505 CHECK_EQ(0x12345678, f(base::uint64_to_double(value1)));
506 uint64_t value2 = 0x8765'4321'1234'5678;
507 CHECK_EQ(static_cast<int>(0x87654321), f(base::uint64_to_double(value2)));
508 }
509
510 using F8 = int (*)(float x, float y);
TEST(AssemblerIa32SSE)511 TEST(AssemblerIa32SSE) {
512 CcTest::InitializeVM();
513
514 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
515 HandleScope scope(isolate);
516 v8::internal::byte buffer[256];
517 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
518 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
519 {
520 __ movss(xmm0, Operand(esp, kSystemPointerSize));
521 __ movss(xmm1, Operand(esp, 2 * kSystemPointerSize));
522 __ shufps(xmm0, xmm0, 0x0);
523 __ shufps(xmm1, xmm1, 0x0);
524 __ movaps(xmm2, xmm1);
525 __ addps(xmm2, xmm0);
526 __ mulps(xmm2, xmm1);
527 __ subps(xmm2, xmm0);
528 __ divps(xmm2, xmm1);
529 __ cvttss2si(eax, xmm2);
530 __ ret(0);
531 }
532
533 CodeDesc desc;
534 assm.GetCode(isolate, &desc);
535 Handle<Code> code =
536 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
537 #ifdef OBJECT_PRINT
538 StdoutStream os;
539 code->Print(os);
540 #endif
541
542 F8 f = FUNCTION_CAST<F8>(code->entry());
543 CHECK_EQ(2, f(1.0, 2.0));
544 }
545
TEST(AssemblerIa32SSE3)546 TEST(AssemblerIa32SSE3) {
547 CcTest::InitializeVM();
548 if (!CpuFeatures::IsSupported(SSE3)) return;
549
550 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
551 HandleScope scope(isolate);
552 v8::internal::byte buffer[256];
553 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
554 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
555 {
556 CpuFeatureScope fscope(&assm, SSE3);
557 __ movss(xmm0, Operand(esp, kSystemPointerSize));
558 __ movss(xmm1, Operand(esp, 2 * kSystemPointerSize));
559 __ shufps(xmm0, xmm0, 0x0);
560 __ shufps(xmm1, xmm1, 0x0);
561 __ haddps(xmm1, xmm0);
562 __ cvttss2si(eax, xmm1);
563 __ ret(0);
564 }
565
566 CodeDesc desc;
567 assm.GetCode(isolate, &desc);
568 Handle<Code> code =
569 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
570 #ifdef OBJECT_PRINT
571 StdoutStream os;
572 code->Print(os);
573 #endif
574
575 F8 f = FUNCTION_CAST<F8>(code->entry());
576 CHECK_EQ(4, f(1.0, 2.0));
577 }
578
579 using F9 = int (*)(double x, double y, double z);
TEST(AssemblerX64FMA_sd)580 TEST(AssemblerX64FMA_sd) {
581 CcTest::InitializeVM();
582 if (!CpuFeatures::IsSupported(FMA3)) return;
583
584 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
585 HandleScope scope(isolate);
586 v8::internal::byte buffer[1024];
587 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
588 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
589 {
590 CpuFeatureScope fscope(&assm, FMA3);
591 Label exit;
592 __ movsd(xmm0, Operand(esp, 1 * kSystemPointerSize));
593 __ movsd(xmm1, Operand(esp, 3 * kSystemPointerSize));
594 __ movsd(xmm2, Operand(esp, 5 * kSystemPointerSize));
595 // argument in xmm0, xmm1 and xmm2
596 // xmm0 * xmm1 + xmm2
597 __ movaps(xmm3, xmm0);
598 __ mulsd(xmm3, xmm1);
599 __ addsd(xmm3, xmm2); // Expected result in xmm3
600
601 __ AllocateStackSpace(kDoubleSize); // For memory operand
602 // vfmadd132sd
603 __ mov(eax, Immediate(1)); // Test number
604 __ movaps(xmm4, xmm0);
605 __ vfmadd132sd(xmm4, xmm2, xmm1);
606 __ ucomisd(xmm4, xmm3);
607 __ j(not_equal, &exit);
608 // vfmadd213sd
609 __ inc(eax);
610 __ movaps(xmm4, xmm1);
611 __ vfmadd213sd(xmm4, xmm0, xmm2);
612 __ ucomisd(xmm4, xmm3);
613 __ j(not_equal, &exit);
614 // vfmadd231sd
615 __ inc(eax);
616 __ movaps(xmm4, xmm2);
617 __ vfmadd231sd(xmm4, xmm0, xmm1);
618 __ ucomisd(xmm4, xmm3);
619 __ j(not_equal, &exit);
620
621 // vfmadd132sd
622 __ inc(eax);
623 __ movaps(xmm4, xmm0);
624 __ movsd(Operand(esp, 0), xmm1);
625 __ vfmadd132sd(xmm4, xmm2, Operand(esp, 0));
626 __ ucomisd(xmm4, xmm3);
627 __ j(not_equal, &exit);
628 // vfmadd213sd
629 __ inc(eax);
630 __ movaps(xmm4, xmm1);
631 __ movsd(Operand(esp, 0), xmm2);
632 __ vfmadd213sd(xmm4, xmm0, Operand(esp, 0));
633 __ ucomisd(xmm4, xmm3);
634 __ j(not_equal, &exit);
635 // vfmadd231sd
636 __ inc(eax);
637 __ movaps(xmm4, xmm2);
638 __ movsd(Operand(esp, 0), xmm1);
639 __ vfmadd231sd(xmm4, xmm0, Operand(esp, 0));
640 __ ucomisd(xmm4, xmm3);
641 __ j(not_equal, &exit);
642
643 // xmm0 * xmm1 - xmm2
644 __ movaps(xmm3, xmm0);
645 __ mulsd(xmm3, xmm1);
646 __ subsd(xmm3, xmm2); // Expected result in xmm3
647
648 // vfmsub132sd
649 __ inc(eax);
650 __ movaps(xmm4, xmm0);
651 __ vfmsub132sd(xmm4, xmm2, xmm1);
652 __ ucomisd(xmm4, xmm3);
653 __ j(not_equal, &exit);
654 // vfmadd213sd
655 __ inc(eax);
656 __ movaps(xmm4, xmm1);
657 __ vfmsub213sd(xmm4, xmm0, xmm2);
658 __ ucomisd(xmm4, xmm3);
659 __ j(not_equal, &exit);
660 // vfmsub231sd
661 __ inc(eax);
662 __ movaps(xmm4, xmm2);
663 __ vfmsub231sd(xmm4, xmm0, xmm1);
664 __ ucomisd(xmm4, xmm3);
665 __ j(not_equal, &exit);
666
667 // vfmsub132sd
668 __ inc(eax);
669 __ movaps(xmm4, xmm0);
670 __ movsd(Operand(esp, 0), xmm1);
671 __ vfmsub132sd(xmm4, xmm2, Operand(esp, 0));
672 __ ucomisd(xmm4, xmm3);
673 __ j(not_equal, &exit);
674 // vfmsub213sd
675 __ inc(eax);
676 __ movaps(xmm4, xmm1);
677 __ movsd(Operand(esp, 0), xmm2);
678 __ vfmsub213sd(xmm4, xmm0, Operand(esp, 0));
679 __ ucomisd(xmm4, xmm3);
680 __ j(not_equal, &exit);
681 // vfmsub231sd
682 __ inc(eax);
683 __ movaps(xmm4, xmm2);
684 __ movsd(Operand(esp, 0), xmm1);
685 __ vfmsub231sd(xmm4, xmm0, Operand(esp, 0));
686 __ ucomisd(xmm4, xmm3);
687 __ j(not_equal, &exit);
688
689
690 // - xmm0 * xmm1 + xmm2
691 __ movaps(xmm3, xmm0);
692 __ mulsd(xmm3, xmm1);
693 __ Move(xmm4, (uint64_t)1 << 63);
694 __ xorpd(xmm3, xmm4);
695 __ addsd(xmm3, xmm2); // Expected result in xmm3
696
697 // vfnmadd132sd
698 __ inc(eax);
699 __ movaps(xmm4, xmm0);
700 __ vfnmadd132sd(xmm4, xmm2, xmm1);
701 __ ucomisd(xmm4, xmm3);
702 __ j(not_equal, &exit);
703 // vfmadd213sd
704 __ inc(eax);
705 __ movaps(xmm4, xmm1);
706 __ vfnmadd213sd(xmm4, xmm0, xmm2);
707 __ ucomisd(xmm4, xmm3);
708 __ j(not_equal, &exit);
709 // vfnmadd231sd
710 __ inc(eax);
711 __ movaps(xmm4, xmm2);
712 __ vfnmadd231sd(xmm4, xmm0, xmm1);
713 __ ucomisd(xmm4, xmm3);
714 __ j(not_equal, &exit);
715
716 // vfnmadd132sd
717 __ inc(eax);
718 __ movaps(xmm4, xmm0);
719 __ movsd(Operand(esp, 0), xmm1);
720 __ vfnmadd132sd(xmm4, xmm2, Operand(esp, 0));
721 __ ucomisd(xmm4, xmm3);
722 __ j(not_equal, &exit);
723 // vfnmadd213sd
724 __ inc(eax);
725 __ movaps(xmm4, xmm1);
726 __ movsd(Operand(esp, 0), xmm2);
727 __ vfnmadd213sd(xmm4, xmm0, Operand(esp, 0));
728 __ ucomisd(xmm4, xmm3);
729 __ j(not_equal, &exit);
730 // vfnmadd231sd
731 __ inc(eax);
732 __ movaps(xmm4, xmm2);
733 __ movsd(Operand(esp, 0), xmm1);
734 __ vfnmadd231sd(xmm4, xmm0, Operand(esp, 0));
735 __ ucomisd(xmm4, xmm3);
736 __ j(not_equal, &exit);
737
738
739 // - xmm0 * xmm1 - xmm2
740 __ movaps(xmm3, xmm0);
741 __ mulsd(xmm3, xmm1);
742 __ Move(xmm4, (uint64_t)1 << 63);
743 __ xorpd(xmm3, xmm4);
744 __ subsd(xmm3, xmm2); // Expected result in xmm3
745
746 // vfnmsub132sd
747 __ inc(eax);
748 __ movaps(xmm4, xmm0);
749 __ vfnmsub132sd(xmm4, xmm2, xmm1);
750 __ ucomisd(xmm4, xmm3);
751 __ j(not_equal, &exit);
752 // vfmsub213sd
753 __ inc(eax);
754 __ movaps(xmm4, xmm1);
755 __ vfnmsub213sd(xmm4, xmm0, xmm2);
756 __ ucomisd(xmm4, xmm3);
757 __ j(not_equal, &exit);
758 // vfnmsub231sd
759 __ inc(eax);
760 __ movaps(xmm4, xmm2);
761 __ vfnmsub231sd(xmm4, xmm0, xmm1);
762 __ ucomisd(xmm4, xmm3);
763 __ j(not_equal, &exit);
764
765 // vfnmsub132sd
766 __ inc(eax);
767 __ movaps(xmm4, xmm0);
768 __ movsd(Operand(esp, 0), xmm1);
769 __ vfnmsub132sd(xmm4, xmm2, Operand(esp, 0));
770 __ ucomisd(xmm4, xmm3);
771 __ j(not_equal, &exit);
772 // vfnmsub213sd
773 __ inc(eax);
774 __ movaps(xmm4, xmm1);
775 __ movsd(Operand(esp, 0), xmm2);
776 __ vfnmsub213sd(xmm4, xmm0, Operand(esp, 0));
777 __ ucomisd(xmm4, xmm3);
778 __ j(not_equal, &exit);
779 // vfnmsub231sd
780 __ inc(eax);
781 __ movaps(xmm4, xmm2);
782 __ movsd(Operand(esp, 0), xmm1);
783 __ vfnmsub231sd(xmm4, xmm0, Operand(esp, 0));
784 __ ucomisd(xmm4, xmm3);
785 __ j(not_equal, &exit);
786
787
788 __ xor_(eax, eax);
789 __ bind(&exit);
790 __ add(esp, Immediate(kDoubleSize));
791 __ ret(0);
792 }
793
794 CodeDesc desc;
795 assm.GetCode(isolate, &desc);
796 Handle<Code> code =
797 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
798 #ifdef OBJECT_PRINT
799 StdoutStream os;
800 code->Print(os);
801 #endif
802
803 F9 f = FUNCTION_CAST<F9>(code->entry());
804 CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
805 }
806
807 using F10 = int (*)(float x, float y, float z);
TEST(AssemblerX64FMA_ss)808 TEST(AssemblerX64FMA_ss) {
809 CcTest::InitializeVM();
810 if (!CpuFeatures::IsSupported(FMA3)) return;
811
812 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
813 HandleScope scope(isolate);
814 v8::internal::byte buffer[1024];
815 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
816 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
817 {
818 CpuFeatureScope fscope(&assm, FMA3);
819 Label exit;
820 __ movss(xmm0, Operand(esp, 1 * kSystemPointerSize));
821 __ movss(xmm1, Operand(esp, 2 * kSystemPointerSize));
822 __ movss(xmm2, Operand(esp, 3 * kSystemPointerSize));
823 // arguments in xmm0, xmm1 and xmm2
824 // xmm0 * xmm1 + xmm2
825 __ movaps(xmm3, xmm0);
826 __ mulss(xmm3, xmm1);
827 __ addss(xmm3, xmm2); // Expected result in xmm3
828
829 __ AllocateStackSpace(kDoubleSize); // For memory operand
830 // vfmadd132ss
831 __ mov(eax, Immediate(1)); // Test number
832 __ movaps(xmm4, xmm0);
833 __ vfmadd132ss(xmm4, xmm2, xmm1);
834 __ ucomiss(xmm4, xmm3);
835 __ j(not_equal, &exit);
836 // vfmadd213ss
837 __ inc(eax);
838 __ movaps(xmm4, xmm1);
839 __ vfmadd213ss(xmm4, xmm0, xmm2);
840 __ ucomiss(xmm4, xmm3);
841 __ j(not_equal, &exit);
842 // vfmadd231ss
843 __ inc(eax);
844 __ movaps(xmm4, xmm2);
845 __ vfmadd231ss(xmm4, xmm0, xmm1);
846 __ ucomiss(xmm4, xmm3);
847 __ j(not_equal, &exit);
848
849 // vfmadd132ss
850 __ inc(eax);
851 __ movaps(xmm4, xmm0);
852 __ movss(Operand(esp, 0), xmm1);
853 __ vfmadd132ss(xmm4, xmm2, Operand(esp, 0));
854 __ ucomiss(xmm4, xmm3);
855 __ j(not_equal, &exit);
856 // vfmadd213ss
857 __ inc(eax);
858 __ movaps(xmm4, xmm1);
859 __ movss(Operand(esp, 0), xmm2);
860 __ vfmadd213ss(xmm4, xmm0, Operand(esp, 0));
861 __ ucomiss(xmm4, xmm3);
862 __ j(not_equal, &exit);
863 // vfmadd231ss
864 __ inc(eax);
865 __ movaps(xmm4, xmm2);
866 __ movss(Operand(esp, 0), xmm1);
867 __ vfmadd231ss(xmm4, xmm0, Operand(esp, 0));
868 __ ucomiss(xmm4, xmm3);
869 __ j(not_equal, &exit);
870
871 // xmm0 * xmm1 - xmm2
872 __ movaps(xmm3, xmm0);
873 __ mulss(xmm3, xmm1);
874 __ subss(xmm3, xmm2); // Expected result in xmm3
875
876 // vfmsub132ss
877 __ inc(eax);
878 __ movaps(xmm4, xmm0);
879 __ vfmsub132ss(xmm4, xmm2, xmm1);
880 __ ucomiss(xmm4, xmm3);
881 __ j(not_equal, &exit);
882 // vfmadd213ss
883 __ inc(eax);
884 __ movaps(xmm4, xmm1);
885 __ vfmsub213ss(xmm4, xmm0, xmm2);
886 __ ucomiss(xmm4, xmm3);
887 __ j(not_equal, &exit);
888 // vfmsub231ss
889 __ inc(eax);
890 __ movaps(xmm4, xmm2);
891 __ vfmsub231ss(xmm4, xmm0, xmm1);
892 __ ucomiss(xmm4, xmm3);
893 __ j(not_equal, &exit);
894
895 // vfmsub132ss
896 __ inc(eax);
897 __ movaps(xmm4, xmm0);
898 __ movss(Operand(esp, 0), xmm1);
899 __ vfmsub132ss(xmm4, xmm2, Operand(esp, 0));
900 __ ucomiss(xmm4, xmm3);
901 __ j(not_equal, &exit);
902 // vfmsub213ss
903 __ inc(eax);
904 __ movaps(xmm4, xmm1);
905 __ movss(Operand(esp, 0), xmm2);
906 __ vfmsub213ss(xmm4, xmm0, Operand(esp, 0));
907 __ ucomiss(xmm4, xmm3);
908 __ j(not_equal, &exit);
909 // vfmsub231ss
910 __ inc(eax);
911 __ movaps(xmm4, xmm2);
912 __ movss(Operand(esp, 0), xmm1);
913 __ vfmsub231ss(xmm4, xmm0, Operand(esp, 0));
914 __ ucomiss(xmm4, xmm3);
915 __ j(not_equal, &exit);
916
917
918 // - xmm0 * xmm1 + xmm2
919 __ movaps(xmm3, xmm0);
920 __ mulss(xmm3, xmm1);
921 __ Move(xmm4, (uint32_t)1 << 31);
922 __ xorps(xmm3, xmm4);
923 __ addss(xmm3, xmm2); // Expected result in xmm3
924
925 // vfnmadd132ss
926 __ inc(eax);
927 __ movaps(xmm4, xmm0);
928 __ vfnmadd132ss(xmm4, xmm2, xmm1);
929 __ ucomiss(xmm4, xmm3);
930 __ j(not_equal, &exit);
931 // vfmadd213ss
932 __ inc(eax);
933 __ movaps(xmm4, xmm1);
934 __ vfnmadd213ss(xmm4, xmm0, xmm2);
935 __ ucomiss(xmm4, xmm3);
936 __ j(not_equal, &exit);
937 // vfnmadd231ss
938 __ inc(eax);
939 __ movaps(xmm4, xmm2);
940 __ vfnmadd231ss(xmm4, xmm0, xmm1);
941 __ ucomiss(xmm4, xmm3);
942 __ j(not_equal, &exit);
943
944 // vfnmadd132ss
945 __ inc(eax);
946 __ movaps(xmm4, xmm0);
947 __ movss(Operand(esp, 0), xmm1);
948 __ vfnmadd132ss(xmm4, xmm2, Operand(esp, 0));
949 __ ucomiss(xmm4, xmm3);
950 __ j(not_equal, &exit);
951 // vfnmadd213ss
952 __ inc(eax);
953 __ movaps(xmm4, xmm1);
954 __ movss(Operand(esp, 0), xmm2);
955 __ vfnmadd213ss(xmm4, xmm0, Operand(esp, 0));
956 __ ucomiss(xmm4, xmm3);
957 __ j(not_equal, &exit);
958 // vfnmadd231ss
959 __ inc(eax);
960 __ movaps(xmm4, xmm2);
961 __ movss(Operand(esp, 0), xmm1);
962 __ vfnmadd231ss(xmm4, xmm0, Operand(esp, 0));
963 __ ucomiss(xmm4, xmm3);
964 __ j(not_equal, &exit);
965
966
967 // - xmm0 * xmm1 - xmm2
968 __ movaps(xmm3, xmm0);
969 __ mulss(xmm3, xmm1);
970 __ Move(xmm4, (uint32_t)1 << 31);
971 __ xorps(xmm3, xmm4);
972 __ subss(xmm3, xmm2); // Expected result in xmm3
973
974 // vfnmsub132ss
975 __ inc(eax);
976 __ movaps(xmm4, xmm0);
977 __ vfnmsub132ss(xmm4, xmm2, xmm1);
978 __ ucomiss(xmm4, xmm3);
979 __ j(not_equal, &exit);
980 // vfmsub213ss
981 __ inc(eax);
982 __ movaps(xmm4, xmm1);
983 __ vfnmsub213ss(xmm4, xmm0, xmm2);
984 __ ucomiss(xmm4, xmm3);
985 __ j(not_equal, &exit);
986 // vfnmsub231ss
987 __ inc(eax);
988 __ movaps(xmm4, xmm2);
989 __ vfnmsub231ss(xmm4, xmm0, xmm1);
990 __ ucomiss(xmm4, xmm3);
991 __ j(not_equal, &exit);
992
993 // vfnmsub132ss
994 __ inc(eax);
995 __ movaps(xmm4, xmm0);
996 __ movss(Operand(esp, 0), xmm1);
997 __ vfnmsub132ss(xmm4, xmm2, Operand(esp, 0));
998 __ ucomiss(xmm4, xmm3);
999 __ j(not_equal, &exit);
1000 // vfnmsub213ss
1001 __ inc(eax);
1002 __ movaps(xmm4, xmm1);
1003 __ movss(Operand(esp, 0), xmm2);
1004 __ vfnmsub213ss(xmm4, xmm0, Operand(esp, 0));
1005 __ ucomiss(xmm4, xmm3);
1006 __ j(not_equal, &exit);
1007 // vfnmsub231ss
1008 __ inc(eax);
1009 __ movaps(xmm4, xmm2);
1010 __ movss(Operand(esp, 0), xmm1);
1011 __ vfnmsub231ss(xmm4, xmm0, Operand(esp, 0));
1012 __ ucomiss(xmm4, xmm3);
1013 __ j(not_equal, &exit);
1014
1015
1016 __ xor_(eax, eax);
1017 __ bind(&exit);
1018 __ add(esp, Immediate(kDoubleSize));
1019 __ ret(0);
1020 }
1021
1022 CodeDesc desc;
1023 assm.GetCode(isolate, &desc);
1024 Handle<Code> code =
1025 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1026 #ifdef OBJECT_PRINT
1027 StdoutStream os;
1028 code->Print(os);
1029 #endif
1030
1031 F10 f = FUNCTION_CAST<F10>(code->entry());
1032 CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1033 }
1034
1035
TEST(AssemblerIa32BMI1)1036 TEST(AssemblerIa32BMI1) {
1037 CcTest::InitializeVM();
1038 if (!CpuFeatures::IsSupported(BMI1)) return;
1039
1040 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1041 HandleScope scope(isolate);
1042 v8::internal::byte buffer[1024];
1043 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
1044 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
1045 {
1046 CpuFeatureScope fscope(&assm, BMI1);
1047 Label exit;
1048
1049 __ push(ebx); // save ebx
1050 __ mov(ecx, Immediate(0x55667788u)); // source operand
1051 __ push(ecx); // For memory operand
1052
1053 // andn
1054 __ mov(edx, Immediate(0x20000000u));
1055
1056 __ mov(eax, Immediate(1)); // Test number
1057 __ andn(ebx, edx, ecx);
1058 __ cmp(ebx, Immediate(0x55667788u)); // expected result
1059 __ j(not_equal, &exit);
1060
1061 __ inc(eax);
1062 __ andn(ebx, edx, Operand(esp, 0));
1063 __ cmp(ebx, Immediate(0x55667788u)); // expected result
1064 __ j(not_equal, &exit);
1065
1066 // bextr
1067 __ mov(edx, Immediate(0x00002808u));
1068
1069 __ inc(eax);
1070 __ bextr(ebx, ecx, edx);
1071 __ cmp(ebx, Immediate(0x00556677u)); // expected result
1072 __ j(not_equal, &exit);
1073
1074 __ inc(eax);
1075 __ bextr(ebx, Operand(esp, 0), edx);
1076 __ cmp(ebx, Immediate(0x00556677u)); // expected result
1077 __ j(not_equal, &exit);
1078
1079 // blsi
1080 __ inc(eax);
1081 __ blsi(ebx, ecx);
1082 __ cmp(ebx, Immediate(0x00000008u)); // expected result
1083 __ j(not_equal, &exit);
1084
1085 __ inc(eax);
1086 __ blsi(ebx, Operand(esp, 0));
1087 __ cmp(ebx, Immediate(0x00000008u)); // expected result
1088 __ j(not_equal, &exit);
1089
1090 // blsmsk
1091 __ inc(eax);
1092 __ blsmsk(ebx, ecx);
1093 __ cmp(ebx, Immediate(0x0000000Fu)); // expected result
1094 __ j(not_equal, &exit);
1095
1096 __ inc(eax);
1097 __ blsmsk(ebx, Operand(esp, 0));
1098 __ cmp(ebx, Immediate(0x0000000Fu)); // expected result
1099 __ j(not_equal, &exit);
1100
1101 // blsr
1102 __ inc(eax);
1103 __ blsr(ebx, ecx);
1104 __ cmp(ebx, Immediate(0x55667780u)); // expected result
1105 __ j(not_equal, &exit);
1106
1107 __ inc(eax);
1108 __ blsr(ebx, Operand(esp, 0));
1109 __ cmp(ebx, Immediate(0x55667780u)); // expected result
1110 __ j(not_equal, &exit);
1111
1112 // tzcnt
1113 __ inc(eax);
1114 __ tzcnt(ebx, ecx);
1115 __ cmp(ebx, Immediate(3)); // expected result
1116 __ j(not_equal, &exit);
1117
1118 __ inc(eax);
1119 __ tzcnt(ebx, Operand(esp, 0));
1120 __ cmp(ebx, Immediate(3)); // expected result
1121 __ j(not_equal, &exit);
1122
1123 __ xor_(eax, eax);
1124 __ bind(&exit);
1125 __ pop(ecx);
1126 __ pop(ebx);
1127 __ ret(0);
1128 }
1129
1130 CodeDesc desc;
1131 assm.GetCode(isolate, &desc);
1132 Handle<Code> code =
1133 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1134 #ifdef OBJECT_PRINT
1135 StdoutStream os;
1136 code->Print(os);
1137 #endif
1138
1139 F0 f = FUNCTION_CAST<F0>(code->entry());
1140 CHECK_EQ(0, f());
1141 }
1142
1143
TEST(AssemblerIa32LZCNT)1144 TEST(AssemblerIa32LZCNT) {
1145 CcTest::InitializeVM();
1146 if (!CpuFeatures::IsSupported(LZCNT)) return;
1147
1148 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1149 HandleScope scope(isolate);
1150 v8::internal::byte buffer[256];
1151 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
1152 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
1153 {
1154 CpuFeatureScope fscope(&assm, LZCNT);
1155 Label exit;
1156
1157 __ push(ebx); // save ebx
1158 __ mov(ecx, Immediate(0x55667788u)); // source operand
1159 __ push(ecx); // For memory operand
1160
1161 __ mov(eax, Immediate(1)); // Test number
1162 __ lzcnt(ebx, ecx);
1163 __ cmp(ebx, Immediate(1)); // expected result
1164 __ j(not_equal, &exit);
1165
1166 __ inc(eax);
1167 __ lzcnt(ebx, Operand(esp, 0));
1168 __ cmp(ebx, Immediate(1)); // expected result
1169 __ j(not_equal, &exit);
1170
1171 __ xor_(eax, eax);
1172 __ bind(&exit);
1173 __ pop(ecx);
1174 __ pop(ebx);
1175 __ ret(0);
1176 }
1177
1178 CodeDesc desc;
1179 assm.GetCode(isolate, &desc);
1180 Handle<Code> code =
1181 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1182 #ifdef OBJECT_PRINT
1183 StdoutStream os;
1184 code->Print(os);
1185 #endif
1186
1187 F0 f = FUNCTION_CAST<F0>(code->entry());
1188 CHECK_EQ(0, f());
1189 }
1190
1191
TEST(AssemblerIa32POPCNT)1192 TEST(AssemblerIa32POPCNT) {
1193 CcTest::InitializeVM();
1194 if (!CpuFeatures::IsSupported(POPCNT)) return;
1195
1196 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1197 HandleScope scope(isolate);
1198 v8::internal::byte buffer[256];
1199 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
1200 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
1201 {
1202 CpuFeatureScope fscope(&assm, POPCNT);
1203 Label exit;
1204
1205 __ push(ebx); // save ebx
1206 __ mov(ecx, Immediate(0x11111100u)); // source operand
1207 __ push(ecx); // For memory operand
1208
1209 __ mov(eax, Immediate(1)); // Test number
1210 __ popcnt(ebx, ecx);
1211 __ cmp(ebx, Immediate(6)); // expected result
1212 __ j(not_equal, &exit);
1213
1214 __ inc(eax);
1215 __ popcnt(ebx, Operand(esp, 0));
1216 __ cmp(ebx, Immediate(6)); // expected result
1217 __ j(not_equal, &exit);
1218
1219 __ xor_(eax, eax);
1220 __ bind(&exit);
1221 __ pop(ecx);
1222 __ pop(ebx);
1223 __ ret(0);
1224 }
1225
1226 CodeDesc desc;
1227 assm.GetCode(isolate, &desc);
1228 Handle<Code> code =
1229 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1230 #ifdef OBJECT_PRINT
1231 StdoutStream os;
1232 code->Print(os);
1233 #endif
1234
1235 F0 f = FUNCTION_CAST<F0>(code->entry());
1236 CHECK_EQ(0, f());
1237 }
1238
1239
TEST(AssemblerIa32BMI2)1240 TEST(AssemblerIa32BMI2) {
1241 CcTest::InitializeVM();
1242 if (!CpuFeatures::IsSupported(BMI2)) return;
1243
1244 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1245 HandleScope scope(isolate);
1246 v8::internal::byte buffer[2048];
1247 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes,
1248 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
1249 {
1250 CpuFeatureScope fscope(&assm, BMI2);
1251 Label exit;
1252
1253 __ push(ebx); // save ebx
1254 __ push(esi); // save esi
1255 __ mov(ecx, Immediate(0x55667788u)); // source operand
1256 __ push(ecx); // For memory operand
1257
1258 // bzhi
1259 __ mov(edx, Immediate(9));
1260
1261 __ mov(eax, Immediate(1)); // Test number
1262 __ bzhi(ebx, ecx, edx);
1263 __ cmp(ebx, Immediate(0x00000188u)); // expected result
1264 __ j(not_equal, &exit);
1265
1266 __ inc(eax);
1267 __ bzhi(ebx, Operand(esp, 0), edx);
1268 __ cmp(ebx, Immediate(0x00000188u)); // expected result
1269 __ j(not_equal, &exit);
1270
1271 // mulx
1272 __ mov(edx, Immediate(0x00001000u));
1273
1274 __ inc(eax);
1275 __ mulx(ebx, esi, ecx);
1276 __ cmp(ebx, Immediate(0x00000556u)); // expected result
1277 __ j(not_equal, &exit);
1278 __ cmp(esi, Immediate(0x67788000u)); // expected result
1279 __ j(not_equal, &exit);
1280
1281 __ inc(eax);
1282 __ mulx(ebx, esi, Operand(esp, 0));
1283 __ cmp(ebx, Immediate(0x00000556u)); // expected result
1284 __ j(not_equal, &exit);
1285 __ cmp(esi, Immediate(0x67788000u)); // expected result
1286 __ j(not_equal, &exit);
1287
1288 // pdep
1289 __ mov(edx, Immediate(0xFFFFFFF0u));
1290
1291 __ inc(eax);
1292 __ pdep(ebx, edx, ecx);
1293 __ cmp(ebx, Immediate(0x55667400u)); // expected result
1294 __ j(not_equal, &exit);
1295
1296 __ inc(eax);
1297 __ pdep(ebx, edx, Operand(esp, 0));
1298 __ cmp(ebx, Immediate(0x55667400u)); // expected result
1299 __ j(not_equal, &exit);
1300
1301 // pext
1302 __ mov(edx, Immediate(0xFFFFFFF0u));
1303
1304 __ inc(eax);
1305 __ pext(ebx, edx, ecx);
1306 __ cmp(ebx, Immediate(0x0000FFFEu)); // expected result
1307 __ j(not_equal, &exit);
1308
1309 __ inc(eax);
1310 __ pext(ebx, edx, Operand(esp, 0));
1311 __ cmp(ebx, Immediate(0x0000FFFEu)); // expected result
1312 __ j(not_equal, &exit);
1313
1314 // sarx
1315 __ mov(edx, Immediate(4));
1316
1317 __ inc(eax);
1318 __ sarx(ebx, ecx, edx);
1319 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1320 __ j(not_equal, &exit);
1321
1322 __ inc(eax);
1323 __ sarx(ebx, Operand(esp, 0), edx);
1324 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1325 __ j(not_equal, &exit);
1326
1327 // shlx
1328 __ mov(edx, Immediate(4));
1329
1330 __ inc(eax);
1331 __ shlx(ebx, ecx, edx);
1332 __ cmp(ebx, Immediate(0x56677880u)); // expected result
1333 __ j(not_equal, &exit);
1334
1335 __ inc(eax);
1336 __ shlx(ebx, Operand(esp, 0), edx);
1337 __ cmp(ebx, Immediate(0x56677880u)); // expected result
1338 __ j(not_equal, &exit);
1339
1340 // shrx
1341 __ mov(edx, Immediate(4));
1342
1343 __ inc(eax);
1344 __ shrx(ebx, ecx, edx);
1345 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1346 __ j(not_equal, &exit);
1347
1348 __ inc(eax);
1349 __ shrx(ebx, Operand(esp, 0), edx);
1350 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1351 __ j(not_equal, &exit);
1352
1353 // rorx
1354 __ inc(eax);
1355 __ rorx(ebx, ecx, 0x4);
1356 __ cmp(ebx, Immediate(0x85566778u)); // expected result
1357 __ j(not_equal, &exit);
1358
1359 __ inc(eax);
1360 __ rorx(ebx, Operand(esp, 0), 0x4);
1361 __ cmp(ebx, Immediate(0x85566778u)); // expected result
1362 __ j(not_equal, &exit);
1363
1364 __ xor_(eax, eax);
1365 __ bind(&exit);
1366 __ pop(ecx);
1367 __ pop(esi);
1368 __ pop(ebx);
1369 __ ret(0);
1370 }
1371
1372 CodeDesc desc;
1373 assm.GetCode(isolate, &desc);
1374 Handle<Code> code =
1375 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1376 #ifdef OBJECT_PRINT
1377 StdoutStream os;
1378 code->Print(os);
1379 #endif
1380
1381 F0 f = FUNCTION_CAST<F0>(code->entry());
1382 CHECK_EQ(0, f());
1383 }
1384
1385
TEST(AssemblerIa32JumpTables1)1386 TEST(AssemblerIa32JumpTables1) {
1387 // Test jump tables with forward jumps.
1388 CcTest::InitializeVM();
1389 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1390 HandleScope scope(isolate);
1391 Assembler assm(AssemblerOptions{});
1392
1393 const int kNumCases = 512;
1394 int values[kNumCases];
1395 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1396 Label labels[kNumCases];
1397
1398 Label done, table;
1399 __ mov(eax, Operand(esp, 4));
1400 __ jmp(Operand::JumpTable(eax, times_system_pointer_size, &table));
1401 __ ud2();
1402 __ bind(&table);
1403 for (int i = 0; i < kNumCases; ++i) {
1404 __ dd(&labels[i]);
1405 }
1406
1407 for (int i = 0; i < kNumCases; ++i) {
1408 __ bind(&labels[i]);
1409 __ mov(eax, Immediate(values[i]));
1410 __ jmp(&done);
1411 }
1412
1413 __ bind(&done);
1414 __ ret(0);
1415
1416 CodeDesc desc;
1417 assm.GetCode(isolate, &desc);
1418 Handle<Code> code =
1419 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1420 #ifdef OBJECT_PRINT
1421 StdoutStream os;
1422 code->Print(os);
1423 #endif
1424 F1 f = FUNCTION_CAST<F1>(code->entry());
1425 for (int i = 0; i < kNumCases; ++i) {
1426 int res = f(i);
1427 ::printf("f(%d) = %d\n", i, res);
1428 CHECK_EQ(values[i], res);
1429 }
1430 }
1431
1432
TEST(AssemblerIa32JumpTables2)1433 TEST(AssemblerIa32JumpTables2) {
1434 // Test jump tables with backward jumps.
1435 CcTest::InitializeVM();
1436 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1437 HandleScope scope(isolate);
1438 Assembler assm(AssemblerOptions{});
1439
1440 const int kNumCases = 512;
1441 int values[kNumCases];
1442 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1443 Label labels[kNumCases];
1444
1445 Label done, table;
1446 __ mov(eax, Operand(esp, 4));
1447 __ jmp(Operand::JumpTable(eax, times_system_pointer_size, &table));
1448 __ ud2();
1449
1450 for (int i = 0; i < kNumCases; ++i) {
1451 __ bind(&labels[i]);
1452 __ mov(eax, Immediate(values[i]));
1453 __ jmp(&done);
1454 }
1455
1456 __ bind(&table);
1457 for (int i = 0; i < kNumCases; ++i) {
1458 __ dd(&labels[i]);
1459 }
1460
1461 __ bind(&done);
1462 __ ret(0);
1463
1464 CodeDesc desc;
1465 assm.GetCode(isolate, &desc);
1466 Handle<Code> code =
1467 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1468 #ifdef OBJECT_PRINT
1469 StdoutStream os;
1470 code->Print(os);
1471 #endif
1472 F1 f = FUNCTION_CAST<F1>(code->entry());
1473 for (int i = 0; i < kNumCases; ++i) {
1474 int res = f(i);
1475 ::printf("f(%d) = %d\n", i, res);
1476 CHECK_EQ(values[i], res);
1477 }
1478 }
1479
TEST(Regress621926)1480 TEST(Regress621926) {
1481 // Bug description:
1482 // The opcodes for cmpw r/m16, r16 and cmpw r16, r/m16 were swapped.
1483 // This was causing non-commutative comparisons to produce the wrong result.
1484 CcTest::InitializeVM();
1485 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1486 HandleScope scope(isolate);
1487 Assembler assm(AssemblerOptions{});
1488
1489 uint16_t a = 42;
1490
1491 Label fail;
1492 __ push(ebx);
1493 __ mov(ebx, Immediate(reinterpret_cast<intptr_t>(&a)));
1494 __ mov(eax, Immediate(41));
1495 __ cmpw(eax, Operand(ebx, 0));
1496 __ j(above_equal, &fail);
1497 __ cmpw(Operand(ebx, 0), eax);
1498 __ j(below_equal, &fail);
1499 __ mov(eax, 1);
1500 __ pop(ebx);
1501 __ ret(0);
1502 __ bind(&fail);
1503 __ mov(eax, 0);
1504 __ pop(ebx);
1505 __ ret(0);
1506
1507 CodeDesc desc;
1508 assm.GetCode(isolate, &desc);
1509 Handle<Code> code =
1510 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1511
1512 #ifdef OBJECT_PRINT
1513 StdoutStream os;
1514 code->Print(os);
1515 #endif
1516
1517 F0 f = FUNCTION_CAST<F0>(code->entry());
1518 CHECK_EQ(1, f());
1519 }
1520
TEST(DeoptExitSizeIsFixed)1521 TEST(DeoptExitSizeIsFixed) {
1522 CHECK(Deoptimizer::kSupportsFixedDeoptExitSizes);
1523
1524 Isolate* isolate = CcTest::i_isolate();
1525 HandleScope handles(isolate);
1526 v8::internal::byte buffer[256];
1527 MacroAssembler masm(isolate, v8::internal::CodeObjectRequired::kYes,
1528 ExternalAssemblerBuffer(buffer, sizeof(buffer)));
1529
1530 STATIC_ASSERT(static_cast<int>(kFirstDeoptimizeKind) == 0);
1531 for (int i = 0; i < kDeoptimizeKindCount; i++) {
1532 DeoptimizeKind kind = static_cast<DeoptimizeKind>(i);
1533 Label before_exit;
1534 masm.bind(&before_exit);
1535 if (kind == DeoptimizeKind::kEagerWithResume) {
1536 Builtin target = Deoptimizer::GetDeoptWithResumeBuiltin(
1537 DeoptimizeReason::kDynamicCheckMaps);
1538 masm.CallForDeoptimization(target, 42, &before_exit, kind, &before_exit,
1539 nullptr);
1540 CHECK_EQ(masm.SizeOfCodeGeneratedSince(&before_exit),
1541 Deoptimizer::kEagerWithResumeBeforeArgsSize);
1542 } else {
1543 Builtin target = Deoptimizer::GetDeoptimizationEntry(kind);
1544 masm.CallForDeoptimization(target, 42, &before_exit, kind, &before_exit,
1545 nullptr);
1546 CHECK_EQ(masm.SizeOfCodeGeneratedSince(&before_exit),
1547 kind == DeoptimizeKind::kLazy
1548 ? Deoptimizer::kLazyDeoptExitSize
1549 : Deoptimizer::kNonLazyDeoptExitSize);
1550 }
1551 }
1552 }
1553
TEST(CpuFeatures_ProbeImpl)1554 TEST(CpuFeatures_ProbeImpl) {
1555 // Support for a newer extension implies support for the older extensions.
1556 CHECK_IMPLIES(CpuFeatures::IsSupported(FMA3), CpuFeatures::IsSupported(AVX));
1557 CHECK_IMPLIES(CpuFeatures::IsSupported(AVX2), CpuFeatures::IsSupported(AVX));
1558 CHECK_IMPLIES(CpuFeatures::IsSupported(AVX),
1559 CpuFeatures::IsSupported(SSE4_2));
1560 CHECK_IMPLIES(CpuFeatures::IsSupported(SSE4_2),
1561 CpuFeatures::IsSupported(SSE4_1));
1562 CHECK_IMPLIES(CpuFeatures::IsSupported(SSE4_1),
1563 CpuFeatures::IsSupported(SSSE3));
1564 CHECK_IMPLIES(CpuFeatures::IsSupported(SSSE3),
1565 CpuFeatures::IsSupported(SSE3));
1566
1567 // Check the reverse, if an older extension is not supported, a newer
1568 // extension cannot be supported.
1569 CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE3),
1570 !CpuFeatures::IsSupported(SSSE3));
1571 CHECK_IMPLIES(!CpuFeatures::IsSupported(SSSE3),
1572 !CpuFeatures::IsSupported(SSE4_1));
1573 CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE4_1),
1574 !CpuFeatures::IsSupported(SSE4_2));
1575 CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE4_2),
1576 !CpuFeatures::IsSupported(AVX));
1577 CHECK_IMPLIES(!CpuFeatures::IsSupported(AVX),
1578 !CpuFeatures::IsSupported(AVX2));
1579 CHECK_IMPLIES(!CpuFeatures::IsSupported(AVX),
1580 !CpuFeatures::IsSupported(FMA3));
1581 }
1582
1583 #undef __
1584
1585 } // namespace internal
1586 } // namespace v8
1587