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 28342 : 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 28342 : 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 28342 : 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 28342 : 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 28342 : 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 28342 : 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 28342 : 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 5 : __ 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 5 : Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kSystemPointerSize);
532 :
533 : // Test 6.
534 : __ movl(rdx, sp2c2); // Sanity check.
535 5 : __ cmpl(rdx, Immediate(0x105));
536 5 : __ j(not_equal, &exit);
537 : __ incq(rax);
538 :
539 10 : __ movl(rdx, Operand(sp2c2, 2 * kSystemPointerSize));
540 5 : __ cmpl(rdx, Immediate(0x103));
541 5 : __ j(not_equal, &exit);
542 : __ incq(rax);
543 :
544 : // Non-zero to zero displacement.
545 10 : __ movl(rdx, Operand(sp2c2, -2 * kSystemPointerSize));
546 5 : __ cmpl(rdx, Immediate(0x107));
547 5 : __ j(not_equal, &exit);
548 : __ incq(rax);
549 :
550 :
551 5 : Operand bp0 = Operand(rbp, 0);
552 :
553 : // Test 9.
554 : __ movl(rdx, bp0); // Sanity check.
555 5 : __ cmpl(rdx, Immediate(0x100));
556 5 : __ j(not_equal, &exit);
557 : __ incq(rax);
558 :
559 : // Zero to non-zero displacement.
560 10 : __ movl(rdx, Operand(bp0, -2 * kSystemPointerSize));
561 5 : __ cmpl(rdx, Immediate(0x102));
562 5 : __ j(not_equal, &exit);
563 : __ incq(rax);
564 :
565 5 : Operand bp2 = Operand(rbp, -2 * kSystemPointerSize);
566 :
567 : // Test 11.
568 : __ movl(rdx, bp2); // Sanity check.
569 5 : __ cmpl(rdx, Immediate(0x102));
570 5 : __ j(not_equal, &exit);
571 : __ incq(rax);
572 :
573 : // Non-zero to zero displacement.
574 10 : __ movl(rdx, Operand(bp2, 2 * kSystemPointerSize));
575 5 : __ cmpl(rdx, Immediate(0x100));
576 5 : __ j(not_equal, &exit);
577 : __ incq(rax);
578 :
579 10 : __ movl(rdx, Operand(bp2, -2 * kSystemPointerSize));
580 5 : __ cmpl(rdx, Immediate(0x104));
581 5 : __ j(not_equal, &exit);
582 : __ incq(rax);
583 :
584 : Operand bp2c4 =
585 5 : Operand(rbp, rcx, times_pointer_size, -4 * kSystemPointerSize);
586 :
587 : // Test 14:
588 : __ movl(rdx, bp2c4); // Sanity check.
589 5 : __ cmpl(rdx, Immediate(0x102));
590 5 : __ j(not_equal, &exit);
591 : __ incq(rax);
592 :
593 10 : __ movl(rdx, Operand(bp2c4, 2 * kSystemPointerSize));
594 5 : __ cmpl(rdx, Immediate(0x100));
595 5 : __ j(not_equal, &exit);
596 : __ incq(rax);
597 :
598 10 : __ movl(rdx, Operand(bp2c4, -2 * kSystemPointerSize));
599 5 : __ cmpl(rdx, Immediate(0x104));
600 5 : __ j(not_equal, &exit);
601 : __ incq(rax);
602 :
603 5 : Operand bx0 = Operand(rbx, 0);
604 :
605 : // Test 17.
606 : __ movl(rdx, bx0); // Sanity check.
607 5 : __ cmpl(rdx, Immediate(0x105));
608 5 : __ j(not_equal, &exit);
609 : __ incq(rax);
610 :
611 10 : __ movl(rdx, Operand(bx0, 5 * kSystemPointerSize));
612 5 : __ cmpl(rdx, Immediate(0x100));
613 5 : __ j(not_equal, &exit);
614 : __ incq(rax);
615 :
616 10 : __ movl(rdx, Operand(bx0, -4 * kSystemPointerSize));
617 5 : __ cmpl(rdx, Immediate(0x109));
618 5 : __ j(not_equal, &exit);
619 : __ incq(rax);
620 :
621 5 : Operand bx2 = Operand(rbx, 2 * kSystemPointerSize);
622 :
623 : // Test 20.
624 : __ movl(rdx, bx2); // Sanity check.
625 5 : __ cmpl(rdx, Immediate(0x103));
626 5 : __ j(not_equal, &exit);
627 : __ incq(rax);
628 :
629 10 : __ movl(rdx, Operand(bx2, 2 * kSystemPointerSize));
630 5 : __ cmpl(rdx, Immediate(0x101));
631 5 : __ j(not_equal, &exit);
632 : __ incq(rax);
633 :
634 : // Non-zero to zero displacement.
635 10 : __ movl(rdx, Operand(bx2, -2 * kSystemPointerSize));
636 5 : __ cmpl(rdx, Immediate(0x105));
637 5 : __ j(not_equal, &exit);
638 : __ incq(rax);
639 :
640 : Operand bx2c2 =
641 5 : Operand(rbx, rcx, times_pointer_size, -2 * kSystemPointerSize);
642 :
643 : // Test 23.
644 : __ movl(rdx, bx2c2); // Sanity check.
645 5 : __ cmpl(rdx, Immediate(0x105));
646 5 : __ j(not_equal, &exit);
647 : __ incq(rax);
648 :
649 10 : __ movl(rdx, Operand(bx2c2, 2 * kSystemPointerSize));
650 5 : __ cmpl(rdx, Immediate(0x103));
651 5 : __ j(not_equal, &exit);
652 : __ incq(rax);
653 :
654 10 : __ movl(rdx, Operand(bx2c2, -2 * kSystemPointerSize));
655 5 : __ cmpl(rdx, Immediate(0x107));
656 5 : __ j(not_equal, &exit);
657 : __ incq(rax);
658 :
659 5 : Operand r80 = Operand(r8, 0);
660 :
661 : // Test 26.
662 : __ movl(rdx, r80); // Sanity check.
663 5 : __ cmpl(rdx, Immediate(0x80808080));
664 5 : __ j(not_equal, &exit);
665 : __ incq(rax);
666 :
667 10 : __ movl(rdx, Operand(r80, -8 * kIntSize));
668 5 : __ cmpl(rdx, Immediate(0x78787878));
669 5 : __ j(not_equal, &exit);
670 : __ incq(rax);
671 :
672 10 : __ movl(rdx, Operand(r80, 8 * kIntSize));
673 5 : __ cmpl(rdx, Immediate(0x88888888));
674 5 : __ j(not_equal, &exit);
675 : __ incq(rax);
676 :
677 10 : __ movl(rdx, Operand(r80, -64 * kIntSize));
678 5 : __ cmpl(rdx, Immediate(0x40404040));
679 5 : __ j(not_equal, &exit);
680 : __ incq(rax);
681 :
682 10 : __ movl(rdx, Operand(r80, 64 * kIntSize));
683 5 : __ cmpl(rdx, Immediate(0xC0C0C0C0));
684 5 : __ j(not_equal, &exit);
685 : __ incq(rax);
686 :
687 5 : Operand r88 = Operand(r8, 8 * kIntSize);
688 :
689 : // Test 31.
690 : __ movl(rdx, r88); // Sanity check.
691 5 : __ cmpl(rdx, Immediate(0x88888888));
692 5 : __ j(not_equal, &exit);
693 : __ incq(rax);
694 :
695 10 : __ movl(rdx, Operand(r88, -8 * kIntSize));
696 5 : __ cmpl(rdx, Immediate(0x80808080));
697 5 : __ j(not_equal, &exit);
698 : __ incq(rax);
699 :
700 10 : __ movl(rdx, Operand(r88, 8 * kIntSize));
701 5 : __ cmpl(rdx, Immediate(0x90909090));
702 5 : __ j(not_equal, &exit);
703 : __ incq(rax);
704 :
705 10 : __ movl(rdx, Operand(r88, -64 * kIntSize));
706 5 : __ cmpl(rdx, Immediate(0x48484848));
707 5 : __ j(not_equal, &exit);
708 : __ incq(rax);
709 :
710 10 : __ movl(rdx, Operand(r88, 64 * kIntSize));
711 5 : __ cmpl(rdx, Immediate(0xC8C8C8C8));
712 5 : __ j(not_equal, &exit);
713 : __ incq(rax);
714 :
715 :
716 5 : Operand r864 = Operand(r8, 64 * kIntSize);
717 :
718 : // Test 36.
719 : __ movl(rdx, r864); // Sanity check.
720 5 : __ cmpl(rdx, Immediate(0xC0C0C0C0));
721 5 : __ j(not_equal, &exit);
722 : __ incq(rax);
723 :
724 10 : __ movl(rdx, Operand(r864, -8 * kIntSize));
725 5 : __ cmpl(rdx, Immediate(0xB8B8B8B8));
726 5 : __ j(not_equal, &exit);
727 : __ incq(rax);
728 :
729 10 : __ movl(rdx, Operand(r864, 8 * kIntSize));
730 5 : __ cmpl(rdx, Immediate(0xC8C8C8C8));
731 5 : __ j(not_equal, &exit);
732 : __ incq(rax);
733 :
734 10 : __ movl(rdx, Operand(r864, -64 * kIntSize));
735 5 : __ cmpl(rdx, Immediate(0x80808080));
736 5 : __ j(not_equal, &exit);
737 : __ incq(rax);
738 :
739 10 : __ movl(rdx, Operand(r864, 32 * kIntSize));
740 5 : __ cmpl(rdx, Immediate(0xE0E0E0E0));
741 5 : __ j(not_equal, &exit);
742 : __ incq(rax);
743 :
744 : // 32-bit offset to 8-bit offset.
745 10 : __ movl(rdx, Operand(r864, -60 * kIntSize));
746 5 : __ cmpl(rdx, Immediate(0x84848484));
747 5 : __ j(not_equal, &exit);
748 : __ incq(rax);
749 :
750 10 : __ movl(rdx, Operand(r864, 60 * kIntSize));
751 5 : __ cmpl(rdx, Immediate(0xFCFCFCFC));
752 5 : __ j(not_equal, &exit);
753 : __ incq(rax);
754 :
755 : // Test unaligned offsets.
756 :
757 : // Test 43.
758 10 : __ movl(rdx, Operand(r80, 2));
759 5 : __ cmpl(rdx, Immediate(0x81818080));
760 5 : __ j(not_equal, &exit);
761 : __ incq(rax);
762 :
763 10 : __ movl(rdx, Operand(r80, -2));
764 5 : __ cmpl(rdx, Immediate(0x80807F7F));
765 5 : __ j(not_equal, &exit);
766 : __ incq(rax);
767 :
768 10 : __ movl(rdx, Operand(r80, 126));
769 5 : __ cmpl(rdx, Immediate(0xA0A09F9F));
770 5 : __ j(not_equal, &exit);
771 : __ incq(rax);
772 :
773 10 : __ movl(rdx, Operand(r80, -126));
774 5 : __ cmpl(rdx, Immediate(0x61616060));
775 5 : __ j(not_equal, &exit);
776 : __ incq(rax);
777 :
778 10 : __ movl(rdx, Operand(r80, 254));
779 5 : __ cmpl(rdx, Immediate(0xC0C0BFBF));
780 5 : __ j(not_equal, &exit);
781 : __ incq(rax);
782 :
783 10 : __ movl(rdx, Operand(r80, -254));
784 5 : __ cmpl(rdx, Immediate(0x41414040));
785 5 : __ j(not_equal, &exit);
786 : __ incq(rax);
787 :
788 : // Success.
789 :
790 : __ movl(rax, Immediate(0));
791 5 : __ bind(&exit);
792 10 : __ leaq(rsp, Operand(rbp, kSystemPointerSize));
793 5 : __ popq(rbp);
794 5 : __ popq(rbx);
795 5 : __ popq(r14);
796 5 : __ popq(r13);
797 : ExitCode(masm);
798 5 : __ ret(0);
799 :
800 :
801 5 : CodeDesc desc;
802 5 : masm->GetCode(isolate, &desc);
803 5 : buffer->MakeExecutable();
804 : // Call the function from C++.
805 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
806 : int result = f.Call();
807 5 : CHECK_EQ(0, result);
808 5 : }
809 :
810 :
811 28342 : TEST(LoadAndStoreWithRepresentation) {
812 5 : Isolate* isolate = CcTest::i_isolate();
813 : HandleScope handles(isolate);
814 : auto buffer = AllocateAssemblerBuffer();
815 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
816 20 : buffer->CreateView());
817 :
818 : MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
819 : EntryCode(masm);
820 5 : __ subq(rsp, Immediate(1 * kSystemPointerSize));
821 5 : Label exit;
822 :
823 : // Test 1.
824 : __ movq(rax, Immediate(1)); // Test number.
825 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
826 : __ movq(rcx, Immediate(-1));
827 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
828 5 : Representation::UInteger8());
829 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
830 : __ movl(rdx, Immediate(255));
831 5 : __ cmpq(rcx, rdx);
832 5 : __ j(not_equal, &exit);
833 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
834 5 : Representation::UInteger8());
835 5 : __ cmpq(rcx, rdx);
836 5 : __ j(not_equal, &exit);
837 :
838 : // Test 2.
839 : __ movq(rax, Immediate(2)); // Test number.
840 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
841 5 : __ Set(rcx, V8_2PART_UINT64_C(0xDEADBEAF, 12345678));
842 5 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx, Representation::Smi());
843 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
844 5 : __ Set(rdx, V8_2PART_UINT64_C(0xDEADBEAF, 12345678));
845 5 : __ cmpq(rcx, rdx);
846 5 : __ j(not_equal, &exit);
847 5 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize), Representation::Smi());
848 5 : __ cmpq(rcx, rdx);
849 5 : __ j(not_equal, &exit);
850 :
851 : // Test 3.
852 : __ movq(rax, Immediate(3)); // Test number.
853 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
854 : __ movq(rcx, Immediate(-1));
855 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
856 5 : Representation::Integer32());
857 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
858 : __ movl(rdx, Immediate(-1));
859 5 : __ cmpq(rcx, rdx);
860 5 : __ j(not_equal, &exit);
861 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
862 5 : Representation::Integer32());
863 5 : __ cmpq(rcx, rdx);
864 5 : __ j(not_equal, &exit);
865 :
866 : // Test 4.
867 : __ movq(rax, Immediate(4)); // Test number.
868 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
869 : __ movl(rcx, Immediate(0x44332211));
870 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
871 5 : Representation::HeapObject());
872 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
873 : __ movl(rdx, Immediate(0x44332211));
874 5 : __ cmpq(rcx, rdx);
875 5 : __ j(not_equal, &exit);
876 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
877 5 : Representation::HeapObject());
878 5 : __ cmpq(rcx, rdx);
879 5 : __ j(not_equal, &exit);
880 :
881 : // Test 5.
882 : __ movq(rax, Immediate(5)); // Test number.
883 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
884 5 : __ Set(rcx, V8_2PART_UINT64_C(0x12345678, DEADBEAF));
885 5 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx, Representation::Tagged());
886 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
887 5 : __ Set(rdx, V8_2PART_UINT64_C(0x12345678, DEADBEAF));
888 5 : __ cmpq(rcx, rdx);
889 5 : __ j(not_equal, &exit);
890 5 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize), Representation::Tagged());
891 5 : __ cmpq(rcx, rdx);
892 5 : __ j(not_equal, &exit);
893 :
894 : // Test 6.
895 : __ movq(rax, Immediate(6)); // Test number.
896 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
897 5 : __ Set(rcx, V8_2PART_UINT64_C(0x11223344, 55667788));
898 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
899 5 : Representation::External());
900 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
901 5 : __ Set(rdx, V8_2PART_UINT64_C(0x11223344, 55667788));
902 5 : __ cmpq(rcx, rdx);
903 5 : __ j(not_equal, &exit);
904 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
905 5 : Representation::External());
906 5 : __ cmpq(rcx, rdx);
907 5 : __ j(not_equal, &exit);
908 :
909 : // Test 7.
910 : __ movq(rax, Immediate(7)); // Test number.
911 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
912 : __ movq(rcx, Immediate(-1));
913 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
914 5 : Representation::Integer8());
915 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
916 : __ movl(rdx, Immediate(255));
917 5 : __ cmpq(rcx, rdx);
918 5 : __ j(not_equal, &exit);
919 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
920 5 : Representation::Integer8());
921 : __ movq(rcx, Immediate(-1));
922 5 : __ cmpq(rcx, rdx);
923 5 : __ j(not_equal, &exit);
924 :
925 : // Test 8.
926 : __ movq(rax, Immediate(8)); // Test number.
927 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
928 : __ movq(rcx, Immediate(-1));
929 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
930 5 : Representation::Integer16());
931 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
932 : __ movl(rdx, Immediate(65535));
933 5 : __ cmpq(rcx, rdx);
934 5 : __ j(not_equal, &exit);
935 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
936 5 : Representation::Integer16());
937 : __ movq(rcx, Immediate(-1));
938 5 : __ cmpq(rcx, rdx);
939 5 : __ j(not_equal, &exit);
940 :
941 : // Test 9.
942 : __ movq(rax, Immediate(9)); // Test number.
943 10 : __ movq(Operand(rsp, 0 * kSystemPointerSize), Immediate(0));
944 : __ movq(rcx, Immediate(-1));
945 : __ Store(Operand(rsp, 0 * kSystemPointerSize), rcx,
946 5 : Representation::UInteger16());
947 10 : __ movq(rcx, Operand(rsp, 0 * kSystemPointerSize));
948 : __ movl(rdx, Immediate(65535));
949 5 : __ cmpq(rcx, rdx);
950 5 : __ j(not_equal, &exit);
951 : __ Load(rdx, Operand(rsp, 0 * kSystemPointerSize),
952 5 : Representation::UInteger16());
953 5 : __ cmpq(rcx, rdx);
954 5 : __ j(not_equal, &exit);
955 :
956 : __ xorq(rax, rax); // Success.
957 5 : __ bind(&exit);
958 5 : __ addq(rsp, Immediate(1 * kSystemPointerSize));
959 : ExitCode(masm);
960 5 : __ ret(0);
961 :
962 5 : CodeDesc desc;
963 5 : masm->GetCode(isolate, &desc);
964 5 : buffer->MakeExecutable();
965 : // Call the function from C++.
966 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
967 : int result = f.Call();
968 5 : CHECK_EQ(0, result);
969 5 : }
970 :
971 5 : void TestFloat32x4Abs(MacroAssembler* masm, Label* exit, float x, float y,
972 : float z, float w) {
973 5 : __ subq(rsp, Immediate(kSimd128Size));
974 :
975 5 : __ Move(xmm1, x);
976 10 : __ Movss(Operand(rsp, 0 * kFloatSize), xmm1);
977 : __ Move(xmm2, y);
978 10 : __ Movss(Operand(rsp, 1 * kFloatSize), xmm2);
979 : __ Move(xmm3, z);
980 10 : __ Movss(Operand(rsp, 2 * kFloatSize), xmm3);
981 : __ Move(xmm4, w);
982 10 : __ Movss(Operand(rsp, 3 * kFloatSize), xmm4);
983 10 : __ Movups(xmm0, Operand(rsp, 0));
984 :
985 5 : __ Absps(xmm0);
986 10 : __ Movups(Operand(rsp, 0), xmm0);
987 :
988 : __ incq(rax);
989 5 : __ Move(xmm1, fabsf(x));
990 10 : __ Ucomiss(xmm1, Operand(rsp, 0 * kFloatSize));
991 5 : __ j(not_equal, exit);
992 : __ incq(rax);
993 5 : __ Move(xmm2, fabsf(y));
994 10 : __ Ucomiss(xmm2, Operand(rsp, 1 * kFloatSize));
995 5 : __ j(not_equal, exit);
996 : __ incq(rax);
997 5 : __ Move(xmm3, fabsf(z));
998 10 : __ Ucomiss(xmm3, Operand(rsp, 2 * kFloatSize));
999 5 : __ j(not_equal, exit);
1000 : __ incq(rax);
1001 5 : __ Move(xmm4, fabsf(w));
1002 10 : __ Ucomiss(xmm4, Operand(rsp, 3 * kFloatSize));
1003 5 : __ j(not_equal, exit);
1004 :
1005 5 : __ addq(rsp, Immediate(kSimd128Size));
1006 5 : }
1007 :
1008 5 : void TestFloat32x4Neg(MacroAssembler* masm, Label* exit, float x, float y,
1009 : float z, float w) {
1010 5 : __ subq(rsp, Immediate(kSimd128Size));
1011 :
1012 5 : __ Move(xmm1, x);
1013 10 : __ Movss(Operand(rsp, 0 * kFloatSize), xmm1);
1014 : __ Move(xmm2, y);
1015 10 : __ Movss(Operand(rsp, 1 * kFloatSize), xmm2);
1016 : __ Move(xmm3, z);
1017 10 : __ Movss(Operand(rsp, 2 * kFloatSize), xmm3);
1018 : __ Move(xmm4, w);
1019 10 : __ Movss(Operand(rsp, 3 * kFloatSize), xmm4);
1020 10 : __ Movups(xmm0, Operand(rsp, 0));
1021 :
1022 5 : __ Negps(xmm0);
1023 10 : __ Movups(Operand(rsp, 0), xmm0);
1024 :
1025 : __ incq(rax);
1026 5 : __ Move(xmm1, -x);
1027 10 : __ Ucomiss(xmm1, Operand(rsp, 0 * kFloatSize));
1028 5 : __ j(not_equal, exit);
1029 : __ incq(rax);
1030 5 : __ Move(xmm2, -y);
1031 10 : __ Ucomiss(xmm2, Operand(rsp, 1 * kFloatSize));
1032 5 : __ j(not_equal, exit);
1033 : __ incq(rax);
1034 5 : __ Move(xmm3, -z);
1035 10 : __ Ucomiss(xmm3, Operand(rsp, 2 * kFloatSize));
1036 5 : __ j(not_equal, exit);
1037 : __ incq(rax);
1038 5 : __ Move(xmm4, -w);
1039 10 : __ Ucomiss(xmm4, Operand(rsp, 3 * kFloatSize));
1040 5 : __ j(not_equal, exit);
1041 :
1042 5 : __ addq(rsp, Immediate(kSimd128Size));
1043 5 : }
1044 :
1045 5 : void TestFloat64x2Abs(MacroAssembler* masm, Label* exit, double x, double y) {
1046 5 : __ subq(rsp, Immediate(kSimd128Size));
1047 :
1048 5 : __ Move(xmm1, x);
1049 10 : __ Movsd(Operand(rsp, 0 * kDoubleSize), xmm1);
1050 : __ Move(xmm2, y);
1051 10 : __ Movsd(Operand(rsp, 1 * kDoubleSize), xmm2);
1052 5 : __ movupd(xmm0, Operand(rsp, 0));
1053 :
1054 5 : __ Abspd(xmm0);
1055 5 : __ movupd(Operand(rsp, 0), xmm0);
1056 :
1057 : __ incq(rax);
1058 5 : __ Move(xmm1, fabs(x));
1059 10 : __ Ucomisd(xmm1, Operand(rsp, 0 * kDoubleSize));
1060 5 : __ j(not_equal, exit);
1061 : __ incq(rax);
1062 5 : __ Move(xmm2, fabs(y));
1063 10 : __ Ucomisd(xmm2, Operand(rsp, 1 * kDoubleSize));
1064 5 : __ j(not_equal, exit);
1065 :
1066 5 : __ addq(rsp, Immediate(kSimd128Size));
1067 5 : }
1068 :
1069 5 : void TestFloat64x2Neg(MacroAssembler* masm, Label* exit, double x, double y) {
1070 5 : __ subq(rsp, Immediate(kSimd128Size));
1071 :
1072 5 : __ Move(xmm1, x);
1073 10 : __ Movsd(Operand(rsp, 0 * kDoubleSize), xmm1);
1074 : __ Move(xmm2, y);
1075 10 : __ Movsd(Operand(rsp, 1 * kDoubleSize), xmm2);
1076 5 : __ movupd(xmm0, Operand(rsp, 0));
1077 :
1078 5 : __ Negpd(xmm0);
1079 5 : __ movupd(Operand(rsp, 0), xmm0);
1080 :
1081 : __ incq(rax);
1082 5 : __ Move(xmm1, -x);
1083 10 : __ Ucomisd(xmm1, Operand(rsp, 0 * kDoubleSize));
1084 5 : __ j(not_equal, exit);
1085 : __ incq(rax);
1086 5 : __ Move(xmm2, -y);
1087 10 : __ Ucomisd(xmm2, Operand(rsp, 1 * kDoubleSize));
1088 5 : __ j(not_equal, exit);
1089 :
1090 5 : __ addq(rsp, Immediate(kSimd128Size));
1091 5 : }
1092 :
1093 28342 : TEST(SIMDMacros) {
1094 5 : Isolate* isolate = CcTest::i_isolate();
1095 : HandleScope handles(isolate);
1096 : auto buffer = AllocateAssemblerBuffer();
1097 : MacroAssembler assembler(isolate, v8::internal::CodeObjectRequired::kYes,
1098 20 : buffer->CreateView());
1099 :
1100 : MacroAssembler* masm = &assembler;
1101 : EntryCode(masm);
1102 5 : Label exit;
1103 :
1104 : __ xorq(rax, rax);
1105 5 : TestFloat32x4Abs(masm, &exit, 1.5, -1.5, 0.5, -0.5);
1106 5 : TestFloat32x4Neg(masm, &exit, 1.5, -1.5, 0.5, -0.5);
1107 5 : TestFloat64x2Abs(masm, &exit, 1.75, -1.75);
1108 5 : TestFloat64x2Neg(masm, &exit, 1.75, -1.75);
1109 :
1110 : __ xorq(rax, rax); // Success.
1111 5 : __ bind(&exit);
1112 : ExitCode(masm);
1113 5 : __ ret(0);
1114 :
1115 5 : CodeDesc desc;
1116 5 : masm->GetCode(isolate, &desc);
1117 5 : buffer->MakeExecutable();
1118 : // Call the function from C++.
1119 5 : auto f = GeneratedCode<F0>::FromBuffer(CcTest::i_isolate(), buffer->start());
1120 : int result = f.Call();
1121 5 : CHECK_EQ(0, result);
1122 5 : }
1123 :
1124 28342 : TEST(AreAliased) {
1125 : DCHECK(!AreAliased(rax));
1126 : DCHECK(!AreAliased(rax, no_reg));
1127 : DCHECK(!AreAliased(no_reg, rax, no_reg));
1128 :
1129 : DCHECK(AreAliased(rax, rax));
1130 : DCHECK(!AreAliased(no_reg, no_reg));
1131 :
1132 : DCHECK(!AreAliased(rax, rbx, rcx, rdx, no_reg));
1133 : DCHECK(AreAliased(rax, rbx, rcx, rdx, rax, no_reg));
1134 :
1135 : // no_regs are allowed in
1136 : DCHECK(!AreAliased(rax, no_reg, rbx, no_reg, rcx, no_reg, rdx, no_reg));
1137 : DCHECK(AreAliased(rax, no_reg, rbx, no_reg, rcx, no_reg, rdx, rax, no_reg));
1138 5 : }
1139 :
1140 : #undef __
1141 :
1142 : } // namespace test_macro_assembler_x64
1143 : } // namespace internal
1144 85011 : } // namespace v8
|