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