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