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 <stdlib.h>
29 :
30 : #include "src/v8.h"
31 :
32 : #include "src/base/platform/platform.h"
33 : #include "src/heap/factory.h"
34 : #include "src/macro-assembler.h"
35 : #include "src/objects-inl.h"
36 : #include "src/objects/smi.h"
37 : #include "src/simulator.h"
38 : #include "test/cctest/cctest.h"
39 : #include "test/common/assembler-tester.h"
40 :
41 : namespace v8 {
42 : namespace internal {
43 : namespace test_macro_assembler_x64 {
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 five arguments
49 : // in RSI, RDI, 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 :
54 : typedef int(F0)();
55 :
56 : #define __ masm->
57 :
58 : static void EntryCode(MacroAssembler* masm) {
59 : // Smi constant register is callee save.
60 40 : __ pushq(kRootRegister);
61 40 : __ InitializeRootRegister();
62 : }
63 :
64 40 : static void ExitCode(MacroAssembler* masm) { __ popq(kRootRegister); }
65 :
66 25880 : TEST(Smi) {
67 : // Check that C++ Smi operations work as expected.
68 : int64_t test_numbers[] = {
69 : 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
70 : Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
71 : Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
72 5 : };
73 : int test_number_count = 15;
74 80 : for (int i = 0; i < test_number_count; i++) {
75 75 : int64_t number = test_numbers[i];
76 : bool is_valid = Smi::IsValid(number);
77 75 : bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
78 75 : CHECK_EQ(is_in_range, is_valid);
79 75 : if (is_valid) {
80 : Smi smi_from_intptr = Smi::FromIntptr(number);
81 65 : if (static_cast<int>(number) == number) { // Is a 32-bit int.
82 65 : Smi smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
83 65 : CHECK_EQ(smi_from_int, smi_from_intptr);
84 : }
85 65 : int64_t smi_value = smi_from_intptr->value();
86 65 : CHECK_EQ(number, smi_value);
87 : }
88 : }
89 5 : }
90 :
91 60 : static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi value) {
92 60 : __ movl(rax, Immediate(id));
93 60 : __ Move(rcx, value);
94 60 : __ Set(rdx, static_cast<intptr_t>(value.ptr()));
95 60 : __ cmpq(rcx, rdx);
96 60 : __ j(not_equal, exit);
97 60 : }
98 :
99 :
100 : // Test that we can move a Smi value literally into a register.
101 25880 : TEST(SmiMove) {
102 5 : Isolate* isolate = CcTest::i_isolate();
103 : HandleScope handles(isolate);
104 : auto buffer = AllocateAssemblerBuffer();
105 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
106 20 : buffer->CreateView());
107 : MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
108 : EntryCode(masm);
109 5 : Label exit;
110 :
111 5 : TestMoveSmi(masm, &exit, 1, Smi::zero());
112 5 : TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
113 5 : TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
114 5 : TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
115 5 : TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
116 5 : TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
117 5 : TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
118 5 : TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
119 5 : TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
120 5 : TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
121 5 : TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
122 5 : TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
123 :
124 : __ xorq(rax, rax); // Success.
125 5 : __ bind(&exit);
126 : ExitCode(masm);
127 5 : __ ret(0);
128 :
129 5 : CodeDesc desc;
130 5 : masm->GetCode(isolate, &desc);
131 5 : buffer->MakeExecutable();
132 : // Call the function from C++.
133 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
134 : int result = f.Call();
135 5 : CHECK_EQ(0, result);
136 5 : }
137 :
138 :
139 95 : void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
140 95 : __ Move(rcx, Smi::FromInt(x));
141 95 : __ movq(r8, rcx);
142 95 : __ Move(rdx, Smi::FromInt(y));
143 : __ movq(r9, rdx);
144 95 : __ SmiCompare(rcx, rdx);
145 95 : if (x < y) {
146 35 : __ movl(rax, Immediate(id + 1));
147 35 : __ j(greater_equal, exit);
148 60 : } else if (x > y) {
149 35 : __ movl(rax, Immediate(id + 2));
150 35 : __ j(less_equal, exit);
151 : } else {
152 25 : CHECK_EQ(x, y);
153 25 : __ movl(rax, Immediate(id + 3));
154 25 : __ j(not_equal, exit);
155 : }
156 95 : __ movl(rax, Immediate(id + 4));
157 95 : __ cmpq(rcx, r8);
158 95 : __ j(not_equal, exit);
159 : __ incq(rax);
160 95 : __ cmpq(rdx, r9);
161 95 : __ j(not_equal, exit);
162 :
163 95 : if (x != y) {
164 70 : __ SmiCompare(rdx, rcx);
165 70 : if (y < x) {
166 35 : __ movl(rax, Immediate(id + 9));
167 35 : __ j(greater_equal, exit);
168 : } else {
169 35 : CHECK(y > x);
170 35 : __ movl(rax, Immediate(id + 10));
171 35 : __ j(less_equal, exit);
172 : }
173 : } else {
174 25 : __ cmpq(rcx, rcx);
175 25 : __ movl(rax, Immediate(id + 11));
176 25 : __ j(not_equal, exit);
177 : __ incq(rax);
178 25 : __ cmpq(rcx, r8);
179 25 : __ j(not_equal, exit);
180 : }
181 95 : }
182 :
183 :
184 : // Test that we can compare smis for equality (and more).
185 25880 : TEST(SmiCompare) {
186 5 : Isolate* isolate = CcTest::i_isolate();
187 : HandleScope handles(isolate);
188 : auto buffer = AllocateAssemblerBuffer(2 * Assembler::kMinimalBufferSize);
189 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
190 20 : buffer->CreateView());
191 :
192 : MacroAssembler* masm = &assembler;
193 : EntryCode(masm);
194 5 : Label exit;
195 :
196 5 : TestSmiCompare(masm, &exit, 0x10, 0, 0);
197 5 : TestSmiCompare(masm, &exit, 0x20, 0, 1);
198 5 : TestSmiCompare(masm, &exit, 0x30, 1, 0);
199 5 : TestSmiCompare(masm, &exit, 0x40, 1, 1);
200 5 : TestSmiCompare(masm, &exit, 0x50, 0, -1);
201 5 : TestSmiCompare(masm, &exit, 0x60, -1, 0);
202 5 : TestSmiCompare(masm, &exit, 0x70, -1, -1);
203 5 : TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
204 5 : TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
205 5 : TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
206 5 : TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
207 5 : TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
208 5 : TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
209 5 : TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
210 5 : TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
211 5 : TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
212 5 : TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
213 5 : TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
214 5 : TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
215 :
216 : __ xorq(rax, rax); // Success.
217 5 : __ bind(&exit);
218 : ExitCode(masm);
219 5 : __ ret(0);
220 :
221 5 : CodeDesc desc;
222 5 : masm->GetCode(isolate, &desc);
223 5 : buffer->MakeExecutable();
224 : // Call the function from C++.
225 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
226 : int result = f.Call();
227 5 : CHECK_EQ(0, result);
228 5 : }
229 :
230 25880 : TEST(SmiTag) {
231 5 : Isolate* isolate = CcTest::i_isolate();
232 : HandleScope handles(isolate);
233 : auto buffer = AllocateAssemblerBuffer();
234 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
235 20 : buffer->CreateView());
236 :
237 : MacroAssembler* masm = &assembler;
238 : EntryCode(masm);
239 5 : Label exit;
240 :
241 : __ movq(rax, Immediate(1)); // Test number.
242 : __ movq(rcx, Immediate(0));
243 5 : __ SmiTag(rcx, rcx);
244 5 : __ Set(rdx, Smi::kZero.ptr());
245 5 : __ cmpq(rcx, rdx);
246 5 : __ j(not_equal, &exit);
247 :
248 : __ movq(rax, Immediate(2)); // Test number.
249 : __ movq(rcx, Immediate(1024));
250 5 : __ SmiTag(rcx, rcx);
251 5 : __ Set(rdx, Smi::FromInt(1024).ptr());
252 5 : __ cmpq(rcx, rdx);
253 5 : __ j(not_equal, &exit);
254 :
255 : __ movq(rax, Immediate(3)); // Test number.
256 : __ movq(rcx, Immediate(-1));
257 5 : __ SmiTag(rcx, rcx);
258 5 : __ Set(rdx, Smi::FromInt(-1).ptr());
259 5 : __ cmpq(rcx, rdx);
260 5 : __ j(not_equal, &exit);
261 :
262 : __ movq(rax, Immediate(4)); // Test number.
263 : __ movq(rcx, Immediate(Smi::kMaxValue));
264 5 : __ SmiTag(rcx, rcx);
265 5 : __ Set(rdx, Smi::FromInt(Smi::kMaxValue).ptr());
266 5 : __ cmpq(rcx, rdx);
267 5 : __ j(not_equal, &exit);
268 :
269 : __ movq(rax, Immediate(5)); // Test number.
270 : __ movq(rcx, Immediate(Smi::kMinValue));
271 5 : __ SmiTag(rcx, rcx);
272 5 : __ Set(rdx, Smi::FromInt(Smi::kMinValue).ptr());
273 5 : __ cmpq(rcx, rdx);
274 5 : __ j(not_equal, &exit);
275 :
276 : // Different target register.
277 :
278 : __ movq(rax, Immediate(6)); // Test number.
279 : __ movq(rcx, Immediate(0));
280 5 : __ SmiTag(r8, rcx);
281 5 : __ Set(rdx, Smi::zero().ptr());
282 5 : __ cmpq(r8, rdx);
283 5 : __ j(not_equal, &exit);
284 :
285 : __ movq(rax, Immediate(7)); // Test number.
286 : __ movq(rcx, Immediate(1024));
287 5 : __ SmiTag(r8, rcx);
288 5 : __ Set(rdx, Smi::FromInt(1024).ptr());
289 5 : __ cmpq(r8, rdx);
290 5 : __ j(not_equal, &exit);
291 :
292 : __ movq(rax, Immediate(8)); // Test number.
293 : __ movq(rcx, Immediate(-1));
294 5 : __ SmiTag(r8, rcx);
295 5 : __ Set(rdx, Smi::FromInt(-1).ptr());
296 5 : __ cmpq(r8, rdx);
297 5 : __ j(not_equal, &exit);
298 :
299 : __ movq(rax, Immediate(9)); // Test number.
300 : __ movq(rcx, Immediate(Smi::kMaxValue));
301 5 : __ SmiTag(r8, rcx);
302 5 : __ Set(rdx, Smi::FromInt(Smi::kMaxValue).ptr());
303 5 : __ cmpq(r8, rdx);
304 5 : __ j(not_equal, &exit);
305 :
306 : __ movq(rax, Immediate(10)); // Test number.
307 : __ movq(rcx, Immediate(Smi::kMinValue));
308 5 : __ SmiTag(r8, rcx);
309 5 : __ Set(rdx, Smi::FromInt(Smi::kMinValue).ptr());
310 5 : __ cmpq(r8, rdx);
311 5 : __ j(not_equal, &exit);
312 :
313 :
314 : __ xorq(rax, rax); // Success.
315 5 : __ bind(&exit);
316 : ExitCode(masm);
317 5 : __ ret(0);
318 :
319 5 : CodeDesc desc;
320 5 : masm->GetCode(isolate, &desc);
321 5 : buffer->MakeExecutable();
322 : // Call the function from C++.
323 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
324 : int result = f.Call();
325 5 : CHECK_EQ(0, result);
326 5 : }
327 :
328 25880 : TEST(SmiCheck) {
329 5 : Isolate* isolate = CcTest::i_isolate();
330 : HandleScope handles(isolate);
331 : auto buffer = AllocateAssemblerBuffer();
332 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
333 20 : buffer->CreateView());
334 :
335 : MacroAssembler* masm = &assembler;
336 : EntryCode(masm);
337 5 : Label exit;
338 : Condition cond;
339 :
340 : __ movl(rax, Immediate(1)); // Test number.
341 :
342 : // CheckSmi
343 :
344 : __ movl(rcx, Immediate(0));
345 5 : __ SmiTag(rcx, rcx);
346 5 : cond = masm->CheckSmi(rcx);
347 5 : __ j(NegateCondition(cond), &exit);
348 :
349 : __ incq(rax);
350 5 : __ xorq(rcx, Immediate(kSmiTagMask));
351 5 : cond = masm->CheckSmi(rcx);
352 5 : __ j(cond, &exit);
353 :
354 : __ incq(rax);
355 : __ movl(rcx, Immediate(-1));
356 5 : __ SmiTag(rcx, rcx);
357 5 : cond = masm->CheckSmi(rcx);
358 5 : __ j(NegateCondition(cond), &exit);
359 :
360 : __ incq(rax);
361 5 : __ xorq(rcx, Immediate(kSmiTagMask));
362 5 : cond = masm->CheckSmi(rcx);
363 5 : __ j(cond, &exit);
364 :
365 : __ incq(rax);
366 : __ movl(rcx, Immediate(Smi::kMaxValue));
367 5 : __ SmiTag(rcx, rcx);
368 5 : cond = masm->CheckSmi(rcx);
369 5 : __ j(NegateCondition(cond), &exit);
370 :
371 : __ incq(rax);
372 5 : __ xorq(rcx, Immediate(kSmiTagMask));
373 5 : cond = masm->CheckSmi(rcx);
374 5 : __ j(cond, &exit);
375 :
376 : __ incq(rax);
377 : __ movl(rcx, Immediate(Smi::kMinValue));
378 5 : __ SmiTag(rcx, rcx);
379 5 : cond = masm->CheckSmi(rcx);
380 5 : __ j(NegateCondition(cond), &exit);
381 :
382 : __ incq(rax);
383 5 : __ xorq(rcx, Immediate(kSmiTagMask));
384 5 : cond = masm->CheckSmi(rcx);
385 5 : __ j(cond, &exit);
386 :
387 : // Success
388 : __ xorq(rax, rax);
389 :
390 5 : __ bind(&exit);
391 : ExitCode(masm);
392 5 : __ ret(0);
393 :
394 5 : CodeDesc desc;
395 5 : masm->GetCode(isolate, &desc);
396 5 : buffer->MakeExecutable();
397 : // Call the function from C++.
398 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
399 : int result = f.Call();
400 5 : CHECK_EQ(0, result);
401 5 : }
402 :
403 25 : void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
404 25 : __ movl(rax, Immediate(id));
405 :
406 225 : for (int i = 0; i < 8; i++) {
407 200 : __ Move(rcx, Smi::FromInt(x));
408 200 : SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
409 200 : CHECK(index.reg == rcx || index.reg == rdx);
410 200 : __ shlq(index.reg, Immediate(index.scale));
411 200 : __ Set(r8, static_cast<intptr_t>(x) << i);
412 200 : __ cmpq(index.reg, r8);
413 200 : __ j(not_equal, exit);
414 : __ incq(rax);
415 200 : __ Move(rcx, Smi::FromInt(x));
416 200 : index = masm->SmiToIndex(rcx, rcx, i);
417 200 : CHECK(index.reg == rcx);
418 200 : __ shlq(rcx, Immediate(index.scale));
419 200 : __ Set(r8, static_cast<intptr_t>(x) << i);
420 200 : __ cmpq(rcx, r8);
421 200 : __ j(not_equal, exit);
422 : __ incq(rax);
423 : }
424 25 : }
425 :
426 25880 : TEST(SmiIndex) {
427 5 : Isolate* isolate = CcTest::i_isolate();
428 : HandleScope handles(isolate);
429 : auto buffer = AllocateAssemblerBuffer();
430 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
431 20 : buffer->CreateView());
432 :
433 : MacroAssembler* masm = &assembler;
434 : EntryCode(masm);
435 5 : Label exit;
436 :
437 5 : TestSmiIndex(masm, &exit, 0x10, 0);
438 5 : TestSmiIndex(masm, &exit, 0x20, 1);
439 5 : TestSmiIndex(masm, &exit, 0x30, 100);
440 5 : TestSmiIndex(masm, &exit, 0x40, 1000);
441 5 : TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
442 :
443 : __ xorq(rax, rax); // Success.
444 5 : __ bind(&exit);
445 : ExitCode(masm);
446 5 : __ ret(0);
447 :
448 5 : CodeDesc desc;
449 5 : masm->GetCode(isolate, &desc);
450 5 : buffer->MakeExecutable();
451 : // Call the function from C++.
452 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
453 : int result = f.Call();
454 5 : CHECK_EQ(0, result);
455 5 : }
456 :
457 25880 : TEST(OperandOffset) {
458 : uint32_t data[256];
459 5 : for (uint32_t i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
460 :
461 5 : Isolate* isolate = CcTest::i_isolate();
462 : HandleScope handles(isolate);
463 : auto buffer = AllocateAssemblerBuffer();
464 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
465 20 : buffer->CreateView());
466 :
467 : MacroAssembler* masm = &assembler;
468 5 : Label exit;
469 :
470 : EntryCode(masm);
471 5 : __ pushq(r13);
472 5 : __ pushq(r14);
473 5 : __ pushq(rbx);
474 5 : __ pushq(rbp);
475 5 : __ pushq(Immediate(0x100)); // <-- rbp
476 : __ movq(rbp, rsp);
477 5 : __ pushq(Immediate(0x101));
478 5 : __ pushq(Immediate(0x102));
479 5 : __ pushq(Immediate(0x103));
480 5 : __ pushq(Immediate(0x104));
481 5 : __ pushq(Immediate(0x105)); // <-- rbx
482 5 : __ pushq(Immediate(0x106));
483 5 : __ pushq(Immediate(0x107));
484 5 : __ pushq(Immediate(0x108));
485 5 : __ pushq(Immediate(0x109)); // <-- rsp
486 : // rbp = rsp[9]
487 : // r15 = rsp[3]
488 : // rbx = rsp[5]
489 : // r13 = rsp[7]
490 10 : __ leaq(r14, Operand(rsp, 3 * kSystemPointerSize));
491 10 : __ leaq(r13, Operand(rbp, -3 * kSystemPointerSize));
492 10 : __ leaq(rbx, Operand(rbp, -5 * kSystemPointerSize));
493 : __ movl(rcx, Immediate(2));
494 : __ Move(r8, reinterpret_cast<Address>(&data[128]), RelocInfo::NONE);
495 : __ movl(rax, Immediate(1));
496 :
497 5 : Operand sp0 = Operand(rsp, 0);
498 :
499 : // Test 1.
500 : __ movl(rdx, sp0); // Sanity check.
501 5 : __ cmpl(rdx, Immediate(0x109));
502 5 : __ j(not_equal, &exit);
503 : __ incq(rax);
504 :
505 : // Test 2.
506 : // Zero to non-zero displacement.
507 10 : __ movl(rdx, Operand(sp0, 2 * kSystemPointerSize));
508 5 : __ cmpl(rdx, Immediate(0x107));
509 5 : __ j(not_equal, &exit);
510 : __ incq(rax);
511 :
512 5 : Operand sp2 = Operand(rsp, 2 * kSystemPointerSize);
513 :
514 : // Test 3.
515 : __ movl(rdx, sp2); // Sanity check.
516 5 : __ cmpl(rdx, Immediate(0x107));
517 5 : __ j(not_equal, &exit);
518 : __ incq(rax);
519 :
520 10 : __ movl(rdx, Operand(sp2, 2 * kSystemPointerSize));
521 5 : __ cmpl(rdx, Immediate(0x105));
522 5 : __ j(not_equal, &exit);
523 : __ incq(rax);
524 :
525 : // Non-zero to zero displacement.
526 10 : __ movl(rdx, Operand(sp2, -2 * kSystemPointerSize));
527 5 : __ cmpl(rdx, Immediate(0x109));
528 5 : __ j(not_equal, &exit);
529 : __ incq(rax);
530 :
531 : Operand sp2c2 =
532 5 : Operand(rsp, rcx, times_system_pointer_size, 2 * kSystemPointerSize);
533 :
534 : // Test 6.
535 : __ movl(rdx, sp2c2); // Sanity check.
536 5 : __ cmpl(rdx, Immediate(0x105));
537 5 : __ j(not_equal, &exit);
538 : __ incq(rax);
539 :
540 10 : __ movl(rdx, Operand(sp2c2, 2 * kSystemPointerSize));
541 5 : __ cmpl(rdx, Immediate(0x103));
542 5 : __ j(not_equal, &exit);
543 : __ incq(rax);
544 :
545 : // Non-zero to zero displacement.
546 10 : __ movl(rdx, Operand(sp2c2, -2 * kSystemPointerSize));
547 5 : __ cmpl(rdx, Immediate(0x107));
548 5 : __ j(not_equal, &exit);
549 : __ incq(rax);
550 :
551 :
552 5 : Operand bp0 = Operand(rbp, 0);
553 :
554 : // Test 9.
555 : __ movl(rdx, bp0); // Sanity check.
556 5 : __ cmpl(rdx, Immediate(0x100));
557 5 : __ j(not_equal, &exit);
558 : __ incq(rax);
559 :
560 : // Zero to non-zero displacement.
561 10 : __ movl(rdx, Operand(bp0, -2 * kSystemPointerSize));
562 5 : __ cmpl(rdx, Immediate(0x102));
563 5 : __ j(not_equal, &exit);
564 : __ incq(rax);
565 :
566 5 : Operand bp2 = Operand(rbp, -2 * kSystemPointerSize);
567 :
568 : // Test 11.
569 : __ movl(rdx, bp2); // Sanity check.
570 5 : __ cmpl(rdx, Immediate(0x102));
571 5 : __ j(not_equal, &exit);
572 : __ incq(rax);
573 :
574 : // Non-zero to zero displacement.
575 10 : __ movl(rdx, Operand(bp2, 2 * kSystemPointerSize));
576 5 : __ cmpl(rdx, Immediate(0x100));
577 5 : __ j(not_equal, &exit);
578 : __ incq(rax);
579 :
580 10 : __ movl(rdx, Operand(bp2, -2 * kSystemPointerSize));
581 5 : __ cmpl(rdx, Immediate(0x104));
582 5 : __ j(not_equal, &exit);
583 : __ incq(rax);
584 :
585 : Operand bp2c4 =
586 5 : Operand(rbp, rcx, times_system_pointer_size, -4 * kSystemPointerSize);
587 :
588 : // Test 14:
589 : __ movl(rdx, bp2c4); // Sanity check.
590 5 : __ cmpl(rdx, Immediate(0x102));
591 5 : __ j(not_equal, &exit);
592 : __ incq(rax);
593 :
594 10 : __ movl(rdx, Operand(bp2c4, 2 * kSystemPointerSize));
595 5 : __ cmpl(rdx, Immediate(0x100));
596 5 : __ j(not_equal, &exit);
597 : __ incq(rax);
598 :
599 10 : __ movl(rdx, Operand(bp2c4, -2 * kSystemPointerSize));
600 5 : __ cmpl(rdx, Immediate(0x104));
601 5 : __ j(not_equal, &exit);
602 : __ incq(rax);
603 :
604 5 : Operand bx0 = Operand(rbx, 0);
605 :
606 : // Test 17.
607 : __ movl(rdx, bx0); // Sanity check.
608 5 : __ cmpl(rdx, Immediate(0x105));
609 5 : __ j(not_equal, &exit);
610 : __ incq(rax);
611 :
612 10 : __ movl(rdx, Operand(bx0, 5 * kSystemPointerSize));
613 5 : __ cmpl(rdx, Immediate(0x100));
614 5 : __ j(not_equal, &exit);
615 : __ incq(rax);
616 :
617 10 : __ movl(rdx, Operand(bx0, -4 * kSystemPointerSize));
618 5 : __ cmpl(rdx, Immediate(0x109));
619 5 : __ j(not_equal, &exit);
620 : __ incq(rax);
621 :
622 5 : Operand bx2 = Operand(rbx, 2 * kSystemPointerSize);
623 :
624 : // Test 20.
625 : __ movl(rdx, bx2); // Sanity check.
626 5 : __ cmpl(rdx, Immediate(0x103));
627 5 : __ j(not_equal, &exit);
628 : __ incq(rax);
629 :
630 10 : __ movl(rdx, Operand(bx2, 2 * kSystemPointerSize));
631 5 : __ cmpl(rdx, Immediate(0x101));
632 5 : __ j(not_equal, &exit);
633 : __ incq(rax);
634 :
635 : // Non-zero to zero displacement.
636 10 : __ movl(rdx, Operand(bx2, -2 * kSystemPointerSize));
637 5 : __ cmpl(rdx, Immediate(0x105));
638 5 : __ j(not_equal, &exit);
639 : __ incq(rax);
640 :
641 : Operand bx2c2 =
642 5 : Operand(rbx, rcx, times_system_pointer_size, -2 * kSystemPointerSize);
643 :
644 : // Test 23.
645 : __ movl(rdx, bx2c2); // Sanity check.
646 5 : __ cmpl(rdx, Immediate(0x105));
647 5 : __ j(not_equal, &exit);
648 : __ incq(rax);
649 :
650 10 : __ movl(rdx, Operand(bx2c2, 2 * kSystemPointerSize));
651 5 : __ cmpl(rdx, Immediate(0x103));
652 5 : __ j(not_equal, &exit);
653 : __ incq(rax);
654 :
655 10 : __ movl(rdx, Operand(bx2c2, -2 * kSystemPointerSize));
656 5 : __ cmpl(rdx, Immediate(0x107));
657 5 : __ j(not_equal, &exit);
658 : __ incq(rax);
659 :
660 5 : Operand r80 = Operand(r8, 0);
661 :
662 : // Test 26.
663 : __ movl(rdx, r80); // Sanity check.
664 5 : __ cmpl(rdx, Immediate(0x80808080));
665 5 : __ j(not_equal, &exit);
666 : __ incq(rax);
667 :
668 10 : __ movl(rdx, Operand(r80, -8 * kIntSize));
669 5 : __ cmpl(rdx, Immediate(0x78787878));
670 5 : __ j(not_equal, &exit);
671 : __ incq(rax);
672 :
673 10 : __ movl(rdx, Operand(r80, 8 * kIntSize));
674 5 : __ cmpl(rdx, Immediate(0x88888888));
675 5 : __ j(not_equal, &exit);
676 : __ incq(rax);
677 :
678 10 : __ movl(rdx, Operand(r80, -64 * kIntSize));
679 5 : __ cmpl(rdx, Immediate(0x40404040));
680 5 : __ j(not_equal, &exit);
681 : __ incq(rax);
682 :
683 10 : __ movl(rdx, Operand(r80, 64 * kIntSize));
684 5 : __ cmpl(rdx, Immediate(0xC0C0C0C0));
685 5 : __ j(not_equal, &exit);
686 : __ incq(rax);
687 :
688 5 : Operand r88 = Operand(r8, 8 * kIntSize);
689 :
690 : // Test 31.
691 : __ movl(rdx, r88); // Sanity check.
692 5 : __ cmpl(rdx, Immediate(0x88888888));
693 5 : __ j(not_equal, &exit);
694 : __ incq(rax);
695 :
696 10 : __ movl(rdx, Operand(r88, -8 * kIntSize));
697 5 : __ cmpl(rdx, Immediate(0x80808080));
698 5 : __ j(not_equal, &exit);
699 : __ incq(rax);
700 :
701 10 : __ movl(rdx, Operand(r88, 8 * kIntSize));
702 5 : __ cmpl(rdx, Immediate(0x90909090));
703 5 : __ j(not_equal, &exit);
704 : __ incq(rax);
705 :
706 10 : __ movl(rdx, Operand(r88, -64 * kIntSize));
707 5 : __ cmpl(rdx, Immediate(0x48484848));
708 5 : __ j(not_equal, &exit);
709 : __ incq(rax);
710 :
711 10 : __ movl(rdx, Operand(r88, 64 * kIntSize));
712 5 : __ cmpl(rdx, Immediate(0xC8C8C8C8));
713 5 : __ j(not_equal, &exit);
714 : __ incq(rax);
715 :
716 :
717 5 : Operand r864 = Operand(r8, 64 * kIntSize);
718 :
719 : // Test 36.
720 : __ movl(rdx, r864); // Sanity check.
721 5 : __ cmpl(rdx, Immediate(0xC0C0C0C0));
722 5 : __ j(not_equal, &exit);
723 : __ incq(rax);
724 :
725 10 : __ movl(rdx, Operand(r864, -8 * kIntSize));
726 5 : __ cmpl(rdx, Immediate(0xB8B8B8B8));
727 5 : __ j(not_equal, &exit);
728 : __ incq(rax);
729 :
730 10 : __ movl(rdx, Operand(r864, 8 * kIntSize));
731 5 : __ cmpl(rdx, Immediate(0xC8C8C8C8));
732 5 : __ j(not_equal, &exit);
733 : __ incq(rax);
734 :
735 10 : __ movl(rdx, Operand(r864, -64 * kIntSize));
736 5 : __ cmpl(rdx, Immediate(0x80808080));
737 5 : __ j(not_equal, &exit);
738 : __ incq(rax);
739 :
740 10 : __ movl(rdx, Operand(r864, 32 * kIntSize));
741 5 : __ cmpl(rdx, Immediate(0xE0E0E0E0));
742 5 : __ j(not_equal, &exit);
743 : __ incq(rax);
744 :
745 : // 32-bit offset to 8-bit offset.
746 10 : __ movl(rdx, Operand(r864, -60 * kIntSize));
747 5 : __ cmpl(rdx, Immediate(0x84848484));
748 5 : __ j(not_equal, &exit);
749 : __ incq(rax);
750 :
751 10 : __ movl(rdx, Operand(r864, 60 * kIntSize));
752 5 : __ cmpl(rdx, Immediate(0xFCFCFCFC));
753 5 : __ j(not_equal, &exit);
754 : __ incq(rax);
755 :
756 : // Test unaligned offsets.
757 :
758 : // Test 43.
759 10 : __ movl(rdx, Operand(r80, 2));
760 5 : __ cmpl(rdx, Immediate(0x81818080));
761 5 : __ j(not_equal, &exit);
762 : __ incq(rax);
763 :
764 10 : __ movl(rdx, Operand(r80, -2));
765 5 : __ cmpl(rdx, Immediate(0x80807F7F));
766 5 : __ j(not_equal, &exit);
767 : __ incq(rax);
768 :
769 10 : __ movl(rdx, Operand(r80, 126));
770 5 : __ cmpl(rdx, Immediate(0xA0A09F9F));
771 5 : __ j(not_equal, &exit);
772 : __ incq(rax);
773 :
774 10 : __ movl(rdx, Operand(r80, -126));
775 5 : __ cmpl(rdx, Immediate(0x61616060));
776 5 : __ j(not_equal, &exit);
777 : __ incq(rax);
778 :
779 10 : __ movl(rdx, Operand(r80, 254));
780 5 : __ cmpl(rdx, Immediate(0xC0C0BFBF));
781 5 : __ j(not_equal, &exit);
782 : __ incq(rax);
783 :
784 10 : __ movl(rdx, Operand(r80, -254));
785 5 : __ cmpl(rdx, Immediate(0x41414040));
786 5 : __ j(not_equal, &exit);
787 : __ incq(rax);
788 :
789 : // Success.
790 :
791 : __ movl(rax, Immediate(0));
792 5 : __ bind(&exit);
793 10 : __ leaq(rsp, Operand(rbp, kSystemPointerSize));
794 5 : __ popq(rbp);
795 5 : __ popq(rbx);
796 5 : __ popq(r14);
797 5 : __ popq(r13);
798 : ExitCode(masm);
799 5 : __ ret(0);
800 :
801 :
802 5 : CodeDesc desc;
803 5 : masm->GetCode(isolate, &desc);
804 5 : buffer->MakeExecutable();
805 : // Call the function from C++.
806 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
807 : int result = f.Call();
808 5 : CHECK_EQ(0, result);
809 5 : }
810 :
811 :
812 25880 : TEST(LoadAndStoreWithRepresentation) {
813 5 : Isolate* isolate = CcTest::i_isolate();
814 : HandleScope handles(isolate);
815 : auto buffer = AllocateAssemblerBuffer();
816 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
817 20 : buffer->CreateView());
818 :
819 : MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
820 : EntryCode(masm);
821 5 : __ subq(rsp, Immediate(1 * kSystemPointerSize));
822 5 : Label exit;
823 :
824 : // Test 1.
825 : __ movq(rax, Immediate(1)); // Test number.
826 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
827 : __ movq(rcx, Immediate(-1));
828 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
829 5 : Representation::UInteger8());
830 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
831 : __ movl(rdx, Immediate(255));
832 5 : __ cmpq(rcx, rdx);
833 5 : __ j(not_equal, &exit);
834 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
835 5 : Representation::UInteger8());
836 5 : __ cmpq(rcx, rdx);
837 5 : __ j(not_equal, &exit);
838 :
839 : // Test 2.
840 : __ movq(rax, Immediate(2)); // Test number.
841 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
842 5 : __ Set(rcx, V8_2PART_UINT64_C(0xDEADBEAF, 12345678));
843 5 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx, Representation::Smi());
844 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
845 5 : __ Set(rdx, V8_2PART_UINT64_C(0xDEADBEAF, 12345678));
846 5 : __ cmpq(rcx, rdx);
847 5 : __ j(not_equal, &exit);
848 5 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize), Representation::Smi());
849 5 : __ cmpq(rcx, rdx);
850 5 : __ j(not_equal, &exit);
851 :
852 : // Test 3.
853 : __ movq(rax, Immediate(3)); // Test number.
854 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
855 : __ movq(rcx, Immediate(-1));
856 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
857 5 : Representation::Integer32());
858 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
859 : __ movl(rdx, Immediate(-1));
860 5 : __ cmpq(rcx, rdx);
861 5 : __ j(not_equal, &exit);
862 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
863 5 : Representation::Integer32());
864 5 : __ cmpq(rcx, rdx);
865 5 : __ j(not_equal, &exit);
866 :
867 : // Test 4.
868 : __ movq(rax, Immediate(4)); // Test number.
869 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
870 : __ movl(rcx, Immediate(0x44332211));
871 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
872 5 : Representation::HeapObject());
873 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
874 : __ movl(rdx, Immediate(0x44332211));
875 5 : __ cmpq(rcx, rdx);
876 5 : __ j(not_equal, &exit);
877 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
878 5 : Representation::HeapObject());
879 5 : __ cmpq(rcx, rdx);
880 5 : __ j(not_equal, &exit);
881 :
882 : // Test 5.
883 : __ movq(rax, Immediate(5)); // Test number.
884 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
885 5 : __ Set(rcx, V8_2PART_UINT64_C(0x12345678, DEADBEAF));
886 5 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx, Representation::Tagged());
887 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
888 5 : __ Set(rdx, V8_2PART_UINT64_C(0x12345678, DEADBEAF));
889 5 : __ cmpq(rcx, rdx);
890 5 : __ j(not_equal, &exit);
891 5 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize), Representation::Tagged());
892 5 : __ cmpq(rcx, rdx);
893 5 : __ j(not_equal, &exit);
894 :
895 : // Test 6.
896 : __ movq(rax, Immediate(6)); // Test number.
897 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
898 5 : __ Set(rcx, V8_2PART_UINT64_C(0x11223344, 55667788));
899 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
900 5 : Representation::External());
901 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
902 5 : __ Set(rdx, V8_2PART_UINT64_C(0x11223344, 55667788));
903 5 : __ cmpq(rcx, rdx);
904 5 : __ j(not_equal, &exit);
905 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
906 5 : Representation::External());
907 5 : __ cmpq(rcx, rdx);
908 5 : __ j(not_equal, &exit);
909 :
910 : // Test 7.
911 : __ movq(rax, Immediate(7)); // Test number.
912 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
913 : __ movq(rcx, Immediate(-1));
914 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
915 5 : Representation::Integer8());
916 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
917 : __ movl(rdx, Immediate(255));
918 5 : __ cmpq(rcx, rdx);
919 5 : __ j(not_equal, &exit);
920 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
921 5 : Representation::Integer8());
922 : __ movq(rcx, Immediate(-1));
923 5 : __ cmpq(rcx, rdx);
924 5 : __ j(not_equal, &exit);
925 :
926 : // Test 8.
927 : __ movq(rax, Immediate(8)); // Test number.
928 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
929 : __ movq(rcx, Immediate(-1));
930 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
931 5 : Representation::Integer16());
932 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
933 : __ movl(rdx, Immediate(65535));
934 5 : __ cmpq(rcx, rdx);
935 5 : __ j(not_equal, &exit);
936 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
937 5 : Representation::Integer16());
938 : __ movq(rcx, Immediate(-1));
939 5 : __ cmpq(rcx, rdx);
940 5 : __ j(not_equal, &exit);
941 :
942 : // Test 9.
943 : __ movq(rax, Immediate(9)); // Test number.
944 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
945 : __ movq(rcx, Immediate(-1));
946 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
947 5 : Representation::UInteger16());
948 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
949 : __ movl(rdx, Immediate(65535));
950 5 : __ cmpq(rcx, rdx);
951 5 : __ j(not_equal, &exit);
952 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
953 5 : Representation::UInteger16());
954 5 : __ cmpq(rcx, rdx);
955 5 : __ j(not_equal, &exit);
956 :
957 : __ xorq(rax, rax); // Success.
958 5 : __ bind(&exit);
959 5 : __ addq(rsp, Immediate(1 * kSystemPointerSize));
960 : ExitCode(masm);
961 5 : __ ret(0);
962 :
963 5 : CodeDesc desc;
964 5 : masm->GetCode(isolate, &desc);
965 5 : buffer->MakeExecutable();
966 : // Call the function from C++.
967 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
968 : int result = f.Call();
969 5 : CHECK_EQ(0, result);
970 5 : }
971 :
972 5 : void TestFloat32x4Abs(MacroAssembler* masm, Label* exit, float x, float y,
973 : float z, float w) {
974 5 : __ subq(rsp, Immediate(kSimd128Size));
975 :
976 5 : __ Move(xmm1, x);
977 10 : __ Movss(Operand(rsp, 0 * kFloatSize), xmm1);
978 : __ Move(xmm2, y);
979 10 : __ Movss(Operand(rsp, 1 * kFloatSize), xmm2);
980 : __ Move(xmm3, z);
981 10 : __ Movss(Operand(rsp, 2 * kFloatSize), xmm3);
982 : __ Move(xmm4, w);
983 10 : __ Movss(Operand(rsp, 3 * kFloatSize), xmm4);
984 10 : __ Movups(xmm0, Operand(rsp, 0));
985 :
986 5 : __ Absps(xmm0);
987 10 : __ Movups(Operand(rsp, 0), xmm0);
988 :
989 : __ incq(rax);
990 5 : __ Move(xmm1, fabsf(x));
991 10 : __ Ucomiss(xmm1, Operand(rsp, 0 * kFloatSize));
992 5 : __ j(not_equal, exit);
993 : __ incq(rax);
994 5 : __ Move(xmm2, fabsf(y));
995 10 : __ Ucomiss(xmm2, Operand(rsp, 1 * kFloatSize));
996 5 : __ j(not_equal, exit);
997 : __ incq(rax);
998 5 : __ Move(xmm3, fabsf(z));
999 10 : __ Ucomiss(xmm3, Operand(rsp, 2 * kFloatSize));
1000 5 : __ j(not_equal, exit);
1001 : __ incq(rax);
1002 5 : __ Move(xmm4, fabsf(w));
1003 10 : __ Ucomiss(xmm4, Operand(rsp, 3 * kFloatSize));
1004 5 : __ j(not_equal, exit);
1005 :
1006 5 : __ addq(rsp, Immediate(kSimd128Size));
1007 5 : }
1008 :
1009 5 : void TestFloat32x4Neg(MacroAssembler* masm, Label* exit, float x, float y,
1010 : float z, float w) {
1011 5 : __ subq(rsp, Immediate(kSimd128Size));
1012 :
1013 5 : __ Move(xmm1, x);
1014 10 : __ Movss(Operand(rsp, 0 * kFloatSize), xmm1);
1015 : __ Move(xmm2, y);
1016 10 : __ Movss(Operand(rsp, 1 * kFloatSize), xmm2);
1017 : __ Move(xmm3, z);
1018 10 : __ Movss(Operand(rsp, 2 * kFloatSize), xmm3);
1019 : __ Move(xmm4, w);
1020 10 : __ Movss(Operand(rsp, 3 * kFloatSize), xmm4);
1021 10 : __ Movups(xmm0, Operand(rsp, 0));
1022 :
1023 5 : __ Negps(xmm0);
1024 10 : __ Movups(Operand(rsp, 0), xmm0);
1025 :
1026 : __ incq(rax);
1027 5 : __ Move(xmm1, -x);
1028 10 : __ Ucomiss(xmm1, Operand(rsp, 0 * kFloatSize));
1029 5 : __ j(not_equal, exit);
1030 : __ incq(rax);
1031 5 : __ Move(xmm2, -y);
1032 10 : __ Ucomiss(xmm2, Operand(rsp, 1 * kFloatSize));
1033 5 : __ j(not_equal, exit);
1034 : __ incq(rax);
1035 5 : __ Move(xmm3, -z);
1036 10 : __ Ucomiss(xmm3, Operand(rsp, 2 * kFloatSize));
1037 5 : __ j(not_equal, exit);
1038 : __ incq(rax);
1039 5 : __ Move(xmm4, -w);
1040 10 : __ Ucomiss(xmm4, Operand(rsp, 3 * kFloatSize));
1041 5 : __ j(not_equal, exit);
1042 :
1043 5 : __ addq(rsp, Immediate(kSimd128Size));
1044 5 : }
1045 :
1046 5 : void TestFloat64x2Abs(MacroAssembler* masm, Label* exit, double x, double y) {
1047 5 : __ subq(rsp, Immediate(kSimd128Size));
1048 :
1049 5 : __ Move(xmm1, x);
1050 10 : __ Movsd(Operand(rsp, 0 * kDoubleSize), xmm1);
1051 : __ Move(xmm2, y);
1052 10 : __ Movsd(Operand(rsp, 1 * kDoubleSize), xmm2);
1053 5 : __ movupd(xmm0, Operand(rsp, 0));
1054 :
1055 5 : __ Abspd(xmm0);
1056 5 : __ movupd(Operand(rsp, 0), xmm0);
1057 :
1058 : __ incq(rax);
1059 5 : __ Move(xmm1, fabs(x));
1060 10 : __ Ucomisd(xmm1, Operand(rsp, 0 * kDoubleSize));
1061 5 : __ j(not_equal, exit);
1062 : __ incq(rax);
1063 5 : __ Move(xmm2, fabs(y));
1064 10 : __ Ucomisd(xmm2, Operand(rsp, 1 * kDoubleSize));
1065 5 : __ j(not_equal, exit);
1066 :
1067 5 : __ addq(rsp, Immediate(kSimd128Size));
1068 5 : }
1069 :
1070 5 : void TestFloat64x2Neg(MacroAssembler* masm, Label* exit, double x, double y) {
1071 5 : __ subq(rsp, Immediate(kSimd128Size));
1072 :
1073 5 : __ Move(xmm1, x);
1074 10 : __ Movsd(Operand(rsp, 0 * kDoubleSize), xmm1);
1075 : __ Move(xmm2, y);
1076 10 : __ Movsd(Operand(rsp, 1 * kDoubleSize), xmm2);
1077 5 : __ movupd(xmm0, Operand(rsp, 0));
1078 :
1079 5 : __ Negpd(xmm0);
1080 5 : __ movupd(Operand(rsp, 0), xmm0);
1081 :
1082 : __ incq(rax);
1083 5 : __ Move(xmm1, -x);
1084 10 : __ Ucomisd(xmm1, Operand(rsp, 0 * kDoubleSize));
1085 5 : __ j(not_equal, exit);
1086 : __ incq(rax);
1087 5 : __ Move(xmm2, -y);
1088 10 : __ Ucomisd(xmm2, Operand(rsp, 1 * kDoubleSize));
1089 5 : __ j(not_equal, exit);
1090 :
1091 5 : __ addq(rsp, Immediate(kSimd128Size));
1092 5 : }
1093 :
1094 25880 : TEST(SIMDMacros) {
1095 5 : Isolate* isolate = CcTest::i_isolate();
1096 : HandleScope handles(isolate);
1097 : auto buffer = AllocateAssemblerBuffer();
1098 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
1099 20 : buffer->CreateView());
1100 :
1101 : MacroAssembler* masm = &assembler;
1102 : EntryCode(masm);
1103 5 : Label exit;
1104 :
1105 : __ xorq(rax, rax);
1106 5 : TestFloat32x4Abs(masm, &exit, 1.5, -1.5, 0.5, -0.5);
1107 5 : TestFloat32x4Neg(masm, &exit, 1.5, -1.5, 0.5, -0.5);
1108 5 : TestFloat64x2Abs(masm, &exit, 1.75, -1.75);
1109 5 : TestFloat64x2Neg(masm, &exit, 1.75, -1.75);
1110 :
1111 : __ xorq(rax, rax); // Success.
1112 5 : __ bind(&exit);
1113 : ExitCode(masm);
1114 5 : __ ret(0);
1115 :
1116 5 : CodeDesc desc;
1117 5 : masm->GetCode(isolate, &desc);
1118 5 : buffer->MakeExecutable();
1119 : // Call the function from C++.
1120 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
1121 : int result = f.Call();
1122 5 : CHECK_EQ(0, result);
1123 5 : }
1124 :
1125 25880 : TEST(AreAliased) {
1126 : DCHECK(!AreAliased(rax));
1127 : DCHECK(!AreAliased(rax, no_reg));
1128 : DCHECK(!AreAliased(no_reg, rax, no_reg));
1129 :
1130 : DCHECK(AreAliased(rax, rax));
1131 : DCHECK(!AreAliased(no_reg, no_reg));
1132 :
1133 : DCHECK(!AreAliased(rax, rbx, rcx, rdx, no_reg));
1134 : DCHECK(AreAliased(rax, rbx, rcx, rdx, rax, no_reg));
1135 :
1136 : // no_regs are allowed in
1137 : DCHECK(!AreAliased(rax, no_reg, rbx, no_reg, rcx, no_reg, rdx, no_reg));
1138 : DCHECK(AreAliased(rax, no_reg, rbx, no_reg, rcx, no_reg, rdx, rax, no_reg));
1139 5 : }
1140 :
1141 : #undef __
1142 :
1143 : } // namespace test_macro_assembler_x64
1144 : } // namespace internal
1145 77625 : } // namespace v8
|