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