Line data Source code
1 : // Copyright 2009 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 <cstdlib>
29 : #include <iostream>
30 :
31 : #include "src/v8.h"
32 :
33 : #include "src/base/platform/platform.h"
34 : #include "src/base/utils/random-number-generator.h"
35 : #include "src/double.h"
36 : #include "src/factory.h"
37 : #include "src/macro-assembler.h"
38 : #include "src/objects-inl.h"
39 : #include "src/ostreams.h"
40 : #include "test/cctest/cctest.h"
41 :
42 : namespace v8 {
43 : namespace internal {
44 :
45 : // Test the x64 assembler by compiling some simple functions into
46 : // a buffer and executing them. These tests do not initialize the
47 : // V8 library, create a context, or use any V8 objects.
48 : // The AMD64 calling convention is used, with the first six arguments
49 : // in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in
50 : // the XMM registers. The return value is in RAX.
51 : // This calling convention is used on Linux, with GCC, and on Mac OS,
52 : // with GCC. A different convention is used on 64-bit windows,
53 : // where the first four integer arguments are passed in RCX, RDX, R8 and R9.
54 :
55 : typedef int (*F0)();
56 : typedef int (*F1)(int64_t x);
57 : typedef int (*F2)(int64_t x, int64_t y);
58 : typedef unsigned (*F3)(double x);
59 : typedef uint64_t (*F4)(uint64_t* x, uint64_t* y);
60 : typedef uint64_t (*F5)(uint64_t x);
61 :
62 : #ifdef _WIN64
63 : static const Register arg1 = rcx;
64 : static const Register arg2 = rdx;
65 : #else
66 : static const Register arg1 = rdi;
67 : static const Register arg2 = rsi;
68 : #endif
69 :
70 : #define __ assm.
71 :
72 :
73 23724 : TEST(AssemblerX64ReturnOperation) {
74 6 : CcTest::InitializeVM();
75 : // Allocate an executable page of memory.
76 : size_t actual_size;
77 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
78 6 : Assembler::kMinimalBufferSize, &actual_size, true));
79 6 : CHECK(buffer);
80 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
81 :
82 : // Assemble a simple function that copies argument 2 and returns it.
83 : __ movq(rax, arg2);
84 6 : __ nop();
85 6 : __ ret(0);
86 :
87 : CodeDesc desc;
88 6 : assm.GetCode(CcTest::i_isolate(), &desc);
89 : // Call the function from C++.
90 6 : int result = FUNCTION_CAST<F2>(buffer)(3, 2);
91 6 : CHECK_EQ(2, result);
92 6 : }
93 :
94 :
95 23724 : TEST(AssemblerX64StackOperations) {
96 6 : CcTest::InitializeVM();
97 : // Allocate an executable page of memory.
98 : size_t actual_size;
99 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
100 6 : Assembler::kMinimalBufferSize, &actual_size, true));
101 6 : CHECK(buffer);
102 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
103 :
104 : // Assemble a simple function that copies argument 2 and returns it.
105 : // We compile without stack frame pointers, so the gdb debugger shows
106 : // incorrect stack frames when debugging this function (which has them).
107 6 : __ pushq(rbp);
108 : __ movq(rbp, rsp);
109 6 : __ pushq(arg2); // Value at (rbp - 8)
110 6 : __ pushq(arg2); // Value at (rbp - 16)
111 6 : __ pushq(arg1); // Value at (rbp - 24)
112 6 : __ popq(rax);
113 6 : __ popq(rax);
114 6 : __ popq(rax);
115 6 : __ popq(rbp);
116 6 : __ nop();
117 6 : __ ret(0);
118 :
119 : CodeDesc desc;
120 6 : assm.GetCode(CcTest::i_isolate(), &desc);
121 : // Call the function from C++.
122 6 : int result = FUNCTION_CAST<F2>(buffer)(3, 2);
123 6 : CHECK_EQ(2, result);
124 6 : }
125 :
126 :
127 23724 : TEST(AssemblerX64ArithmeticOperations) {
128 6 : CcTest::InitializeVM();
129 : // Allocate an executable page of memory.
130 : size_t actual_size;
131 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
132 6 : Assembler::kMinimalBufferSize, &actual_size, true));
133 6 : CHECK(buffer);
134 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
135 :
136 : // Assemble a simple function that adds arguments returning the sum.
137 : __ movq(rax, arg2);
138 6 : __ addq(rax, arg1);
139 6 : __ ret(0);
140 :
141 : CodeDesc desc;
142 6 : assm.GetCode(CcTest::i_isolate(), &desc);
143 : // Call the function from C++.
144 6 : int result = FUNCTION_CAST<F2>(buffer)(3, 2);
145 6 : CHECK_EQ(5, result);
146 6 : }
147 :
148 :
149 23724 : TEST(AssemblerX64CmpbOperation) {
150 6 : CcTest::InitializeVM();
151 : // Allocate an executable page of memory.
152 : size_t actual_size;
153 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
154 6 : Assembler::kMinimalBufferSize, &actual_size, true));
155 6 : CHECK(buffer);
156 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
157 :
158 : // Assemble a function that compare argument byte returing 1 if equal else 0.
159 : // On Windows, it compares rcx with rdx which does not require REX prefix;
160 : // on Linux, it compares rdi with rsi which requires REX prefix.
161 :
162 : Label done;
163 : __ movq(rax, Immediate(1));
164 : __ cmpb(arg1, arg2);
165 6 : __ j(equal, &done);
166 : __ movq(rax, Immediate(0));
167 6 : __ bind(&done);
168 6 : __ ret(0);
169 :
170 : CodeDesc desc;
171 6 : assm.GetCode(CcTest::i_isolate(), &desc);
172 : // Call the function from C++.
173 6 : int result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002);
174 6 : CHECK_EQ(1, result);
175 6 : result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003);
176 6 : CHECK_EQ(0, result);
177 6 : }
178 :
179 23724 : TEST(Regression684407) {
180 6 : CcTest::InitializeVM();
181 : // Allocate an executable page of memory.
182 : size_t actual_size;
183 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
184 6 : Assembler::kMinimalBufferSize, &actual_size, true));
185 6 : CHECK(buffer);
186 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
187 6 : Address before = assm.pc();
188 : __ cmpl(Operand(arg1, 0),
189 12 : Immediate(0, RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE));
190 6 : Address after = assm.pc();
191 6 : size_t instruction_size = static_cast<size_t>(after - before);
192 : // Check that the immediate is not encoded as uint8.
193 6 : CHECK_LT(sizeof(uint32_t), instruction_size);
194 6 : }
195 :
196 23724 : TEST(AssemblerX64ImulOperation) {
197 6 : CcTest::InitializeVM();
198 : // Allocate an executable page of memory.
199 : size_t actual_size;
200 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
201 6 : Assembler::kMinimalBufferSize, &actual_size, true));
202 6 : CHECK(buffer);
203 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
204 :
205 : // Assemble a simple function that multiplies arguments returning the high
206 : // word.
207 : __ movq(rax, arg2);
208 : __ imulq(arg1);
209 : __ movq(rax, rdx);
210 6 : __ ret(0);
211 :
212 : CodeDesc desc;
213 6 : assm.GetCode(CcTest::i_isolate(), &desc);
214 : // Call the function from C++.
215 6 : int result = FUNCTION_CAST<F2>(buffer)(3, 2);
216 6 : CHECK_EQ(0, result);
217 6 : result = FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l);
218 6 : CHECK_EQ(1, result);
219 6 : result = FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l);
220 6 : CHECK_EQ(-1, result);
221 6 : }
222 :
223 23724 : TEST(AssemblerX64testbwqOperation) {
224 6 : CcTest::InitializeVM();
225 6 : v8::HandleScope scope(CcTest::isolate());
226 : // Allocate an executable page of memory.
227 : size_t actual_size;
228 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
229 6 : Assembler::kMinimalBufferSize, &actual_size, true));
230 6 : CHECK(buffer);
231 18 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
232 :
233 6 : __ pushq(rbx);
234 6 : __ pushq(rdi);
235 6 : __ pushq(rsi);
236 6 : __ pushq(r12);
237 6 : __ pushq(r13);
238 6 : __ pushq(r14);
239 6 : __ pushq(r15);
240 :
241 : // Assemble a simple function that tests testb and testw
242 : Label bad;
243 : Label done;
244 :
245 : // Test immediate testb and testw
246 : __ movq(rax, Immediate(2));
247 : __ movq(rbx, Immediate(4));
248 : __ movq(rcx, Immediate(8));
249 : __ movq(rdx, Immediate(16));
250 : __ movq(rsi, Immediate(32));
251 : __ movq(rdi, Immediate(64));
252 : __ movq(r10, Immediate(128));
253 : __ movq(r11, Immediate(0));
254 : __ movq(r12, Immediate(0));
255 : __ movq(r13, Immediate(0));
256 6 : __ testb(rax, Immediate(2));
257 6 : __ j(zero, &bad);
258 6 : __ testb(rbx, Immediate(4));
259 6 : __ j(zero, &bad);
260 6 : __ testb(rcx, Immediate(8));
261 6 : __ j(zero, &bad);
262 6 : __ testb(rdx, Immediate(16));
263 6 : __ j(zero, &bad);
264 6 : __ testb(rsi, Immediate(32));
265 6 : __ j(zero, &bad);
266 6 : __ testb(rdi, Immediate(64));
267 6 : __ j(zero, &bad);
268 6 : __ testb(r10, Immediate(128));
269 6 : __ j(zero, &bad);
270 6 : __ testw(rax, Immediate(2));
271 6 : __ j(zero, &bad);
272 6 : __ testw(rbx, Immediate(4));
273 6 : __ j(zero, &bad);
274 6 : __ testw(rcx, Immediate(8));
275 6 : __ j(zero, &bad);
276 6 : __ testw(rdx, Immediate(16));
277 6 : __ j(zero, &bad);
278 6 : __ testw(rsi, Immediate(32));
279 6 : __ j(zero, &bad);
280 6 : __ testw(rdi, Immediate(64));
281 6 : __ j(zero, &bad);
282 6 : __ testw(r10, Immediate(128));
283 6 : __ j(zero, &bad);
284 :
285 : // Test reg, reg testb and testw
286 : __ movq(rax, Immediate(2));
287 : __ movq(rbx, Immediate(2));
288 6 : __ testb(rax, rbx);
289 6 : __ j(zero, &bad);
290 : __ movq(rbx, Immediate(4));
291 : __ movq(rax, Immediate(4));
292 6 : __ testb(rbx, rax);
293 6 : __ j(zero, &bad);
294 : __ movq(rax, Immediate(8));
295 6 : __ testb(rcx, rax);
296 6 : __ j(zero, &bad);
297 : __ movq(rax, Immediate(16));
298 6 : __ testb(rdx, rax);
299 6 : __ j(zero, &bad);
300 : __ movq(rax, Immediate(32));
301 6 : __ testb(rsi, rax);
302 6 : __ j(zero, &bad);
303 : __ movq(rax, Immediate(64));
304 6 : __ testb(rdi, rax);
305 6 : __ j(zero, &bad);
306 : __ movq(rax, Immediate(128));
307 6 : __ testb(r10, rax);
308 6 : __ j(zero, &bad);
309 : __ movq(rax, Immediate(2));
310 : __ movq(rbx, Immediate(2));
311 6 : __ testw(rax, rbx);
312 6 : __ j(zero, &bad);
313 : __ movq(rbx, Immediate(4));
314 : __ movq(rax, Immediate(4));
315 6 : __ testw(rbx, rax);
316 6 : __ j(zero, &bad);
317 : __ movq(rax, Immediate(8));
318 6 : __ testw(rcx, rax);
319 6 : __ j(zero, &bad);
320 : __ movq(rax, Immediate(16));
321 6 : __ testw(rdx, rax);
322 6 : __ j(zero, &bad);
323 : __ movq(rax, Immediate(32));
324 6 : __ testw(rsi, rax);
325 6 : __ j(zero, &bad);
326 : __ movq(rax, Immediate(64));
327 6 : __ testw(rdi, rax);
328 6 : __ j(zero, &bad);
329 : __ movq(rax, Immediate(128));
330 6 : __ testw(r10, rax);
331 6 : __ j(zero, &bad);
332 :
333 : // Test diffrrent extended register coding combinations.
334 : __ movq(rax, Immediate(5));
335 : __ movq(r11, Immediate(5));
336 6 : __ testb(r11, rax);
337 6 : __ j(zero, &bad);
338 6 : __ testb(rax, r11);
339 6 : __ j(zero, &bad);
340 6 : __ testw(r11, rax);
341 6 : __ j(zero, &bad);
342 6 : __ testw(rax, r11);
343 6 : __ j(zero, &bad);
344 : __ movq(r11, Immediate(3));
345 : __ movq(r12, Immediate(3));
346 : __ movq(rdi, Immediate(3));
347 6 : __ testb(r12, rdi);
348 6 : __ j(zero, &bad);
349 6 : __ testb(rdi, r12);
350 6 : __ j(zero, &bad);
351 6 : __ testb(r12, r11);
352 6 : __ j(zero, &bad);
353 6 : __ testb(r11, r12);
354 6 : __ j(zero, &bad);
355 6 : __ testw(r12, r11);
356 6 : __ j(zero, &bad);
357 6 : __ testw(r11, r12);
358 6 : __ j(zero, &bad);
359 :
360 : // Test sign-extended imediate tests
361 : __ movq(r11, Immediate(2));
362 : __ shlq(r11, Immediate(32));
363 : __ testq(r11, Immediate(-1));
364 6 : __ j(zero, &bad);
365 :
366 : // All tests passed
367 : __ movq(rax, Immediate(1));
368 6 : __ jmp(&done);
369 :
370 6 : __ bind(&bad);
371 : __ movq(rax, Immediate(0));
372 6 : __ bind(&done);
373 :
374 6 : __ popq(r15);
375 6 : __ popq(r14);
376 6 : __ popq(r13);
377 6 : __ popq(r12);
378 6 : __ popq(rsi);
379 6 : __ popq(rdi);
380 6 : __ popq(rbx);
381 :
382 6 : __ ret(0);
383 :
384 : CodeDesc desc;
385 6 : assm.GetCode(CcTest::i_isolate(), &desc);
386 : // Call the function from C++.
387 6 : int result = FUNCTION_CAST<F2>(buffer)(0, 0);
388 12 : CHECK_EQ(1, result);
389 6 : }
390 :
391 23724 : TEST(AssemblerX64XchglOperations) {
392 6 : CcTest::InitializeVM();
393 : // Allocate an executable page of memory.
394 : size_t actual_size;
395 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
396 6 : Assembler::kMinimalBufferSize, &actual_size, true));
397 6 : CHECK(buffer);
398 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
399 :
400 12 : __ movq(rax, Operand(arg1, 0));
401 12 : __ movq(r11, Operand(arg2, 0));
402 : __ xchgl(rax, r11);
403 12 : __ movq(Operand(arg1, 0), rax);
404 12 : __ movq(Operand(arg2, 0), r11);
405 6 : __ ret(0);
406 :
407 : CodeDesc desc;
408 6 : assm.GetCode(CcTest::i_isolate(), &desc);
409 : // Call the function from C++.
410 6 : uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
411 6 : uint64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
412 6 : uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
413 6 : CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 40000000), left);
414 6 : CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 20000000), right);
415 6 : USE(result);
416 6 : }
417 :
418 :
419 23724 : TEST(AssemblerX64OrlOperations) {
420 6 : CcTest::InitializeVM();
421 : // Allocate an executable page of memory.
422 : size_t actual_size;
423 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
424 6 : Assembler::kMinimalBufferSize, &actual_size, true));
425 6 : CHECK(buffer);
426 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
427 :
428 12 : __ movq(rax, Operand(arg2, 0));
429 12 : __ orl(Operand(arg1, 0), rax);
430 6 : __ ret(0);
431 :
432 : CodeDesc desc;
433 6 : assm.GetCode(CcTest::i_isolate(), &desc);
434 : // Call the function from C++.
435 6 : uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
436 6 : uint64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
437 6 : uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
438 6 : CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 60000000), left);
439 6 : USE(result);
440 6 : }
441 :
442 :
443 23724 : TEST(AssemblerX64RollOperations) {
444 6 : CcTest::InitializeVM();
445 : // Allocate an executable page of memory.
446 : size_t actual_size;
447 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
448 6 : Assembler::kMinimalBufferSize, &actual_size, true));
449 6 : CHECK(buffer);
450 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
451 :
452 : __ movq(rax, arg1);
453 : __ roll(rax, Immediate(1));
454 6 : __ ret(0);
455 :
456 : CodeDesc desc;
457 6 : assm.GetCode(CcTest::i_isolate(), &desc);
458 : // Call the function from C++.
459 : uint64_t src = V8_2PART_UINT64_C(0x10000000, C0000000);
460 6 : uint64_t result = FUNCTION_CAST<F5>(buffer)(src);
461 6 : CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 80000001), result);
462 6 : }
463 :
464 :
465 23724 : TEST(AssemblerX64SublOperations) {
466 6 : CcTest::InitializeVM();
467 : // Allocate an executable page of memory.
468 : size_t actual_size;
469 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
470 6 : Assembler::kMinimalBufferSize, &actual_size, true));
471 6 : CHECK(buffer);
472 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
473 :
474 12 : __ movq(rax, Operand(arg2, 0));
475 12 : __ subl(Operand(arg1, 0), rax);
476 6 : __ ret(0);
477 :
478 : CodeDesc desc;
479 6 : assm.GetCode(CcTest::i_isolate(), &desc);
480 : // Call the function from C++.
481 6 : uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
482 6 : uint64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
483 6 : uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
484 6 : CHECK_EQ(V8_2PART_UINT64_C(0x10000000, e0000000), left);
485 6 : USE(result);
486 6 : }
487 :
488 :
489 23724 : TEST(AssemblerX64TestlOperations) {
490 6 : CcTest::InitializeVM();
491 : // Allocate an executable page of memory.
492 : size_t actual_size;
493 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
494 6 : Assembler::kMinimalBufferSize, &actual_size, true));
495 6 : CHECK(buffer);
496 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
497 :
498 : // Set rax with the ZF flag of the testl instruction.
499 : Label done;
500 : __ movq(rax, Immediate(1));
501 12 : __ movq(r11, Operand(arg2, 0));
502 12 : __ testl(Operand(arg1, 0), r11);
503 6 : __ j(zero, &done, Label::kNear);
504 : __ movq(rax, Immediate(0));
505 6 : __ bind(&done);
506 6 : __ ret(0);
507 :
508 : CodeDesc desc;
509 6 : assm.GetCode(CcTest::i_isolate(), &desc);
510 : // Call the function from C++.
511 6 : uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
512 6 : uint64_t right = V8_2PART_UINT64_C(0x30000000, 00000000);
513 6 : uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
514 6 : CHECK_EQ(1u, result);
515 6 : }
516 :
517 23724 : TEST(AssemblerX64TestwOperations) {
518 : typedef uint16_t (*F)(uint16_t * x);
519 6 : CcTest::InitializeVM();
520 : // Allocate an executable page of memory.
521 : size_t actual_size;
522 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
523 6 : Assembler::kMinimalBufferSize, &actual_size, true));
524 6 : CHECK(buffer);
525 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
526 :
527 : // Set rax with the ZF flag of the testl instruction.
528 : Label done;
529 : __ movq(rax, Immediate(1));
530 6 : __ testw(Operand(arg1, 0), Immediate(0xf0f0));
531 6 : __ j(not_zero, &done, Label::kNear);
532 : __ movq(rax, Immediate(0));
533 6 : __ bind(&done);
534 6 : __ ret(0);
535 :
536 : CodeDesc desc;
537 6 : assm.GetCode(CcTest::i_isolate(), &desc);
538 : // Call the function from C++.
539 6 : uint16_t operand = 0x8000;
540 6 : uint16_t result = FUNCTION_CAST<F>(buffer)(&operand);
541 6 : CHECK_EQ(1u, result);
542 6 : }
543 :
544 23724 : TEST(AssemblerX64XorlOperations) {
545 6 : CcTest::InitializeVM();
546 : // Allocate an executable page of memory.
547 : size_t actual_size;
548 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
549 6 : Assembler::kMinimalBufferSize, &actual_size, true));
550 6 : CHECK(buffer);
551 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
552 :
553 12 : __ movq(rax, Operand(arg2, 0));
554 12 : __ xorl(Operand(arg1, 0), rax);
555 6 : __ ret(0);
556 :
557 : CodeDesc desc;
558 6 : assm.GetCode(CcTest::i_isolate(), &desc);
559 : // Call the function from C++.
560 6 : uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
561 6 : uint64_t right = V8_2PART_UINT64_C(0x30000000, 60000000);
562 6 : uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
563 6 : CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 40000000), left);
564 6 : USE(result);
565 6 : }
566 :
567 :
568 23724 : TEST(AssemblerX64MemoryOperands) {
569 6 : CcTest::InitializeVM();
570 : // Allocate an executable page of memory.
571 : size_t actual_size;
572 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
573 6 : Assembler::kMinimalBufferSize, &actual_size, true));
574 6 : CHECK(buffer);
575 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
576 :
577 : // Assemble a simple function that copies argument 2 and returns it.
578 6 : __ pushq(rbp);
579 : __ movq(rbp, rsp);
580 :
581 6 : __ pushq(arg2); // Value at (rbp - 8)
582 6 : __ pushq(arg2); // Value at (rbp - 16)
583 6 : __ pushq(arg1); // Value at (rbp - 24)
584 :
585 : const int kStackElementSize = 8;
586 12 : __ movq(rax, Operand(rbp, -3 * kStackElementSize));
587 6 : __ popq(arg2);
588 6 : __ popq(arg2);
589 6 : __ popq(arg2);
590 6 : __ popq(rbp);
591 6 : __ nop();
592 6 : __ ret(0);
593 :
594 : CodeDesc desc;
595 6 : assm.GetCode(CcTest::i_isolate(), &desc);
596 : // Call the function from C++.
597 6 : int result = FUNCTION_CAST<F2>(buffer)(3, 2);
598 6 : CHECK_EQ(3, result);
599 6 : }
600 :
601 :
602 23724 : TEST(AssemblerX64ControlFlow) {
603 6 : CcTest::InitializeVM();
604 : // Allocate an executable page of memory.
605 : size_t actual_size;
606 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
607 6 : Assembler::kMinimalBufferSize, &actual_size, true));
608 6 : CHECK(buffer);
609 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
610 :
611 : // Assemble a simple function that copies argument 1 and returns it.
612 6 : __ pushq(rbp);
613 :
614 : __ movq(rbp, rsp);
615 : __ movq(rax, arg1);
616 : Label target;
617 6 : __ jmp(&target);
618 : __ movq(rax, arg2);
619 6 : __ bind(&target);
620 6 : __ popq(rbp);
621 6 : __ ret(0);
622 :
623 : CodeDesc desc;
624 6 : assm.GetCode(CcTest::i_isolate(), &desc);
625 : // Call the function from C++.
626 6 : int result = FUNCTION_CAST<F2>(buffer)(3, 2);
627 6 : CHECK_EQ(3, result);
628 6 : }
629 :
630 :
631 23724 : TEST(AssemblerX64LoopImmediates) {
632 6 : CcTest::InitializeVM();
633 : // Allocate an executable page of memory.
634 : size_t actual_size;
635 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
636 6 : Assembler::kMinimalBufferSize, &actual_size, true));
637 6 : CHECK(buffer);
638 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
639 : // Assemble two loops using rax as counter, and verify the ending counts.
640 : Label Fail;
641 : __ movq(rax, Immediate(-3));
642 : Label Loop1_test;
643 : Label Loop1_body;
644 6 : __ jmp(&Loop1_test);
645 6 : __ bind(&Loop1_body);
646 6 : __ addq(rax, Immediate(7));
647 6 : __ bind(&Loop1_test);
648 6 : __ cmpq(rax, Immediate(20));
649 6 : __ j(less_equal, &Loop1_body);
650 : // Did the loop terminate with the expected value?
651 6 : __ cmpq(rax, Immediate(25));
652 6 : __ j(not_equal, &Fail);
653 :
654 : Label Loop2_test;
655 : Label Loop2_body;
656 : __ movq(rax, Immediate(0x11FEED00));
657 6 : __ jmp(&Loop2_test);
658 6 : __ bind(&Loop2_body);
659 6 : __ addq(rax, Immediate(-0x1100));
660 6 : __ bind(&Loop2_test);
661 6 : __ cmpq(rax, Immediate(0x11FE8000));
662 6 : __ j(greater, &Loop2_body);
663 : // Did the loop terminate with the expected value?
664 6 : __ cmpq(rax, Immediate(0x11FE7600));
665 6 : __ j(not_equal, &Fail);
666 :
667 : __ movq(rax, Immediate(1));
668 6 : __ ret(0);
669 6 : __ bind(&Fail);
670 : __ movq(rax, Immediate(0));
671 6 : __ ret(0);
672 :
673 : CodeDesc desc;
674 6 : assm.GetCode(CcTest::i_isolate(), &desc);
675 : // Call the function from C++.
676 6 : int result = FUNCTION_CAST<F0>(buffer)();
677 6 : CHECK_EQ(1, result);
678 6 : }
679 :
680 :
681 23724 : TEST(OperandRegisterDependency) {
682 6 : int offsets[4] = {0, 1, 0xfed, 0xbeefcad};
683 30 : for (int i = 0; i < 4; i++) {
684 24 : int offset = offsets[i];
685 24 : CHECK(Operand(rax, offset).AddressUsesRegister(rax));
686 24 : CHECK(!Operand(rax, offset).AddressUsesRegister(r8));
687 24 : CHECK(!Operand(rax, offset).AddressUsesRegister(rcx));
688 :
689 24 : CHECK(Operand(rax, rax, times_1, offset).AddressUsesRegister(rax));
690 24 : CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(r8));
691 24 : CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(rcx));
692 :
693 24 : CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rax));
694 24 : CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rcx));
695 24 : CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r8));
696 24 : CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r9));
697 24 : CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rdx));
698 24 : CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rsp));
699 :
700 24 : CHECK(Operand(rsp, offset).AddressUsesRegister(rsp));
701 24 : CHECK(!Operand(rsp, offset).AddressUsesRegister(rax));
702 24 : CHECK(!Operand(rsp, offset).AddressUsesRegister(r15));
703 :
704 24 : CHECK(Operand(rbp, offset).AddressUsesRegister(rbp));
705 24 : CHECK(!Operand(rbp, offset).AddressUsesRegister(rax));
706 24 : CHECK(!Operand(rbp, offset).AddressUsesRegister(r13));
707 :
708 24 : CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rbp));
709 24 : CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rax));
710 24 : CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rcx));
711 24 : CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r13));
712 24 : CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r8));
713 24 : CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rsp));
714 :
715 24 : CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rsp));
716 24 : CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rbp));
717 24 : CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rax));
718 24 : CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r15));
719 24 : CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r13));
720 : }
721 6 : }
722 :
723 :
724 23724 : TEST(AssemblerX64LabelChaining) {
725 : // Test chaining of label usages within instructions (issue 1644).
726 6 : CcTest::InitializeVM();
727 6 : v8::HandleScope scope(CcTest::isolate());
728 12 : Assembler assm(CcTest::i_isolate(), nullptr, 0);
729 :
730 : Label target;
731 6 : __ j(equal, &target);
732 6 : __ j(not_equal, &target);
733 6 : __ bind(&target);
734 12 : __ nop();
735 6 : }
736 :
737 :
738 23724 : TEST(AssemblerMultiByteNop) {
739 6 : CcTest::InitializeVM();
740 6 : v8::HandleScope scope(CcTest::isolate());
741 : byte buffer[1024];
742 : Isolate* isolate = CcTest::i_isolate();
743 12 : Assembler assm(isolate, buffer, sizeof(buffer));
744 6 : __ pushq(rbx);
745 6 : __ pushq(rcx);
746 6 : __ pushq(rdx);
747 6 : __ pushq(rdi);
748 6 : __ pushq(rsi);
749 : __ movq(rax, Immediate(1));
750 : __ movq(rbx, Immediate(2));
751 : __ movq(rcx, Immediate(3));
752 : __ movq(rdx, Immediate(4));
753 : __ movq(rdi, Immediate(5));
754 : __ movq(rsi, Immediate(6));
755 102 : for (int i = 0; i < 16; i++) {
756 96 : int before = assm.pc_offset();
757 96 : __ Nop(i);
758 192 : CHECK_EQ(assm.pc_offset() - before, i);
759 : }
760 :
761 : Label fail;
762 6 : __ cmpq(rax, Immediate(1));
763 6 : __ j(not_equal, &fail);
764 6 : __ cmpq(rbx, Immediate(2));
765 6 : __ j(not_equal, &fail);
766 6 : __ cmpq(rcx, Immediate(3));
767 6 : __ j(not_equal, &fail);
768 6 : __ cmpq(rdx, Immediate(4));
769 6 : __ j(not_equal, &fail);
770 6 : __ cmpq(rdi, Immediate(5));
771 6 : __ j(not_equal, &fail);
772 6 : __ cmpq(rsi, Immediate(6));
773 6 : __ j(not_equal, &fail);
774 : __ movq(rax, Immediate(42));
775 6 : __ popq(rsi);
776 6 : __ popq(rdi);
777 6 : __ popq(rdx);
778 6 : __ popq(rcx);
779 6 : __ popq(rbx);
780 6 : __ ret(0);
781 6 : __ bind(&fail);
782 : __ movq(rax, Immediate(13));
783 6 : __ popq(rsi);
784 6 : __ popq(rdi);
785 6 : __ popq(rdx);
786 6 : __ popq(rcx);
787 6 : __ popq(rbx);
788 6 : __ ret(0);
789 :
790 : CodeDesc desc;
791 6 : assm.GetCode(isolate, &desc);
792 : Handle<Code> code =
793 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
794 :
795 6 : F0 f = FUNCTION_CAST<F0>(code->entry());
796 6 : int res = f();
797 12 : CHECK_EQ(42, res);
798 6 : }
799 :
800 :
801 : #ifdef __GNUC__
802 : #define ELEMENT_COUNT 4u
803 :
804 12 : void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
805 6 : v8::HandleScope scope(CcTest::isolate());
806 6 : v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
807 : byte buffer[1024];
808 :
809 6 : CHECK(args[0]->IsArray());
810 : v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
811 6 : CHECK_EQ(ELEMENT_COUNT, vec->Length());
812 :
813 : Isolate* isolate = CcTest::i_isolate();
814 12 : Assembler assm(isolate, buffer, sizeof(buffer));
815 :
816 : // Remove return address from the stack for fix stack frame alignment.
817 6 : __ popq(rcx);
818 :
819 : // Store input vector on the stack.
820 18 : for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
821 : __ movl(rax, Immediate(vec->Get(context, i)
822 12 : .ToLocalChecked()
823 : ->Int32Value(context)
824 24 : .FromJust()));
825 : __ shlq(rax, Immediate(0x20));
826 : __ orq(rax, Immediate(vec->Get(context, ++i)
827 12 : .ToLocalChecked()
828 : ->Int32Value(context)
829 24 : .FromJust()));
830 12 : __ pushq(rax);
831 : }
832 :
833 : // Read vector into a xmm register.
834 6 : __ xorps(xmm0, xmm0);
835 6 : __ movdqa(xmm0, Operand(rsp, 0));
836 : // Create mask and store it in the return register.
837 6 : __ movmskps(rax, xmm0);
838 :
839 : // Remove unused data from the stack.
840 6 : __ addq(rsp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
841 : // Restore return address.
842 6 : __ pushq(rcx);
843 :
844 6 : __ ret(0);
845 :
846 : CodeDesc desc;
847 6 : assm.GetCode(isolate, &desc);
848 : Handle<Code> code =
849 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
850 :
851 6 : F0 f = FUNCTION_CAST<F0>(code->entry());
852 6 : int res = f();
853 12 : args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
854 6 : }
855 :
856 :
857 23724 : TEST(StackAlignmentForSSE2) {
858 6 : CcTest::InitializeVM();
859 6 : CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
860 :
861 6 : v8::Isolate* isolate = CcTest::isolate();
862 6 : v8::HandleScope handle_scope(isolate);
863 : v8::Local<v8::ObjectTemplate> global_template =
864 6 : v8::ObjectTemplate::New(isolate);
865 : global_template->Set(v8_str("do_sse2"),
866 18 : v8::FunctionTemplate::New(isolate, DoSSE2));
867 :
868 12 : LocalContext env(nullptr, global_template);
869 : CompileRun(
870 : "function foo(vec) {"
871 : " return do_sse2(vec);"
872 : "}");
873 :
874 6 : v8::Local<v8::Object> global_object = env->Global();
875 : v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
876 24 : global_object->Get(env.local(), v8_str("foo")).ToLocalChecked());
877 :
878 6 : int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
879 6 : v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
880 30 : for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
881 72 : v8_vec->Set(env.local(), i, v8_num(vec[i])).FromJust();
882 : }
883 :
884 : v8::Local<v8::Value> args[] = { v8_vec };
885 : v8::Local<v8::Value> result =
886 12 : foo->Call(env.local(), global_object, 1, args).ToLocalChecked();
887 :
888 : // The mask should be 0b1000.
889 18 : CHECK_EQ(8, result->Int32Value(env.local()).FromJust());
890 6 : }
891 :
892 : #undef ELEMENT_COUNT
893 : #endif // __GNUC__
894 :
895 :
896 23724 : TEST(AssemblerX64Extractps) {
897 6 : CcTest::InitializeVM();
898 6 : if (!CpuFeatures::IsSupported(SSE4_1)) return;
899 :
900 6 : v8::HandleScope scope(CcTest::isolate());
901 : byte buffer[256];
902 : Isolate* isolate = CcTest::i_isolate();
903 12 : Assembler assm(isolate, buffer, sizeof(buffer));
904 : { CpuFeatureScope fscope2(&assm, SSE4_1);
905 6 : __ extractps(rax, xmm0, 0x1);
906 6 : __ ret(0);
907 : }
908 :
909 : CodeDesc desc;
910 6 : assm.GetCode(isolate, &desc);
911 : Handle<Code> code =
912 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
913 : #ifdef OBJECT_PRINT
914 : OFStream os(stdout);
915 : code->Print(os);
916 : #endif
917 :
918 6 : F3 f = FUNCTION_CAST<F3>(code->entry());
919 : uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
920 6 : CHECK_EQ(0x12345678u, f(uint64_to_double(value1)));
921 : uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
922 12 : CHECK_EQ(0x87654321u, f(uint64_to_double(value2)));
923 : }
924 :
925 :
926 : typedef int (*F6)(float x, float y);
927 23724 : TEST(AssemblerX64SSE) {
928 6 : CcTest::InitializeVM();
929 :
930 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
931 : HandleScope scope(isolate);
932 : v8::internal::byte buffer[256];
933 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
934 6 : v8::internal::CodeObjectRequired::kYes);
935 : {
936 6 : __ shufps(xmm0, xmm0, 0x0); // brocast first argument
937 6 : __ shufps(xmm1, xmm1, 0x0); // brocast second argument
938 6 : __ movaps(xmm2, xmm1);
939 6 : __ addps(xmm2, xmm0);
940 6 : __ mulps(xmm2, xmm1);
941 6 : __ subps(xmm2, xmm0);
942 6 : __ divps(xmm2, xmm1);
943 6 : __ cvttss2si(rax, xmm2);
944 6 : __ ret(0);
945 : }
946 :
947 : CodeDesc desc;
948 6 : assm.GetCode(isolate, &desc);
949 : Handle<Code> code =
950 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
951 : #ifdef OBJECT_PRINT
952 : OFStream os(stdout);
953 : code->Print(os);
954 : #endif
955 :
956 6 : F6 f = FUNCTION_CAST<F6>(code->entry());
957 6 : CHECK_EQ(2, f(1.0, 2.0));
958 6 : }
959 :
960 :
961 : typedef int (*F7)(double x, double y, double z);
962 23724 : TEST(AssemblerX64FMA_sd) {
963 6 : CcTest::InitializeVM();
964 6 : if (!CpuFeatures::IsSupported(FMA3)) return;
965 :
966 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
967 : HandleScope scope(isolate);
968 : v8::internal::byte buffer[1024];
969 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
970 6 : v8::internal::CodeObjectRequired::kYes);
971 : {
972 : CpuFeatureScope fscope(&assm, FMA3);
973 : Label exit;
974 : // argument in xmm0, xmm1 and xmm2
975 : // xmm0 * xmm1 + xmm2
976 6 : __ movaps(xmm3, xmm0);
977 6 : __ mulsd(xmm3, xmm1);
978 6 : __ addsd(xmm3, xmm2); // Expected result in xmm3
979 :
980 6 : __ subq(rsp, Immediate(kDoubleSize)); // For memory operand
981 : // vfmadd132sd
982 : __ movl(rax, Immediate(1)); // Test number
983 6 : __ movaps(xmm8, xmm0);
984 : __ vfmadd132sd(xmm8, xmm2, xmm1);
985 6 : __ ucomisd(xmm8, xmm3);
986 6 : __ j(not_equal, &exit);
987 : // vfmadd213sd
988 : __ incq(rax);
989 6 : __ movaps(xmm8, xmm1);
990 : __ vfmadd213sd(xmm8, xmm0, xmm2);
991 6 : __ ucomisd(xmm8, xmm3);
992 6 : __ j(not_equal, &exit);
993 : // vfmadd231sd
994 : __ incq(rax);
995 6 : __ movaps(xmm8, xmm2);
996 : __ vfmadd231sd(xmm8, xmm0, xmm1);
997 6 : __ ucomisd(xmm8, xmm3);
998 6 : __ j(not_equal, &exit);
999 :
1000 : // vfmadd132sd
1001 : __ incq(rax);
1002 6 : __ movaps(xmm8, xmm0);
1003 6 : __ movsd(Operand(rsp, 0), xmm1);
1004 12 : __ vfmadd132sd(xmm8, xmm2, Operand(rsp, 0));
1005 6 : __ ucomisd(xmm8, xmm3);
1006 6 : __ j(not_equal, &exit);
1007 : // vfmadd213sd
1008 : __ incq(rax);
1009 6 : __ movaps(xmm8, xmm1);
1010 6 : __ movsd(Operand(rsp, 0), xmm2);
1011 12 : __ vfmadd213sd(xmm8, xmm0, Operand(rsp, 0));
1012 6 : __ ucomisd(xmm8, xmm3);
1013 6 : __ j(not_equal, &exit);
1014 : // vfmadd231sd
1015 : __ incq(rax);
1016 6 : __ movaps(xmm8, xmm2);
1017 6 : __ movsd(Operand(rsp, 0), xmm1);
1018 12 : __ vfmadd231sd(xmm8, xmm0, Operand(rsp, 0));
1019 6 : __ ucomisd(xmm8, xmm3);
1020 6 : __ j(not_equal, &exit);
1021 :
1022 : // xmm0 * xmm1 - xmm2
1023 6 : __ movaps(xmm3, xmm0);
1024 6 : __ mulsd(xmm3, xmm1);
1025 6 : __ subsd(xmm3, xmm2); // Expected result in xmm3
1026 :
1027 : // vfmsub132sd
1028 : __ incq(rax);
1029 6 : __ movaps(xmm8, xmm0);
1030 : __ vfmsub132sd(xmm8, xmm2, xmm1);
1031 6 : __ ucomisd(xmm8, xmm3);
1032 6 : __ j(not_equal, &exit);
1033 : // vfmadd213sd
1034 : __ incq(rax);
1035 6 : __ movaps(xmm8, xmm1);
1036 : __ vfmsub213sd(xmm8, xmm0, xmm2);
1037 6 : __ ucomisd(xmm8, xmm3);
1038 6 : __ j(not_equal, &exit);
1039 : // vfmsub231sd
1040 : __ incq(rax);
1041 6 : __ movaps(xmm8, xmm2);
1042 : __ vfmsub231sd(xmm8, xmm0, xmm1);
1043 6 : __ ucomisd(xmm8, xmm3);
1044 6 : __ j(not_equal, &exit);
1045 :
1046 : // vfmsub132sd
1047 : __ incq(rax);
1048 6 : __ movaps(xmm8, xmm0);
1049 6 : __ movsd(Operand(rsp, 0), xmm1);
1050 12 : __ vfmsub132sd(xmm8, xmm2, Operand(rsp, 0));
1051 6 : __ ucomisd(xmm8, xmm3);
1052 6 : __ j(not_equal, &exit);
1053 : // vfmsub213sd
1054 : __ incq(rax);
1055 6 : __ movaps(xmm8, xmm1);
1056 6 : __ movsd(Operand(rsp, 0), xmm2);
1057 12 : __ vfmsub213sd(xmm8, xmm0, Operand(rsp, 0));
1058 6 : __ ucomisd(xmm8, xmm3);
1059 6 : __ j(not_equal, &exit);
1060 : // vfmsub231sd
1061 : __ incq(rax);
1062 6 : __ movaps(xmm8, xmm2);
1063 6 : __ movsd(Operand(rsp, 0), xmm1);
1064 12 : __ vfmsub231sd(xmm8, xmm0, Operand(rsp, 0));
1065 6 : __ ucomisd(xmm8, xmm3);
1066 6 : __ j(not_equal, &exit);
1067 :
1068 :
1069 : // - xmm0 * xmm1 + xmm2
1070 6 : __ movaps(xmm3, xmm0);
1071 6 : __ mulsd(xmm3, xmm1);
1072 6 : __ Move(xmm4, (uint64_t)1 << 63);
1073 6 : __ xorpd(xmm3, xmm4);
1074 6 : __ addsd(xmm3, xmm2); // Expected result in xmm3
1075 :
1076 : // vfnmadd132sd
1077 : __ incq(rax);
1078 6 : __ movaps(xmm8, xmm0);
1079 : __ vfnmadd132sd(xmm8, xmm2, xmm1);
1080 6 : __ ucomisd(xmm8, xmm3);
1081 6 : __ j(not_equal, &exit);
1082 : // vfmadd213sd
1083 : __ incq(rax);
1084 6 : __ movaps(xmm8, xmm1);
1085 : __ vfnmadd213sd(xmm8, xmm0, xmm2);
1086 6 : __ ucomisd(xmm8, xmm3);
1087 6 : __ j(not_equal, &exit);
1088 : // vfnmadd231sd
1089 : __ incq(rax);
1090 6 : __ movaps(xmm8, xmm2);
1091 : __ vfnmadd231sd(xmm8, xmm0, xmm1);
1092 6 : __ ucomisd(xmm8, xmm3);
1093 6 : __ j(not_equal, &exit);
1094 :
1095 : // vfnmadd132sd
1096 : __ incq(rax);
1097 6 : __ movaps(xmm8, xmm0);
1098 6 : __ movsd(Operand(rsp, 0), xmm1);
1099 12 : __ vfnmadd132sd(xmm8, xmm2, Operand(rsp, 0));
1100 6 : __ ucomisd(xmm8, xmm3);
1101 6 : __ j(not_equal, &exit);
1102 : // vfnmadd213sd
1103 : __ incq(rax);
1104 6 : __ movaps(xmm8, xmm1);
1105 6 : __ movsd(Operand(rsp, 0), xmm2);
1106 12 : __ vfnmadd213sd(xmm8, xmm0, Operand(rsp, 0));
1107 6 : __ ucomisd(xmm8, xmm3);
1108 6 : __ j(not_equal, &exit);
1109 : // vfnmadd231sd
1110 : __ incq(rax);
1111 6 : __ movaps(xmm8, xmm2);
1112 6 : __ movsd(Operand(rsp, 0), xmm1);
1113 12 : __ vfnmadd231sd(xmm8, xmm0, Operand(rsp, 0));
1114 6 : __ ucomisd(xmm8, xmm3);
1115 6 : __ j(not_equal, &exit);
1116 :
1117 :
1118 : // - xmm0 * xmm1 - xmm2
1119 6 : __ movaps(xmm3, xmm0);
1120 6 : __ mulsd(xmm3, xmm1);
1121 6 : __ Move(xmm4, (uint64_t)1 << 63);
1122 6 : __ xorpd(xmm3, xmm4);
1123 6 : __ subsd(xmm3, xmm2); // Expected result in xmm3
1124 :
1125 : // vfnmsub132sd
1126 : __ incq(rax);
1127 6 : __ movaps(xmm8, xmm0);
1128 : __ vfnmsub132sd(xmm8, xmm2, xmm1);
1129 6 : __ ucomisd(xmm8, xmm3);
1130 6 : __ j(not_equal, &exit);
1131 : // vfmsub213sd
1132 : __ incq(rax);
1133 6 : __ movaps(xmm8, xmm1);
1134 : __ vfnmsub213sd(xmm8, xmm0, xmm2);
1135 6 : __ ucomisd(xmm8, xmm3);
1136 6 : __ j(not_equal, &exit);
1137 : // vfnmsub231sd
1138 : __ incq(rax);
1139 6 : __ movaps(xmm8, xmm2);
1140 : __ vfnmsub231sd(xmm8, xmm0, xmm1);
1141 6 : __ ucomisd(xmm8, xmm3);
1142 6 : __ j(not_equal, &exit);
1143 :
1144 : // vfnmsub132sd
1145 : __ incq(rax);
1146 6 : __ movaps(xmm8, xmm0);
1147 6 : __ movsd(Operand(rsp, 0), xmm1);
1148 12 : __ vfnmsub132sd(xmm8, xmm2, Operand(rsp, 0));
1149 6 : __ ucomisd(xmm8, xmm3);
1150 6 : __ j(not_equal, &exit);
1151 : // vfnmsub213sd
1152 : __ incq(rax);
1153 6 : __ movaps(xmm8, xmm1);
1154 6 : __ movsd(Operand(rsp, 0), xmm2);
1155 12 : __ vfnmsub213sd(xmm8, xmm0, Operand(rsp, 0));
1156 6 : __ ucomisd(xmm8, xmm3);
1157 6 : __ j(not_equal, &exit);
1158 : // vfnmsub231sd
1159 : __ incq(rax);
1160 6 : __ movaps(xmm8, xmm2);
1161 6 : __ movsd(Operand(rsp, 0), xmm1);
1162 12 : __ vfnmsub231sd(xmm8, xmm0, Operand(rsp, 0));
1163 6 : __ ucomisd(xmm8, xmm3);
1164 6 : __ j(not_equal, &exit);
1165 :
1166 :
1167 : __ xorl(rax, rax);
1168 6 : __ bind(&exit);
1169 6 : __ addq(rsp, Immediate(kDoubleSize));
1170 6 : __ ret(0);
1171 : }
1172 :
1173 : CodeDesc desc;
1174 6 : assm.GetCode(isolate, &desc);
1175 : Handle<Code> code =
1176 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
1177 : #ifdef OBJECT_PRINT
1178 : OFStream os(stdout);
1179 : code->Print(os);
1180 : #endif
1181 :
1182 6 : F7 f = FUNCTION_CAST<F7>(code->entry());
1183 6 : CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
1184 : }
1185 :
1186 :
1187 : typedef int (*F8)(float x, float y, float z);
1188 23724 : TEST(AssemblerX64FMA_ss) {
1189 6 : CcTest::InitializeVM();
1190 6 : if (!CpuFeatures::IsSupported(FMA3)) return;
1191 :
1192 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1193 : HandleScope scope(isolate);
1194 : v8::internal::byte buffer[1024];
1195 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
1196 6 : v8::internal::CodeObjectRequired::kYes);
1197 : {
1198 : CpuFeatureScope fscope(&assm, FMA3);
1199 : Label exit;
1200 : // arguments in xmm0, xmm1 and xmm2
1201 : // xmm0 * xmm1 + xmm2
1202 6 : __ movaps(xmm3, xmm0);
1203 6 : __ mulss(xmm3, xmm1);
1204 6 : __ addss(xmm3, xmm2); // Expected result in xmm3
1205 :
1206 6 : __ subq(rsp, Immediate(kDoubleSize)); // For memory operand
1207 : // vfmadd132ss
1208 : __ movl(rax, Immediate(1)); // Test number
1209 6 : __ movaps(xmm8, xmm0);
1210 : __ vfmadd132ss(xmm8, xmm2, xmm1);
1211 6 : __ ucomiss(xmm8, xmm3);
1212 6 : __ j(not_equal, &exit);
1213 : // vfmadd213ss
1214 : __ incq(rax);
1215 6 : __ movaps(xmm8, xmm1);
1216 : __ vfmadd213ss(xmm8, xmm0, xmm2);
1217 6 : __ ucomiss(xmm8, xmm3);
1218 6 : __ j(not_equal, &exit);
1219 : // vfmadd231ss
1220 : __ incq(rax);
1221 6 : __ movaps(xmm8, xmm2);
1222 : __ vfmadd231ss(xmm8, xmm0, xmm1);
1223 6 : __ ucomiss(xmm8, xmm3);
1224 6 : __ j(not_equal, &exit);
1225 :
1226 : // vfmadd132ss
1227 : __ incq(rax);
1228 6 : __ movaps(xmm8, xmm0);
1229 6 : __ movss(Operand(rsp, 0), xmm1);
1230 12 : __ vfmadd132ss(xmm8, xmm2, Operand(rsp, 0));
1231 6 : __ ucomiss(xmm8, xmm3);
1232 6 : __ j(not_equal, &exit);
1233 : // vfmadd213ss
1234 : __ incq(rax);
1235 6 : __ movaps(xmm8, xmm1);
1236 6 : __ movss(Operand(rsp, 0), xmm2);
1237 12 : __ vfmadd213ss(xmm8, xmm0, Operand(rsp, 0));
1238 6 : __ ucomiss(xmm8, xmm3);
1239 6 : __ j(not_equal, &exit);
1240 : // vfmadd231ss
1241 : __ incq(rax);
1242 6 : __ movaps(xmm8, xmm2);
1243 6 : __ movss(Operand(rsp, 0), xmm1);
1244 12 : __ vfmadd231ss(xmm8, xmm0, Operand(rsp, 0));
1245 6 : __ ucomiss(xmm8, xmm3);
1246 6 : __ j(not_equal, &exit);
1247 :
1248 : // xmm0 * xmm1 - xmm2
1249 6 : __ movaps(xmm3, xmm0);
1250 6 : __ mulss(xmm3, xmm1);
1251 6 : __ subss(xmm3, xmm2); // Expected result in xmm3
1252 :
1253 : // vfmsub132ss
1254 : __ incq(rax);
1255 6 : __ movaps(xmm8, xmm0);
1256 : __ vfmsub132ss(xmm8, xmm2, xmm1);
1257 6 : __ ucomiss(xmm8, xmm3);
1258 6 : __ j(not_equal, &exit);
1259 : // vfmadd213ss
1260 : __ incq(rax);
1261 6 : __ movaps(xmm8, xmm1);
1262 : __ vfmsub213ss(xmm8, xmm0, xmm2);
1263 6 : __ ucomiss(xmm8, xmm3);
1264 6 : __ j(not_equal, &exit);
1265 : // vfmsub231ss
1266 : __ incq(rax);
1267 6 : __ movaps(xmm8, xmm2);
1268 : __ vfmsub231ss(xmm8, xmm0, xmm1);
1269 6 : __ ucomiss(xmm8, xmm3);
1270 6 : __ j(not_equal, &exit);
1271 :
1272 : // vfmsub132ss
1273 : __ incq(rax);
1274 6 : __ movaps(xmm8, xmm0);
1275 6 : __ movss(Operand(rsp, 0), xmm1);
1276 12 : __ vfmsub132ss(xmm8, xmm2, Operand(rsp, 0));
1277 6 : __ ucomiss(xmm8, xmm3);
1278 6 : __ j(not_equal, &exit);
1279 : // vfmsub213ss
1280 : __ incq(rax);
1281 6 : __ movaps(xmm8, xmm1);
1282 6 : __ movss(Operand(rsp, 0), xmm2);
1283 12 : __ vfmsub213ss(xmm8, xmm0, Operand(rsp, 0));
1284 6 : __ ucomiss(xmm8, xmm3);
1285 6 : __ j(not_equal, &exit);
1286 : // vfmsub231ss
1287 : __ incq(rax);
1288 6 : __ movaps(xmm8, xmm2);
1289 6 : __ movss(Operand(rsp, 0), xmm1);
1290 12 : __ vfmsub231ss(xmm8, xmm0, Operand(rsp, 0));
1291 6 : __ ucomiss(xmm8, xmm3);
1292 6 : __ j(not_equal, &exit);
1293 :
1294 :
1295 : // - xmm0 * xmm1 + xmm2
1296 6 : __ movaps(xmm3, xmm0);
1297 6 : __ mulss(xmm3, xmm1);
1298 6 : __ Move(xmm4, (uint32_t)1 << 31);
1299 6 : __ xorps(xmm3, xmm4);
1300 6 : __ addss(xmm3, xmm2); // Expected result in xmm3
1301 :
1302 : // vfnmadd132ss
1303 : __ incq(rax);
1304 6 : __ movaps(xmm8, xmm0);
1305 : __ vfnmadd132ss(xmm8, xmm2, xmm1);
1306 6 : __ ucomiss(xmm8, xmm3);
1307 6 : __ j(not_equal, &exit);
1308 : // vfmadd213ss
1309 : __ incq(rax);
1310 6 : __ movaps(xmm8, xmm1);
1311 : __ vfnmadd213ss(xmm8, xmm0, xmm2);
1312 6 : __ ucomiss(xmm8, xmm3);
1313 6 : __ j(not_equal, &exit);
1314 : // vfnmadd231ss
1315 : __ incq(rax);
1316 6 : __ movaps(xmm8, xmm2);
1317 : __ vfnmadd231ss(xmm8, xmm0, xmm1);
1318 6 : __ ucomiss(xmm8, xmm3);
1319 6 : __ j(not_equal, &exit);
1320 :
1321 : // vfnmadd132ss
1322 : __ incq(rax);
1323 6 : __ movaps(xmm8, xmm0);
1324 6 : __ movss(Operand(rsp, 0), xmm1);
1325 12 : __ vfnmadd132ss(xmm8, xmm2, Operand(rsp, 0));
1326 6 : __ ucomiss(xmm8, xmm3);
1327 6 : __ j(not_equal, &exit);
1328 : // vfnmadd213ss
1329 : __ incq(rax);
1330 6 : __ movaps(xmm8, xmm1);
1331 6 : __ movss(Operand(rsp, 0), xmm2);
1332 12 : __ vfnmadd213ss(xmm8, xmm0, Operand(rsp, 0));
1333 6 : __ ucomiss(xmm8, xmm3);
1334 6 : __ j(not_equal, &exit);
1335 : // vfnmadd231ss
1336 : __ incq(rax);
1337 6 : __ movaps(xmm8, xmm2);
1338 6 : __ movss(Operand(rsp, 0), xmm1);
1339 12 : __ vfnmadd231ss(xmm8, xmm0, Operand(rsp, 0));
1340 6 : __ ucomiss(xmm8, xmm3);
1341 6 : __ j(not_equal, &exit);
1342 :
1343 :
1344 : // - xmm0 * xmm1 - xmm2
1345 6 : __ movaps(xmm3, xmm0);
1346 6 : __ mulss(xmm3, xmm1);
1347 6 : __ Move(xmm4, (uint32_t)1 << 31);
1348 6 : __ xorps(xmm3, xmm4);
1349 6 : __ subss(xmm3, xmm2); // Expected result in xmm3
1350 :
1351 : // vfnmsub132ss
1352 : __ incq(rax);
1353 6 : __ movaps(xmm8, xmm0);
1354 : __ vfnmsub132ss(xmm8, xmm2, xmm1);
1355 6 : __ ucomiss(xmm8, xmm3);
1356 6 : __ j(not_equal, &exit);
1357 : // vfmsub213ss
1358 : __ incq(rax);
1359 6 : __ movaps(xmm8, xmm1);
1360 : __ vfnmsub213ss(xmm8, xmm0, xmm2);
1361 6 : __ ucomiss(xmm8, xmm3);
1362 6 : __ j(not_equal, &exit);
1363 : // vfnmsub231ss
1364 : __ incq(rax);
1365 6 : __ movaps(xmm8, xmm2);
1366 : __ vfnmsub231ss(xmm8, xmm0, xmm1);
1367 6 : __ ucomiss(xmm8, xmm3);
1368 6 : __ j(not_equal, &exit);
1369 :
1370 : // vfnmsub132ss
1371 : __ incq(rax);
1372 6 : __ movaps(xmm8, xmm0);
1373 6 : __ movss(Operand(rsp, 0), xmm1);
1374 12 : __ vfnmsub132ss(xmm8, xmm2, Operand(rsp, 0));
1375 6 : __ ucomiss(xmm8, xmm3);
1376 6 : __ j(not_equal, &exit);
1377 : // vfnmsub213ss
1378 : __ incq(rax);
1379 6 : __ movaps(xmm8, xmm1);
1380 6 : __ movss(Operand(rsp, 0), xmm2);
1381 12 : __ vfnmsub213ss(xmm8, xmm0, Operand(rsp, 0));
1382 6 : __ ucomiss(xmm8, xmm3);
1383 6 : __ j(not_equal, &exit);
1384 : // vfnmsub231ss
1385 : __ incq(rax);
1386 6 : __ movaps(xmm8, xmm2);
1387 6 : __ movss(Operand(rsp, 0), xmm1);
1388 12 : __ vfnmsub231ss(xmm8, xmm0, Operand(rsp, 0));
1389 6 : __ ucomiss(xmm8, xmm3);
1390 6 : __ j(not_equal, &exit);
1391 :
1392 :
1393 : __ xorl(rax, rax);
1394 6 : __ bind(&exit);
1395 6 : __ addq(rsp, Immediate(kDoubleSize));
1396 6 : __ ret(0);
1397 : }
1398 :
1399 : CodeDesc desc;
1400 6 : assm.GetCode(isolate, &desc);
1401 : Handle<Code> code =
1402 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
1403 : #ifdef OBJECT_PRINT
1404 : OFStream os(stdout);
1405 : code->Print(os);
1406 : #endif
1407 :
1408 6 : F8 f = FUNCTION_CAST<F8>(code->entry());
1409 6 : CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1410 : }
1411 :
1412 :
1413 23724 : TEST(AssemblerX64SSE_ss) {
1414 6 : CcTest::InitializeVM();
1415 :
1416 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1417 : HandleScope scope(isolate);
1418 : v8::internal::byte buffer[1024];
1419 12 : Assembler assm(isolate, buffer, sizeof(buffer));
1420 : {
1421 : Label exit;
1422 : // arguments in xmm0, xmm1 and xmm2
1423 : __ movl(rax, Immediate(0));
1424 :
1425 6 : __ movaps(xmm3, xmm0);
1426 6 : __ maxss(xmm3, xmm1);
1427 6 : __ ucomiss(xmm3, xmm1);
1428 6 : __ j(parity_even, &exit);
1429 6 : __ j(not_equal, &exit);
1430 : __ movl(rax, Immediate(1));
1431 :
1432 6 : __ movaps(xmm3, xmm1);
1433 6 : __ minss(xmm3, xmm2);
1434 6 : __ ucomiss(xmm3, xmm1);
1435 6 : __ j(parity_even, &exit);
1436 6 : __ j(not_equal, &exit);
1437 : __ movl(rax, Immediate(2));
1438 :
1439 6 : __ movaps(xmm3, xmm2);
1440 6 : __ subss(xmm3, xmm1);
1441 6 : __ ucomiss(xmm3, xmm0);
1442 6 : __ j(parity_even, &exit);
1443 6 : __ j(not_equal, &exit);
1444 : __ movl(rax, Immediate(3));
1445 :
1446 6 : __ movaps(xmm3, xmm0);
1447 6 : __ addss(xmm3, xmm1);
1448 6 : __ ucomiss(xmm3, xmm2);
1449 6 : __ j(parity_even, &exit);
1450 6 : __ j(not_equal, &exit);
1451 : __ movl(rax, Immediate(4));
1452 :
1453 6 : __ movaps(xmm3, xmm0);
1454 6 : __ mulss(xmm3, xmm1);
1455 6 : __ ucomiss(xmm3, xmm1);
1456 6 : __ j(parity_even, &exit);
1457 6 : __ j(not_equal, &exit);
1458 : __ movl(rax, Immediate(5));
1459 :
1460 6 : __ movaps(xmm3, xmm0);
1461 6 : __ divss(xmm3, xmm1);
1462 6 : __ mulss(xmm3, xmm2);
1463 6 : __ mulss(xmm3, xmm1);
1464 6 : __ ucomiss(xmm3, xmm2);
1465 6 : __ j(parity_even, &exit);
1466 6 : __ j(not_equal, &exit);
1467 : __ movl(rax, Immediate(6));
1468 :
1469 : // result in eax
1470 6 : __ bind(&exit);
1471 6 : __ ret(0);
1472 : }
1473 :
1474 : CodeDesc desc;
1475 6 : assm.GetCode(isolate, &desc);
1476 : Handle<Code> code =
1477 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
1478 : #ifdef OBJECT_PRINT
1479 : OFStream os(stdout);
1480 : code->Print(os);
1481 : #endif
1482 :
1483 6 : F8 f = FUNCTION_CAST<F8>(code->entry());
1484 6 : int res = f(1.0f, 2.0f, 3.0f);
1485 6 : PrintF("f(1,2,3) = %d\n", res);
1486 6 : CHECK_EQ(6, res);
1487 6 : }
1488 :
1489 :
1490 23724 : TEST(AssemblerX64AVX_ss) {
1491 6 : CcTest::InitializeVM();
1492 6 : if (!CpuFeatures::IsSupported(AVX)) return;
1493 :
1494 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1495 : HandleScope scope(isolate);
1496 : v8::internal::byte buffer[1024];
1497 12 : Assembler assm(isolate, buffer, sizeof(buffer));
1498 : {
1499 : CpuFeatureScope avx_scope(&assm, AVX);
1500 : Label exit;
1501 : // arguments in xmm0, xmm1 and xmm2
1502 6 : __ subq(rsp, Immediate(kDoubleSize * 2)); // For memory operand
1503 :
1504 : __ movl(rdx, Immediate(0xc2f64000)); // -123.125
1505 6 : __ vmovd(xmm4, rdx);
1506 12 : __ vmovss(Operand(rsp, 0), xmm4);
1507 12 : __ vmovss(xmm5, Operand(rsp, 0));
1508 : __ vmovaps(xmm6, xmm5);
1509 6 : __ vmovd(rcx, xmm6);
1510 6 : __ cmpl(rcx, rdx);
1511 : __ movl(rax, Immediate(9));
1512 6 : __ j(not_equal, &exit);
1513 :
1514 : __ movl(rax, Immediate(0));
1515 : __ vmaxss(xmm3, xmm0, xmm1);
1516 6 : __ vucomiss(xmm3, xmm1);
1517 6 : __ j(parity_even, &exit);
1518 6 : __ j(not_equal, &exit);
1519 : __ movl(rax, Immediate(1));
1520 :
1521 : __ vminss(xmm3, xmm1, xmm2);
1522 6 : __ vucomiss(xmm3, xmm1);
1523 6 : __ j(parity_even, &exit);
1524 6 : __ j(not_equal, &exit);
1525 : __ movl(rax, Immediate(2));
1526 :
1527 : __ vsubss(xmm3, xmm2, xmm1);
1528 6 : __ vucomiss(xmm3, xmm0);
1529 6 : __ j(parity_even, &exit);
1530 6 : __ j(not_equal, &exit);
1531 : __ movl(rax, Immediate(3));
1532 :
1533 : __ vaddss(xmm3, xmm0, xmm1);
1534 6 : __ vucomiss(xmm3, xmm2);
1535 6 : __ j(parity_even, &exit);
1536 6 : __ j(not_equal, &exit);
1537 : __ movl(rax, Immediate(4));
1538 :
1539 : __ vmulss(xmm3, xmm0, xmm1);
1540 6 : __ vucomiss(xmm3, xmm1);
1541 6 : __ j(parity_even, &exit);
1542 6 : __ j(not_equal, &exit);
1543 : __ movl(rax, Immediate(5));
1544 :
1545 : __ vdivss(xmm3, xmm0, xmm1);
1546 : __ vmulss(xmm3, xmm3, xmm2);
1547 : __ vmulss(xmm3, xmm3, xmm1);
1548 6 : __ vucomiss(xmm3, xmm2);
1549 6 : __ j(parity_even, &exit);
1550 6 : __ j(not_equal, &exit);
1551 : __ movl(rax, Immediate(6));
1552 :
1553 : // result in eax
1554 6 : __ bind(&exit);
1555 6 : __ addq(rsp, Immediate(kDoubleSize * 2));
1556 6 : __ ret(0);
1557 : }
1558 :
1559 : CodeDesc desc;
1560 6 : assm.GetCode(isolate, &desc);
1561 : Handle<Code> code =
1562 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
1563 : #ifdef OBJECT_PRINT
1564 : OFStream os(stdout);
1565 : code->Print(os);
1566 : #endif
1567 :
1568 6 : F8 f = FUNCTION_CAST<F8>(code->entry());
1569 6 : int res = f(1.0f, 2.0f, 3.0f);
1570 6 : PrintF("f(1,2,3) = %d\n", res);
1571 6 : CHECK_EQ(6, res);
1572 : }
1573 :
1574 :
1575 23724 : TEST(AssemblerX64AVX_sd) {
1576 6 : CcTest::InitializeVM();
1577 6 : if (!CpuFeatures::IsSupported(AVX)) return;
1578 :
1579 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1580 : HandleScope scope(isolate);
1581 : v8::internal::byte buffer[1024];
1582 12 : Assembler assm(isolate, buffer, sizeof(buffer));
1583 : {
1584 : CpuFeatureScope avx_scope(&assm, AVX);
1585 : Label exit;
1586 : // arguments in xmm0, xmm1 and xmm2
1587 6 : __ subq(rsp, Immediate(kDoubleSize * 2)); // For memory operand
1588 : __ movl(rax, Immediate(0));
1589 :
1590 6 : __ vmaxsd(xmm4, xmm0, xmm1);
1591 6 : __ vmovsd(Operand(rsp, kDoubleSize), xmm4);
1592 6 : __ vmovsd(xmm5, Operand(rsp, kDoubleSize));
1593 6 : __ vmovsd(xmm6, xmm6, xmm5);
1594 : __ vmovapd(xmm3, xmm6);
1595 :
1596 : // Test vcvtss2sd & vcvtsd2ss
1597 : __ movl(rax, Immediate(9));
1598 6 : __ movq(rdx, V8_INT64_C(0x426D1A0000000000));
1599 12 : __ movq(Operand(rsp, 0), rdx);
1600 6 : __ vcvtsd2ss(xmm6, xmm6, Operand(rsp, 0));
1601 : __ vcvtss2sd(xmm7, xmm6, xmm6);
1602 6 : __ vcvtsd2ss(xmm8, xmm7, xmm7);
1603 12 : __ vmovss(Operand(rsp, 0), xmm8);
1604 12 : __ vcvtss2sd(xmm9, xmm8, Operand(rsp, 0));
1605 6 : __ vmovq(rcx, xmm9);
1606 6 : __ cmpq(rcx, rdx);
1607 6 : __ j(not_equal, &exit);
1608 :
1609 : // Test vcvttsd2si
1610 : __ movl(rax, Immediate(10));
1611 : __ movl(rdx, Immediate(123));
1612 : __ vcvtlsi2sd(xmm6, xmm6, rdx);
1613 6 : __ vcvttsd2si(rcx, xmm6);
1614 6 : __ cmpl(rcx, rdx);
1615 6 : __ j(not_equal, &exit);
1616 : __ xorl(rcx, rcx);
1617 6 : __ vmovsd(Operand(rsp, 0), xmm6);
1618 6 : __ vcvttsd2si(rcx, Operand(rsp, 0));
1619 6 : __ cmpl(rcx, rdx);
1620 6 : __ j(not_equal, &exit);
1621 :
1622 : // Test vcvttsd2siq
1623 : __ movl(rax, Immediate(11));
1624 6 : __ movq(rdx, V8_INT64_C(0x426D1A94A2000000)); // 1.0e12
1625 6 : __ vmovq(xmm6, rdx);
1626 6 : __ vcvttsd2siq(rcx, xmm6);
1627 6 : __ movq(rdx, V8_INT64_C(1000000000000));
1628 6 : __ cmpq(rcx, rdx);
1629 6 : __ j(not_equal, &exit);
1630 : __ xorq(rcx, rcx);
1631 6 : __ vmovsd(Operand(rsp, 0), xmm6);
1632 6 : __ vcvttsd2siq(rcx, Operand(rsp, 0));
1633 6 : __ cmpq(rcx, rdx);
1634 6 : __ j(not_equal, &exit);
1635 :
1636 : // Test vmovmskpd
1637 : __ movl(rax, Immediate(12));
1638 6 : __ movq(rdx, V8_INT64_C(0x426D1A94A2000000)); // 1.0e12
1639 6 : __ vmovq(xmm6, rdx);
1640 6 : __ movq(rdx, V8_INT64_C(0xC26D1A94A2000000)); // -1.0e12
1641 6 : __ vmovq(xmm7, rdx);
1642 6 : __ shufps(xmm6, xmm7, 0x44);
1643 : __ vmovmskpd(rdx, xmm6);
1644 6 : __ cmpl(rdx, Immediate(2));
1645 6 : __ j(not_equal, &exit);
1646 :
1647 : // Test vpcmpeqd
1648 6 : __ movq(rdx, V8_UINT64_C(0x0123456789abcdef));
1649 6 : __ movq(rcx, V8_UINT64_C(0x0123456788888888));
1650 6 : __ vmovq(xmm6, rdx);
1651 6 : __ vmovq(xmm7, rcx);
1652 : __ vpcmpeqd(xmm8, xmm6, xmm7);
1653 6 : __ vmovq(rdx, xmm8);
1654 6 : __ movq(rcx, V8_UINT64_C(0xffffffff00000000));
1655 6 : __ cmpq(rcx, rdx);
1656 : __ movl(rax, Immediate(13));
1657 6 : __ j(not_equal, &exit);
1658 :
1659 : // Test vpsllq, vpsrlq
1660 : __ movl(rax, Immediate(13));
1661 6 : __ movq(rdx, V8_UINT64_C(0x0123456789abcdef));
1662 6 : __ vmovq(xmm6, rdx);
1663 : __ vpsrlq(xmm7, xmm6, 4);
1664 6 : __ vmovq(rdx, xmm7);
1665 6 : __ movq(rcx, V8_UINT64_C(0x00123456789abcde));
1666 6 : __ cmpq(rdx, rcx);
1667 6 : __ j(not_equal, &exit);
1668 : __ vpsllq(xmm7, xmm6, 12);
1669 6 : __ vmovq(rdx, xmm7);
1670 6 : __ movq(rcx, V8_UINT64_C(0x3456789abcdef000));
1671 6 : __ cmpq(rdx, rcx);
1672 6 : __ j(not_equal, &exit);
1673 :
1674 : // Test vandpd, vorpd, vxorpd
1675 : __ movl(rax, Immediate(14));
1676 : __ movl(rdx, Immediate(0x00ff00ff));
1677 : __ movl(rcx, Immediate(0x0f0f0f0f));
1678 6 : __ vmovd(xmm4, rdx);
1679 6 : __ vmovd(xmm5, rcx);
1680 : __ vandpd(xmm6, xmm4, xmm5);
1681 6 : __ vmovd(rdx, xmm6);
1682 6 : __ cmpl(rdx, Immediate(0x000f000f));
1683 6 : __ j(not_equal, &exit);
1684 : __ vorpd(xmm6, xmm4, xmm5);
1685 6 : __ vmovd(rdx, xmm6);
1686 6 : __ cmpl(rdx, Immediate(0x0fff0fff));
1687 6 : __ j(not_equal, &exit);
1688 : __ vxorpd(xmm6, xmm4, xmm5);
1689 6 : __ vmovd(rdx, xmm6);
1690 6 : __ cmpl(rdx, Immediate(0x0ff00ff0));
1691 6 : __ j(not_equal, &exit);
1692 :
1693 : // Test vsqrtsd
1694 : __ movl(rax, Immediate(15));
1695 6 : __ movq(rdx, V8_UINT64_C(0x4004000000000000)); // 2.5
1696 6 : __ vmovq(xmm4, rdx);
1697 6 : __ vmulsd(xmm5, xmm4, xmm4);
1698 6 : __ vmovsd(Operand(rsp, 0), xmm5);
1699 6 : __ vsqrtsd(xmm6, xmm5, xmm5);
1700 6 : __ vmovq(rcx, xmm6);
1701 6 : __ cmpq(rcx, rdx);
1702 6 : __ j(not_equal, &exit);
1703 6 : __ vsqrtsd(xmm7, xmm7, Operand(rsp, 0));
1704 6 : __ vmovq(rcx, xmm7);
1705 6 : __ cmpq(rcx, rdx);
1706 6 : __ j(not_equal, &exit);
1707 :
1708 : // Test vroundsd
1709 : __ movl(rax, Immediate(16));
1710 6 : __ movq(rdx, V8_UINT64_C(0x4002000000000000)); // 2.25
1711 6 : __ vmovq(xmm4, rdx);
1712 6 : __ vroundsd(xmm5, xmm4, xmm4, kRoundUp);
1713 6 : __ movq(rcx, V8_UINT64_C(0x4008000000000000)); // 3.0
1714 6 : __ vmovq(xmm6, rcx);
1715 : __ vucomisd(xmm5, xmm6);
1716 6 : __ j(not_equal, &exit);
1717 :
1718 : // Test vcvtlsi2sd
1719 : __ movl(rax, Immediate(17));
1720 : __ movl(rdx, Immediate(6));
1721 6 : __ movq(rcx, V8_UINT64_C(0x4018000000000000)); // 6.0
1722 6 : __ vmovq(xmm5, rcx);
1723 : __ vcvtlsi2sd(xmm6, xmm6, rdx);
1724 : __ vucomisd(xmm5, xmm6);
1725 6 : __ j(not_equal, &exit);
1726 12 : __ movl(Operand(rsp, 0), rdx);
1727 12 : __ vcvtlsi2sd(xmm7, xmm7, Operand(rsp, 0));
1728 : __ vucomisd(xmm5, xmm6);
1729 6 : __ j(not_equal, &exit);
1730 :
1731 : // Test vcvtqsi2sd
1732 : __ movl(rax, Immediate(18));
1733 6 : __ movq(rdx, V8_UINT64_C(0x2000000000000000)); // 2 << 0x3c
1734 6 : __ movq(rcx, V8_UINT64_C(0x43c0000000000000));
1735 6 : __ vmovq(xmm5, rcx);
1736 : __ vcvtqsi2sd(xmm6, xmm6, rdx);
1737 : __ vucomisd(xmm5, xmm6);
1738 6 : __ j(not_equal, &exit);
1739 :
1740 : // Test vcvtsd2si
1741 : __ movl(rax, Immediate(19));
1742 6 : __ movq(rdx, V8_UINT64_C(0x4018000000000000)); // 6.0
1743 6 : __ vmovq(xmm5, rdx);
1744 6 : __ vcvtsd2si(rcx, xmm5);
1745 6 : __ cmpl(rcx, Immediate(6));
1746 6 : __ j(not_equal, &exit);
1747 :
1748 6 : __ movq(rdx, V8_INT64_C(0x3ff0000000000000)); // 1.0
1749 6 : __ vmovq(xmm7, rdx);
1750 6 : __ vmulsd(xmm1, xmm1, xmm7);
1751 12 : __ movq(Operand(rsp, 0), rdx);
1752 6 : __ vmovq(xmm6, Operand(rsp, 0));
1753 6 : __ vmulsd(xmm1, xmm1, xmm6);
1754 :
1755 : __ vucomisd(xmm3, xmm1);
1756 6 : __ j(parity_even, &exit);
1757 6 : __ j(not_equal, &exit);
1758 : __ movl(rax, Immediate(1));
1759 :
1760 6 : __ vminsd(xmm3, xmm1, xmm2);
1761 : __ vucomisd(xmm3, xmm1);
1762 6 : __ j(parity_even, &exit);
1763 6 : __ j(not_equal, &exit);
1764 : __ movl(rax, Immediate(2));
1765 :
1766 6 : __ vsubsd(xmm3, xmm2, xmm1);
1767 : __ vucomisd(xmm3, xmm0);
1768 6 : __ j(parity_even, &exit);
1769 6 : __ j(not_equal, &exit);
1770 : __ movl(rax, Immediate(3));
1771 :
1772 6 : __ vaddsd(xmm3, xmm0, xmm1);
1773 : __ vucomisd(xmm3, xmm2);
1774 6 : __ j(parity_even, &exit);
1775 6 : __ j(not_equal, &exit);
1776 : __ movl(rax, Immediate(4));
1777 :
1778 6 : __ vmulsd(xmm3, xmm0, xmm1);
1779 : __ vucomisd(xmm3, xmm1);
1780 6 : __ j(parity_even, &exit);
1781 6 : __ j(not_equal, &exit);
1782 : __ movl(rax, Immediate(5));
1783 :
1784 6 : __ vdivsd(xmm3, xmm0, xmm1);
1785 6 : __ vmulsd(xmm3, xmm3, xmm2);
1786 6 : __ vmulsd(xmm3, xmm3, xmm1);
1787 : __ vucomisd(xmm3, xmm2);
1788 6 : __ j(parity_even, &exit);
1789 6 : __ j(not_equal, &exit);
1790 : __ movl(rax, Immediate(6));
1791 :
1792 : // result in eax
1793 6 : __ bind(&exit);
1794 6 : __ addq(rsp, Immediate(kDoubleSize * 2));
1795 6 : __ ret(0);
1796 : }
1797 :
1798 : CodeDesc desc;
1799 6 : assm.GetCode(isolate, &desc);
1800 : Handle<Code> code =
1801 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
1802 : #ifdef OBJECT_PRINT
1803 : OFStream os(stdout);
1804 : code->Print(os);
1805 : #endif
1806 :
1807 6 : F7 f = FUNCTION_CAST<F7>(code->entry());
1808 6 : int res = f(1.0, 2.0, 3.0);
1809 6 : PrintF("f(1,2,3) = %d\n", res);
1810 6 : CHECK_EQ(6, res);
1811 : }
1812 :
1813 :
1814 23724 : TEST(AssemblerX64BMI1) {
1815 6 : CcTest::InitializeVM();
1816 6 : if (!CpuFeatures::IsSupported(BMI1)) return;
1817 :
1818 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1819 : HandleScope scope(isolate);
1820 : v8::internal::byte buffer[1024];
1821 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
1822 6 : v8::internal::CodeObjectRequired::kYes);
1823 : {
1824 : CpuFeatureScope fscope(&assm, BMI1);
1825 : Label exit;
1826 :
1827 6 : __ movq(rcx, V8_UINT64_C(0x1122334455667788)); // source operand
1828 6 : __ pushq(rcx); // For memory operand
1829 :
1830 : // andn
1831 6 : __ movq(rdx, V8_UINT64_C(0x1000000020000000));
1832 :
1833 : __ movl(rax, Immediate(1)); // Test number
1834 : __ andnq(r8, rdx, rcx);
1835 6 : __ movq(r9, V8_UINT64_C(0x0122334455667788)); // expected result
1836 6 : __ cmpq(r8, r9);
1837 6 : __ j(not_equal, &exit);
1838 :
1839 : __ incq(rax);
1840 12 : __ andnq(r8, rdx, Operand(rsp, 0));
1841 6 : __ movq(r9, V8_UINT64_C(0x0122334455667788)); // expected result
1842 6 : __ cmpq(r8, r9);
1843 6 : __ j(not_equal, &exit);
1844 :
1845 : __ incq(rax);
1846 : __ andnl(r8, rdx, rcx);
1847 6 : __ movq(r9, V8_UINT64_C(0x0000000055667788)); // expected result
1848 6 : __ cmpq(r8, r9);
1849 6 : __ j(not_equal, &exit);
1850 :
1851 : __ incq(rax);
1852 12 : __ andnl(r8, rdx, Operand(rsp, 0));
1853 6 : __ movq(r9, V8_UINT64_C(0x0000000055667788)); // expected result
1854 6 : __ cmpq(r8, r9);
1855 6 : __ j(not_equal, &exit);
1856 :
1857 : // bextr
1858 6 : __ movq(rdx, V8_UINT64_C(0x0000000000002808));
1859 :
1860 : __ incq(rax);
1861 : __ bextrq(r8, rcx, rdx);
1862 6 : __ movq(r9, V8_UINT64_C(0x0000003344556677)); // expected result
1863 6 : __ cmpq(r8, r9);
1864 6 : __ j(not_equal, &exit);
1865 :
1866 : __ incq(rax);
1867 12 : __ bextrq(r8, Operand(rsp, 0), rdx);
1868 6 : __ movq(r9, V8_UINT64_C(0x0000003344556677)); // expected result
1869 6 : __ cmpq(r8, r9);
1870 6 : __ j(not_equal, &exit);
1871 :
1872 : __ incq(rax);
1873 : __ bextrl(r8, rcx, rdx);
1874 6 : __ movq(r9, V8_UINT64_C(0x0000000000556677)); // expected result
1875 6 : __ cmpq(r8, r9);
1876 6 : __ j(not_equal, &exit);
1877 :
1878 : __ incq(rax);
1879 12 : __ bextrl(r8, Operand(rsp, 0), rdx);
1880 6 : __ movq(r9, V8_UINT64_C(0x0000000000556677)); // expected result
1881 6 : __ cmpq(r8, r9);
1882 6 : __ j(not_equal, &exit);
1883 :
1884 : // blsi
1885 : __ incq(rax);
1886 : __ blsiq(r8, rcx);
1887 6 : __ movq(r9, V8_UINT64_C(0x0000000000000008)); // expected result
1888 6 : __ cmpq(r8, r9);
1889 6 : __ j(not_equal, &exit);
1890 :
1891 : __ incq(rax);
1892 12 : __ blsiq(r8, Operand(rsp, 0));
1893 6 : __ movq(r9, V8_UINT64_C(0x0000000000000008)); // expected result
1894 6 : __ cmpq(r8, r9);
1895 6 : __ j(not_equal, &exit);
1896 :
1897 : __ incq(rax);
1898 : __ blsil(r8, rcx);
1899 6 : __ movq(r9, V8_UINT64_C(0x0000000000000008)); // expected result
1900 6 : __ cmpq(r8, r9);
1901 6 : __ j(not_equal, &exit);
1902 :
1903 : __ incq(rax);
1904 12 : __ blsil(r8, Operand(rsp, 0));
1905 6 : __ movq(r9, V8_UINT64_C(0x0000000000000008)); // expected result
1906 6 : __ cmpq(r8, r9);
1907 6 : __ j(not_equal, &exit);
1908 :
1909 : // blsmsk
1910 : __ incq(rax);
1911 : __ blsmskq(r8, rcx);
1912 6 : __ movq(r9, V8_UINT64_C(0x000000000000000f)); // expected result
1913 6 : __ cmpq(r8, r9);
1914 6 : __ j(not_equal, &exit);
1915 :
1916 : __ incq(rax);
1917 12 : __ blsmskq(r8, Operand(rsp, 0));
1918 6 : __ movq(r9, V8_UINT64_C(0x000000000000000f)); // expected result
1919 6 : __ cmpq(r8, r9);
1920 6 : __ j(not_equal, &exit);
1921 :
1922 : __ incq(rax);
1923 : __ blsmskl(r8, rcx);
1924 6 : __ movq(r9, V8_UINT64_C(0x000000000000000f)); // expected result
1925 6 : __ cmpq(r8, r9);
1926 6 : __ j(not_equal, &exit);
1927 :
1928 : __ incq(rax);
1929 12 : __ blsmskl(r8, Operand(rsp, 0));
1930 6 : __ movq(r9, V8_UINT64_C(0x000000000000000f)); // expected result
1931 6 : __ cmpq(r8, r9);
1932 6 : __ j(not_equal, &exit);
1933 :
1934 : // blsr
1935 : __ incq(rax);
1936 : __ blsrq(r8, rcx);
1937 6 : __ movq(r9, V8_UINT64_C(0x1122334455667780)); // expected result
1938 6 : __ cmpq(r8, r9);
1939 6 : __ j(not_equal, &exit);
1940 :
1941 : __ incq(rax);
1942 12 : __ blsrq(r8, Operand(rsp, 0));
1943 6 : __ movq(r9, V8_UINT64_C(0x1122334455667780)); // expected result
1944 6 : __ cmpq(r8, r9);
1945 6 : __ j(not_equal, &exit);
1946 :
1947 : __ incq(rax);
1948 : __ blsrl(r8, rcx);
1949 6 : __ movq(r9, V8_UINT64_C(0x0000000055667780)); // expected result
1950 6 : __ cmpq(r8, r9);
1951 6 : __ j(not_equal, &exit);
1952 :
1953 : __ incq(rax);
1954 12 : __ blsrl(r8, Operand(rsp, 0));
1955 6 : __ movq(r9, V8_UINT64_C(0x0000000055667780)); // expected result
1956 6 : __ cmpq(r8, r9);
1957 6 : __ j(not_equal, &exit);
1958 :
1959 : // tzcnt
1960 : __ incq(rax);
1961 6 : __ tzcntq(r8, rcx);
1962 6 : __ movq(r9, V8_UINT64_C(0x0000000000000003)); // expected result
1963 6 : __ cmpq(r8, r9);
1964 6 : __ j(not_equal, &exit);
1965 :
1966 : __ incq(rax);
1967 6 : __ tzcntq(r8, Operand(rsp, 0));
1968 6 : __ movq(r9, V8_UINT64_C(0x0000000000000003)); // expected result
1969 6 : __ cmpq(r8, r9);
1970 6 : __ j(not_equal, &exit);
1971 :
1972 : __ incq(rax);
1973 6 : __ tzcntl(r8, rcx);
1974 6 : __ movq(r9, V8_UINT64_C(0x0000000000000003)); // expected result
1975 6 : __ cmpq(r8, r9);
1976 6 : __ j(not_equal, &exit);
1977 :
1978 : __ incq(rax);
1979 6 : __ tzcntl(r8, Operand(rsp, 0));
1980 6 : __ movq(r9, V8_UINT64_C(0x0000000000000003)); // expected result
1981 6 : __ cmpq(r8, r9);
1982 6 : __ j(not_equal, &exit);
1983 :
1984 : __ xorl(rax, rax);
1985 6 : __ bind(&exit);
1986 6 : __ popq(rcx);
1987 6 : __ ret(0);
1988 : }
1989 :
1990 : CodeDesc desc;
1991 6 : assm.GetCode(isolate, &desc);
1992 : Handle<Code> code =
1993 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
1994 : #ifdef OBJECT_PRINT
1995 : OFStream os(stdout);
1996 : code->Print(os);
1997 : #endif
1998 :
1999 6 : F0 f = FUNCTION_CAST<F0>(code->entry());
2000 6 : CHECK_EQ(0, f());
2001 : }
2002 :
2003 :
2004 23724 : TEST(AssemblerX64LZCNT) {
2005 6 : CcTest::InitializeVM();
2006 6 : if (!CpuFeatures::IsSupported(LZCNT)) return;
2007 :
2008 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
2009 : HandleScope scope(isolate);
2010 : v8::internal::byte buffer[256];
2011 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
2012 6 : v8::internal::CodeObjectRequired::kYes);
2013 : {
2014 : CpuFeatureScope fscope(&assm, LZCNT);
2015 : Label exit;
2016 :
2017 6 : __ movq(rcx, V8_UINT64_C(0x1122334455667788)); // source operand
2018 6 : __ pushq(rcx); // For memory operand
2019 :
2020 : __ movl(rax, Immediate(1)); // Test number
2021 6 : __ lzcntq(r8, rcx);
2022 6 : __ movq(r9, V8_UINT64_C(0x0000000000000003)); // expected result
2023 6 : __ cmpq(r8, r9);
2024 6 : __ j(not_equal, &exit);
2025 :
2026 : __ incq(rax);
2027 6 : __ lzcntq(r8, Operand(rsp, 0));
2028 6 : __ movq(r9, V8_UINT64_C(0x0000000000000003)); // expected result
2029 6 : __ cmpq(r8, r9);
2030 6 : __ j(not_equal, &exit);
2031 :
2032 : __ incq(rax);
2033 6 : __ lzcntl(r8, rcx);
2034 6 : __ movq(r9, V8_UINT64_C(0x0000000000000001)); // expected result
2035 6 : __ cmpq(r8, r9);
2036 6 : __ j(not_equal, &exit);
2037 :
2038 : __ incq(rax);
2039 6 : __ lzcntl(r8, Operand(rsp, 0));
2040 6 : __ movq(r9, V8_UINT64_C(0x0000000000000001)); // expected result
2041 6 : __ cmpq(r8, r9);
2042 6 : __ j(not_equal, &exit);
2043 :
2044 : __ xorl(rax, rax);
2045 6 : __ bind(&exit);
2046 6 : __ popq(rcx);
2047 6 : __ ret(0);
2048 : }
2049 :
2050 : CodeDesc desc;
2051 6 : assm.GetCode(isolate, &desc);
2052 : Handle<Code> code =
2053 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
2054 : #ifdef OBJECT_PRINT
2055 : OFStream os(stdout);
2056 : code->Print(os);
2057 : #endif
2058 :
2059 6 : F0 f = FUNCTION_CAST<F0>(code->entry());
2060 6 : CHECK_EQ(0, f());
2061 : }
2062 :
2063 :
2064 23724 : TEST(AssemblerX64POPCNT) {
2065 6 : CcTest::InitializeVM();
2066 6 : if (!CpuFeatures::IsSupported(POPCNT)) return;
2067 :
2068 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
2069 : HandleScope scope(isolate);
2070 : v8::internal::byte buffer[256];
2071 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
2072 6 : v8::internal::CodeObjectRequired::kYes);
2073 : {
2074 : CpuFeatureScope fscope(&assm, POPCNT);
2075 : Label exit;
2076 :
2077 6 : __ movq(rcx, V8_UINT64_C(0x1111111111111100)); // source operand
2078 6 : __ pushq(rcx); // For memory operand
2079 :
2080 : __ movl(rax, Immediate(1)); // Test number
2081 6 : __ popcntq(r8, rcx);
2082 6 : __ movq(r9, V8_UINT64_C(0x000000000000000e)); // expected result
2083 6 : __ cmpq(r8, r9);
2084 6 : __ j(not_equal, &exit);
2085 :
2086 : __ incq(rax);
2087 6 : __ popcntq(r8, Operand(rsp, 0));
2088 6 : __ movq(r9, V8_UINT64_C(0x000000000000000e)); // expected result
2089 6 : __ cmpq(r8, r9);
2090 6 : __ j(not_equal, &exit);
2091 :
2092 : __ incq(rax);
2093 6 : __ popcntl(r8, rcx);
2094 6 : __ movq(r9, V8_UINT64_C(0x0000000000000006)); // expected result
2095 6 : __ cmpq(r8, r9);
2096 6 : __ j(not_equal, &exit);
2097 :
2098 : __ incq(rax);
2099 6 : __ popcntl(r8, Operand(rsp, 0));
2100 6 : __ movq(r9, V8_UINT64_C(0x0000000000000006)); // expected result
2101 6 : __ cmpq(r8, r9);
2102 6 : __ j(not_equal, &exit);
2103 :
2104 : __ xorl(rax, rax);
2105 6 : __ bind(&exit);
2106 6 : __ popq(rcx);
2107 6 : __ ret(0);
2108 : }
2109 :
2110 : CodeDesc desc;
2111 6 : assm.GetCode(isolate, &desc);
2112 : Handle<Code> code =
2113 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
2114 : #ifdef OBJECT_PRINT
2115 : OFStream os(stdout);
2116 : code->Print(os);
2117 : #endif
2118 :
2119 6 : F0 f = FUNCTION_CAST<F0>(code->entry());
2120 6 : CHECK_EQ(0, f());
2121 : }
2122 :
2123 :
2124 23724 : TEST(AssemblerX64BMI2) {
2125 6 : CcTest::InitializeVM();
2126 6 : if (!CpuFeatures::IsSupported(BMI2)) return;
2127 :
2128 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
2129 : HandleScope scope(isolate);
2130 : v8::internal::byte buffer[2048];
2131 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
2132 6 : v8::internal::CodeObjectRequired::kYes);
2133 : {
2134 : CpuFeatureScope fscope(&assm, BMI2);
2135 : Label exit;
2136 6 : __ pushq(rbx); // save rbx
2137 6 : __ movq(rcx, V8_UINT64_C(0x1122334455667788)); // source operand
2138 6 : __ pushq(rcx); // For memory operand
2139 :
2140 : // bzhi
2141 6 : __ movq(rdx, V8_UINT64_C(0x0000000000000009));
2142 :
2143 : __ movl(rax, Immediate(1)); // Test number
2144 : __ bzhiq(r8, rcx, rdx);
2145 6 : __ movq(r9, V8_UINT64_C(0x0000000000000188)); // expected result
2146 6 : __ cmpq(r8, r9);
2147 6 : __ j(not_equal, &exit);
2148 :
2149 : __ incq(rax);
2150 12 : __ bzhiq(r8, Operand(rsp, 0), rdx);
2151 6 : __ movq(r9, V8_UINT64_C(0x0000000000000188)); // expected result
2152 6 : __ cmpq(r8, r9);
2153 6 : __ j(not_equal, &exit);
2154 :
2155 : __ incq(rax);
2156 : __ bzhil(r8, rcx, rdx);
2157 6 : __ movq(r9, V8_UINT64_C(0x0000000000000188)); // expected result
2158 6 : __ cmpq(r8, r9);
2159 6 : __ j(not_equal, &exit);
2160 :
2161 : __ incq(rax);
2162 12 : __ bzhil(r8, Operand(rsp, 0), rdx);
2163 6 : __ movq(r9, V8_UINT64_C(0x0000000000000188)); // expected result
2164 6 : __ cmpq(r8, r9);
2165 6 : __ j(not_equal, &exit);
2166 :
2167 : // mulx
2168 6 : __ movq(rdx, V8_UINT64_C(0x0000000000001000));
2169 :
2170 : __ incq(rax);
2171 : __ mulxq(r8, r9, rcx);
2172 6 : __ movq(rbx, V8_UINT64_C(0x0000000000000112)); // expected result
2173 6 : __ cmpq(r8, rbx);
2174 6 : __ j(not_equal, &exit);
2175 6 : __ movq(rbx, V8_UINT64_C(0x2334455667788000)); // expected result
2176 6 : __ cmpq(r9, rbx);
2177 6 : __ j(not_equal, &exit);
2178 :
2179 : __ incq(rax);
2180 12 : __ mulxq(r8, r9, Operand(rsp, 0));
2181 6 : __ movq(rbx, V8_UINT64_C(0x0000000000000112)); // expected result
2182 6 : __ cmpq(r8, rbx);
2183 6 : __ j(not_equal, &exit);
2184 6 : __ movq(rbx, V8_UINT64_C(0x2334455667788000)); // expected result
2185 6 : __ cmpq(r9, rbx);
2186 6 : __ j(not_equal, &exit);
2187 :
2188 : __ incq(rax);
2189 : __ mulxl(r8, r9, rcx);
2190 6 : __ movq(rbx, V8_UINT64_C(0x0000000000000556)); // expected result
2191 6 : __ cmpq(r8, rbx);
2192 6 : __ j(not_equal, &exit);
2193 6 : __ movq(rbx, V8_UINT64_C(0x0000000067788000)); // expected result
2194 6 : __ cmpq(r9, rbx);
2195 6 : __ j(not_equal, &exit);
2196 :
2197 : __ incq(rax);
2198 12 : __ mulxl(r8, r9, Operand(rsp, 0));
2199 6 : __ movq(rbx, V8_UINT64_C(0x0000000000000556)); // expected result
2200 6 : __ cmpq(r8, rbx);
2201 6 : __ j(not_equal, &exit);
2202 6 : __ movq(rbx, V8_UINT64_C(0x0000000067788000)); // expected result
2203 6 : __ cmpq(r9, rbx);
2204 6 : __ j(not_equal, &exit);
2205 :
2206 : // pdep
2207 6 : __ movq(rdx, V8_UINT64_C(0xfffffffffffffff0));
2208 :
2209 : __ incq(rax);
2210 : __ pdepq(r8, rdx, rcx);
2211 6 : __ movq(r9, V8_UINT64_C(0x1122334455667400)); // expected result
2212 6 : __ cmpq(r8, r9);
2213 6 : __ j(not_equal, &exit);
2214 :
2215 : __ incq(rax);
2216 12 : __ pdepq(r8, rdx, Operand(rsp, 0));
2217 6 : __ movq(r9, V8_UINT64_C(0x1122334455667400)); // expected result
2218 6 : __ cmpq(r8, r9);
2219 6 : __ j(not_equal, &exit);
2220 :
2221 : __ incq(rax);
2222 : __ pdepl(r8, rdx, rcx);
2223 6 : __ movq(r9, V8_UINT64_C(0x0000000055667400)); // expected result
2224 6 : __ cmpq(r8, r9);
2225 6 : __ j(not_equal, &exit);
2226 :
2227 : __ incq(rax);
2228 12 : __ pdepl(r8, rdx, Operand(rsp, 0));
2229 6 : __ movq(r9, V8_UINT64_C(0x0000000055667400)); // expected result
2230 6 : __ cmpq(r8, r9);
2231 6 : __ j(not_equal, &exit);
2232 :
2233 : // pext
2234 6 : __ movq(rdx, V8_UINT64_C(0xfffffffffffffff0));
2235 :
2236 : __ incq(rax);
2237 : __ pextq(r8, rdx, rcx);
2238 6 : __ movq(r9, V8_UINT64_C(0x0000000003fffffe)); // expected result
2239 6 : __ cmpq(r8, r9);
2240 6 : __ j(not_equal, &exit);
2241 :
2242 : __ incq(rax);
2243 12 : __ pextq(r8, rdx, Operand(rsp, 0));
2244 6 : __ movq(r9, V8_UINT64_C(0x0000000003fffffe)); // expected result
2245 6 : __ cmpq(r8, r9);
2246 6 : __ j(not_equal, &exit);
2247 :
2248 : __ incq(rax);
2249 : __ pextl(r8, rdx, rcx);
2250 6 : __ movq(r9, V8_UINT64_C(0x000000000000fffe)); // expected result
2251 6 : __ cmpq(r8, r9);
2252 6 : __ j(not_equal, &exit);
2253 :
2254 : __ incq(rax);
2255 12 : __ pextl(r8, rdx, Operand(rsp, 0));
2256 6 : __ movq(r9, V8_UINT64_C(0x000000000000fffe)); // expected result
2257 6 : __ cmpq(r8, r9);
2258 6 : __ j(not_equal, &exit);
2259 :
2260 : // sarx
2261 6 : __ movq(rdx, V8_UINT64_C(0x0000000000000004));
2262 :
2263 : __ incq(rax);
2264 : __ sarxq(r8, rcx, rdx);
2265 6 : __ movq(r9, V8_UINT64_C(0x0112233445566778)); // expected result
2266 6 : __ cmpq(r8, r9);
2267 6 : __ j(not_equal, &exit);
2268 :
2269 : __ incq(rax);
2270 12 : __ sarxq(r8, Operand(rsp, 0), rdx);
2271 6 : __ movq(r9, V8_UINT64_C(0x0112233445566778)); // expected result
2272 6 : __ cmpq(r8, r9);
2273 6 : __ j(not_equal, &exit);
2274 :
2275 : __ incq(rax);
2276 : __ sarxl(r8, rcx, rdx);
2277 6 : __ movq(r9, V8_UINT64_C(0x0000000005566778)); // expected result
2278 6 : __ cmpq(r8, r9);
2279 6 : __ j(not_equal, &exit);
2280 :
2281 : __ incq(rax);
2282 12 : __ sarxl(r8, Operand(rsp, 0), rdx);
2283 6 : __ movq(r9, V8_UINT64_C(0x0000000005566778)); // expected result
2284 6 : __ cmpq(r8, r9);
2285 6 : __ j(not_equal, &exit);
2286 :
2287 : // shlx
2288 6 : __ movq(rdx, V8_UINT64_C(0x0000000000000004));
2289 :
2290 : __ incq(rax);
2291 : __ shlxq(r8, rcx, rdx);
2292 6 : __ movq(r9, V8_UINT64_C(0x1223344556677880)); // expected result
2293 6 : __ cmpq(r8, r9);
2294 6 : __ j(not_equal, &exit);
2295 :
2296 : __ incq(rax);
2297 12 : __ shlxq(r8, Operand(rsp, 0), rdx);
2298 6 : __ movq(r9, V8_UINT64_C(0x1223344556677880)); // expected result
2299 6 : __ cmpq(r8, r9);
2300 6 : __ j(not_equal, &exit);
2301 :
2302 : __ incq(rax);
2303 : __ shlxl(r8, rcx, rdx);
2304 6 : __ movq(r9, V8_UINT64_C(0x0000000056677880)); // expected result
2305 6 : __ cmpq(r8, r9);
2306 6 : __ j(not_equal, &exit);
2307 :
2308 : __ incq(rax);
2309 12 : __ shlxl(r8, Operand(rsp, 0), rdx);
2310 6 : __ movq(r9, V8_UINT64_C(0x0000000056677880)); // expected result
2311 6 : __ cmpq(r8, r9);
2312 6 : __ j(not_equal, &exit);
2313 :
2314 : // shrx
2315 6 : __ movq(rdx, V8_UINT64_C(0x0000000000000004));
2316 :
2317 : __ incq(rax);
2318 : __ shrxq(r8, rcx, rdx);
2319 6 : __ movq(r9, V8_UINT64_C(0x0112233445566778)); // expected result
2320 6 : __ cmpq(r8, r9);
2321 6 : __ j(not_equal, &exit);
2322 :
2323 : __ incq(rax);
2324 12 : __ shrxq(r8, Operand(rsp, 0), rdx);
2325 6 : __ movq(r9, V8_UINT64_C(0x0112233445566778)); // expected result
2326 6 : __ cmpq(r8, r9);
2327 6 : __ j(not_equal, &exit);
2328 :
2329 : __ incq(rax);
2330 : __ shrxl(r8, rcx, rdx);
2331 6 : __ movq(r9, V8_UINT64_C(0x0000000005566778)); // expected result
2332 6 : __ cmpq(r8, r9);
2333 6 : __ j(not_equal, &exit);
2334 :
2335 : __ incq(rax);
2336 12 : __ shrxl(r8, Operand(rsp, 0), rdx);
2337 6 : __ movq(r9, V8_UINT64_C(0x0000000005566778)); // expected result
2338 6 : __ cmpq(r8, r9);
2339 6 : __ j(not_equal, &exit);
2340 :
2341 : // rorx
2342 : __ incq(rax);
2343 6 : __ rorxq(r8, rcx, 0x4);
2344 6 : __ movq(r9, V8_UINT64_C(0x8112233445566778)); // expected result
2345 6 : __ cmpq(r8, r9);
2346 6 : __ j(not_equal, &exit);
2347 :
2348 : __ incq(rax);
2349 6 : __ rorxq(r8, Operand(rsp, 0), 0x4);
2350 6 : __ movq(r9, V8_UINT64_C(0x8112233445566778)); // expected result
2351 6 : __ cmpq(r8, r9);
2352 6 : __ j(not_equal, &exit);
2353 :
2354 : __ incq(rax);
2355 6 : __ rorxl(r8, rcx, 0x4);
2356 6 : __ movq(r9, V8_UINT64_C(0x0000000085566778)); // expected result
2357 6 : __ cmpq(r8, r9);
2358 6 : __ j(not_equal, &exit);
2359 :
2360 : __ incq(rax);
2361 6 : __ rorxl(r8, Operand(rsp, 0), 0x4);
2362 6 : __ movq(r9, V8_UINT64_C(0x0000000085566778)); // expected result
2363 6 : __ cmpq(r8, r9);
2364 6 : __ j(not_equal, &exit);
2365 :
2366 : __ xorl(rax, rax);
2367 6 : __ bind(&exit);
2368 6 : __ popq(rcx);
2369 6 : __ popq(rbx);
2370 6 : __ ret(0);
2371 : }
2372 :
2373 : CodeDesc desc;
2374 6 : assm.GetCode(isolate, &desc);
2375 : Handle<Code> code =
2376 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
2377 : #ifdef OBJECT_PRINT
2378 : OFStream os(stdout);
2379 : code->Print(os);
2380 : #endif
2381 :
2382 6 : F0 f = FUNCTION_CAST<F0>(code->entry());
2383 6 : CHECK_EQ(0, f());
2384 : }
2385 :
2386 :
2387 23724 : TEST(AssemblerX64JumpTables1) {
2388 : // Test jump tables with forward jumps.
2389 6 : CcTest::InitializeVM();
2390 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
2391 : HandleScope scope(isolate);
2392 : MacroAssembler assm(isolate, nullptr, 0,
2393 6 : v8::internal::CodeObjectRequired::kYes);
2394 :
2395 : const int kNumCases = 512;
2396 : int values[kNumCases];
2397 6 : isolate->random_number_generator()->NextBytes(values, sizeof(values));
2398 3078 : Label labels[kNumCases];
2399 :
2400 : Label done, table;
2401 12 : __ leaq(arg2, Operand(&table));
2402 6 : __ jmp(Operand(arg2, arg1, times_8, 0));
2403 6 : __ ud2();
2404 6 : __ bind(&table);
2405 3078 : for (int i = 0; i < kNumCases; ++i) {
2406 3072 : __ dq(&labels[i]);
2407 : }
2408 :
2409 3072 : for (int i = 0; i < kNumCases; ++i) {
2410 3072 : __ bind(&labels[i]);
2411 3072 : __ movq(rax, Immediate(values[i]));
2412 3072 : __ jmp(&done);
2413 : }
2414 :
2415 6 : __ bind(&done);
2416 6 : __ ret(0);
2417 :
2418 : CodeDesc desc;
2419 6 : assm.GetCode(isolate, &desc);
2420 : Handle<Code> code =
2421 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
2422 : #ifdef OBJECT_PRINT
2423 : code->Print(std::cout);
2424 : #endif
2425 :
2426 6 : F1 f = FUNCTION_CAST<F1>(code->entry());
2427 3078 : for (int i = 0; i < kNumCases; ++i) {
2428 3072 : int res = f(i);
2429 3072 : PrintF("f(%d) = %d\n", i, res);
2430 3072 : CHECK_EQ(values[i], res);
2431 : }
2432 6 : }
2433 :
2434 :
2435 23724 : TEST(AssemblerX64JumpTables2) {
2436 : // Test jump tables with backwards jumps.
2437 6 : CcTest::InitializeVM();
2438 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
2439 : HandleScope scope(isolate);
2440 : MacroAssembler assm(isolate, nullptr, 0,
2441 6 : v8::internal::CodeObjectRequired::kYes);
2442 :
2443 : const int kNumCases = 512;
2444 : int values[kNumCases];
2445 6 : isolate->random_number_generator()->NextBytes(values, sizeof(values));
2446 3078 : Label labels[kNumCases];
2447 :
2448 : Label done, table;
2449 12 : __ leaq(arg2, Operand(&table));
2450 6 : __ jmp(Operand(arg2, arg1, times_8, 0));
2451 6 : __ ud2();
2452 :
2453 3078 : for (int i = 0; i < kNumCases; ++i) {
2454 3072 : __ bind(&labels[i]);
2455 3072 : __ movq(rax, Immediate(values[i]));
2456 3072 : __ jmp(&done);
2457 : }
2458 :
2459 6 : __ bind(&done);
2460 6 : __ ret(0);
2461 :
2462 6 : __ bind(&table);
2463 3078 : for (int i = 0; i < kNumCases; ++i) {
2464 3072 : __ dq(&labels[i]);
2465 : }
2466 :
2467 : CodeDesc desc;
2468 6 : assm.GetCode(isolate, &desc);
2469 : Handle<Code> code =
2470 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
2471 : #ifdef OBJECT_PRINT
2472 : code->Print(std::cout);
2473 : #endif
2474 :
2475 6 : F1 f = FUNCTION_CAST<F1>(code->entry());
2476 3078 : for (int i = 0; i < kNumCases; ++i) {
2477 3072 : int res = f(i);
2478 3072 : PrintF("f(%d) = %d\n", i, res);
2479 3072 : CHECK_EQ(values[i], res);
2480 : }
2481 6 : }
2482 :
2483 23724 : TEST(AssemblerX64PslldWithXmm15) {
2484 6 : CcTest::InitializeVM();
2485 : // Allocate an executable page of memory.
2486 : size_t actual_size;
2487 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2488 6 : Assembler::kMinimalBufferSize, &actual_size, true));
2489 6 : CHECK(buffer);
2490 12 : Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
2491 :
2492 6 : __ movq(xmm15, arg1);
2493 6 : __ pslld(xmm15, 1);
2494 6 : __ movq(rax, xmm15);
2495 6 : __ ret(0);
2496 :
2497 : CodeDesc desc;
2498 6 : assm.GetCode(CcTest::i_isolate(), &desc);
2499 6 : uint64_t result = FUNCTION_CAST<F5>(buffer)(V8_UINT64_C(0x1122334455667788));
2500 6 : CHECK_EQ(V8_UINT64_C(0x22446688aaccef10), result);
2501 6 : }
2502 :
2503 : typedef float (*F9)(float x, float y);
2504 23724 : TEST(AssemblerX64vmovups) {
2505 6 : CcTest::InitializeVM();
2506 6 : if (!CpuFeatures::IsSupported(AVX)) return;
2507 :
2508 6 : Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
2509 : HandleScope scope(isolate);
2510 : v8::internal::byte buffer[256];
2511 : MacroAssembler assm(isolate, buffer, sizeof(buffer),
2512 6 : v8::internal::CodeObjectRequired::kYes);
2513 : {
2514 : CpuFeatureScope avx_scope(&assm, AVX);
2515 6 : __ shufps(xmm0, xmm0, 0x0); // brocast first argument
2516 6 : __ shufps(xmm1, xmm1, 0x0); // brocast second argument
2517 : // copy xmm1 to xmm0 through the stack to test the "vmovups reg, mem".
2518 6 : __ subq(rsp, Immediate(kSimd128Size));
2519 12 : __ vmovups(Operand(rsp, 0), xmm1);
2520 12 : __ vmovups(xmm0, Operand(rsp, 0));
2521 6 : __ addq(rsp, Immediate(kSimd128Size));
2522 :
2523 6 : __ ret(0);
2524 : }
2525 :
2526 : CodeDesc desc;
2527 6 : assm.GetCode(isolate, &desc);
2528 : Handle<Code> code =
2529 6 : isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
2530 : #ifdef OBJECT_PRINT
2531 : OFStream os(stdout);
2532 : code->Print(os);
2533 : #endif
2534 :
2535 6 : F9 f = FUNCTION_CAST<F9>(code->entry());
2536 6 : CHECK_EQ(-1.5, f(1.5, -1.5));
2537 : }
2538 :
2539 : #undef __
2540 :
2541 : } // namespace internal
2542 71154 : } // namespace v8
|