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