Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
assembler_arm64_test.cc
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h"
6#if defined(TARGET_ARCH_ARM64)
7
10#include "vm/cpu.h"
11#include "vm/os.h"
12#include "vm/unit_test.h"
13#include "vm/virtual_memory.h"
14
15namespace dart {
16namespace compiler {
17#define __ assembler->
18
19#if defined(PRODUCT)
20#define EXPECT_DISASSEMBLY(expected)
21#else
22#define EXPECT_DISASSEMBLY(expected) \
23 EXPECT_STREQ(expected, test->RelativeDisassembly())
24#endif
25
26ASSEMBLER_TEST_GENERATE(Simple, assembler) {
27 __ add(R0, ZR, Operand(ZR));
28 __ add(R0, R0, Operand(42));
29 __ ret();
30}
31
32ASSEMBLER_TEST_RUN(Simple, test) {
33 typedef int64_t (*Int64Return)() DART_UNUSED;
34 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
35 EXPECT_DISASSEMBLY(
36 "add r0, zr, zr\n"
37 "add r0, r0, #0x2a\n"
38 "ret\n");
39}
40
41// Move wide immediate tests.
42// movz
43ASSEMBLER_TEST_GENERATE(Movz0, assembler) {
44 __ movz(R0, Immediate(42), 0);
45 __ ret();
46}
47
49 typedef int64_t (*Int64Return)() DART_UNUSED;
50 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
51 EXPECT_DISASSEMBLY(
52 "movz r0, #0x2a\n"
53 "ret\n");
54}
55
56ASSEMBLER_TEST_GENERATE(Movz1, assembler) {
57 __ movz(R0, Immediate(42), 0); // Overwritten by next instruction.
58 __ movz(R0, Immediate(42), 1);
59 __ ret();
60}
61
63 typedef int64_t (*Int64Return)() DART_UNUSED;
64 EXPECT_EQ(42LL << 16, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
65 EXPECT_DISASSEMBLY(
66 "movz r0, #0x2a\n"
67 "movz r0, #0x2a lsl 16\n"
68 "ret\n");
69}
70
71ASSEMBLER_TEST_GENERATE(Movz2, assembler) {
72 __ movz(R0, Immediate(42), 2);
73 __ ret();
74}
75
77 typedef int64_t (*Int64Return)() DART_UNUSED;
78 EXPECT_EQ(42LL << 32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
79 EXPECT_DISASSEMBLY(
80 "movz r0, #0x2a lsl 32\n"
81 "ret\n");
82}
83
84ASSEMBLER_TEST_GENERATE(Movz3, assembler) {
85 __ movz(R0, Immediate(42), 3);
86 __ ret();
87}
88
90 typedef int64_t (*Int64Return)() DART_UNUSED;
91 EXPECT_EQ(42LL << 48, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
92 EXPECT_DISASSEMBLY(
93 "movz r0, #0x2a lsl 48\n"
94 "ret\n");
95}
96
97// movn
98ASSEMBLER_TEST_GENERATE(Movn0, assembler) {
99 __ movn(R0, Immediate(42), 0);
100 __ ret();
101}
102
103ASSEMBLER_TEST_RUN(Movn0, test) {
104 typedef int64_t (*Int64Return)() DART_UNUSED;
105 EXPECT_EQ(~42LL, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
106 EXPECT_DISASSEMBLY(
107 "movn r0, #0x2a\n"
108 "ret\n");
109}
110
111ASSEMBLER_TEST_GENERATE(Movn1, assembler) {
112 __ movn(R0, Immediate(42), 1);
113 __ ret();
114}
115
116ASSEMBLER_TEST_RUN(Movn1, test) {
117 typedef int64_t (*Int64Return)() DART_UNUSED;
118 EXPECT_EQ(~(42LL << 16), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
119 EXPECT_DISASSEMBLY(
120 "movn r0, #0x2a lsl 16\n"
121 "ret\n");
122}
123
124ASSEMBLER_TEST_GENERATE(Movn2, assembler) {
125 __ movn(R0, Immediate(42), 2);
126 __ ret();
127}
128
129ASSEMBLER_TEST_RUN(Movn2, test) {
130 typedef int64_t (*Int64Return)() DART_UNUSED;
131 EXPECT_EQ(~(42LL << 32), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
132 EXPECT_DISASSEMBLY(
133 "movn r0, #0x2a lsl 32\n"
134 "ret\n");
135}
136
137ASSEMBLER_TEST_GENERATE(Movn3, assembler) {
138 __ movn(R0, Immediate(42), 3);
139 __ ret();
140}
141
142ASSEMBLER_TEST_RUN(Movn3, test) {
143 typedef int64_t (*Int64Return)() DART_UNUSED;
144 EXPECT_EQ(~(42LL << 48), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
145 EXPECT_DISASSEMBLY(
146 "movn r0, #0x2a lsl 48\n"
147 "ret\n");
148}
149
150// movk
151ASSEMBLER_TEST_GENERATE(Movk0, assembler) {
152 __ movz(R0, Immediate(1), 3);
153 __ movk(R0, Immediate(42), 0);
154 __ ret();
155}
156
157ASSEMBLER_TEST_RUN(Movk0, test) {
158 typedef int64_t (*Int64Return)() DART_UNUSED;
159 EXPECT_EQ(42LL | (1LL << 48),
160 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
161 EXPECT_DISASSEMBLY(
162 "movz r0, #0x1 lsl 48\n"
163 "movk r0, #0x2a\n"
164 "ret\n");
165}
166
167ASSEMBLER_TEST_GENERATE(Movk1, assembler) {
168 __ movz(R0, Immediate(1), 0);
169 __ movk(R0, Immediate(42), 1);
170 __ ret();
171}
172
173ASSEMBLER_TEST_RUN(Movk1, test) {
174 typedef int64_t (*Int64Return)() DART_UNUSED;
175 EXPECT_EQ((42LL << 16) | 1,
176 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
177 EXPECT_DISASSEMBLY(
178 "movz r0, #0x1\n"
179 "movk r0, #0x2a lsl 16\n"
180 "ret\n");
181}
182
183ASSEMBLER_TEST_GENERATE(Movk2, assembler) {
184 __ movz(R0, Immediate(1), 0);
185 __ movk(R0, Immediate(42), 2);
186 __ ret();
187}
188
189ASSEMBLER_TEST_RUN(Movk2, test) {
190 typedef int64_t (*Int64Return)() DART_UNUSED;
191 EXPECT_EQ((42LL << 32) | 1,
192 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
193 EXPECT_DISASSEMBLY(
194 "movz r0, #0x1\n"
195 "movk r0, #0x2a lsl 32\n"
196 "ret\n");
197}
198
199ASSEMBLER_TEST_GENERATE(Movk3, assembler) {
200 __ movz(R0, Immediate(1), 0);
201 __ movk(R0, Immediate(42), 3);
202 __ ret();
203}
204
205ASSEMBLER_TEST_RUN(Movk3, test) {
206 typedef int64_t (*Int64Return)() DART_UNUSED;
207 EXPECT_EQ((42LL << 48) | 1,
208 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
209 EXPECT_DISASSEMBLY(
210 "movz r0, #0x1\n"
211 "movk r0, #0x2a lsl 48\n"
212 "ret\n");
213}
214
215ASSEMBLER_TEST_GENERATE(MovzBig, assembler) {
216 __ movz(R0, Immediate(0x8000), 0);
217 __ ret();
218}
219
220ASSEMBLER_TEST_RUN(MovzBig, test) {
221 typedef int64_t (*Int64Return)() DART_UNUSED;
222 EXPECT_EQ(0x8000, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
223 EXPECT_DISASSEMBLY(
224 "movz r0, #0x8000\n"
225 "ret\n");
226}
227
228// add tests.
229ASSEMBLER_TEST_GENERATE(AddReg, assembler) {
230 __ movz(R0, Immediate(20), 0);
231 __ movz(R1, Immediate(22), 0);
232 __ add(R0, R0, Operand(R1));
233 __ ret();
234}
235
236ASSEMBLER_TEST_RUN(AddReg, test) {
237 typedef int64_t (*Int64Return)() DART_UNUSED;
238 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
239 EXPECT_DISASSEMBLY(
240 "movz r0, #0x14\n"
241 "movz r1, #0x16\n"
242 "add r0, r0, r1\n"
243 "ret\n");
244}
245
246ASSEMBLER_TEST_GENERATE(AddLSLReg, assembler) {
247 __ movz(R0, Immediate(20), 0);
248 __ movz(R1, Immediate(11), 0);
249 __ add(R0, R0, Operand(R1, LSL, 1));
250 __ ret();
251}
252
253ASSEMBLER_TEST_RUN(AddLSLReg, test) {
254 typedef int64_t (*Int64Return)() DART_UNUSED;
255 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
256 EXPECT_DISASSEMBLY(
257 "movz r0, #0x14\n"
258 "movz r1, #0xb\n"
259 "add r0, r0, r1 lsl #1\n"
260 "ret\n");
261}
262
263ASSEMBLER_TEST_GENERATE(AddLSRReg, assembler) {
264 __ movz(R0, Immediate(20), 0);
265 __ movz(R1, Immediate(44), 0);
266 __ add(R0, R0, Operand(R1, LSR, 1));
267 __ ret();
268}
269
270ASSEMBLER_TEST_RUN(AddLSRReg, test) {
271 typedef int64_t (*Int64Return)() DART_UNUSED;
272 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
273 EXPECT_DISASSEMBLY(
274 "movz r0, #0x14\n"
275 "movz r1, #0x2c\n"
276 "add r0, r0, r1 lsr #1\n"
277 "ret\n");
278}
279
280ASSEMBLER_TEST_GENERATE(AddASRReg, assembler) {
281 __ movz(R0, Immediate(20), 0);
282 __ movz(R1, Immediate(44), 0);
283 __ add(R0, R0, Operand(R1, ASR, 1));
284 __ ret();
285}
286
287ASSEMBLER_TEST_RUN(AddASRReg, test) {
288 typedef int64_t (*Int64Return)() DART_UNUSED;
289 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
290 EXPECT_DISASSEMBLY(
291 "movz r0, #0x14\n"
292 "movz r1, #0x2c\n"
293 "add r0, r0, r1 asr #1\n"
294 "ret\n");
295}
296
297ASSEMBLER_TEST_GENERATE(AddASRNegReg, assembler) {
298 __ movz(R0, Immediate(43), 0);
299 __ movn(R1, Immediate(0), 0); // R1 <- -1
300 __ add(R1, ZR, Operand(R1, LSL, 3)); // R1 <- -8
301 __ add(R0, R0, Operand(R1, ASR, 3)); // R0 <- 43 + (-8 >> 3)
302 __ ret();
303}
304
305ASSEMBLER_TEST_RUN(AddASRNegReg, test) {
306 typedef int64_t (*Int64Return)() DART_UNUSED;
307 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
308 EXPECT_DISASSEMBLY(
309 "movz r0, #0x2b\n"
310 "movn r1, #0x0\n"
311 "add r1, zr, r1 lsl #3\n"
312 "add r0, r0, r1 asr #3\n"
313 "ret\n");
314}
315
316// TODO(zra): test other sign extension modes.
317ASSEMBLER_TEST_GENERATE(AddExtReg, assembler) {
318 __ movz(R0, Immediate(43), 0);
319 __ movz(R1, Immediate(0xffff), 0);
320 __ movk(R1, Immediate(0xffff), 1); // R1 <- -1 (32-bit)
321 __ add(R0, R0, Operand(R1, SXTW, 0)); // R0 <- R0 + (sign extended R1)
322 __ ret();
323}
324
325ASSEMBLER_TEST_RUN(AddExtReg, test) {
326 typedef int64_t (*Int64Return)() DART_UNUSED;
327 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
328 EXPECT_DISASSEMBLY(
329 "movz r0, #0x2b\n"
330 "movz r1, #0xffff\n"
331 "movk r1, #0xffff lsl 16\n"
332 "add r0, r0, r1 sxtw\n"
333 "ret\n");
334}
335
336ASSEMBLER_TEST_GENERATE(AddCarryInOut, assembler) {
337 __ LoadImmediate(R2, -1);
338 __ LoadImmediate(R1, 1);
339 __ LoadImmediate(R0, 0);
340 __ adds(IP0, R2, Operand(R1)); // c_out = 1.
341 __ adcs(IP0, R2, R0); // c_in = 1, c_out = 1.
342 __ adc(R0, R0, R0); // c_in = 1.
343 __ ret();
344}
345
346ASSEMBLER_TEST_RUN(AddCarryInOut, test) {
347 typedef int64_t (*Int64Return)() DART_UNUSED;
348 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
349 EXPECT_DISASSEMBLY(
350 "movn r2, #0x0\n"
351 "movz r1, #0x1\n"
352 "movz r0, #0x0\n"
353 "adds tmp, r2, r1\n"
354 "adcs tmp, r2, r0\n"
355 "adc r0, r0, r0\n"
356 "ret\n");
357}
358
359ASSEMBLER_TEST_GENERATE(SubCarryInOut, assembler) {
360 __ LoadImmediate(R1, 1);
361 __ LoadImmediate(R0, 0);
362 __ subs(IP0, R0, Operand(R1)); // c_out = 1.
363 __ sbcs(IP0, R0, R0); // c_in = 1, c_out = 1.
364 __ sbc(R0, R0, R0); // c_in = 1.
365 __ ret();
366}
367
368ASSEMBLER_TEST_RUN(SubCarryInOut, test) {
369 typedef int64_t (*Int64Return)() DART_UNUSED;
370 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
371 EXPECT_DISASSEMBLY(
372 "movz r1, #0x1\n"
373 "movz r0, #0x0\n"
374 "subs tmp, r0, r1\n"
375 "sbcs tmp, r0, r0\n"
376 "sbc r0, r0, r0\n"
377 "ret\n");
378}
379
380ASSEMBLER_TEST_GENERATE(Overflow, assembler) {
381 __ LoadImmediate(R0, 0);
382 __ LoadImmediate(R1, 1);
383 __ LoadImmediate(R2, 0xFFFFFFFFFFFFFFFF);
384 __ LoadImmediate(R3, 0x7FFFFFFFFFFFFFFF);
385 __ adds(IP0, R2, Operand(R1)); // c_out = 1.
386 __ adcs(IP0, R3, R0); // c_in = 1, c_out = 1, v = 1.
387 __ csinc(R0, R0, R0, VS); // R0 = v ? R0 : R0 + 1.
388 __ ret();
389}
390
391ASSEMBLER_TEST_RUN(Overflow, test) {
392 typedef int64_t (*Int64Return)() DART_UNUSED;
393 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
394 EXPECT_DISASSEMBLY(
395 "movz r0, #0x0\n"
396 "movz r1, #0x1\n"
397 "movn r2, #0x0\n"
398 "mov r3, 0x7fffffffffffffff\n"
399 "adds tmp, r2, r1\n"
400 "adcs tmp, r3, r0\n"
401 "csinc r0, r0, r0, vs\n"
402 "ret\n");
403}
404
405ASSEMBLER_TEST_GENERATE(WordAddCarryInOut, assembler) {
406 __ LoadImmediate(R2, -1);
407 __ LoadImmediate(R1, 1);
408 __ LoadImmediate(R0, 0);
409 __ addsw(IP0, R2, Operand(R1)); // c_out = 1.
410 __ adcsw(IP0, R2, R0); // c_in = 1, c_out = 1.
411 __ adcw(R0, R0, R0); // c_in = 1.
412 __ ret();
413}
414
415ASSEMBLER_TEST_RUN(WordAddCarryInOut, test) {
416 typedef int64_t (*Int64Return)() DART_UNUSED;
417 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
418 EXPECT_DISASSEMBLY(
419 "movn r2, #0x0\n"
420 "movz r1, #0x1\n"
421 "movz r0, #0x0\n"
422 "addws tmp, r2, r1\n"
423 "adcws tmp, r2, r0\n"
424 "adcw r0, r0, r0\n"
425 "ret\n");
426}
427
428ASSEMBLER_TEST_GENERATE(WordSubCarryInOut, assembler) {
429 __ LoadImmediate(R1, 1);
430 __ LoadImmediate(R0, 0);
431 __ subsw(IP0, R0, Operand(R1)); // c_out = 1.
432 __ sbcsw(IP0, R0, R0); // c_in = 1, c_out = 1.
433 __ sbcw(R0, R0, R0); // c_in = 1.
434 __ ret();
435}
436
437ASSEMBLER_TEST_RUN(WordSubCarryInOut, test) {
438 typedef int64_t (*Int64Return)() DART_UNUSED;
439 EXPECT_EQ(0x0FFFFFFFF, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
440 EXPECT_DISASSEMBLY(
441 "movz r1, #0x1\n"
442 "movz r0, #0x0\n"
443 "subws tmp, r0, r1\n"
444 "sbcws tmp, r0, r0\n"
445 "sbcw r0, r0, r0\n"
446 "ret\n");
447}
448
449ASSEMBLER_TEST_GENERATE(WordOverflow, assembler) {
450 __ LoadImmediate(R0, 0);
451 __ LoadImmediate(R1, 1);
452 __ LoadImmediate(R2, 0xFFFFFFFF);
453 __ LoadImmediate(R3, 0x7FFFFFFF);
454 __ addsw(IP0, R2, Operand(R1)); // c_out = 1.
455 __ adcsw(IP0, R3, R0); // c_in = 1, c_out = 1, v = 1.
456 __ csinc(R0, R0, R0, VS); // R0 = v ? R0 : R0 + 1.
457 __ ret();
458}
459
460ASSEMBLER_TEST_RUN(WordOverflow, test) {
461 typedef int64_t (*Int64Return)() DART_UNUSED;
462 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
463 EXPECT_DISASSEMBLY(
464 "movz r0, #0x0\n"
465 "movz r1, #0x1\n"
466 "mov r2, 0xffffffff\n"
467 "mov r3, 0x7fffffff\n"
468 "addws tmp, r2, r1\n"
469 "adcws tmp, r3, r0\n"
470 "csinc r0, r0, r0, vs\n"
471 "ret\n");
472}
473
474// Loads and Stores.
475ASSEMBLER_TEST_GENERATE(SimpleLoadStore, assembler) {
476 __ SetupDartSP();
477
478 __ sub(CSP, CSP,
479 Operand(2 * target::kWordSize)); // Must not access beyond CSP.
480
481 __ movz(R0, Immediate(43), 0);
482 __ movz(R1, Immediate(42), 0);
483 __ str(R1, Address(SP, -1 * target::kWordSize, Address::PreIndex));
484 __ ldr(R0, Address(SP, 1 * target::kWordSize, Address::PostIndex));
485 __ RestoreCSP();
486 __ ret();
487}
488
489ASSEMBLER_TEST_RUN(SimpleLoadStore, test) {
490 typedef int64_t (*Int64Return)() DART_UNUSED;
491 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
492 EXPECT_DISASSEMBLY(
493 "mov sp, csp\n"
494 "sub csp, csp, #0x1000\n"
495 "sub csp, csp, #0x10\n"
496 "movz r0, #0x2b\n"
497 "movz r1, #0x2a\n"
498 "str r1, [sp, #-8]!\n"
499 "ldr r0, [sp], #8 !\n"
500 "mov csp, sp\n"
501 "ret\n");
502}
503
504ASSEMBLER_TEST_GENERATE(SimpleLoadStoreHeapTag, assembler) {
505 __ SetupDartSP();
506 __ movz(R0, Immediate(43), 0);
507 __ movz(R1, Immediate(42), 0);
508 __ add(R2, SP, Operand(1));
509 __ str(R1, Address(R2, -1));
510 __ ldr(R0, Address(R2, -1));
511 __ RestoreCSP();
512 __ ret();
513}
514
515ASSEMBLER_TEST_RUN(SimpleLoadStoreHeapTag, test) {
516 typedef int64_t (*Int64Return)() DART_UNUSED;
517 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
518 EXPECT_DISASSEMBLY(
519 "mov sp, csp\n"
520 "sub csp, csp, #0x1000\n"
521 "movz r0, #0x2b\n"
522 "movz r1, #0x2a\n"
523 "add r2, sp, #0x1\n"
524 "str r1, [r2, #-1]\n"
525 "ldr r0, [r2, #-1]\n"
526 "mov csp, sp\n"
527 "ret\n");
528}
529
530ASSEMBLER_TEST_GENERATE(LoadStoreLargeIndex, assembler) {
531 __ SetupDartSP();
532
533 __ sub(CSP, CSP,
534 Operand(32 * target::kWordSize)); // Must not access beyond CSP.
535
536 __ movz(R0, Immediate(43), 0);
537 __ movz(R1, Immediate(42), 0);
538 // Largest negative offset that can fit in the signed 9-bit immediate field.
539 __ str(R1, Address(SP, -32 * target::kWordSize, Address::PreIndex));
540 // Largest positive kWordSize aligned offset that we can fit.
541 __ ldr(R0, Address(SP, 31 * target::kWordSize, Address::PostIndex));
542 // Correction.
543 __ add(SP, SP, Operand(target::kWordSize)); // Restore SP.
544 __ RestoreCSP();
545 __ ret();
546}
547
548ASSEMBLER_TEST_RUN(LoadStoreLargeIndex, test) {
549 typedef int64_t (*Int64Return)() DART_UNUSED;
550 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
551 EXPECT_DISASSEMBLY(
552 "mov sp, csp\n"
553 "sub csp, csp, #0x1000\n"
554 "sub csp, csp, #0x100\n"
555 "movz r0, #0x2b\n"
556 "movz r1, #0x2a\n"
557 "str r1, [sp, #-256]!\n"
558 "ldr r0, [sp], #248 !\n"
559 "add sp, sp, #0x8\n"
560 "mov csp, sp\n"
561 "ret\n");
562}
563
564ASSEMBLER_TEST_GENERATE(LoadStoreLargeOffset, assembler) {
565 __ SetupDartSP();
566 __ movz(R0, Immediate(43), 0);
567 __ movz(R1, Immediate(42), 0);
568 __ sub(SP, SP, Operand(512 * target::kWordSize));
569 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
570 __ str(R1, Address(SP, 512 * target::kWordSize, Address::Offset));
571 __ add(SP, SP, Operand(512 * target::kWordSize));
572 __ ldr(R0, Address(SP));
573 __ RestoreCSP();
574 __ ret();
575}
576
577ASSEMBLER_TEST_RUN(LoadStoreLargeOffset, test) {
578 typedef int64_t (*Int64Return)() DART_UNUSED;
579 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
580 EXPECT_DISASSEMBLY(
581 "mov sp, csp\n"
582 "sub csp, csp, #0x1000\n"
583 "movz r0, #0x2b\n"
584 "movz r1, #0x2a\n"
585 "sub sp, sp, #0x1000\n"
586 "and csp, sp, 0xfffffffffffffff0\n"
587 "str r1, [sp, #4096]\n"
588 "add sp, sp, #0x1000\n"
589 "ldr r0, [sp]\n"
590 "mov csp, sp\n"
591 "ret\n");
592}
593
594ASSEMBLER_TEST_GENERATE(LoadStoreExtReg, assembler) {
595 __ SetupDartSP();
596 __ movz(R0, Immediate(43), 0);
597 __ movz(R1, Immediate(42), 0);
598 __ movz(R2, Immediate(0xfff8), 0);
599 __ movk(R2, Immediate(0xffff), 1); // R2 <- -8 (int32_t).
600 // This should sign extend R2, and add to SP to get address,
601 // i.e. SP - kWordSize.
602 __ str(R1, Address(SP, R2, SXTW));
603 __ sub(SP, SP, Operand(target::kWordSize));
604 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
605 __ ldr(R0, Address(SP));
606 __ add(SP, SP, Operand(target::kWordSize));
607 __ RestoreCSP();
608 __ ret();
609}
610
611ASSEMBLER_TEST_RUN(LoadStoreExtReg, test) {
612 typedef int64_t (*Int64Return)() DART_UNUSED;
613 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
614 EXPECT_DISASSEMBLY(
615 "mov sp, csp\n"
616 "sub csp, csp, #0x1000\n"
617 "movz r0, #0x2b\n"
618 "movz r1, #0x2a\n"
619 "movz r2, #0xfff8\n"
620 "movk r2, #0xffff lsl 16\n"
621 "str r1, [sp, r2 sxtw]\n"
622 "sub sp, sp, #0x8\n"
623 "and csp, sp, 0xfffffffffffffff0\n"
624 "ldr r0, [sp]\n"
625 "add sp, sp, #0x8\n"
626 "mov csp, sp\n"
627 "ret\n");
628}
629
630ASSEMBLER_TEST_GENERATE(LoadStoreScaledReg, assembler) {
631 __ SetupDartSP();
632 __ movz(R0, Immediate(43), 0);
633 __ movz(R1, Immediate(42), 0);
634 __ movz(R2, Immediate(10), 0);
635 __ sub(SP, SP, Operand(10 * target::kWordSize));
636 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
637 // Store R1 into SP + R2 * kWordSize.
638 __ str(R1, Address(SP, R2, UXTX, Address::Scaled));
639 __ ldr(R0, Address(SP, R2, UXTX, Address::Scaled));
640 __ add(SP, SP, Operand(10 * target::kWordSize));
641 __ RestoreCSP();
642 __ ret();
643}
644
645ASSEMBLER_TEST_RUN(LoadStoreScaledReg, test) {
646 typedef int64_t (*Int64Return)() DART_UNUSED;
647 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
648 EXPECT_DISASSEMBLY(
649 "mov sp, csp\n"
650 "sub csp, csp, #0x1000\n"
651 "movz r0, #0x2b\n"
652 "movz r1, #0x2a\n"
653 "movz r2, #0xa\n"
654 "sub sp, sp, #0x50\n"
655 "and csp, sp, 0xfffffffffffffff0\n"
656 "str r1, [sp, r2 uxtx scaled]\n"
657 "ldr r0, [sp, r2 uxtx scaled]\n"
658 "add sp, sp, #0x50\n"
659 "mov csp, sp\n"
660 "ret\n");
661}
662
663ASSEMBLER_TEST_GENERATE(LoadSigned32Bit, assembler) {
664 __ SetupDartSP();
665
666 __ sub(CSP, CSP,
667 Operand(2 * target::kWordSize)); // Must not access beyond CSP.
668
669 __ LoadImmediate(R1, 0xffffffff);
670 __ str(R1, Address(SP, -4, Address::PreIndex), kFourBytes);
671 __ ldr(R0, Address(SP), kFourBytes);
672 __ ldr(R1, Address(SP, 4, Address::PostIndex), kFourBytes);
673 __ RestoreCSP();
674 __ ret();
675}
676
677ASSEMBLER_TEST_RUN(LoadSigned32Bit, test) {
678 typedef int64_t (*Int64Return)() DART_UNUSED;
679 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
680 EXPECT_DISASSEMBLY(
681 "mov sp, csp\n"
682 "sub csp, csp, #0x1000\n"
683 "sub csp, csp, #0x10\n"
684 "mov r1, 0xffffffff\n"
685 "strw r1, [sp, #-4]!\n"
686 "ldrsw r0, [sp]\n"
687 "ldrsw r1, [sp], #4 !\n"
688 "mov csp, sp\n"
689 "ret\n");
690}
691
692ASSEMBLER_TEST_GENERATE(SimpleLoadStorePair, assembler) {
693 __ SetupDartSP();
694
695 __ sub(CSP, CSP,
696 Operand(2 * target::kWordSize)); // Must not access beyond CSP.
697
698 __ LoadImmediate(R2, 43);
699 __ LoadImmediate(R3, 42);
700 __ stp(R2, R3, Address(SP, -2 * target::kWordSize, Address::PairPreIndex));
701 __ ldp(R0, R1, Address(SP, 2 * target::kWordSize, Address::PairPostIndex));
702 __ sub(R0, R0, Operand(R1));
703 __ RestoreCSP();
704 __ ret();
705}
706
707ASSEMBLER_TEST_RUN(SimpleLoadStorePair, test) {
708 typedef int64_t (*Int64Return)() DART_UNUSED;
709 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
710 EXPECT_DISASSEMBLY(
711 "mov sp, csp\n"
712 "sub csp, csp, #0x1000\n"
713 "sub csp, csp, #0x10\n"
714 "movz r2, #0x2b\n"
715 "movz r3, #0x2a\n"
716 "stp r2, r3, [sp, #-16]!\n"
717 "ldp r0, r1, [sp], #16 !\n"
718 "sub r0, r0, r1\n"
719 "mov csp, sp\n"
720 "ret\n");
721}
722
723ASSEMBLER_TEST_GENERATE(LoadStorePairOffset, assembler) {
724 __ SetupDartSP();
725 __ LoadImmediate(R2, 43);
726 __ LoadImmediate(R3, 42);
727 __ sub(SP, SP, Operand(4 * target::kWordSize));
728 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
729 __ stp(R2, R3, Address::Pair(SP, 2 * target::kWordSize));
730 __ ldp(R0, R1, Address::Pair(SP, 2 * target::kWordSize));
731 __ add(SP, SP, Operand(4 * target::kWordSize));
732 __ sub(R0, R0, Operand(R1));
733 __ RestoreCSP();
734 __ ret();
735}
736
737ASSEMBLER_TEST_RUN(LoadStorePairOffset, test) {
738 typedef int64_t (*Int64Return)() DART_UNUSED;
739 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
740 EXPECT_DISASSEMBLY(
741 "mov sp, csp\n"
742 "sub csp, csp, #0x1000\n"
743 "movz r2, #0x2b\n"
744 "movz r3, #0x2a\n"
745 "sub sp, sp, #0x20\n"
746 "and csp, sp, 0xfffffffffffffff0\n"
747 "stp r2, r3, [sp, #16]\n"
748 "ldp r0, r1, [sp, #16]\n"
749 "add sp, sp, #0x20\n"
750 "sub r0, r0, r1\n"
751 "mov csp, sp\n"
752 "ret\n");
753}
754
755ASSEMBLER_TEST_GENERATE(LoadStorePairUnsigned32, assembler) {
756 __ SetupDartSP();
757 __ LoadImmediate(R2, 0xAABBCCDDEEFF9988);
758 __ LoadImmediate(R3, 0xBBCCDDEEFF998877);
759 __ sub(SP, SP, Operand(4 * target::kWordSize));
760 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
761 __ stp(R2, R3, Address(SP, 2 * sizeof(uint32_t), Address::PairOffset),
763 __ ldp(R0, R1, Address(SP, 2 * sizeof(uint32_t), Address::PairOffset),
765 __ add(SP, SP, Operand(4 * target::kWordSize));
766 __ sub(R0, R0, Operand(R1));
767 __ RestoreCSP();
768 __ ret();
769}
770
771ASSEMBLER_TEST_RUN(LoadStorePairUnsigned32, test) {
772 typedef int64_t (*Int64Return)() DART_UNUSED;
773 EXPECT_EQ(-278523631, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
774 EXPECT_DISASSEMBLY(
775 "mov sp, csp\n"
776 "sub csp, csp, #0x1000\n"
777 "movz r2, #0x9988\n"
778 "movk r2, #0xeeff lsl 16\n"
779 "movk r2, #0xccdd lsl 32\n"
780 "movk r2, #0xaabb lsl 48\n"
781 "movz r3, #0x8877\n"
782 "movk r3, #0xff99 lsl 16\n"
783 "movk r3, #0xddee lsl 32\n"
784 "movk r3, #0xbbcc lsl 48\n"
785 "sub sp, sp, #0x20\n"
786 "and csp, sp, 0xfffffffffffffff0\n"
787 "stpw r2, r3, [sp, #8]\n"
788 "ldpw r0, r1, [sp, #8]\n"
789 "add sp, sp, #0x20\n"
790 "sub r0, r0, r1\n"
791 "mov csp, sp\n"
792 "ret\n");
793}
794
795ASSEMBLER_TEST_GENERATE(LoadStorePairSigned32, assembler) {
796 __ SetupDartSP();
797 __ LoadImmediate(R2, 0xAABBCCDDEEFF9988);
798 __ LoadImmediate(R3, 0xBBCCDDEEFF998877);
799 __ sub(SP, SP, Operand(4 * target::kWordSize));
800 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
801 __ stp(R2, R3, Address(SP, 2 * sizeof(int32_t), Address::PairOffset),
802 kFourBytes);
803 __ ldp(R0, R1, Address(SP, 2 * sizeof(int32_t), Address::PairOffset),
804 kFourBytes);
805 __ add(SP, SP, Operand(4 * target::kWordSize));
806 __ sub(R0, R0, Operand(R1));
807 __ RestoreCSP();
808 __ ret();
809}
810
811ASSEMBLER_TEST_RUN(LoadStorePairSigned32, test) {
812 typedef int64_t (*Int64Return)() DART_UNUSED;
813 EXPECT_EQ(-278523631, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
814 EXPECT_DISASSEMBLY(
815 "mov sp, csp\n"
816 "sub csp, csp, #0x1000\n"
817 "movz r2, #0x9988\n"
818 "movk r2, #0xeeff lsl 16\n"
819 "movk r2, #0xccdd lsl 32\n"
820 "movk r2, #0xaabb lsl 48\n"
821 "movz r3, #0x8877\n"
822 "movk r3, #0xff99 lsl 16\n"
823 "movk r3, #0xddee lsl 32\n"
824 "movk r3, #0xbbcc lsl 48\n"
825 "sub sp, sp, #0x20\n"
826 "and csp, sp, 0xfffffffffffffff0\n"
827 "stpw r2, r3, [sp, #8]\n"
828 "ldpsw r0, r1, [sp, #8]\n"
829 "add sp, sp, #0x20\n"
830 "sub r0, r0, r1\n"
831 "mov csp, sp\n"
832 "ret\n");
833}
834
835ASSEMBLER_TEST_GENERATE(PushRegisterPair, assembler) {
836 __ SetupDartSP();
837 __ LoadImmediate(R2, 12);
838 __ LoadImmediate(R3, 21);
839 __ PushRegisterPair(R2, R3);
840 __ Pop(R0);
841 __ Pop(R1);
842 __ RestoreCSP();
843 __ ret();
844}
845
846ASSEMBLER_TEST_RUN(PushRegisterPair, test) {
847 EXPECT(test != nullptr);
848 typedef int (*PushRegisterPair)() DART_UNUSED;
849 EXPECT_EQ(12, EXECUTE_TEST_CODE_INT64(PushRegisterPair, test->entry()));
850 EXPECT_DISASSEMBLY(
851 "mov sp, csp\n"
852 "sub csp, csp, #0x1000\n"
853 "movz r2, #0xc\n"
854 "movz r3, #0x15\n"
855 "stp r2, r3, [sp, #-16]!\n"
856 "ldr r0, [sp], #8 !\n"
857 "ldr r1, [sp], #8 !\n"
858 "mov csp, sp\n"
859 "ret\n");
860}
861
862ASSEMBLER_TEST_GENERATE(PushRegisterPairReversed, assembler) {
863 __ SetupDartSP();
864 __ LoadImmediate(R3, 12);
865 __ LoadImmediate(R2, 21);
866 __ PushRegisterPair(R3, R2);
867 __ Pop(R0);
868 __ Pop(R1);
869 __ RestoreCSP();
870 __ ret();
871}
872
873ASSEMBLER_TEST_RUN(PushRegisterPairReversed, test) {
874 EXPECT(test != nullptr);
875 typedef int (*PushRegisterPairReversed)() DART_UNUSED;
876 EXPECT_EQ(12,
877 EXECUTE_TEST_CODE_INT64(PushRegisterPairReversed, test->entry()));
878 EXPECT_DISASSEMBLY(
879 "mov sp, csp\n"
880 "sub csp, csp, #0x1000\n"
881 "movz r3, #0xc\n"
882 "movz r2, #0x15\n"
883 "stp r3, r2, [sp, #-16]!\n"
884 "ldr r0, [sp], #8 !\n"
885 "ldr r1, [sp], #8 !\n"
886 "mov csp, sp\n"
887 "ret\n");
888}
889
890ASSEMBLER_TEST_GENERATE(PopRegisterPair, assembler) {
891 __ SetupDartSP();
892 __ LoadImmediate(R2, 12);
893 __ LoadImmediate(R3, 21);
894 __ Push(R3);
895 __ Push(R2);
896 __ PopRegisterPair(R0, R1);
897 __ RestoreCSP();
898 __ ret();
899}
900
901ASSEMBLER_TEST_RUN(PopRegisterPair, test) {
902 EXPECT(test != nullptr);
903 typedef int (*PopRegisterPair)() DART_UNUSED;
904 EXPECT_EQ(12, EXECUTE_TEST_CODE_INT64(PopRegisterPair, test->entry()));
905 EXPECT_DISASSEMBLY(
906 "mov sp, csp\n"
907 "sub csp, csp, #0x1000\n"
908 "movz r2, #0xc\n"
909 "movz r3, #0x15\n"
910 "str r3, [sp, #-8]!\n"
911 "str r2, [sp, #-8]!\n"
912 "ldp r0, r1, [sp], #16 !\n"
913 "mov csp, sp\n"
914 "ret\n");
915}
916
917ASSEMBLER_TEST_GENERATE(PopRegisterPairReversed, assembler) {
918 __ SetupDartSP();
919 __ LoadImmediate(R3, 12);
920 __ LoadImmediate(R2, 21);
921 __ Push(R3);
922 __ Push(R2);
923 __ PopRegisterPair(R1, R0);
924 __ RestoreCSP();
925 __ ret();
926}
927
928ASSEMBLER_TEST_RUN(PopRegisterPairReversed, test) {
929 EXPECT(test != nullptr);
930 typedef int (*PopRegisterPairReversed)() DART_UNUSED;
931 EXPECT_EQ(12,
932 EXECUTE_TEST_CODE_INT64(PopRegisterPairReversed, test->entry()));
933 EXPECT_DISASSEMBLY(
934 "mov sp, csp\n"
935 "sub csp, csp, #0x1000\n"
936 "movz r3, #0xc\n"
937 "movz r2, #0x15\n"
938 "str r3, [sp, #-8]!\n"
939 "str r2, [sp, #-8]!\n"
940 "ldp r1, r0, [sp], #16 !\n"
941 "mov csp, sp\n"
942 "ret\n");
943}
944
945ASSEMBLER_TEST_GENERATE(LoadStoreDoublePair, assembler) {
946 __ SetupDartSP();
947 __ LoadDImmediate(V1, 3.0);
948 __ LoadDImmediate(V2, 4.0);
949 __ PushDoublePair(V1, V2);
950 __ LoadDImmediate(V1, 0.0);
951 __ LoadDImmediate(V2, 0.0);
952 __ PopDoublePair(V1, V2);
953 __ fsubd(V0, V2, V1);
954 __ RestoreCSP();
955 __ ret();
956}
957
958ASSEMBLER_TEST_RUN(LoadStoreDoublePair, test) {
959 typedef double (*DoubleReturn)() DART_UNUSED;
960 EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
961 EXPECT_DISASSEMBLY(
962 "mov sp, csp\n"
963 "sub csp, csp, #0x1000\n"
964 "fmovd v1, 3.000000\n"
965 "fmovd v2, 4.000000\n"
966 "fstpd v1, v2, [sp, #-16]!\n"
967 "veor v1, v1, v1\n"
968 "veor v2, v2, v2\n"
969 "fldpd v1, v2, [sp], #16 !\n"
970 "fsubd v0, v2, v1\n"
971 "mov csp, sp\n"
972 "ret\n");
973}
974
975ASSEMBLER_TEST_GENERATE(LoadStoreQuadPair, assembler) {
976 __ SetupDartSP();
977 __ LoadDImmediate(V1, 3.0);
978 __ LoadDImmediate(V2, 4.0);
979 __ PushQuadPair(V1, V2);
980 __ LoadDImmediate(V1, 0.0);
981 __ LoadDImmediate(V2, 0.0);
982 __ PopQuadPair(V1, V2);
983 __ fsubd(V0, V2, V1);
984 __ RestoreCSP();
985 __ ret();
986}
987
988ASSEMBLER_TEST_RUN(LoadStoreQuadPair, test) {
989 typedef double (*DoubleReturn)() DART_UNUSED;
990 EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
991 EXPECT_DISASSEMBLY(
992 "mov sp, csp\n"
993 "sub csp, csp, #0x1000\n"
994 "fmovd v1, 3.000000\n"
995 "fmovd v2, 4.000000\n"
996 "fstpq v1, v2, [sp, #-32]!\n"
997 "veor v1, v1, v1\n"
998 "veor v2, v2, v2\n"
999 "fldpq v1, v2, [sp], #32 !\n"
1000 "fsubd v0, v2, v1\n"
1001 "mov csp, sp\n"
1002 "ret\n");
1003}
1004
1005ASSEMBLER_TEST_GENERATE(Semaphore, assembler) {
1006 __ SetupDartSP();
1007 __ movz(R0, Immediate(40), 0);
1008 __ movz(R1, Immediate(42), 0);
1009 __ Push(R0);
1010 Label retry;
1011 __ Bind(&retry);
1012 __ ldxr(R0, SP);
1013 __ stxr(TMP, R1, SP); // IP == 0, success
1014 __ cmp(TMP, Operand(0));
1015 __ b(&retry, NE); // NE if context switch occurred between ldrex and strex.
1016 __ Pop(R0); // 42
1017 __ RestoreCSP();
1018 __ ret();
1019}
1020
1021ASSEMBLER_TEST_RUN(Semaphore, test) {
1022 EXPECT(test != nullptr);
1023 typedef intptr_t (*Semaphore)() DART_UNUSED;
1024 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Semaphore, test->entry()));
1025 EXPECT_DISASSEMBLY(
1026 "mov sp, csp\n"
1027 "sub csp, csp, #0x1000\n"
1028 "movz r0, #0x28\n"
1029 "movz r1, #0x2a\n"
1030 "str r0, [sp, #-8]!\n"
1031 "ldxr r0, sp\n"
1032 "stxr tmp, r1, sp\n"
1033 "cmp tmp, #0x0\n"
1034 "bne -12\n"
1035 "ldr r0, [sp], #8 !\n"
1036 "mov csp, sp\n"
1037 "ret\n");
1038}
1039
1040ASSEMBLER_TEST_GENERATE(FailedSemaphore, assembler) {
1041 __ SetupDartSP();
1042 __ movz(R0, Immediate(40), 0);
1043 __ movz(R1, Immediate(42), 0);
1044 __ Push(R0);
1045 __ ldxr(R0, SP);
1046 __ clrex(); // Simulate a context switch.
1047 __ stxr(TMP, R1, SP); // IP == 1, failure
1048 __ Pop(R0); // 40
1049 __ add(R0, R0, Operand(TMP));
1050 __ RestoreCSP();
1051 __ ret();
1052}
1053
1054ASSEMBLER_TEST_RUN(FailedSemaphore, test) {
1055 EXPECT(test != nullptr);
1056 typedef intptr_t (*FailedSemaphore)() DART_UNUSED;
1057 EXPECT_EQ(41, EXECUTE_TEST_CODE_INT64(FailedSemaphore, test->entry()));
1058 EXPECT_DISASSEMBLY(
1059 "mov sp, csp\n"
1060 "sub csp, csp, #0x1000\n"
1061 "movz r0, #0x28\n"
1062 "movz r1, #0x2a\n"
1063 "str r0, [sp, #-8]!\n"
1064 "ldxr r0, sp\n"
1065 "clrex\n"
1066 "stxr tmp, r1, sp\n"
1067 "ldr r0, [sp], #8 !\n"
1068 "add r0, r0, tmp\n"
1069 "mov csp, sp\n"
1070 "ret\n");
1071}
1072
1073ASSEMBLER_TEST_GENERATE(Semaphore32, assembler) {
1074 __ SetupDartSP();
1075 __ movz(R0, Immediate(40), 0);
1076 __ add(R0, R0, Operand(R0, LSL, 32));
1077 __ Push(R0);
1078
1079 __ movz(R0, Immediate(40), 0);
1080 __ movz(R1, Immediate(42), 0);
1081
1082 Label retry;
1083 __ Bind(&retry);
1084 __ ldxr(R0, SP, kFourBytes);
1085 // 32 bit operation should ignore the high word of R0 that was pushed on the
1086 // stack.
1087 __ stxr(TMP, R1, SP, kFourBytes); // IP == 0, success
1088 __ cmp(TMP, Operand(0));
1089 __ b(&retry, NE); // NE if context switch occurred between ldrex and strex.
1090 __ Pop(R0); // 42 + 42 * 2**32
1091 __ RestoreCSP();
1092 __ ret();
1093}
1094
1095ASSEMBLER_TEST_RUN(Semaphore32, test) {
1096 EXPECT(test != nullptr);
1097 typedef intptr_t (*Semaphore32)() DART_UNUSED;
1098 // Lower word has been atomically switched from 40 to 42k, whereas upper word
1099 // is unchanged at 40.
1100 EXPECT_EQ(42 + (DART_INT64_C(40) << 32),
1101 EXECUTE_TEST_CODE_INT64(Semaphore32, test->entry()));
1102 EXPECT_DISASSEMBLY(
1103 "mov sp, csp\n"
1104 "sub csp, csp, #0x1000\n"
1105 "movz r0, #0x28\n"
1106 "add r0, r0, r0 lsl #32\n"
1107 "str r0, [sp, #-8]!\n"
1108 "movz r0, #0x28\n"
1109 "movz r1, #0x2a\n"
1110 "ldxrw r0, sp\n"
1111 "stxrw tmp, r1, sp\n"
1112 "cmp tmp, #0x0\n"
1113 "bne -12\n"
1114 "ldr r0, [sp], #8 !\n"
1115 "mov csp, sp\n"
1116 "ret\n");
1117}
1118
1119ASSEMBLER_TEST_GENERATE(FailedSemaphore32, assembler) {
1120 __ SetupDartSP();
1121 __ movz(R0, Immediate(40), 0);
1122 __ add(R0, R0, Operand(R0, LSL, 32));
1123 __ Push(R0);
1124
1125 __ movz(R0, Immediate(40), 0);
1126 __ movz(R1, Immediate(42), 0);
1127
1128 __ ldxr(R0, SP, kFourBytes);
1129 __ clrex(); // Simulate a context switch.
1130 __ stxr(TMP, R1, SP, kFourBytes); // IP == 1, failure
1131 __ Pop(R0); // 40
1132 __ add(R0, R0, Operand(TMP));
1133 __ RestoreCSP();
1134 __ ret();
1135}
1136
1137ASSEMBLER_TEST_RUN(FailedSemaphore32, test) {
1138 EXPECT(test != nullptr);
1139 typedef intptr_t (*FailedSemaphore32)() DART_UNUSED;
1140 // Lower word has had the failure code (1) added to it. Upper word is
1141 // unchanged at 40.
1142 EXPECT_EQ(41 + (DART_INT64_C(40) << 32),
1143 EXECUTE_TEST_CODE_INT64(FailedSemaphore32, test->entry()));
1144 EXPECT_DISASSEMBLY(
1145 "mov sp, csp\n"
1146 "sub csp, csp, #0x1000\n"
1147 "movz r0, #0x28\n"
1148 "add r0, r0, r0 lsl #32\n"
1149 "str r0, [sp, #-8]!\n"
1150 "movz r0, #0x28\n"
1151 "movz r1, #0x2a\n"
1152 "ldxrw r0, sp\n"
1153 "clrex\n"
1154 "stxrw tmp, r1, sp\n"
1155 "ldr r0, [sp], #8 !\n"
1156 "add r0, r0, tmp\n"
1157 "mov csp, sp\n"
1158 "ret\n");
1159}
1160
1161ASSEMBLER_TEST_GENERATE(LoadStoreExclusiveR31, assembler) {
1162 __ AddImmediate(CSP, CSP, -16);
1163 __ ldxr(ZR, CSP, kEightBytes);
1164 __ stxr(ZR, ZR, CSP, kEightBytes);
1165 __ AddImmediate(CSP, CSP, 16);
1166 __ LoadImmediate(R0, 42);
1167 __ ret();
1168}
1169
1170ASSEMBLER_TEST_RUN(LoadStoreExclusiveR31, test) {
1171 EXPECT(test != nullptr);
1172 typedef intptr_t (*LoadStoreExclusiveR31)() DART_UNUSED;
1173 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(LoadStoreExclusiveR31, test->entry()));
1174 EXPECT_DISASSEMBLY(
1175 "sub csp, csp, #0x10\n"
1176 "ldxr zr, csp\n"
1177 "stxr zr, zr, csp\n"
1178 "add csp, csp, #0x10\n"
1179 "movz r0, #0x2a\n"
1180 "ret\n");
1181}
1182
1183ASSEMBLER_TEST_GENERATE(AtomicLoadClear, assembler) {
1184 __ mov(R1, R0);
1185 __ LoadImmediate(R2, 2);
1186 __ ldclr(/*value in*/ R2, /*value out*/ R0, /*address*/ R1);
1187 __ ret();
1188}
1189
1190ASSEMBLER_TEST_RUN(AtomicLoadClear, test) {
1191 typedef intptr_t (*AtomicLoadClear)(intptr_t) DART_UNUSED;
1192 intptr_t x = 42;
1193 EXPECT_EQ(42,
1194 EXECUTE_TEST_CODE_INTPTR_INTPTR(AtomicLoadClear, test->entry(),
1195 reinterpret_cast<intptr_t>(&x)));
1196 EXPECT_EQ(40, x);
1197
1198 EXPECT_DISASSEMBLY(
1199 "mov r1, r0\n"
1200 "movz r2, #0x2\n"
1201 "ldclr r2, r0, [r1]\n"
1202 "ret\n");
1203}
1204
1205ASSEMBLER_TEST_GENERATE(AtomicLoadSet, assembler) {
1206 __ mov(R1, R0);
1207 __ LoadImmediate(R2, 1);
1208 __ ldset(/*value in*/ R2, /*value out*/ R0, /*address*/ R1);
1209 __ ret();
1210}
1211
1212ASSEMBLER_TEST_RUN(AtomicLoadSet, test) {
1213 typedef intptr_t (*AtomicLoadSet)(intptr_t) DART_UNUSED;
1214 int64_t x = 42;
1215 EXPECT_EQ(42,
1216 EXECUTE_TEST_CODE_INTPTR_INTPTR(AtomicLoadSet, test->entry(),
1217 reinterpret_cast<intptr_t>(&x)));
1218 EXPECT_EQ(43, x);
1219
1220 EXPECT_DISASSEMBLY(
1221 "mov r1, r0\n"
1222 "movz r2, #0x1\n"
1223 "ldset r2, r0, [r1]\n"
1224 "ret\n");
1225}
1226
1227ASSEMBLER_TEST_GENERATE(LoadAcquireStoreRelease, assembler) {
1228 // We cannot really test that ldar/stlr have the barrier behavior, but at
1229 // least we can test that the load/store behavior is correct.
1230 Label failed, done;
1231
1232 __ SetupDartSP();
1233 __ EnterFrame(0);
1234
1235 // Test 64-bit ladr.
1236 __ PushImmediate(0x1122334455667788);
1237 __ ldar(R1, SP, kEightBytes);
1238 __ CompareImmediate(R1, 0x1122334455667788);
1239 __ BranchIf(NOT_EQUAL, &failed);
1240 __ Drop(1);
1241
1242 // Test 32-bit ladr - must zero extend.
1243 __ PushImmediate(0x1122334455667788);
1244 __ ldar(R1, SP, kFourBytes);
1245 __ CompareImmediate(R1, 0x55667788);
1246 __ BranchIf(NOT_EQUAL, &failed);
1247 __ Drop(1);
1248
1249 // Test 64-bit stlr.
1250 __ PushImmediate(0);
1251 __ LoadImmediate(R1, 0x1122334455667788);
1252 __ stlr(R1, SP, kEightBytes);
1253 __ Pop(R1);
1254 __ CompareImmediate(R1, 0x1122334455667788);
1255 __ BranchIf(NOT_EQUAL, &failed);
1256
1257 // Test 32-bit stlr.
1258 __ PushImmediate(0);
1259 __ LoadImmediate(R1, 0x1122334455667788);
1260 __ stlr(R1, SP, kFourBytes);
1261 __ Pop(R1);
1262 __ CompareImmediate(R1, 0x55667788);
1263 __ BranchIf(NOT_EQUAL, &failed);
1264
1265 __ LoadImmediate(R0, 0x42);
1266 __ b(&done);
1267
1268 __ Bind(&failed);
1269 __ LoadImmediate(R0, 0x84);
1270
1271 __ Bind(&done);
1272 __ LeaveFrame();
1273 __ RestoreCSP();
1274 __ ret();
1275}
1276
1277ASSEMBLER_TEST_RUN(LoadAcquireStoreRelease, test) {
1278 typedef intptr_t (*LoadAcquireStoreRelease)() DART_UNUSED;
1279 EXPECT_EQ(0x42,
1280 EXECUTE_TEST_CODE_INT64(LoadAcquireStoreRelease, test->entry()));
1281 EXPECT_DISASSEMBLY(
1282 "mov sp, csp\n"
1283 "sub csp, csp, #0x1000\n"
1284 "stp fp, lr, [sp, #-16]!\n"
1285 "mov fp, sp\n"
1286 "movz tmp, #0x7788\n"
1287 "movk tmp, #0x5566 lsl 16\n"
1288 "movk tmp, #0x3344 lsl 32\n"
1289 "movk tmp, #0x1122 lsl 48\n"
1290 "str tmp, [sp, #-8]!\n"
1291 "ldar r1, sp\n"
1292 "movz tmp2, #0x7788\n"
1293 "movk tmp2, #0x5566 lsl 16\n"
1294 "movk tmp2, #0x3344 lsl 32\n"
1295 "movk tmp2, #0x1122 lsl 48\n"
1296 "cmp r1, tmp2\n"
1297 "bne +164\n"
1298 "add sp, sp, #0x8\n"
1299 "movz tmp, #0x7788\n"
1300 "movk tmp, #0x5566 lsl 16\n"
1301 "movk tmp, #0x3344 lsl 32\n"
1302 "movk tmp, #0x1122 lsl 48\n"
1303 "str tmp, [sp, #-8]!\n"
1304 "ldarw r1, sp\n"
1305 "movz tmp2, #0x7788\n"
1306 "movk tmp2, #0x5566 lsl 16\n"
1307 "cmp r1, tmp2\n"
1308 "bne +120\n"
1309 "add sp, sp, #0x8\n"
1310 "movz tmp, #0x0\n"
1311 "str tmp, [sp, #-8]!\n"
1312 "movz r1, #0x7788\n"
1313 "movk r1, #0x5566 lsl 16\n"
1314 "movk r1, #0x3344 lsl 32\n"
1315 "movk r1, #0x1122 lsl 48\n"
1316 "stlr r1, sp\n"
1317 "ldr r1, [sp], #8 !\n"
1318 "movz tmp2, #0x7788\n"
1319 "movk tmp2, #0x5566 lsl 16\n"
1320 "movk tmp2, #0x3344 lsl 32\n"
1321 "movk tmp2, #0x1122 lsl 48\n"
1322 "cmp r1, tmp2\n"
1323 "bne +60\n"
1324 "movz tmp, #0x0\n"
1325 "str tmp, [sp, #-8]!\n"
1326 "movz r1, #0x7788\n"
1327 "movk r1, #0x5566 lsl 16\n"
1328 "movk r1, #0x3344 lsl 32\n"
1329 "movk r1, #0x1122 lsl 48\n"
1330 "stlrw r1, sp\n"
1331 "ldr r1, [sp], #8 !\n"
1332 "movz tmp2, #0x7788\n"
1333 "movk tmp2, #0x5566 lsl 16\n"
1334 "cmp r1, tmp2\n"
1335 "bne +12\n"
1336 "movz r0, #0x42\n"
1337 "b +8\n"
1338 "movz r0, #0x84\n"
1339 "mov sp, fp\n"
1340 "ldp fp, lr, [sp], #16 !\n"
1341 "mov csp, sp\n"
1342 "ret\n");
1343}
1344
1345// Logical register operations.
1346ASSEMBLER_TEST_GENERATE(AndRegs, assembler) {
1347 __ movz(R1, Immediate(43), 0);
1348 __ movz(R2, Immediate(42), 0);
1349 __ and_(R0, R1, Operand(R2));
1350 __ ret();
1351}
1352
1353ASSEMBLER_TEST_RUN(AndRegs, test) {
1354 typedef int64_t (*Int64Return)() DART_UNUSED;
1355 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1356 EXPECT_DISASSEMBLY(
1357 "movz r1, #0x2b\n"
1358 "movz r2, #0x2a\n"
1359 "and r0, r1, r2\n"
1360 "ret\n");
1361}
1362
1363constexpr uint64_t kU64MinusOne = 0xffffffffffffffffull;
1364constexpr uint64_t kU64MinInt32 = 0xffffffff80000000ull;
1365constexpr uint64_t kU64MaxInt32 = 0x000000007fffffffull;
1366constexpr uint64_t kU64MinInt64 = 0x8000000000000000ull;
1367constexpr uint64_t kU64MaxInt64 = 0x7fffffffffffffffull;
1368
1369#define FOR_EACH_ASR_64_TEST_CONFIG(M) \
1370 M(0ull, 0, 0ull) \
1371 M(1ull, 0, 1ull) \
1372 M(kU64MaxInt32, 0, kU64MaxInt32) \
1373 M(kU64MaxInt64, 0, kU64MaxInt64) \
1374 M(kU64MinInt32, 0, kU64MinInt32) \
1375 M(kU64MinInt64, 0, kU64MinInt64) \
1376 M(0ull, 1, 0ull) \
1377 M(1ull, 1, 0ull) \
1378 M(4ull, 1, 2ull) \
1379 M(0xffffull, 1, 0x7fffull) \
1380 M(0xffffffffull, 1, 0x7fffffffull) \
1381 M(kU64MaxInt32, 1, 0x3fffffffull) \
1382 M(kU64MaxInt64, 1, 0x3fffffffffffffffull) \
1383 M(kU64MinInt32, 1, 0xffffffffc0000000ull) \
1384 M(kU64MinInt64, 1, 0xc000000000000000ull) \
1385 M(kU64MinusOne, 1, kU64MinusOne) \
1386 M(1ull, 2, 0ull) \
1387 M(4ull, 2, 1ull) \
1388 M(0xffffull, 2, 0x3fffull) \
1389 M(0xffffffffull, 2, 0x3fffffffull) \
1390 M(kU64MaxInt32, 2, 0x1fffffffull) \
1391 M(kU64MaxInt64, 2, 0x1fffffffffffffffull) \
1392 M(kU64MinInt32, 2, 0xffffffffe0000000ull) \
1393 M(kU64MinInt64, 2, 0xe000000000000000ull) \
1394 M(kU64MinusOne, 2, kU64MinusOne) \
1395 M(0ull, 31, 0ull) \
1396 M(1ull, 31, 0ull) \
1397 M(4ull, 31, 0ull) \
1398 M(0xffffull, 31, 0ull) \
1399 M(0xffffffffull, 31, 1ull) \
1400 M(kU64MaxInt32, 31, 0ull) \
1401 M(kU64MaxInt64, 31, 0xffffffffull) \
1402 M(kU64MinInt32, 31, kU64MinusOne) \
1403 M(kU64MinInt64, 31, 0xffffffff00000000ull) \
1404 M(kU64MinusOne, 31, kU64MinusOne) \
1405 M(0ull, 32, 0ull) \
1406 M(1ull, 32, 0ull) \
1407 M(4ull, 32, 0ull) \
1408 M(0xffffull, 32, 0ull) \
1409 M(0xffffffffull, 32, 0ull) \
1410 M(kU64MaxInt64, 32, 0x7fffffffull) \
1411 M(kU64MinInt32, 32, kU64MinusOne) \
1412 M(kU64MinInt64, 32, 0xffffffff80000000ull) \
1413 M(kU64MinusOne, 32, kU64MinusOne) \
1414 M(0ull, 62, 0ull) \
1415 M(1ull, 62, 0ull) \
1416 M(4ull, 62, 0ull) \
1417 M(0xffffull, 62, 0ull) \
1418 M(0xffffffffull, 62, 0ull) \
1419 M(kU64MaxInt64, 62, 1ull) \
1420 M(kU64MinInt32, 62, kU64MinusOne) \
1421 M(kU64MinInt64, 62, 0xfffffffffffffffeull) \
1422 M(kU64MinusOne, 62, kU64MinusOne) \
1423 M(0ull, 63, 0ull) \
1424 M(1ull, 63, 0ull) \
1425 M(4ull, 63, 0ull) \
1426 M(0xffffull, 63, 0ull) \
1427 M(0xffffffffull, 63, 0ull) \
1428 M(kU64MaxInt64, 63, 0ull) \
1429 M(kU64MinInt32, 63, kU64MinusOne) \
1430 M(kU64MinInt64, 63, kU64MinusOne) \
1431 M(kU64MinusOne, 63, kU64MinusOne)
1432
1433#define FOR_EACH_LSR_64_TEST_CONFIG(M) \
1434 M(0ull, 0, 0ull) \
1435 M(1ull, 0, 1ull) \
1436 M(kU64MaxInt32, 0, kU64MaxInt32) \
1437 M(kU64MaxInt64, 0, kU64MaxInt64) \
1438 M(kU64MinInt32, 0, kU64MinInt32) \
1439 M(kU64MinInt64, 0, kU64MinInt64) \
1440 M(0ull, 1, 0ull) \
1441 M(1ull, 1, 0ull) \
1442 M(4ull, 1, 2ull) \
1443 M(0xffffull, 1, 0x7fffull) \
1444 M(0xffffffffull, 1, 0x7fffffffull) \
1445 M(kU64MaxInt32, 1, 0x3fffffffull) \
1446 M(kU64MaxInt64, 1, 0x3fffffffffffffffull) \
1447 M(kU64MinInt32, 1, 0x7fffffffc0000000ull) \
1448 M(kU64MinInt64, 1, 0x4000000000000000ull) \
1449 M(kU64MinusOne, 1, 0x7fffffffffffffffull) \
1450 M(1ull, 2, 0ull) \
1451 M(4ull, 2, 1ull) \
1452 M(0xffffull, 2, 0x3fffull) \
1453 M(0xffffffffull, 2, 0x3fffffffull) \
1454 M(kU64MaxInt32, 2, 0x1fffffffull) \
1455 M(kU64MaxInt64, 2, 0x1fffffffffffffffull) \
1456 M(kU64MinInt32, 2, 0x3fffffffe0000000ull) \
1457 M(kU64MinInt64, 2, 0x2000000000000000ull) \
1458 M(kU64MinusOne, 2, 0x3fffffffffffffffull) \
1459 M(0ull, 31, 0ull) \
1460 M(1ull, 31, 0ull) \
1461 M(4ull, 31, 0ull) \
1462 M(0xffffull, 31, 0ull) \
1463 M(0xffffffffull, 31, 1ull) \
1464 M(kU64MaxInt32, 31, 0ull) \
1465 M(kU64MaxInt64, 31, 0xffffffffull) \
1466 M(kU64MinInt32, 31, 0x1ffffffffull) \
1467 M(kU64MinInt64, 31, 0x100000000ull) \
1468 M(kU64MinusOne, 31, 0x1ffffffffull) \
1469 M(0ull, 32, 0ull) \
1470 M(1ull, 32, 0ull) \
1471 M(4ull, 32, 0ull) \
1472 M(0xffffull, 32, 0ull) \
1473 M(0xffffffffull, 32, 0ull) \
1474 M(kU64MaxInt64, 32, 0x7fffffffull) \
1475 M(kU64MinInt32, 32, 0xffffffffull) \
1476 M(kU64MinInt64, 32, 0x80000000ull) \
1477 M(kU64MinusOne, 32, 0xffffffffull) \
1478 M(0ull, 62, 0ull) \
1479 M(1ull, 62, 0ull) \
1480 M(4ull, 62, 0ull) \
1481 M(0xffffull, 62, 0ull) \
1482 M(0xffffffffull, 62, 0ull) \
1483 M(kU64MaxInt64, 62, 1ull) \
1484 M(kU64MinInt32, 62, 3ull) \
1485 M(kU64MinInt64, 62, 2ull) \
1486 M(kU64MinusOne, 62, 3ull) \
1487 M(0ull, 63, 0ull) \
1488 M(1ull, 63, 0ull) \
1489 M(4ull, 63, 0ull) \
1490 M(0xffffull, 63, 0ull) \
1491 M(0xffffffffull, 63, 0ull) \
1492 M(kU64MaxInt64, 63, 0ull) \
1493 M(kU64MinInt32, 63, 1ull) \
1494 M(kU64MinInt64, 63, 1ull) \
1495 M(kU64MinusOne, 63, 1ull)
1496
1497#define FOR_EACH_LSL_64_TEST_CONFIG(M) \
1498 M(0ull, 0, 0ull) \
1499 M(1ull, 0, 1ull) \
1500 M(kU64MaxInt32, 0, kU64MaxInt32) \
1501 M(kU64MaxInt64, 0, kU64MaxInt64) \
1502 M(kU64MinInt32, 0, kU64MinInt32) \
1503 M(kU64MinInt64, 0, kU64MinInt64) \
1504 M(0ull, 1, 0ull) \
1505 M(1ull, 1, 2ull) \
1506 M(4ull, 1, 8ull) \
1507 M(0xffffull, 1, 0x1fffeull) \
1508 M(0xffffffffull, 1, 0x1fffffffeull) \
1509 M(kU64MaxInt32, 1, 0xfffffffeull) \
1510 M(kU64MaxInt64, 1, 0xfffffffffffffffeull) \
1511 M(kU64MinInt32, 1, 0xffffffff00000000ull) \
1512 M(kU64MinInt64, 1, 0ull) \
1513 M(kU64MinusOne, 1, 0xfffffffffffffffeull) \
1514 M(1ull, 2, 4ull) \
1515 M(4ull, 2, 16ull) \
1516 M(0xffffull, 2, 0x3fffcull) \
1517 M(0xffffffffull, 2, 0x3fffffffcull) \
1518 M(kU64MaxInt32, 2, 0x1fffffffcull) \
1519 M(kU64MaxInt64, 2, 0xfffffffffffffffcull) \
1520 M(kU64MinInt32, 2, 0xfffffffe00000000ull) \
1521 M(kU64MinInt64, 2, 0ull) \
1522 M(kU64MinusOne, 2, 0xfffffffffffffffcull) \
1523 M(0ull, 31, 0ull) \
1524 M(1ull, 31, 0x0000000080000000ull) \
1525 M(4ull, 31, 0x0000000200000000ull) \
1526 M(0xffffull, 31, 0x00007fff80000000ull) \
1527 M(0xffffffffull, 31, 0x7fffffff80000000ull) \
1528 M(kU64MaxInt32, 31, 0x3fffffff80000000ull) \
1529 M(kU64MaxInt64, 31, 0xffffffff80000000ull) \
1530 M(kU64MinInt32, 31, 0xc000000000000000ull) \
1531 M(kU64MinInt64, 31, 0ull) \
1532 M(kU64MinusOne, 31, 0xffffffff80000000ull) \
1533 M(0ull, 32, 0ull) \
1534 M(1ull, 32, 0x0000000100000000ull) \
1535 M(4ull, 32, 0x0000000400000000ull) \
1536 M(0xffffull, 32, 0x0000ffff00000000ull) \
1537 M(0xffffffffull, 32, 0xffffffff00000000ull) \
1538 M(kU64MaxInt64, 32, 0xffffffff00000000ull) \
1539 M(kU64MinInt32, 32, 0x8000000000000000ull) \
1540 M(kU64MinInt64, 32, 0ull) \
1541 M(kU64MinusOne, 32, 0xffffffff00000000ull) \
1542 M(0ull, 62, 0ull) \
1543 M(1ull, 62, 0x4000000000000000ull) \
1544 M(4ull, 62, 0ull) \
1545 M(0xffffull, 62, 0xc000000000000000ull) \
1546 M(0xffffffffull, 62, 0xc000000000000000ull) \
1547 M(kU64MaxInt64, 62, 0xc000000000000000ull) \
1548 M(kU64MinInt32, 62, 0ull) \
1549 M(kU64MinInt64, 62, 0ull) \
1550 M(kU64MinusOne, 62, 0xc000000000000000ull) \
1551 M(0ull, 63, 0ull) \
1552 M(1ull, 63, 0x8000000000000000ull) \
1553 M(4ull, 63, 0ull) \
1554 M(0xffffull, 63, 0x8000000000000000ull) \
1555 M(0xffffffffull, 63, 0x8000000000000000ull) \
1556 M(kU64MaxInt64, 63, 0x8000000000000000ull) \
1557 M(kU64MinInt32, 63, 0ull) \
1558 M(kU64MinInt64, 63, 0ull) \
1559 M(kU64MinusOne, 63, 0x8000000000000000ull)
1560
1561#define SHIFT_64_IMMEDIATE_TEST(macro_op, val, shift, expected) \
1562 ASSEMBLER_TEST_GENERATE(macro_op##_##val##_##shift, assembler) { \
1563 __ LoadImmediate(R1, bit_cast<int64_t>(val)); \
1564 __ macro_op(R0, R1, (shift)); \
1565 __ ret(); \
1566 } \
1567 \
1568 ASSEMBLER_TEST_RUN(macro_op##_##val##_##shift, test) { \
1569 typedef int64_t (*Int64Return)() DART_UNUSED; \
1570 EXPECT_EQ((expected), bit_cast<uint64_t>(EXECUTE_TEST_CODE_INT64( \
1571 Int64Return, test->entry()))); \
1572 }
1573
1574#define ASR_64_IMMEDIATE_TEST(val, shift, expected) \
1575 SHIFT_64_IMMEDIATE_TEST(AsrImmediate, val, shift, expected)
1576
1577#define LSR_64_IMMEDIATE_TEST(val, shift, expected) \
1578 SHIFT_64_IMMEDIATE_TEST(LsrImmediate, val, shift, expected)
1579
1580#define LSL_64_IMMEDIATE_TEST(val, shift, expected) \
1581 SHIFT_64_IMMEDIATE_TEST(LslImmediate, val, shift, expected)
1582
1583FOR_EACH_ASR_64_TEST_CONFIG(ASR_64_IMMEDIATE_TEST)
1584FOR_EACH_LSR_64_TEST_CONFIG(LSR_64_IMMEDIATE_TEST)
1585FOR_EACH_LSL_64_TEST_CONFIG(LSL_64_IMMEDIATE_TEST)
1586
1587#undef LSL_64_IMMEDIATE_TEST
1588#undef LSR_64_IMMEDIATE_TEST
1589#undef ASR_64_IMMEDIATE_TEST
1590#undef SHIFT_64_IMMEDIATE_TEST
1591#undef FOR_EACH_LSL_64_TESTS_LIST
1592#undef FOR_EACH_LSR_64_TESTS_LIST
1593#undef FOR_EACH_ASR_64_TESTS_LIST
1594
1595constexpr uint32_t kU32MinusOne = 0xffffffffu;
1596constexpr uint32_t kU32MinInt32 = 0x80000000u;
1597constexpr uint32_t kU32MaxInt32 = 0x7fffffffu;
1598
1599#define FOR_EACH_ASR_32_TEST_CONFIG(M) \
1600 M(0u, 0, 0u) \
1601 M(1u, 0, 1u) \
1602 M(kU32MaxInt32, 0, kU32MaxInt32) \
1603 M(kU32MinInt32, 0, kU32MinInt32) \
1604 M(0u, 1, 0u) \
1605 M(1u, 1, 0u) \
1606 M(4u, 1, 2u) \
1607 M(0xffffu, 1, 0x7fffu) \
1608 M(0xffffffffu, 1, 0xffffffffu) \
1609 M(kU32MaxInt32, 1, 0x3fffffffu) \
1610 M(kU32MinInt32, 1, 0xc0000000u) \
1611 M(kU32MinusOne, 1, 0xffffffffu) \
1612 M(1u, 2, 0u) \
1613 M(4u, 2, 1u) \
1614 M(0xffffu, 2, 0x3fffu) \
1615 M(0xffffffffu, 2, 0xffffffffu) \
1616 M(kU32MaxInt32, 2, 0x1fffffffu) \
1617 M(kU32MinInt32, 2, 0xe0000000u) \
1618 M(kU32MinusOne, 2, kU32MinusOne) \
1619 M(0u, 31, 0u) \
1620 M(1u, 31, 0u) \
1621 M(4u, 31, 0u) \
1622 M(0xffffu, 31, 0u) \
1623 M(0xffffffffu, 31, 0xffffffffu) \
1624 M(kU32MaxInt32, 31, 0u) \
1625 M(kU32MinInt32, 31, kU32MinusOne) \
1626 M(kU32MinusOne, 31, kU32MinusOne)
1627
1628#define FOR_EACH_LSR_32_TEST_CONFIG(M) \
1629 M(0u, 0, 0u) \
1630 M(1u, 0, 1u) \
1631 M(kU32MaxInt32, 0, kU32MaxInt32) \
1632 M(kU32MinInt32, 0, kU32MinInt32) \
1633 M(0u, 1, 0u) \
1634 M(1u, 1, 0u) \
1635 M(4u, 1, 2u) \
1636 M(0xffffu, 1, 0x7fffu) \
1637 M(0xffffffffu, 1, 0x7fffffffu) \
1638 M(kU32MaxInt32, 1, 0x3fffffffu) \
1639 M(kU32MinInt32, 1, 0x40000000u) \
1640 M(kU32MinusOne, 1, 0x7fffffffu) \
1641 M(1u, 2, 0u) \
1642 M(4u, 2, 1u) \
1643 M(0xffffu, 2, 0x3fffu) \
1644 M(0xffffffffu, 2, 0x3fffffffu) \
1645 M(kU32MaxInt32, 2, 0x1fffffffu) \
1646 M(kU32MinInt32, 2, 0x20000000u) \
1647 M(kU32MinusOne, 2, 0x3fffffffu) \
1648 M(0u, 31, 0u) \
1649 M(1u, 31, 0u) \
1650 M(4u, 31, 0u) \
1651 M(0xffffu, 31, 0u) \
1652 M(0xffffffffu, 31, 1u) \
1653 M(kU32MaxInt32, 31, 0u) \
1654 M(kU32MinInt32, 31, 1u) \
1655 M(kU32MinusOne, 31, 1u)
1656
1657#define FOR_EACH_LSL_32_TEST_CONFIG(M) \
1658 M(0u, 0, 0u) \
1659 M(1u, 0, 1u) \
1660 M(kU32MaxInt32, 0, kU32MaxInt32) \
1661 M(kU32MinInt32, 0, kU32MinInt32) \
1662 M(0u, 1, 0u) \
1663 M(1u, 1, 2u) \
1664 M(4u, 1, 8u) \
1665 M(0xffffu, 1, 0x1fffeu) \
1666 M(0xffffffffu, 1, 0xfffffffeu) \
1667 M(kU32MaxInt32, 1, 0xfffffffeu) \
1668 M(kU32MinInt32, 1, 0x00000000u) \
1669 M(kU32MinusOne, 1, 0xfffffffeu) \
1670 M(1u, 2, 4u) \
1671 M(4u, 2, 16u) \
1672 M(0xffffu, 2, 0x3fffcu) \
1673 M(0xffffffffu, 2, 0xfffffffcu) \
1674 M(kU32MaxInt32, 2, 0xfffffffcu) \
1675 M(kU32MinInt32, 2, 0x00000000u) \
1676 M(kU32MinusOne, 2, 0xfffffffcu) \
1677 M(0u, 31, 0u) \
1678 M(1u, 31, 0x80000000u) \
1679 M(4u, 31, 0x00000000u) \
1680 M(0xffffu, 31, 0x80000000u) \
1681 M(0xffffffffu, 31, 0x80000000u) \
1682 M(kU32MaxInt32, 31, 0x80000000u) \
1683 M(kU32MinInt32, 31, 0x00000000u) \
1684 M(kU32MinusOne, 31, 0x80000000u)
1685
1686#define SHIFT_32_IMMEDIATE_TEST(macro_op, val, shift, expected) \
1687 ASSEMBLER_TEST_GENERATE(macro_op##a_##val##_##shift, assembler) { \
1688 __ LoadImmediate(R1, bit_cast<int32_t>(val)); \
1689 __ macro_op(R0, R1, (shift), kFourBytes); \
1690 __ ret(); \
1691 } \
1692 \
1693 ASSEMBLER_TEST_RUN(macro_op##a_##val##_##shift, test) { \
1694 typedef int32_t (*Int32Return)() DART_UNUSED; \
1695 EXPECT_EQ((expected), bit_cast<uint32_t>((int32_t)EXECUTE_TEST_CODE_INT64( \
1696 Int32Return, test->entry()))); \
1697 }
1698
1699#define ASR_32_IMMEDIATE_TEST(val, shift, expected) \
1700 SHIFT_32_IMMEDIATE_TEST(AsrImmediate, val, shift, expected)
1701
1702#define LSR_32_IMMEDIATE_TEST(val, shift, expected) \
1703 SHIFT_32_IMMEDIATE_TEST(LsrImmediate, val, shift, expected)
1704
1705#define LSL_32_IMMEDIATE_TEST(val, shift, expected) \
1706 SHIFT_32_IMMEDIATE_TEST(LslImmediate, val, shift, expected)
1707
1708FOR_EACH_ASR_32_TEST_CONFIG(ASR_32_IMMEDIATE_TEST)
1709FOR_EACH_LSR_32_TEST_CONFIG(LSR_32_IMMEDIATE_TEST)
1710FOR_EACH_LSL_32_TEST_CONFIG(LSL_32_IMMEDIATE_TEST)
1711
1712#undef LSL_32_IMMEDIATE_TEST
1713#undef LSR_32_IMMEDIATE_TEST
1714#undef ASR_32_IMMEDIATE_TEST
1715#undef SHIFT_32_IMMEDIATE_TEST
1716#undef FOR_EACH_LSL_32_TESTS_LIST
1717#undef FOR_EACH_LSR_32_TESTS_LIST
1718#undef FOR_EACH_ASR_32_TESTS_LIST
1719
1720ASSEMBLER_TEST_GENERATE(LslImmediate, assembler) {
1721 __ LslImmediate(R0, R0, 1);
1722 __ LslImmediate(R0, R0, 2);
1723 __ LslImmediate(R0, R0, 3);
1724 __ LslImmediate(R0, R0, 4);
1725 __ LslImmediate(R0, R0, 60);
1726 __ LslImmediate(R0, R0, 61);
1727 __ LslImmediate(R0, R0, 62);
1728 __ LslImmediate(R0, R0, 63);
1729 __ LslImmediate(R0, R0, 1, kFourBytes);
1730 __ LslImmediate(R0, R0, 2, kFourBytes);
1731 __ LslImmediate(R0, R0, 3, kFourBytes);
1732 __ LslImmediate(R0, R0, 4, kFourBytes);
1733 __ LslImmediate(R0, R0, 28, kFourBytes);
1734 __ LslImmediate(R0, R0, 29, kFourBytes);
1735 __ LslImmediate(R0, R0, 30, kFourBytes);
1736 __ LslImmediate(R0, R0, 31, kFourBytes);
1737}
1738
1739ASSEMBLER_TEST_RUN(LslImmediate, test) {
1740 EXPECT_DISASSEMBLY(
1741 "lsl r0, r0, #1\n"
1742 "lsl r0, r0, #2\n"
1743 "lsl r0, r0, #3\n"
1744 "lsl r0, r0, #4\n"
1745 "lsl r0, r0, #60\n"
1746 "lsl r0, r0, #61\n"
1747 "lsl r0, r0, #62\n"
1748 "lsl r0, r0, #63\n"
1749 "lslw r0, r0, #1\n"
1750 "lslw r0, r0, #2\n"
1751 "lslw r0, r0, #3\n"
1752 "lslw r0, r0, #4\n"
1753 "lslw r0, r0, #28\n"
1754 "lslw r0, r0, #29\n"
1755 "lslw r0, r0, #30\n"
1756 "lslw r0, r0, #31\n");
1757}
1758
1759ASSEMBLER_TEST_GENERATE(LsrImmediate, assembler) {
1760 __ LsrImmediate(R0, R0, 1);
1761 __ LsrImmediate(R0, R0, 2);
1762 __ LsrImmediate(R0, R0, 3);
1763 __ LsrImmediate(R0, R0, 4);
1764 __ LsrImmediate(R0, R0, 60);
1765 __ LsrImmediate(R0, R0, 61);
1766 __ LsrImmediate(R0, R0, 62);
1767 __ LsrImmediate(R0, R0, 63);
1768 __ LsrImmediate(R0, R0, 1, kFourBytes);
1769 __ LsrImmediate(R0, R0, 2, kFourBytes);
1770 __ LsrImmediate(R0, R0, 3, kFourBytes);
1771 __ LsrImmediate(R0, R0, 4, kFourBytes);
1772 __ LsrImmediate(R0, R0, 28, kFourBytes);
1773 __ LsrImmediate(R0, R0, 29, kFourBytes);
1774 __ LsrImmediate(R0, R0, 30, kFourBytes);
1775 __ LsrImmediate(R0, R0, 31, kFourBytes);
1776}
1777
1778ASSEMBLER_TEST_RUN(LsrImmediate, test) {
1779 EXPECT_DISASSEMBLY(
1780 "lsr r0, r0, #1\n"
1781 "lsr r0, r0, #2\n"
1782 "lsr r0, r0, #3\n"
1783 "lsr r0, r0, #4\n"
1784 "lsr r0, r0, #60\n"
1785 "lsr r0, r0, #61\n"
1786 "lsr r0, r0, #62\n"
1787 "lsr r0, r0, #63\n"
1788 "lsrw r0, r0, #1\n"
1789 "lsrw r0, r0, #2\n"
1790 "lsrw r0, r0, #3\n"
1791 "lsrw r0, r0, #4\n"
1792 "lsrw r0, r0, #28\n"
1793 "lsrw r0, r0, #29\n"
1794 "lsrw r0, r0, #30\n"
1795 "lsrw r0, r0, #31\n");
1796}
1797
1798ASSEMBLER_TEST_GENERATE(AsrImmediate, assembler) {
1799 __ AsrImmediate(R0, R0, 1);
1800 __ AsrImmediate(R0, R0, 2);
1801 __ AsrImmediate(R0, R0, 3);
1802 __ AsrImmediate(R0, R0, 4);
1803 __ AsrImmediate(R0, R0, 60);
1804 __ AsrImmediate(R0, R0, 61);
1805 __ AsrImmediate(R0, R0, 62);
1806 __ AsrImmediate(R0, R0, 63);
1807 __ AsrImmediate(R0, R0, 1, kFourBytes);
1808 __ AsrImmediate(R0, R0, 2, kFourBytes);
1809 __ AsrImmediate(R0, R0, 3, kFourBytes);
1810 __ AsrImmediate(R0, R0, 4, kFourBytes);
1811 __ AsrImmediate(R0, R0, 28, kFourBytes);
1812 __ AsrImmediate(R0, R0, 29, kFourBytes);
1813 __ AsrImmediate(R0, R0, 30, kFourBytes);
1814 __ AsrImmediate(R0, R0, 31, kFourBytes);
1815}
1816
1817ASSEMBLER_TEST_RUN(AsrImmediate, test) {
1818 EXPECT_DISASSEMBLY(
1819 "asr r0, r0, #1\n"
1820 "asr r0, r0, #2\n"
1821 "asr r0, r0, #3\n"
1822 "asr r0, r0, #4\n"
1823 "asr r0, r0, #60\n"
1824 "asr r0, r0, #61\n"
1825 "asr r0, r0, #62\n"
1826 "asr r0, r0, #63\n"
1827 "asrw r0, r0, #1\n"
1828 "asrw r0, r0, #2\n"
1829 "asrw r0, r0, #3\n"
1830 "asrw r0, r0, #4\n"
1831 "asrw r0, r0, #28\n"
1832 "asrw r0, r0, #29\n"
1833 "asrw r0, r0, #30\n"
1834 "asrw r0, r0, #31\n");
1835}
1836
1837ASSEMBLER_TEST_GENERATE(AndShiftRegs, assembler) {
1838 __ movz(R1, Immediate(42), 0);
1839 __ movz(R2, Immediate(21), 0);
1840 __ and_(R0, R1, Operand(R2, LSL, 1));
1841 __ ret();
1842}
1843
1844ASSEMBLER_TEST_RUN(AndShiftRegs, test) {
1845 typedef int64_t (*Int64Return)() DART_UNUSED;
1846 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1847 EXPECT_DISASSEMBLY(
1848 "movz r1, #0x2a\n"
1849 "movz r2, #0x15\n"
1850 "and r0, r1, r2 lsl #1\n"
1851 "ret\n");
1852}
1853
1854ASSEMBLER_TEST_GENERATE(BicRegs, assembler) {
1855 __ movz(R1, Immediate(42), 0);
1856 __ movz(R2, Immediate(5), 0);
1857 __ bic(R0, R1, Operand(R2));
1858 __ ret();
1859}
1860
1861ASSEMBLER_TEST_RUN(BicRegs, test) {
1862 typedef int64_t (*Int64Return)() DART_UNUSED;
1863 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1864 EXPECT_DISASSEMBLY(
1865 "movz r1, #0x2a\n"
1866 "movz r2, #0x5\n"
1867 "bic r0, r1, r2\n"
1868 "ret\n");
1869}
1870
1871ASSEMBLER_TEST_GENERATE(OrrRegs, assembler) {
1872 __ movz(R1, Immediate(32), 0);
1873 __ movz(R2, Immediate(10), 0);
1874 __ orr(R0, R1, Operand(R2));
1875 __ ret();
1876}
1877
1878ASSEMBLER_TEST_RUN(OrrRegs, test) {
1879 typedef int64_t (*Int64Return)() DART_UNUSED;
1880 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1881 EXPECT_DISASSEMBLY(
1882 "movz r1, #0x20\n"
1883 "movz r2, #0xa\n"
1884 "orr r0, r1, r2\n"
1885 "ret\n");
1886}
1887
1888ASSEMBLER_TEST_GENERATE(OrnRegs, assembler) {
1889 __ movz(R1, Immediate(32), 0);
1890 __ movn(R2, Immediate(0), 0); // R2 <- 0xffffffffffffffff.
1891 __ movk(R2, Immediate(0xffd5), 0); // R2 <- 0xffffffffffffffe5.
1892 __ orn(R0, R1, Operand(R2));
1893 __ ret();
1894}
1895
1896ASSEMBLER_TEST_RUN(OrnRegs, test) {
1897 typedef int64_t (*Int64Return)() DART_UNUSED;
1898 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1899 EXPECT_DISASSEMBLY(
1900 "movz r1, #0x20\n"
1901 "movn r2, #0x0\n"
1902 "movk r2, #0xffd5\n"
1903 "orn r0, r1, r2\n"
1904 "ret\n");
1905}
1906
1907ASSEMBLER_TEST_GENERATE(EorRegs, assembler) {
1908 __ movz(R1, Immediate(0xffd5), 0);
1909 __ movz(R2, Immediate(0xffff), 0);
1910 __ eor(R0, R1, Operand(R2));
1911 __ ret();
1912}
1913
1914ASSEMBLER_TEST_RUN(EorRegs, test) {
1915 typedef int64_t (*Int64Return)() DART_UNUSED;
1916 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1917 EXPECT_DISASSEMBLY(
1918 "movz r1, #0xffd5\n"
1919 "movz r2, #0xffff\n"
1920 "eor r0, r1, r2\n"
1921 "ret\n");
1922}
1923
1924ASSEMBLER_TEST_GENERATE(EonRegs, assembler) {
1925 __ movz(R1, Immediate(0xffd5), 0);
1926 __ movn(R2, Immediate(0xffff), 0);
1927 __ eon(R0, R1, Operand(R2));
1928 __ ret();
1929}
1930
1931ASSEMBLER_TEST_RUN(EonRegs, test) {
1932 typedef int64_t (*Int64Return)() DART_UNUSED;
1933 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1934 EXPECT_DISASSEMBLY(
1935 "movz r1, #0xffd5\n"
1936 "movn r2, #0xffff\n"
1937 "eon r0, r1, r2\n"
1938 "ret\n");
1939}
1940
1941// Logical immediate operations.
1942ASSEMBLER_TEST_GENERATE(AndImm, assembler) {
1943 __ movz(R1, Immediate(42), 0);
1944 __ andi(R0, R1, Immediate(0xaaaaaaaaaaaaaaaaULL));
1945 __ ret();
1946}
1947
1948ASSEMBLER_TEST_RUN(AndImm, test) {
1949 typedef int64_t (*Int64Return)() DART_UNUSED;
1950 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1951 EXPECT_DISASSEMBLY(
1952 "movz r1, #0x2a\n"
1953 "and r0, r1, 0xaaaaaaaaaaaaaaaa\n"
1954 "ret\n");
1955}
1956
1957ASSEMBLER_TEST_GENERATE(AndImmCsp, assembler) {
1958 // Note we must maintain the ARM64 ABI invariants on CSP here.
1959 __ mov(TMP, CSP);
1960 __ sub(TMP2, CSP, Operand(31));
1961 __ andi(CSP, TMP2, Immediate(~15));
1962 __ mov(R0, CSP);
1963 __ sub(R0, TMP, Operand(R0));
1964 __ mov(CSP, TMP);
1965 __ ret();
1966}
1967
1968ASSEMBLER_TEST_RUN(AndImmCsp, test) {
1969 typedef int64_t (*Int64Return)() DART_UNUSED;
1970 EXPECT_EQ(32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1971 EXPECT_DISASSEMBLY(
1972 "mov tmp, csp\n"
1973 "sub tmp2, csp, #0x1f\n"
1974 "and csp, tmp2, 0xfffffffffffffff0\n"
1975 "mov r0, csp\n"
1976 "sub r0, tmp, r0\n"
1977 "mov csp, tmp\n"
1978 "ret\n");
1979}
1980
1981ASSEMBLER_TEST_GENERATE(AndOneImm, assembler) {
1982 __ movz(R1, Immediate(43), 0);
1983 __ andi(R0, R1, Immediate(1));
1984 __ ret();
1985}
1986
1987ASSEMBLER_TEST_RUN(AndOneImm, test) {
1988 typedef int64_t (*Int64Return)() DART_UNUSED;
1989 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
1990 EXPECT_DISASSEMBLY(
1991 "movz r1, #0x2b\n"
1992 "and r0, r1, 0x1\n"
1993 "ret\n");
1994}
1995
1996ASSEMBLER_TEST_GENERATE(OrrImm, assembler) {
1997 __ movz(R1, Immediate(0), 0);
1998 __ movz(R2, Immediate(0x3f), 0);
1999 __ movz(R3, Immediate(0xa), 0);
2000 __ orri(R1, R1, Immediate(0x0020002000200020ULL));
2001 __ orr(R1, R1, Operand(R3));
2002 __ and_(R0, R1, Operand(R2));
2003 __ ret();
2004}
2005
2006ASSEMBLER_TEST_RUN(OrrImm, test) {
2007 typedef int64_t (*Int64Return)() DART_UNUSED;
2008 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2009 EXPECT_DISASSEMBLY(
2010 "movz r1, #0x0\n"
2011 "movz r2, #0x3f\n"
2012 "movz r3, #0xa\n"
2013 "orr r1, r1, 0x20002000200020\n"
2014 "orr r1, r1, r3\n"
2015 "and r0, r1, r2\n"
2016 "ret\n");
2017}
2018
2019ASSEMBLER_TEST_GENERATE(EorImm, assembler) {
2020 __ movn(R0, Immediate(0), 0);
2021 __ movk(R0, Immediate(0xffd5), 0); // R0 < 0xffffffffffffffd5.
2022 __ movz(R1, Immediate(0x3f), 0);
2023 __ eori(R0, R0, Immediate(0x3f3f3f3f3f3f3f3fULL));
2024 __ and_(R0, R0, Operand(R1));
2025 __ ret();
2026}
2027
2028ASSEMBLER_TEST_RUN(EorImm, test) {
2029 typedef int64_t (*Int64Return)() DART_UNUSED;
2030 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2031 EXPECT_DISASSEMBLY(
2032 "movn r0, #0x0\n"
2033 "movk r0, #0xffd5\n"
2034 "movz r1, #0x3f\n"
2035 "eor r0, r0, 0x3f3f3f3f3f3f3f3f\n"
2036 "and r0, r0, r1\n"
2037 "ret\n");
2038}
2039
2040ASSEMBLER_TEST_GENERATE(Clz, assembler) {
2041 Label error;
2042
2043 __ clz(R1, ZR);
2044 __ cmp(R1, Operand(64));
2045 __ b(&error, NE);
2046 __ LoadImmediate(R2, 42);
2047 __ clz(R2, R2);
2048 __ cmp(R2, Operand(58));
2049 __ b(&error, NE);
2050 __ LoadImmediate(R0, -1);
2051 __ clz(R1, R0);
2052 __ cmp(R1, Operand(0));
2053 __ b(&error, NE);
2054 __ add(R0, ZR, Operand(R0, LSR, 3));
2055 __ clz(R1, R0);
2056 __ cmp(R1, Operand(3));
2057 __ b(&error, NE);
2058 __ mov(R0, ZR);
2059 __ ret();
2060 __ Bind(&error);
2061 __ LoadImmediate(R0, 1);
2062 __ ret();
2063}
2064
2066 typedef int64_t (*Int64Return)() DART_UNUSED;
2067 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2068 EXPECT_DISASSEMBLY(
2069 "clz r1, zr\n"
2070 "cmp r1, #0x40\n"
2071 "bne +60\n"
2072 "movz r2, #0x2a\n"
2073 "clz r2, r2\n"
2074 "cmp r2, #0x3a\n"
2075 "bne +44\n"
2076 "movn r0, #0x0\n"
2077 "clz r1, r0\n"
2078 "cmp r1, #0x0\n"
2079 "bne +28\n"
2080 "add r0, zr, r0 lsr #3\n"
2081 "clz r1, r0\n"
2082 "cmp r1, #0x3\n"
2083 "bne +12\n"
2084 "mov r0, zr\n"
2085 "ret\n"
2086 "movz r0, #0x1\n"
2087 "ret\n");
2088}
2089
2090ASSEMBLER_TEST_GENERATE(Clzw, assembler) {
2091 Label error;
2092
2093 __ clzw(R1, ZR);
2094 __ cmp(R1, Operand(32));
2095 __ b(&error, NE);
2096 __ LoadImmediate(R2, 42);
2097 __ clzw(R2, R2);
2098 __ cmp(R2, Operand(26));
2099 __ b(&error, NE);
2100 __ LoadImmediate(R0, -1);
2101 __ clzw(R1, R0);
2102 __ cmp(R1, Operand(0));
2103 __ b(&error, NE);
2104 __ add(R0, ZR, Operand(R0, LSR, 35));
2105 __ clzw(R1, R0);
2106 __ cmp(R1, Operand(3));
2107 __ b(&error, NE);
2108 __ LoadImmediate(R0, 0xFFFFFFFF0FFFFFFF);
2109 __ clzw(R1, R0);
2110 __ cmp(R1, Operand(4));
2111 __ b(&error, NE);
2112 __ LoadImmediate(R0, 0xFFFFFFFF);
2113 __ clzw(R1, R0);
2114 __ cmp(R1, Operand(0));
2115 __ b(&error, NE);
2116 __ mov(R0, ZR);
2117 __ ret();
2118 __ Bind(&error);
2119 __ LoadImmediate(R0, 1);
2120 __ ret();
2121}
2122
2123ASSEMBLER_TEST_RUN(Clzw, test) {
2124 typedef int64_t (*Int64Return)() DART_UNUSED;
2125 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2126 EXPECT_DISASSEMBLY(
2127 "clzw r1, zr\n"
2128 "cmp r1, #0x20\n"
2129 "bne +92\n"
2130 "movz r2, #0x2a\n"
2131 "clzw r2, r2\n"
2132 "cmp r2, #0x1a\n"
2133 "bne +76\n"
2134 "movn r0, #0x0\n"
2135 "clzw r1, r0\n"
2136 "cmp r1, #0x0\n"
2137 "bne +60\n"
2138 "add r0, zr, r0 lsr #35\n"
2139 "clzw r1, r0\n"
2140 "cmp r1, #0x3\n"
2141 "bne +44\n"
2142 "mov r0, 0xffffffff0fffffff\n"
2143 "clzw r1, r0\n"
2144 "cmp r1, #0x4\n"
2145 "bne +28\n"
2146 "mov r0, 0xffffffff\n"
2147 "clzw r1, r0\n"
2148 "cmp r1, #0x0\n"
2149 "bne +12\n"
2150 "mov r0, zr\n"
2151 "ret\n"
2152 "movz r0, #0x1\n"
2153 "ret\n");
2154}
2155
2156ASSEMBLER_TEST_GENERATE(Rbit, assembler) {
2157 const int64_t immediate = 0x0000000000000015;
2158 __ LoadImmediate(R0, immediate);
2159 __ rbit(R0, R0);
2160 __ ret();
2161}
2162
2163ASSEMBLER_TEST_RUN(Rbit, test) {
2164 typedef int64_t (*Int64Return)() DART_UNUSED;
2165 const int64_t expected = 0xa800000000000000;
2166 EXPECT_EQ(expected, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2167 EXPECT_DISASSEMBLY(
2168 "movz r0, #0x15\n"
2169 "rbit r0, r0\n"
2170 "ret\n");
2171}
2172
2173// Comparisons, branching.
2174ASSEMBLER_TEST_GENERATE(BranchALForward, assembler) {
2175 Label l;
2176 __ movz(R0, Immediate(42), 0);
2177 __ b(&l, AL);
2178 __ movz(R0, Immediate(0), 0);
2179 __ Bind(&l);
2180 __ ret();
2181}
2182
2183ASSEMBLER_TEST_RUN(BranchALForward, test) {
2184 typedef int64_t (*Int64Return)() DART_UNUSED;
2185 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2186 EXPECT_DISASSEMBLY(
2187 "movz r0, #0x2a\n"
2188 "b +8\n"
2189 "movz r0, #0x0\n"
2190 "ret\n");
2191}
2192
2193ASSEMBLER_TEST_GENERATE(BranchALBackwards, assembler) {
2194 Label l, leave;
2195 __ movz(R0, Immediate(42), 0);
2196 __ b(&l, AL);
2197
2198 __ movz(R0, Immediate(0), 0);
2199 __ Bind(&leave);
2200 __ ret();
2201 __ movz(R0, Immediate(0), 0);
2202
2203 __ Bind(&l);
2204 __ b(&leave, AL);
2205 __ movz(R0, Immediate(0), 0);
2206 __ ret();
2207}
2208
2209ASSEMBLER_TEST_RUN(BranchALBackwards, test) {
2210 typedef int64_t (*Int64Return)() DART_UNUSED;
2211 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2212 EXPECT_DISASSEMBLY(
2213 "movz r0, #0x2a\n"
2214 "b +16\n"
2215 "movz r0, #0x0\n"
2216 "ret\n"
2217 "movz r0, #0x0\n"
2218 "b -8\n"
2219 "movz r0, #0x0\n"
2220 "ret\n");
2221}
2222
2223ASSEMBLER_TEST_GENERATE(CmpEqBranch, assembler) {
2224 Label l;
2225
2226 __ movz(R0, Immediate(42), 0);
2227 __ movz(R1, Immediate(234), 0);
2228 __ movz(R2, Immediate(234), 0);
2229
2230 __ cmp(R1, Operand(R2));
2231 __ b(&l, EQ);
2232 __ movz(R0, Immediate(0), 0);
2233 __ Bind(&l);
2234 __ ret();
2235}
2236
2237ASSEMBLER_TEST_RUN(CmpEqBranch, test) {
2238 typedef int64_t (*Int64Return)() DART_UNUSED;
2239 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2240 EXPECT_DISASSEMBLY(
2241 "movz r0, #0x2a\n"
2242 "movz r1, #0xea\n"
2243 "movz r2, #0xea\n"
2244 "cmp r1, r2\n"
2245 "beq +8\n"
2246 "movz r0, #0x0\n"
2247 "ret\n");
2248}
2249
2250ASSEMBLER_TEST_GENERATE(CmpEqBranchNotTaken, assembler) {
2251 Label l;
2252
2253 __ movz(R0, Immediate(0), 0);
2254 __ movz(R1, Immediate(233), 0);
2255 __ movz(R2, Immediate(234), 0);
2256
2257 __ cmp(R1, Operand(R2));
2258 __ b(&l, EQ);
2259 __ movz(R0, Immediate(42), 0);
2260 __ Bind(&l);
2261 __ ret();
2262}
2263
2264ASSEMBLER_TEST_RUN(CmpEqBranchNotTaken, test) {
2265 typedef int64_t (*Int64Return)() DART_UNUSED;
2266 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2267 EXPECT_DISASSEMBLY(
2268 "movz r0, #0x0\n"
2269 "movz r1, #0xe9\n"
2270 "movz r2, #0xea\n"
2271 "cmp r1, r2\n"
2272 "beq +8\n"
2273 "movz r0, #0x2a\n"
2274 "ret\n");
2275}
2276
2277ASSEMBLER_TEST_GENERATE(CmpEq1Branch, assembler) {
2278 Label l;
2279
2280 __ movz(R0, Immediate(42), 0);
2281 __ movz(R1, Immediate(1), 0);
2282
2283 __ cmp(R1, Operand(1));
2284 __ b(&l, EQ);
2285 __ movz(R0, Immediate(0), 0);
2286 __ Bind(&l);
2287 __ ret();
2288}
2289
2290ASSEMBLER_TEST_RUN(CmpEq1Branch, test) {
2291 typedef int64_t (*Int64Return)() DART_UNUSED;
2292 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2293 EXPECT_DISASSEMBLY(
2294 "movz r0, #0x2a\n"
2295 "movz r1, #0x1\n"
2296 "cmp r1, #0x1\n"
2297 "beq +8\n"
2298 "movz r0, #0x0\n"
2299 "ret\n");
2300}
2301
2302ASSEMBLER_TEST_GENERATE(CmnEq1Branch, assembler) {
2303 Label l;
2304
2305 __ movz(R0, Immediate(42), 0);
2306 __ movn(R1, Immediate(0), 0); // R1 <- -1
2307
2308 __ cmn(R1, Operand(1));
2309 __ b(&l, EQ);
2310 __ movz(R0, Immediate(0), 0);
2311 __ Bind(&l);
2312 __ ret();
2313}
2314
2315ASSEMBLER_TEST_RUN(CmnEq1Branch, test) {
2316 typedef int64_t (*Int64Return)() DART_UNUSED;
2317 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2318 EXPECT_DISASSEMBLY(
2319 "movz r0, #0x2a\n"
2320 "movn r1, #0x0\n"
2321 "cmn r1, #0x1\n"
2322 "beq +8\n"
2323 "movz r0, #0x0\n"
2324 "ret\n");
2325}
2326
2327ASSEMBLER_TEST_GENERATE(CmpLtBranch, assembler) {
2328 Label l;
2329
2330 __ movz(R0, Immediate(42), 0);
2331 __ movz(R1, Immediate(233), 0);
2332 __ movz(R2, Immediate(234), 0);
2333
2334 __ cmp(R1, Operand(R2));
2335 __ b(&l, LT);
2336 __ movz(R0, Immediate(0), 0);
2337 __ Bind(&l);
2338 __ ret();
2339}
2340
2341ASSEMBLER_TEST_RUN(CmpLtBranch, test) {
2342 typedef int64_t (*Int64Return)() DART_UNUSED;
2343 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2344 EXPECT_DISASSEMBLY(
2345 "movz r0, #0x2a\n"
2346 "movz r1, #0xe9\n"
2347 "movz r2, #0xea\n"
2348 "cmp r1, r2\n"
2349 "blt +8\n"
2350 "movz r0, #0x0\n"
2351 "ret\n");
2352}
2353
2354ASSEMBLER_TEST_GENERATE(CmpLtBranchNotTaken, assembler) {
2355 Label l;
2356
2357 __ movz(R0, Immediate(0), 0);
2358 __ movz(R1, Immediate(235), 0);
2359 __ movz(R2, Immediate(234), 0);
2360
2361 __ cmp(R1, Operand(R2));
2362 __ b(&l, LT);
2363 __ movz(R0, Immediate(42), 0);
2364 __ Bind(&l);
2365 __ ret();
2366}
2367
2368ASSEMBLER_TEST_RUN(CmpLtBranchNotTaken, test) {
2369 typedef int64_t (*Int64Return)() DART_UNUSED;
2370 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2371 EXPECT_DISASSEMBLY(
2372 "movz r0, #0x0\n"
2373 "movz r1, #0xeb\n"
2374 "movz r2, #0xea\n"
2375 "cmp r1, r2\n"
2376 "blt +8\n"
2377 "movz r0, #0x2a\n"
2378 "ret\n");
2379}
2380
2381ASSEMBLER_TEST_GENERATE(CmpBranchIfZero, assembler) {
2382 Label l;
2383
2384 __ movz(R0, Immediate(42), 0);
2385 __ movz(R1, Immediate(0), 0);
2386
2387 __ cbz(&l, R1);
2388 __ movz(R0, Immediate(0), 0);
2389 __ Bind(&l);
2390 __ ret();
2391}
2392
2393ASSEMBLER_TEST_RUN(CmpBranchIfZero, test) {
2394 typedef int64_t (*Int64Return)() DART_UNUSED;
2395 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2396 EXPECT_DISASSEMBLY(
2397 "movz r0, #0x2a\n"
2398 "movz r1, #0x0\n"
2399 "cbz r1, +8\n"
2400 "movz r0, #0x0\n"
2401 "ret\n");
2402}
2403
2404ASSEMBLER_TEST_GENERATE(CmpBranchIfZeroNotTaken, assembler) {
2405 Label l;
2406
2407 __ movz(R0, Immediate(0), 0);
2408 __ movz(R1, Immediate(1), 0);
2409
2410 __ cbz(&l, R1);
2411 __ movz(R0, Immediate(42), 0);
2412 __ Bind(&l);
2413 __ ret();
2414}
2415
2416ASSEMBLER_TEST_RUN(CmpBranchIfZeroNotTaken, test) {
2417 typedef int64_t (*Int64Return)() DART_UNUSED;
2418 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2419 EXPECT_DISASSEMBLY(
2420 "movz r0, #0x0\n"
2421 "movz r1, #0x1\n"
2422 "cbz r1, +8\n"
2423 "movz r0, #0x2a\n"
2424 "ret\n");
2425}
2426
2427ASSEMBLER_TEST_GENERATE(CmpBranchIfNotZero, assembler) {
2428 Label l;
2429
2430 __ movz(R0, Immediate(42), 0);
2431 __ movz(R1, Immediate(1), 0);
2432
2433 __ cbnz(&l, R1);
2434 __ movz(R0, Immediate(0), 0);
2435 __ Bind(&l);
2436 __ ret();
2437}
2438
2439ASSEMBLER_TEST_RUN(CmpBranchIfNotZero, test) {
2440 typedef int64_t (*Int64Return)() DART_UNUSED;
2441 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2442 EXPECT_DISASSEMBLY(
2443 "movz r0, #0x2a\n"
2444 "movz r1, #0x1\n"
2445 "cbnz r1, +8\n"
2446 "movz r0, #0x0\n"
2447 "ret\n");
2448}
2449
2450ASSEMBLER_TEST_GENERATE(CmpBranchIfNotZeroNotTaken, assembler) {
2451 Label l;
2452
2453 __ movz(R0, Immediate(0), 0);
2454 __ movz(R1, Immediate(0), 0);
2455
2456 __ cbnz(&l, R1);
2457 __ movz(R0, Immediate(42), 0);
2458 __ Bind(&l);
2459 __ ret();
2460}
2461
2462ASSEMBLER_TEST_RUN(CmpBranchIfNotZeroNotTaken, test) {
2463 typedef int64_t (*Int64Return)() DART_UNUSED;
2464 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2465 EXPECT_DISASSEMBLY(
2466 "movz r0, #0x0\n"
2467 "movz r1, #0x0\n"
2468 "cbnz r1, +8\n"
2469 "movz r0, #0x2a\n"
2470 "ret\n");
2471}
2472
2473static constexpr int64_t kBits5And35 = (1 << 5) | (1ll << 35);
2474
2475ASSEMBLER_TEST_GENERATE(TstBranchIfZero, assembler) {
2476 Label l, l2;
2477
2478 __ movz(R0, Immediate(42), 0);
2479 __ LoadImmediate(R1, ~kBits5And35);
2480
2481 __ tbz(&l, R1, 5);
2482 __ movz(R0, Immediate(0), 0);
2483 __ Bind(&l);
2484
2485 __ tbz(&l2, R1, 35);
2486 __ movz(R0, Immediate(0), 0);
2487 __ Bind(&l2);
2488
2489 __ ret();
2490}
2491
2492ASSEMBLER_TEST_RUN(TstBranchIfZero, test) {
2493 typedef int64_t (*Int64Return)() DART_UNUSED;
2494 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2495 EXPECT_DISASSEMBLY(
2496 "movz r0, #0x2a\n"
2497 "movn r1, #0x8 lsl 32\n"
2498 "movk r1, #0xffdf\n"
2499 "tbzw r1, #5, +8\n"
2500 "movz r0, #0x0\n"
2501 "tbz r1, #35, +8\n"
2502 "movz r0, #0x0\n"
2503 "ret\n");
2504}
2505
2506ASSEMBLER_TEST_GENERATE(TstBranchIfZeroNotTaken, assembler) {
2507 Label l;
2508
2509 __ movz(R0, Immediate(0), 0);
2510 __ LoadImmediate(R1, kBits5And35);
2511
2512 __ tbz(&l, R1, 5);
2513 __ movz(R0, Immediate(42), 0);
2514 __ Bind(&l);
2515 __ ret();
2516}
2517
2518ASSEMBLER_TEST_RUN(TstBranchIfZeroNotTaken, test) {
2519 typedef int64_t (*Int64Return)() DART_UNUSED;
2520 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2521 EXPECT_DISASSEMBLY(
2522 "movz r0, #0x0\n"
2523 "movz r1, #0x20\n"
2524 "movk r1, #0x8 lsl 32\n"
2525 "tbzw r1, #5, +8\n"
2526 "movz r0, #0x2a\n"
2527 "ret\n");
2528}
2529
2530ASSEMBLER_TEST_GENERATE(TstBranchIfNotZero, assembler) {
2531 Label l, l2;
2532
2533 __ movz(R0, Immediate(42), 0);
2534 __ LoadImmediate(R1, kBits5And35);
2535
2536 __ tbnz(&l, R1, 5);
2537 __ movz(R0, Immediate(0), 0);
2538 __ Bind(&l);
2539
2540 __ tbnz(&l2, R1, 35);
2541 __ movz(R0, Immediate(0), 0);
2542 __ Bind(&l2);
2543
2544 __ ret();
2545}
2546
2547ASSEMBLER_TEST_RUN(TstBranchIfNotZero, test) {
2548 typedef int64_t (*Int64Return)() DART_UNUSED;
2549 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2550 EXPECT_DISASSEMBLY(
2551 "movz r0, #0x2a\n"
2552 "movz r1, #0x20\n"
2553 "movk r1, #0x8 lsl 32\n"
2554 "tbnzw r1, #5, +8\n"
2555 "movz r0, #0x0\n"
2556 "tbnz r1, #35, +8\n"
2557 "movz r0, #0x0\n"
2558 "ret\n");
2559}
2560
2561ASSEMBLER_TEST_GENERATE(TstBranchIfNotZeroNotTaken, assembler) {
2562 Label l;
2563
2564 __ movz(R0, Immediate(0), 0);
2565 __ LoadImmediate(R1, ~kBits5And35);
2566
2567 __ tbnz(&l, R1, 5);
2568 __ movz(R0, Immediate(42), 0);
2569 __ Bind(&l);
2570 __ ret();
2571}
2572
2573ASSEMBLER_TEST_RUN(TstBranchIfNotZeroNotTaken, test) {
2574 typedef int64_t (*Int64Return)() DART_UNUSED;
2575 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2576 EXPECT_DISASSEMBLY(
2577 "movz r0, #0x0\n"
2578 "movn r1, #0x8 lsl 32\n"
2579 "movk r1, #0xffdf\n"
2580 "tbnzw r1, #5, +8\n"
2581 "movz r0, #0x2a\n"
2582 "ret\n");
2583}
2584
2585ASSEMBLER_TEST_GENERATE(TstBranchIfZeroFar, assembler) {
2586 Label l;
2587
2588 __ movz(R0, Immediate(42), 0);
2589 __ LoadImmediate(R1, ~kBits5And35);
2590
2591 __ tbz(&l, R1, 5);
2592
2593 const intptr_t kRange = 1 << 14; // tbz has 14 bits of range.
2594 for (intptr_t i = 0; i < kRange; i++) {
2595 __ brk(0);
2596 }
2597
2598 __ movz(R0, Immediate(0), 0);
2599 __ Bind(&l);
2600 __ ret();
2601}
2602
2603ASSEMBLER_TEST_RUN(TstBranchIfZeroFar, test) {
2604 typedef int64_t (*Int64Return)() DART_UNUSED;
2605 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2606}
2607
2608ASSEMBLER_TEST_GENERATE(TstBranchIfNotZeroFar, assembler) {
2609 Label l;
2610
2611 __ movz(R0, Immediate(42), 0);
2612 __ LoadImmediate(R1, kBits5And35);
2613
2614 __ tbnz(&l, R1, 5);
2615
2616 const intptr_t kRange = 1 << 14; // tbnz has 14 bits of range.
2617 for (intptr_t i = 0; i < kRange; i++) {
2618 __ brk(0);
2619 }
2620
2621 __ movz(R0, Immediate(0), 0);
2622 __ Bind(&l);
2623 __ ret();
2624}
2625
2626ASSEMBLER_TEST_RUN(TstBranchIfNotZeroFar, test) {
2627 typedef int64_t (*Int64Return)() DART_UNUSED;
2628 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2629}
2630
2631ASSEMBLER_TEST_GENERATE(FcmpEqBranch, assembler) {
2632 Label l;
2633
2634 __ LoadDImmediate(V0, 42.0);
2635 __ LoadDImmediate(V1, 234.0);
2636 __ LoadDImmediate(V2, 234.0);
2637
2638 __ fcmpd(V1, V2);
2639 __ b(&l, EQ);
2640 __ LoadDImmediate(V0, 0.0);
2641 __ Bind(&l);
2642 __ ret();
2643}
2644
2645ASSEMBLER_TEST_RUN(FcmpEqBranch, test) {
2646 typedef double (*DoubleReturn)() DART_UNUSED;
2647 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
2648 EXPECT_DISASSEMBLY(
2649 "movz tmp, #0x4045 lsl 48\n"
2650 "fmovdr v0, tmp\n"
2651 "movz tmp, #0x4000 lsl 32\n"
2652 "movk tmp, #0x406d lsl 48\n"
2653 "fmovdr v1, tmp\n"
2654 "movz tmp, #0x4000 lsl 32\n"
2655 "movk tmp, #0x406d lsl 48\n"
2656 "fmovdr v2, tmp\n"
2657 "fcmpd v1, v2\n"
2658 "beq +8\n"
2659 "veor v0, v0, v0\n"
2660 "ret\n");
2661}
2662
2663ASSEMBLER_TEST_GENERATE(TstBranchIfZeroFar1, assembler) {
2664 Label l;
2665
2666 __ LoadImmediate(R0, 41);
2667 __ tbnz(&l, R0, 5);
2668 __ Stop("Hammertime");
2669
2670 for (int i = 0; i < 0x10000; i++) {
2671 __ add(R0, R0, Operand(1));
2672 __ sub(R0, R0, Operand(1));
2673 }
2674
2675 __ AddImmediate(R0, R0, -1); // Not run.
2676
2677 __ Bind(&l);
2678 __ AddImmediate(R0, R0, 1);
2679 __ ret();
2680}
2681
2682ASSEMBLER_TEST_RUN(TstBranchIfZeroFar1, test) {
2683 typedef int64_t (*Int64Return)() DART_UNUSED;
2684 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2685}
2686
2687ASSEMBLER_TEST_GENERATE(TstBranchIfZeroFar2, assembler) {
2688 Label l;
2689
2690 for (int i = 0; i < 0x10000; i++) {
2691 __ add(R0, R0, Operand(1));
2692 __ sub(R0, R0, Operand(1));
2693 }
2694
2695 __ LoadImmediate(R0, 41);
2696 __ tbnz(&l, R0, 5);
2697 __ Stop("Hammertime");
2698
2699 __ AddImmediate(R0, R0, -1); // Not run.
2700
2701 __ Bind(&l);
2702 __ AddImmediate(R0, R0, 1);
2703 __ ret();
2704}
2705
2706ASSEMBLER_TEST_RUN(TstBranchIfZeroFar2, test) {
2707 typedef int64_t (*Int64Return)() DART_UNUSED;
2708 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2709}
2710
2711ASSEMBLER_TEST_GENERATE(TstBranchIfZeroFar3, assembler) {
2712 Label l, l2;
2713 __ LoadImmediate(R0, 41);
2714 __ b(&l, AL);
2715
2716 __ AddImmediate(R0, R0, -1); // Not run.
2717
2718 __ Bind(&l2);
2719 __ AddImmediate(R0, R0, 1);
2720 __ ret();
2721
2722 for (int i = 0; i < 0x10000; i++) {
2723 __ add(R0, R0, Operand(1));
2724 __ sub(R0, R0, Operand(1));
2725 }
2726
2727 __ Bind(&l);
2728 __ tbnz(&l2, R0, 5);
2729 __ Stop("Hammertime");
2730}
2731
2732ASSEMBLER_TEST_RUN(TstBranchIfZeroFar3, test) {
2733 typedef int64_t (*Int64Return)() DART_UNUSED;
2734 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2735}
2736
2737ASSEMBLER_TEST_GENERATE(FcmpEqBranchNotTaken, assembler) {
2738 Label l;
2739
2740 __ LoadDImmediate(V0, 0.0);
2741 __ LoadDImmediate(V1, 233.0);
2742 __ LoadDImmediate(V2, 234.0);
2743
2744 __ fcmpd(V1, V2);
2745 __ b(&l, EQ);
2746 __ LoadDImmediate(V0, 42.0);
2747 __ Bind(&l);
2748 __ ret();
2749}
2750
2751ASSEMBLER_TEST_RUN(FcmpEqBranchNotTaken, test) {
2752 typedef double (*DoubleReturn)() DART_UNUSED;
2753 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
2754 EXPECT_DISASSEMBLY(
2755 "veor v0, v0, v0\n"
2756 "movz tmp, #0x2000 lsl 32\n"
2757 "movk tmp, #0x406d lsl 48\n"
2758 "fmovdr v1, tmp\n"
2759 "movz tmp, #0x4000 lsl 32\n"
2760 "movk tmp, #0x406d lsl 48\n"
2761 "fmovdr v2, tmp\n"
2762 "fcmpd v1, v2\n"
2763 "beq +12\n"
2764 "movz tmp, #0x4045 lsl 48\n"
2765 "fmovdr v0, tmp\n"
2766 "ret\n");
2767}
2768
2769ASSEMBLER_TEST_GENERATE(FcmpLtBranch, assembler) {
2770 Label l;
2771
2772 __ LoadDImmediate(V0, 42.0);
2773 __ LoadDImmediate(V1, 233.0);
2774 __ LoadDImmediate(V2, 234.0);
2775
2776 __ fcmpd(V1, V2);
2777 __ b(&l, LT);
2778 __ LoadDImmediate(V0, 0.0);
2779 __ Bind(&l);
2780 __ ret();
2781}
2782
2783ASSEMBLER_TEST_RUN(FcmpLtBranch, test) {
2784 typedef double (*DoubleReturn)() DART_UNUSED;
2785 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
2786}
2787
2788ASSEMBLER_TEST_GENERATE(FcmpLtBranchNotTaken, assembler) {
2789 Label l;
2790
2791 __ LoadDImmediate(V0, 0.0);
2792 __ LoadDImmediate(V1, 235.0);
2793 __ LoadDImmediate(V2, 234.0);
2794
2795 __ fcmpd(V1, V2);
2796 __ b(&l, LT);
2797 __ LoadDImmediate(V0, 42.0);
2798 __ Bind(&l);
2799 __ ret();
2800}
2801
2802ASSEMBLER_TEST_RUN(FcmpLtBranchNotTaken, test) {
2803 typedef double (*DoubleReturn)() DART_UNUSED;
2804 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
2805 EXPECT_DISASSEMBLY(
2806 "veor v0, v0, v0\n"
2807 "movz tmp, #0x6000 lsl 32\n"
2808 "movk tmp, #0x406d lsl 48\n"
2809 "fmovdr v1, tmp\n"
2810 "movz tmp, #0x4000 lsl 32\n"
2811 "movk tmp, #0x406d lsl 48\n"
2812 "fmovdr v2, tmp\n"
2813 "fcmpd v1, v2\n"
2814 "blt +12\n"
2815 "movz tmp, #0x4045 lsl 48\n"
2816 "fmovdr v0, tmp\n"
2817 "ret\n");
2818}
2819
2820ASSEMBLER_TEST_GENERATE(FcmpzGtBranch, assembler) {
2821 Label l;
2822
2823 __ LoadDImmediate(V0, 235.0);
2824 __ LoadDImmediate(V1, 233.0);
2825
2826 __ fcmpdz(V1);
2827 __ b(&l, GT);
2828 __ LoadDImmediate(V0, 0.0);
2829 __ ret();
2830 __ Bind(&l);
2831 __ LoadDImmediate(V0, 42.0);
2832 __ ret();
2833}
2834
2835ASSEMBLER_TEST_RUN(FcmpzGtBranch, test) {
2836 typedef double (*DoubleReturn)() DART_UNUSED;
2837 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
2838 EXPECT_DISASSEMBLY(
2839 "movz tmp, #0x6000 lsl 32\n"
2840 "movk tmp, #0x406d lsl 48\n"
2841 "fmovdr v0, tmp\n"
2842 "movz tmp, #0x2000 lsl 32\n"
2843 "movk tmp, #0x406d lsl 48\n"
2844 "fmovdr v1, tmp\n"
2845 "fcmpd v1, #0.0\n"
2846 "bgt +12\n"
2847 "veor v0, v0, v0\n"
2848 "ret\n"
2849 "movz tmp, #0x4045 lsl 48\n"
2850 "fmovdr v0, tmp\n"
2851 "ret\n");
2852}
2853
2854ASSEMBLER_TEST_GENERATE(AndsBranch, assembler) {
2855 Label l;
2856
2857 __ movz(R0, Immediate(42), 0);
2858 __ movz(R1, Immediate(2), 0);
2859 __ movz(R2, Immediate(1), 0);
2860
2861 __ ands(R3, R1, Operand(R2));
2862 __ b(&l, EQ);
2863 __ movz(R0, Immediate(0), 0);
2864 __ Bind(&l);
2865 __ ret();
2866}
2867
2868ASSEMBLER_TEST_RUN(AndsBranch, test) {
2869 typedef int64_t (*Int64Return)() DART_UNUSED;
2870 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2871 EXPECT_DISASSEMBLY(
2872 "movz r0, #0x2a\n"
2873 "movz r1, #0x2\n"
2874 "movz r2, #0x1\n"
2875 "ands r3, r1, r2\n"
2876 "beq +8\n"
2877 "movz r0, #0x0\n"
2878 "ret\n");
2879}
2880
2881ASSEMBLER_TEST_GENERATE(AndsBranchNotTaken, assembler) {
2882 Label l;
2883
2884 __ movz(R0, Immediate(0), 0);
2885 __ movz(R1, Immediate(2), 0);
2886 __ movz(R2, Immediate(2), 0);
2887
2888 __ ands(R3, R1, Operand(R2));
2889 __ b(&l, EQ);
2890 __ movz(R0, Immediate(42), 0);
2891 __ Bind(&l);
2892 __ ret();
2893}
2894
2895ASSEMBLER_TEST_RUN(AndsBranchNotTaken, test) {
2896 typedef int64_t (*Int64Return)() DART_UNUSED;
2897 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2898 EXPECT_DISASSEMBLY(
2899 "movz r0, #0x0\n"
2900 "movz r1, #0x2\n"
2901 "movz r2, #0x2\n"
2902 "ands r3, r1, r2\n"
2903 "beq +8\n"
2904 "movz r0, #0x2a\n"
2905 "ret\n");
2906}
2907
2908ASSEMBLER_TEST_GENERATE(BicsBranch, assembler) {
2909 Label l;
2910
2911 __ movz(R0, Immediate(42), 0);
2912 __ movz(R1, Immediate(2), 0);
2913 __ movz(R2, Immediate(2), 0);
2914
2915 __ bics(R3, R1, Operand(R2));
2916 __ b(&l, EQ);
2917 __ movz(R0, Immediate(0), 0);
2918 __ Bind(&l);
2919 __ ret();
2920}
2921
2922ASSEMBLER_TEST_RUN(BicsBranch, test) {
2923 typedef int64_t (*Int64Return)() DART_UNUSED;
2924 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2925 EXPECT_DISASSEMBLY(
2926 "movz r0, #0x2a\n"
2927 "movz r1, #0x2\n"
2928 "movz r2, #0x2\n"
2929 "bics r3, r1, r2\n"
2930 "beq +8\n"
2931 "movz r0, #0x0\n"
2932 "ret\n");
2933}
2934
2935ASSEMBLER_TEST_GENERATE(BicsBranchNotTaken, assembler) {
2936 Label l;
2937
2938 __ movz(R0, Immediate(0), 0);
2939 __ movz(R1, Immediate(2), 0);
2940 __ movz(R2, Immediate(1), 0);
2941
2942 __ bics(R3, R1, Operand(R2));
2943 __ b(&l, EQ);
2944 __ movz(R0, Immediate(42), 0);
2945 __ Bind(&l);
2946 __ ret();
2947}
2948
2949ASSEMBLER_TEST_RUN(BicsBranchNotTaken, test) {
2950 typedef int64_t (*Int64Return)() DART_UNUSED;
2951 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2952 EXPECT_DISASSEMBLY(
2953 "movz r0, #0x0\n"
2954 "movz r1, #0x2\n"
2955 "movz r2, #0x1\n"
2956 "bics r3, r1, r2\n"
2957 "beq +8\n"
2958 "movz r0, #0x2a\n"
2959 "ret\n");
2960}
2961
2962ASSEMBLER_TEST_GENERATE(AndisBranch, assembler) {
2963 Label l;
2964
2965 __ movz(R0, Immediate(42), 0);
2966 __ movz(R1, Immediate(2), 0);
2967
2968 __ andis(R3, R1, Immediate(1));
2969 __ b(&l, EQ);
2970 __ movz(R0, Immediate(0), 0);
2971 __ Bind(&l);
2972 __ ret();
2973}
2974
2975ASSEMBLER_TEST_RUN(AndisBranch, test) {
2976 typedef int64_t (*Int64Return)() DART_UNUSED;
2977 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
2978 EXPECT_DISASSEMBLY(
2979 "movz r0, #0x2a\n"
2980 "movz r1, #0x2\n"
2981 "ands r3, r1, 0x1\n"
2982 "beq +8\n"
2983 "movz r0, #0x0\n"
2984 "ret\n");
2985}
2986
2987ASSEMBLER_TEST_GENERATE(AndisBranchNotTaken, assembler) {
2988 Label l;
2989
2990 __ movz(R0, Immediate(0), 0);
2991 __ movz(R1, Immediate(2), 0);
2992
2993 __ andis(R3, R1, Immediate(2));
2994 __ b(&l, EQ);
2995 __ movz(R0, Immediate(42), 0);
2996 __ Bind(&l);
2997 __ ret();
2998}
2999
3000ASSEMBLER_TEST_RUN(AndisBranchNotTaken, test) {
3001 typedef int64_t (*Int64Return)() DART_UNUSED;
3002 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3003 EXPECT_DISASSEMBLY(
3004 "movz r0, #0x0\n"
3005 "movz r1, #0x2\n"
3006 "ands r3, r1, 0x2\n"
3007 "beq +8\n"
3008 "movz r0, #0x2a\n"
3009 "ret\n");
3010}
3011
3012// Address of PC-rel offset, br, blr.
3013ASSEMBLER_TEST_GENERATE(AdrBr, assembler) {
3014 __ movz(R0, Immediate(123), 0);
3015 // R1 <- PC + 3*Instr::kInstrSize
3016 __ adr(R1, Immediate(3 * Instr::kInstrSize));
3017 __ br(R1);
3018 __ ret();
3019
3020 // br goes here.
3021 __ movz(R0, Immediate(42), 0);
3022 __ ret();
3023}
3024
3025ASSEMBLER_TEST_RUN(AdrBr, test) {
3026 typedef int64_t (*Int64Return)() DART_UNUSED;
3027 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3028}
3029
3030ASSEMBLER_TEST_GENERATE(AdrBlr, assembler) {
3031 __ movz(R0, Immediate(123), 0);
3032 SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
3033 __ add(R3, ZR, Operand(LR))); // Save LR.
3034 // R1 <- PC + 4*Instr::kInstrSize
3035 __ adr(R1, Immediate(4 * Instr::kInstrSize));
3036 __ blr(R1);
3037 RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(__ add(LR, ZR, Operand(R3)));
3038 __ ret();
3039
3040 // blr goes here.
3041 __ movz(R0, Immediate(42), 0);
3042 __ ret();
3043}
3044
3045ASSEMBLER_TEST_RUN(AdrBlr, test) {
3046 typedef int64_t (*Int64Return)() DART_UNUSED;
3047 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3048}
3049
3050// Misc. arithmetic.
3051ASSEMBLER_TEST_GENERATE(Udiv, assembler) {
3052 __ movz(R0, Immediate(27), 0);
3053 __ movz(R1, Immediate(9), 0);
3054 __ udiv(R2, R0, R1);
3055 __ mov(R0, R2);
3056 __ ret();
3057}
3058
3059ASSEMBLER_TEST_RUN(Udiv, test) {
3060 EXPECT(test != nullptr);
3061 typedef int64_t (*Int64Return)() DART_UNUSED;
3062 EXPECT_EQ(3, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3063 EXPECT_DISASSEMBLY(
3064 "movz r0, #0x1b\n"
3065 "movz r1, #0x9\n"
3066 "udiv r2, r0, r1\n"
3067 "mov r0, r2\n"
3068 "ret\n");
3069}
3070
3071ASSEMBLER_TEST_GENERATE(Sdiv, assembler) {
3072 __ movz(R0, Immediate(27), 0);
3073 __ movz(R1, Immediate(9), 0);
3074 __ neg(R1, R1);
3075 __ sdiv(R2, R0, R1);
3076 __ mov(R0, R2);
3077 __ ret();
3078}
3079
3080ASSEMBLER_TEST_RUN(Sdiv, test) {
3081 EXPECT(test != nullptr);
3082 typedef int64_t (*Int64Return)() DART_UNUSED;
3083 EXPECT_EQ(-3, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3084 EXPECT_DISASSEMBLY(
3085 "movz r0, #0x1b\n"
3086 "movz r1, #0x9\n"
3087 "neg r1, r1\n"
3088 "sdiv r2, r0, r1\n"
3089 "mov r0, r2\n"
3090 "ret\n");
3091}
3092
3093ASSEMBLER_TEST_GENERATE(Udiv_zero, assembler) {
3094 __ movz(R0, Immediate(27), 0);
3095 __ movz(R1, Immediate(0), 0);
3096 __ udiv(R2, R0, R1);
3097 __ mov(R0, R2);
3098 __ ret();
3099}
3100
3101ASSEMBLER_TEST_RUN(Udiv_zero, test) {
3102 EXPECT(test != nullptr);
3103 typedef int64_t (*Int64Return)() DART_UNUSED;
3104 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3105 EXPECT_DISASSEMBLY(
3106 "movz r0, #0x1b\n"
3107 "movz r1, #0x0\n"
3108 "udiv r2, r0, r1\n"
3109 "mov r0, r2\n"
3110 "ret\n");
3111}
3112
3113ASSEMBLER_TEST_GENERATE(Sdiv_zero, assembler) {
3114 __ movz(R0, Immediate(27), 0);
3115 __ movz(R1, Immediate(0), 0);
3116 __ sdiv(R2, R0, R1);
3117 __ mov(R0, R2);
3118 __ ret();
3119}
3120
3121ASSEMBLER_TEST_RUN(Sdiv_zero, test) {
3122 EXPECT(test != nullptr);
3123 typedef int64_t (*Int64Return)() DART_UNUSED;
3124 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3125 EXPECT_DISASSEMBLY(
3126 "movz r0, #0x1b\n"
3127 "movz r1, #0x0\n"
3128 "sdiv r2, r0, r1\n"
3129 "mov r0, r2\n"
3130 "ret\n");
3131}
3132
3133ASSEMBLER_TEST_GENERATE(Udiv_corner, assembler) {
3134 __ movz(R0, Immediate(0x8000), 3); // R0 <- 0x8000000000000000
3135 __ movn(R1, Immediate(0), 0); // R1 <- 0xffffffffffffffff
3136 __ udiv(R2, R0, R1);
3137 __ mov(R0, R2);
3138 __ ret();
3139}
3140
3141ASSEMBLER_TEST_RUN(Udiv_corner, test) {
3142 EXPECT(test != nullptr);
3143 typedef int64_t (*Int64Return)() DART_UNUSED;
3144 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3145 EXPECT_DISASSEMBLY(
3146 "movz r0, #0x8000 lsl 48\n"
3147 "movn r1, #0x0\n"
3148 "udiv r2, r0, r1\n"
3149 "mov r0, r2\n"
3150 "ret\n");
3151}
3152
3153ASSEMBLER_TEST_GENERATE(Sdiv_corner, assembler) {
3154 __ movz(R3, Immediate(0x8000), 3); // R0 <- 0x8000000000000000
3155 __ movn(R1, Immediate(0), 0); // R1 <- 0xffffffffffffffff
3156 __ sdiv(R2, R3, R1);
3157 __ mov(R0, R2);
3158 __ ret();
3159}
3160
3161ASSEMBLER_TEST_RUN(Sdiv_corner, test) {
3162 EXPECT(test != nullptr);
3163 typedef int64_t (*Int64Return)() DART_UNUSED;
3164 EXPECT_EQ(static_cast<int64_t>(0x8000000000000000),
3165 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3166 EXPECT_DISASSEMBLY(
3167 "movz r3, #0x8000 lsl 48\n"
3168 "movn r1, #0x0\n"
3169 "sdiv r2, r3, r1\n"
3170 "mov r0, r2\n"
3171 "ret\n");
3172}
3173
3174ASSEMBLER_TEST_GENERATE(Lslv, assembler) {
3175 __ movz(R1, Immediate(21), 0);
3176 __ movz(R2, Immediate(1), 0);
3177 __ lslv(R0, R1, R2);
3178 __ ret();
3179}
3180
3181ASSEMBLER_TEST_RUN(Lslv, test) {
3182 typedef int64_t (*Int64Return)() DART_UNUSED;
3183 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3184 EXPECT_DISASSEMBLY(
3185 "movz r1, #0x15\n"
3186 "movz r2, #0x1\n"
3187 "lsl r0, r1, r2\n"
3188 "ret\n");
3189}
3190
3191ASSEMBLER_TEST_GENERATE(Lsrv, assembler) {
3192 __ movz(R1, Immediate(84), 0);
3193 __ movz(R2, Immediate(1), 0);
3194 __ lsrv(R0, R1, R2);
3195 __ ret();
3196}
3197
3198ASSEMBLER_TEST_RUN(Lsrv, test) {
3199 typedef int64_t (*Int64Return)() DART_UNUSED;
3200 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3201 EXPECT_DISASSEMBLY(
3202 "movz r1, #0x54\n"
3203 "movz r2, #0x1\n"
3204 "lsr r0, r1, r2\n"
3205 "ret\n");
3206}
3207
3208ASSEMBLER_TEST_GENERATE(LShiftingV, assembler) {
3209 __ movz(R1, Immediate(1), 0);
3210 __ movz(R2, Immediate(63), 0);
3211 __ lslv(R1, R1, R2);
3212 __ lsrv(R0, R1, R2);
3213 __ ret();
3214}
3215
3216ASSEMBLER_TEST_RUN(LShiftingV, test) {
3217 typedef int64_t (*Int64Return)() DART_UNUSED;
3218 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3219 EXPECT_DISASSEMBLY(
3220 "movz r1, #0x1\n"
3221 "movz r2, #0x3f\n"
3222 "lsl r1, r1, r2\n"
3223 "lsr r0, r1, r2\n"
3224 "ret\n");
3225}
3226
3227ASSEMBLER_TEST_GENERATE(RShiftingV, assembler) {
3228 __ movz(R1, Immediate(1), 0);
3229 __ movz(R2, Immediate(63), 0);
3230 __ lslv(R1, R1, R2);
3231 __ asrv(R0, R1, R2);
3232 __ ret();
3233}
3234
3235ASSEMBLER_TEST_RUN(RShiftingV, test) {
3236 typedef int64_t (*Int64Return)() DART_UNUSED;
3237 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3238 EXPECT_DISASSEMBLY(
3239 "movz r1, #0x1\n"
3240 "movz r2, #0x3f\n"
3241 "lsl r1, r1, r2\n"
3242 "asr r0, r1, r2\n"
3243 "ret\n");
3244}
3245
3246ASSEMBLER_TEST_GENERATE(Mult_pos, assembler) {
3247 __ movz(R1, Immediate(6), 0);
3248 __ movz(R2, Immediate(7), 0);
3249 __ mul(R0, R1, R2);
3250 __ ret();
3251}
3252
3253ASSEMBLER_TEST_RUN(Mult_pos, test) {
3254 typedef int64_t (*Int64Return)() DART_UNUSED;
3255 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3256 EXPECT_DISASSEMBLY(
3257 "movz r1, #0x6\n"
3258 "movz r2, #0x7\n"
3259 "mul r0, r1, r2\n"
3260 "ret\n");
3261}
3262
3263ASSEMBLER_TEST_GENERATE(Mult_neg, assembler) {
3264 __ movz(R1, Immediate(6), 0);
3265 __ movz(R2, Immediate(7), 0);
3266 __ neg(R2, R2);
3267 __ mul(R0, R1, R2);
3268 __ ret();
3269}
3270
3271ASSEMBLER_TEST_RUN(Mult_neg, test) {
3272 typedef int64_t (*Int64Return)() DART_UNUSED;
3273 EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3274 EXPECT_DISASSEMBLY(
3275 "movz r1, #0x6\n"
3276 "movz r2, #0x7\n"
3277 "neg r2, r2\n"
3278 "mul r0, r1, r2\n"
3279 "ret\n");
3280}
3281
3282ASSEMBLER_TEST_GENERATE(Smulh_pos, assembler) {
3283 __ movz(R1, Immediate(6), 0);
3284 __ movz(R2, Immediate(7), 0);
3285 __ smulh(R0, R1, R2);
3286 __ ret();
3287}
3288
3289ASSEMBLER_TEST_RUN(Smulh_pos, test) {
3290 typedef int64_t (*Int64Return)() DART_UNUSED;
3291 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3292 EXPECT_DISASSEMBLY(
3293 "movz r1, #0x6\n"
3294 "movz r2, #0x7\n"
3295 "smulh r0, r1, r2\n"
3296 "ret\n");
3297}
3298
3299ASSEMBLER_TEST_GENERATE(Smulh_neg, assembler) {
3300 __ movz(R1, Immediate(6), 0);
3301 __ movz(R2, Immediate(7), 0);
3302 __ neg(R2, R2);
3303 __ smulh(R0, R1, R2);
3304 __ ret();
3305}
3306
3307ASSEMBLER_TEST_RUN(Smulh_neg, test) {
3308 typedef int64_t (*Int64Return)() DART_UNUSED;
3309 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3310 EXPECT_DISASSEMBLY(
3311 "movz r1, #0x6\n"
3312 "movz r2, #0x7\n"
3313 "neg r2, r2\n"
3314 "smulh r0, r1, r2\n"
3315 "ret\n");
3316}
3317
3318ASSEMBLER_TEST_GENERATE(Umulh, assembler) {
3319 __ movz(R1, Immediate(-1), 3); // 0xffff000000000000
3320 __ movz(R2, Immediate(7), 3); // 0x0007000000000000
3321 __ umulh(R0, R1, R2); // 0x0006fff900000000
3322 __ ret();
3323}
3324
3325ASSEMBLER_TEST_RUN(Umulh, test) {
3326 typedef int64_t (*Int64Return)() DART_UNUSED;
3327 EXPECT_EQ(static_cast<int64_t>(0x6fff900000000),
3328 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3329 EXPECT_DISASSEMBLY(
3330 "movz r1, #0xffff lsl 48\n"
3331 "movz r2, #0x7 lsl 48\n"
3332 "umulh r0, r1, r2\n"
3333 "ret\n");
3334}
3335
3336ASSEMBLER_TEST_GENERATE(Umaddl, assembler) {
3337 __ movn(R1, Immediate(0), 0); // W1 = 0xffffffff.
3338 __ movz(R2, Immediate(7), 0); // W2 = 7.
3339 __ movz(R3, Immediate(8), 0); // X3 = 8.
3340 __ umaddl(R0, R1, R2, R3); // X0 = W1*W2 + X3 = 0x700000001.
3341 __ ret();
3342}
3343
3344ASSEMBLER_TEST_RUN(Umaddl, test) {
3345 typedef int64_t (*Int64Return)() DART_UNUSED;
3346 EXPECT_EQ(0x700000001, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3347 EXPECT_DISASSEMBLY(
3348 "movn r1, #0x0\n"
3349 "movz r2, #0x7\n"
3350 "movz r3, #0x8\n"
3351 "umaddl r0, r1, r2, r3\n"
3352 "ret\n");
3353}
3354
3355ASSEMBLER_TEST_GENERATE(Smaddl, assembler) {
3356 __ movn(R1, Immediate(1), 0); // W1 = -2.
3357 __ movz(R2, Immediate(7), 0); // W2 = 7.
3358 __ movz(R3, Immediate(20), 0); // X3 = 20.
3359 __ smaddl(R0, R1, R2, R3); // X0 = W1*W2 + X3 = 6.
3360 __ ret();
3361}
3362
3363ASSEMBLER_TEST_RUN(Smaddl, test) {
3364 typedef int64_t (*Int64Return)() DART_UNUSED;
3365 EXPECT_EQ(6, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3366 EXPECT_DISASSEMBLY(
3367 "movn r1, #0x1\n"
3368 "movz r2, #0x7\n"
3369 "movz r3, #0x14\n"
3370 "smaddl r0, r1, r2, r3\n"
3371 "ret\n");
3372}
3373
3374ASSEMBLER_TEST_GENERATE(Smaddl2, assembler) {
3375 __ movn(R1, Immediate(1), 0); // W1 = -2.
3376 __ movn(R2, Immediate(0), 0); // W2 = -1.
3377 __ smull(R0, R1, R2); // X0 = W1*W2 = 2, alias of smaddl.
3378 __ ret();
3379}
3380
3381ASSEMBLER_TEST_RUN(Smaddl2, test) {
3382 typedef int64_t (*Int64Return)() DART_UNUSED;
3383 EXPECT_EQ(2, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3384 EXPECT_DISASSEMBLY(
3385 "movn r1, #0x1\n"
3386 "movn r2, #0x0\n"
3387 "smull r0, r1, r2\n"
3388 "ret\n");
3389}
3390
3391ASSEMBLER_TEST_GENERATE(Smaddl3, assembler) {
3392 __ movz(R1, Immediate(0xffff), 0); // W1 = 0xffff.
3393 __ movz(R2, Immediate(0xffff), 0); // W2 = 0xffff.
3394 __ smull(R0, R1, R2); // X0 = W1*W2, alias of smaddl.
3395 __ ret();
3396}
3397
3398ASSEMBLER_TEST_RUN(Smaddl3, test) {
3399 typedef int64_t (*Int64Return)() DART_UNUSED;
3400 EXPECT_EQ(0xfffe0001, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3401 EXPECT_DISASSEMBLY(
3402 "movz r1, #0xffff\n"
3403 "movz r2, #0xffff\n"
3404 "smull r0, r1, r2\n"
3405 "ret\n");
3406}
3407
3408ASSEMBLER_TEST_GENERATE(SmaddlOverflow, assembler) {
3409 Label return_ltuae;
3410 __ movz(R1, Immediate(0xffff), 0); // W1 = 0xffff.
3411 __ AddImmediate(R1, 4); // W1 = 0x10003.
3412 __ movz(R2, Immediate(0x7fff), 0); // W2 = 0xffff.
3413 __ smull(R0, R1, R2); // X0 = W1*W2, alias of smaddl.
3414 __ AsrImmediate(R3, R0, 31);
3415 __ cmp(R3, Operand(R0, ASR, 63)); // Detect signed 32 bit overflow.
3416 __ b(&return_ltuae, NE);
3417 __ ret();
3418 __ Bind(&return_ltuae);
3419 __ movz(R0, Immediate(42), 0);
3420 __ ret();
3421}
3422
3423ASSEMBLER_TEST_RUN(SmaddlOverflow, test) {
3424 typedef int64_t (*Int64Return)() DART_UNUSED;
3425 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3426 EXPECT_DISASSEMBLY(
3427 "movz r1, #0xffff\n"
3428 "add r1, r1, #0x4\n"
3429 "movz r2, #0x7fff\n"
3430 "smull r0, r1, r2\n"
3431 "asr r3, r0, #31\n"
3432 "cmp r3, r0 asr #63\n"
3433 "bne +8\n"
3434 "ret\n"
3435 "movz r0, #0x2a\n"
3436 "ret\n");
3437}
3438
3439ASSEMBLER_TEST_GENERATE(SmaddlOverflow2, assembler) {
3440 Label return_ltuae;
3441 __ movz(R1, Immediate(0xffff), 0); // W1 = 0xffff.
3442 __ movn(R2, Immediate(0xffff), 0); // W2 = -0x10000.
3443 __ AddImmediate(R2, -3); // W2 = -0x10003.
3444 __ smull(R0, R1, R2); // X0 = W1*W2, alias of smaddl.
3445 __ AsrImmediate(R3, R0, 31);
3446 __ cmp(R3, Operand(R0, ASR, 63)); // Detect signed 32 bit overflow.
3447 __ b(&return_ltuae, NE);
3448 __ ret();
3449 __ Bind(&return_ltuae);
3450 __ movz(R0, Immediate(42), 0);
3451 __ ret();
3452}
3453
3454ASSEMBLER_TEST_RUN(SmaddlOverflow2, test) {
3455 typedef int64_t (*Int64Return)() DART_UNUSED;
3456 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3457 EXPECT_DISASSEMBLY(
3458 "movz r1, #0xffff\n"
3459 "movn r2, #0xffff\n"
3460 "sub r2, r2, #0x3\n"
3461 "smull r0, r1, r2\n"
3462 "asr r3, r0, #31\n"
3463 "cmp r3, r0 asr #63\n"
3464 "bne +8\n"
3465 "ret\n"
3466 "movz r0, #0x2a\n"
3467 "ret\n");
3468}
3469
3470ASSEMBLER_TEST_GENERATE(SmaddlOverflow3, assembler) {
3471 Label return_ltuae;
3472 __ LoadImmediate(R1, 0x01007fff);
3473 __ LoadImmediate(R2, 0x01007fff);
3474 __ smull(R0, R1, R2); // X0 = W1*W2, alias of smaddl.
3475 __ AsrImmediate(R3, R0, 31);
3476 __ cmp(R3, Operand(R0, ASR, 63)); // Detect signed 32 bit overflow.
3477 __ b(&return_ltuae, NE);
3478 __ ret();
3479 __ Bind(&return_ltuae);
3480 __ movz(R0, Immediate(42), 0);
3481 __ ret();
3482}
3483
3484ASSEMBLER_TEST_RUN(SmaddlOverflow3, test) {
3485 typedef int64_t (*Int64Return)() DART_UNUSED;
3486 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3487 EXPECT_DISASSEMBLY(
3488 "movz r1, #0x7fff\n"
3489 "movk r1, #0x100 lsl 16\n"
3490 "movz r2, #0x7fff\n"
3491 "movk r2, #0x100 lsl 16\n"
3492 "smull r0, r1, r2\n"
3493 "asr r3, r0, #31\n"
3494 "cmp r3, r0 asr #63\n"
3495 "bne +8\n"
3496 "ret\n"
3497 "movz r0, #0x2a\n"
3498 "ret\n");
3499}
3500
3501ASSEMBLER_TEST_GENERATE(NegNoOverflow, assembler) {
3502 Label return_ltuae;
3503 __ LoadImmediate(R1, 0x7fffffff);
3504 __ negsw(R0, R1);
3505 __ sxtw(R0, R0);
3506 __ b(&return_ltuae, VS); // Branch on overflow set.
3507 __ ret();
3508 __ Bind(&return_ltuae);
3509 __ movz(R0, Immediate(42), 0);
3510 __ ret();
3511}
3512
3513ASSEMBLER_TEST_RUN(NegNoOverflow, test) {
3514 typedef int64_t (*Int64Return)() DART_UNUSED;
3515 EXPECT_EQ(-0x7fffffff, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3516 EXPECT_DISASSEMBLY(
3517 "mov r1, 0x7fffffff\n"
3518 "negws r0, r1\n"
3519 "sxtw r0, r0\n"
3520 "bvs +8\n"
3521 "ret\n"
3522 "movz r0, #0x2a\n"
3523 "ret\n");
3524}
3525
3526ASSEMBLER_TEST_GENERATE(NegNoOverflow2, assembler) {
3527 Label return_ltuae;
3528 __ LoadImmediate(R1, 0x7123);
3529 __ negsw(R0, R1);
3530 __ sxtw(R0, R0);
3531 __ b(&return_ltuae, VS); // Branch on overflow set.
3532 __ ret();
3533 __ Bind(&return_ltuae);
3534 __ movz(R0, Immediate(42), 0);
3535 __ ret();
3536}
3537
3538ASSEMBLER_TEST_RUN(NegNoOverflow2, test) {
3539 typedef int64_t (*Int64Return)() DART_UNUSED;
3540 EXPECT_EQ(-0x7123, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3541 EXPECT_DISASSEMBLY(
3542 "movz r1, #0x7123\n"
3543 "negws r0, r1\n"
3544 "sxtw r0, r0\n"
3545 "bvs +8\n"
3546 "ret\n"
3547 "movz r0, #0x2a\n"
3548 "ret\n");
3549}
3550
3551ASSEMBLER_TEST_GENERATE(NegOverflow, assembler) {
3552 Label return_ltuae;
3553 __ LoadImmediate(R1, -0x80000000ll);
3554 __ negsw(R0, R1); // X0 = W1*W2, alias of smaddl.
3555 __ sxtw(R0, R0);
3556 __ b(&return_ltuae, VS); // Branch on overflow set.
3557 __ ret();
3558 __ Bind(&return_ltuae);
3559 __ movz(R0, Immediate(42), 0);
3560 __ ret();
3561}
3562
3563ASSEMBLER_TEST_RUN(NegOverflow, test) {
3564 typedef int64_t (*Int64Return)() DART_UNUSED;
3565 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3566 EXPECT_DISASSEMBLY(
3567 "mov r1, 0xffffffff80000000\n"
3568 "negws r0, r1\n"
3569 "sxtw r0, r0\n"
3570 "bvs +8\n"
3571 "ret\n"
3572 "movz r0, #0x2a\n"
3573 "ret\n");
3574}
3575
3576// Loading immediate values without the object pool.
3577ASSEMBLER_TEST_GENERATE(LoadImmediateSmall, assembler) {
3578 __ LoadImmediate(R0, 42);
3579 __ ret();
3580}
3581
3582ASSEMBLER_TEST_RUN(LoadImmediateSmall, test) {
3583 typedef int64_t (*Int64Return)() DART_UNUSED;
3584 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3585 EXPECT_DISASSEMBLY(
3586 "movz r0, #0x2a\n"
3587 "ret\n");
3588}
3589
3590ASSEMBLER_TEST_GENERATE(LoadImmediateMed, assembler) {
3591 __ LoadImmediate(R0, 0xf1234123);
3592 __ ret();
3593}
3594
3595ASSEMBLER_TEST_RUN(LoadImmediateMed, test) {
3596 typedef int64_t (*Int64Return)() DART_UNUSED;
3597 EXPECT_EQ(0xf1234123, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3598 EXPECT_DISASSEMBLY(
3599 "movz r0, #0x4123\n"
3600 "movk r0, #0xf123 lsl 16\n"
3601 "ret\n");
3602}
3603
3604ASSEMBLER_TEST_GENERATE(LoadImmediateMed2, assembler) {
3605 __ LoadImmediate(R0, 0x4321f1234123);
3606 __ ret();
3607}
3608
3609ASSEMBLER_TEST_RUN(LoadImmediateMed2, test) {
3610 typedef int64_t (*Int64Return)() DART_UNUSED;
3611 EXPECT_EQ(0x4321f1234123,
3612 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3613 EXPECT_DISASSEMBLY(
3614 "movz r0, #0x4123\n"
3615 "movk r0, #0xf123 lsl 16\n"
3616 "movk r0, #0x4321 lsl 32\n"
3617 "ret\n");
3618}
3619
3620ASSEMBLER_TEST_GENERATE(LoadImmediateLarge, assembler) {
3621 __ LoadImmediate(R0, 0x9287436598237465);
3622 __ ret();
3623}
3624
3625ASSEMBLER_TEST_RUN(LoadImmediateLarge, test) {
3626 typedef int64_t (*Int64Return)() DART_UNUSED;
3627 EXPECT_EQ(static_cast<int64_t>(0x9287436598237465),
3628 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3629 EXPECT_DISASSEMBLY(
3630 "movz r0, #0x7465\n"
3631 "movk r0, #0x9823 lsl 16\n"
3632 "movk r0, #0x4365 lsl 32\n"
3633 "movk r0, #0x9287 lsl 48\n"
3634 "ret\n");
3635}
3636
3637ASSEMBLER_TEST_GENERATE(LoadImmediateSmallNeg, assembler) {
3638 __ LoadImmediate(R0, -42);
3639 __ ret();
3640}
3641
3642ASSEMBLER_TEST_RUN(LoadImmediateSmallNeg, test) {
3643 typedef int64_t (*Int64Return)() DART_UNUSED;
3644 EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3645 EXPECT_DISASSEMBLY(
3646 "movn r0, #0x29\n"
3647 "ret\n");
3648}
3649
3650ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg, assembler) {
3651 __ LoadImmediate(R0, -0x1212341234);
3652 __ ret();
3653}
3654
3655ASSEMBLER_TEST_RUN(LoadImmediateMedNeg, test) {
3656 typedef int64_t (*Int64Return)() DART_UNUSED;
3657 EXPECT_EQ(-0x1212341234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3658 EXPECT_DISASSEMBLY(
3659 "movn r0, #0x12 lsl 32\n"
3660 "movk r0, #0xedcb lsl 16\n"
3661 "movk r0, #0xedcc\n"
3662 "ret\n");
3663}
3664
3665ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg2, assembler) {
3666 __ LoadImmediate(R0, -0x1212340000);
3667 __ ret();
3668}
3669
3670ASSEMBLER_TEST_RUN(LoadImmediateMedNeg2, test) {
3671 typedef int64_t (*Int64Return)() DART_UNUSED;
3672 EXPECT_EQ(-0x1212340000, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3673 EXPECT_DISASSEMBLY(
3674 "movn r0, #0x12 lsl 32\n"
3675 "movk r0, #0xedcc lsl 16\n"
3676 "movk r0, #0x0\n"
3677 "ret\n");
3678}
3679
3680ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg3, assembler) {
3681 __ LoadImmediate(R0, -0x1200001234);
3682 __ ret();
3683}
3684
3685ASSEMBLER_TEST_RUN(LoadImmediateMedNeg3, test) {
3686 typedef int64_t (*Int64Return)() DART_UNUSED;
3687 EXPECT_EQ(-0x1200001234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3688 EXPECT_DISASSEMBLY(
3689 "movn r0, #0x12 lsl 32\n"
3690 "movk r0, #0xedcc\n"
3691 "ret\n");
3692}
3693
3694ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg4, assembler) {
3695 __ LoadImmediate(R0, -0x12341234);
3696 __ ret();
3697}
3698
3699ASSEMBLER_TEST_RUN(LoadImmediateMedNeg4, test) {
3700 typedef int64_t (*Int64Return)() DART_UNUSED;
3701 EXPECT_EQ(-0x12341234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
3702 EXPECT_DISASSEMBLY(
3703 "movn r0, #0x1234 lsl 16\n"
3704 "movk r0, #0xedcc\n"
3705 "ret\n");
3706}
3707
3708ASSEMBLER_TEST_GENERATE(LoadHalfWordUnaligned, assembler) {
3709 __ ldr(R1, Address(R0), kTwoBytes);
3710 __ mov(R0, R1);
3711 __ ret();
3712}
3713
3714ASSEMBLER_TEST_RUN(LoadHalfWordUnaligned, test) {
3715 EXPECT(test != nullptr);
3716 typedef intptr_t (*LoadHalfWordUnaligned)(intptr_t) DART_UNUSED;
3717 uint8_t buffer[4] = {
3718 0x89,
3719 0xAB,
3720 0xCD,
3721 0xEF,
3722 };
3723
3724 EXPECT_EQ(
3725 static_cast<int16_t>(static_cast<uint16_t>(0xAB89)),
3726 EXECUTE_TEST_CODE_INTPTR_INTPTR(LoadHalfWordUnaligned, test->entry(),
3727 reinterpret_cast<intptr_t>(&buffer[0])));
3728 EXPECT_EQ(
3729 static_cast<int16_t>(static_cast<uint16_t>(0xCDAB)),
3730 EXECUTE_TEST_CODE_INTPTR_INTPTR(LoadHalfWordUnaligned, test->entry(),
3731 reinterpret_cast<intptr_t>(&buffer[1])));
3732 EXPECT_DISASSEMBLY(
3733 "ldrsh r1, [r0]\n"
3734 "mov r0, r1\n"
3735 "ret\n");
3736}
3737
3738ASSEMBLER_TEST_GENERATE(LoadHalfWordUnsignedUnaligned, assembler) {
3739 __ ldr(R1, Address(R0), kUnsignedTwoBytes);
3740 __ mov(R0, R1);
3741 __ ret();
3742}
3743
3744ASSEMBLER_TEST_RUN(LoadHalfWordUnsignedUnaligned, test) {
3745 EXPECT(test != nullptr);
3746 typedef intptr_t (*LoadHalfWordUnsignedUnaligned)(intptr_t) DART_UNUSED;
3747 uint8_t buffer[4] = {
3748 0x89,
3749 0xAB,
3750 0xCD,
3751 0xEF,
3752 };
3753
3754 EXPECT_EQ(0xAB89, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3755 LoadHalfWordUnsignedUnaligned, test->entry(),
3756 reinterpret_cast<intptr_t>(&buffer[0])));
3757 EXPECT_EQ(0xCDAB, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3758 LoadHalfWordUnsignedUnaligned, test->entry(),
3759 reinterpret_cast<intptr_t>(&buffer[1])));
3760 EXPECT_DISASSEMBLY(
3761 "ldrh r1, [r0]\n"
3762 "mov r0, r1\n"
3763 "ret\n");
3764}
3765
3766ASSEMBLER_TEST_GENERATE(StoreHalfWordUnaligned, assembler) {
3767 __ LoadImmediate(R1, 0xABCD);
3768 __ str(R1, Address(R0), kTwoBytes);
3769 __ mov(R0, R1);
3770 __ ret();
3771}
3772
3773ASSEMBLER_TEST_RUN(StoreHalfWordUnaligned, test) {
3774 EXPECT(test != nullptr);
3775 typedef intptr_t (*StoreHalfWordUnaligned)(intptr_t) DART_UNUSED;
3776 uint8_t buffer[4] = {
3777 0,
3778 0,
3779 0,
3780 0,
3781 };
3782
3783 EXPECT_EQ(0xABCD, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3784 StoreHalfWordUnaligned, test->entry(),
3785 reinterpret_cast<intptr_t>(&buffer[0])));
3786 EXPECT_EQ(0xCD, buffer[0]);
3787 EXPECT_EQ(0xAB, buffer[1]);
3788 EXPECT_EQ(0, buffer[2]);
3789
3790 EXPECT_EQ(0xABCD, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3791 StoreHalfWordUnaligned, test->entry(),
3792 reinterpret_cast<intptr_t>(&buffer[1])));
3793 EXPECT_EQ(0xCD, buffer[1]);
3794 EXPECT_EQ(0xAB, buffer[2]);
3795 EXPECT_EQ(0, buffer[3]);
3796 EXPECT_DISASSEMBLY(
3797 "movz r1, #0xabcd\n"
3798 "strh r1, [r0]\n"
3799 "mov r0, r1\n"
3800 "ret\n");
3801}
3802
3803ASSEMBLER_TEST_GENERATE(LoadWordUnaligned, assembler) {
3804 __ ldr(R1, Address(R0), kUnsignedFourBytes);
3805 __ mov(R0, R1);
3806 __ ret();
3807}
3808
3809ASSEMBLER_TEST_RUN(LoadWordUnaligned, test) {
3810 EXPECT(test != nullptr);
3811 typedef int32_t (*LoadWordUnaligned)(intptr_t) DART_UNUSED;
3812 uint8_t buffer[8] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
3813
3814 EXPECT_EQ(
3815 static_cast<int32_t>(0x78563412),
3816 EXECUTE_TEST_CODE_INT32_INTPTR(LoadWordUnaligned, test->entry(),
3817 reinterpret_cast<intptr_t>(&buffer[0])));
3818 EXPECT_EQ(
3819 static_cast<int32_t>(0x9A785634),
3820 EXECUTE_TEST_CODE_INT32_INTPTR(LoadWordUnaligned, test->entry(),
3821 reinterpret_cast<intptr_t>(&buffer[1])));
3822 EXPECT_EQ(
3823 static_cast<int32_t>(0xBC9A7856),
3824 EXECUTE_TEST_CODE_INT32_INTPTR(LoadWordUnaligned, test->entry(),
3825 reinterpret_cast<intptr_t>(&buffer[2])));
3826 EXPECT_EQ(
3827 static_cast<int32_t>(0xDEBC9A78),
3828 EXECUTE_TEST_CODE_INT32_INTPTR(LoadWordUnaligned, test->entry(),
3829 reinterpret_cast<intptr_t>(&buffer[3])));
3830 EXPECT_DISASSEMBLY(
3831 "ldrw r1, [r0]\n"
3832 "mov r0, r1\n"
3833 "ret\n");
3834}
3835
3836ASSEMBLER_TEST_GENERATE(StoreWordUnaligned, assembler) {
3837 __ LoadImmediate(R1, 0x12345678);
3838 __ str(R1, Address(R0), kUnsignedFourBytes);
3839 __ mov(R0, R1);
3840 __ ret();
3841}
3842
3843ASSEMBLER_TEST_RUN(StoreWordUnaligned, test) {
3844 EXPECT(test != nullptr);
3845 typedef intptr_t (*StoreWordUnaligned)(intptr_t) DART_UNUSED;
3846 uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3847
3848 EXPECT_EQ(0x12345678, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3849 StoreWordUnaligned, test->entry(),
3850 reinterpret_cast<intptr_t>(&buffer[0])));
3851 EXPECT_EQ(0x78, buffer[0]);
3852 EXPECT_EQ(0x56, buffer[1]);
3853 EXPECT_EQ(0x34, buffer[2]);
3854 EXPECT_EQ(0x12, buffer[3]);
3855
3856 EXPECT_EQ(0x12345678, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3857 StoreWordUnaligned, test->entry(),
3858 reinterpret_cast<intptr_t>(&buffer[1])));
3859 EXPECT_EQ(0x78, buffer[1]);
3860 EXPECT_EQ(0x56, buffer[2]);
3861 EXPECT_EQ(0x34, buffer[3]);
3862 EXPECT_EQ(0x12, buffer[4]);
3863
3864 EXPECT_EQ(0x12345678, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3865 StoreWordUnaligned, test->entry(),
3866 reinterpret_cast<intptr_t>(&buffer[2])));
3867 EXPECT_EQ(0x78, buffer[2]);
3868 EXPECT_EQ(0x56, buffer[3]);
3869 EXPECT_EQ(0x34, buffer[4]);
3870 EXPECT_EQ(0x12, buffer[5]);
3871
3872 EXPECT_EQ(0x12345678, EXECUTE_TEST_CODE_INTPTR_INTPTR(
3873 StoreWordUnaligned, test->entry(),
3874 reinterpret_cast<intptr_t>(&buffer[3])));
3875 EXPECT_EQ(0x78, buffer[3]);
3876 EXPECT_EQ(0x56, buffer[4]);
3877 EXPECT_EQ(0x34, buffer[5]);
3878 EXPECT_EQ(0x12, buffer[6]);
3879
3880 EXPECT_DISASSEMBLY(
3881 "movz r1, #0x5678\n"
3882 "movk r1, #0x1234 lsl 16\n"
3883 "strw r1, [r0]\n"
3884 "mov r0, r1\n"
3885 "ret\n");
3886}
3887
3888void EnterTestFrame(Assembler* assembler) {
3889 __ SetupDartSP();
3890 __ EnterFrame(0);
3891 __ Push(CODE_REG);
3892 __ Push(THR);
3893 __ Push(HEAP_BITS);
3894 __ Push(NULL_REG);
3895 __ TagAndPushPP();
3896 __ mov(CODE_REG, R0);
3897 __ mov(THR, R1);
3898 __ RestorePinnedRegisters();
3899 __ LoadPoolPointer(PP);
3900}
3901
3902void LeaveTestFrame(Assembler* assembler) {
3903 __ PopAndUntagPP();
3904 __ Pop(NULL_REG);
3905 __ Pop(HEAP_BITS);
3906 __ Pop(THR);
3907 __ Pop(CODE_REG);
3908 __ LeaveFrame();
3909 __ RestoreCSP();
3910}
3911
3912// Loading immediate values with the object pool.
3913ASSEMBLER_TEST_GENERATE(LoadImmediatePPSmall, assembler) {
3914 EnterTestFrame(assembler);
3915 __ LoadImmediate(R0, 42);
3916 LeaveTestFrame(assembler);
3917 __ ret();
3918}
3919
3920ASSEMBLER_TEST_RUN(LoadImmediatePPSmall, test) {
3921 EXPECT_EQ(42, test->InvokeWithCodeAndThread<int64_t>());
3922}
3923
3924ASSEMBLER_TEST_GENERATE(LoadImmediatePPMed, assembler) {
3925 EnterTestFrame(assembler);
3926 __ LoadImmediate(R0, 0xf1234123);
3927 LeaveTestFrame(assembler);
3928 __ ret();
3929}
3930
3931ASSEMBLER_TEST_RUN(LoadImmediatePPMed, test) {
3932 EXPECT_EQ(0xf1234123, test->InvokeWithCodeAndThread<int64_t>());
3933}
3934
3935ASSEMBLER_TEST_GENERATE(LoadImmediatePPMed2, assembler) {
3936 EnterTestFrame(assembler);
3937 __ LoadImmediate(R0, 0x4321f1234124);
3938 LeaveTestFrame(assembler);
3939 __ ret();
3940}
3941
3942ASSEMBLER_TEST_RUN(LoadImmediatePPMed2, test) {
3943 EXPECT_EQ(0x4321f1234124, test->InvokeWithCodeAndThread<int64_t>());
3944}
3945
3946ASSEMBLER_TEST_GENERATE(LoadImmediatePPLarge, assembler) {
3947 EnterTestFrame(assembler);
3948 __ LoadImmediate(R0, 0x9287436598237465);
3949 LeaveTestFrame(assembler);
3950 __ ret();
3951}
3952
3953ASSEMBLER_TEST_RUN(LoadImmediatePPLarge, test) {
3954 EXPECT_EQ(static_cast<int64_t>(0x9287436598237465),
3955 test->InvokeWithCodeAndThread<int64_t>());
3956}
3957
3958// LoadObject null.
3959ASSEMBLER_TEST_GENERATE(LoadObjectNull, assembler) {
3960 EnterTestFrame(assembler);
3961 __ LoadObject(R0, Object::null_object());
3962 LeaveTestFrame(assembler);
3963 __ ret();
3964}
3965
3966ASSEMBLER_TEST_RUN(LoadObjectNull, test) {
3967 EXPECT_EQ(static_cast<uword>(Object::null()),
3968 test->InvokeWithCodeAndThread<uword>());
3969}
3970
3971// PushObject null.
3972ASSEMBLER_TEST_GENERATE(PushObjectNull, assembler) {
3973 EnterTestFrame(assembler);
3974 __ PushObject(Object::null_object());
3975 __ Pop(R0);
3976 LeaveTestFrame(assembler);
3977 __ ret();
3978}
3979
3980ASSEMBLER_TEST_RUN(PushObjectNull, test) {
3981 EXPECT_EQ(static_cast<uword>(Object::null()),
3982 test->InvokeWithCodeAndThread<uword>());
3983}
3984
3985// CompareObject null.
3986ASSEMBLER_TEST_GENERATE(CompareObjectNull, assembler) {
3987 EnterTestFrame(assembler);
3988 __ LoadObject(R0, Object::bool_true());
3989 __ LoadObject(R1, Object::bool_false());
3990 __ ldr(R2, Address(THR, Thread::object_null_offset()));
3991 __ CompareObject(R2, Object::null_object());
3992 __ csel(R0, R0, R1, EQ);
3993 LeaveTestFrame(assembler);
3994 __ ret();
3995}
3996
3997ASSEMBLER_TEST_RUN(CompareObjectNull, test) {
3998 EXPECT_EQ(static_cast<uword>(Bool::True().ptr()),
3999 test->InvokeWithCodeAndThread<uword>());
4000}
4001
4002ASSEMBLER_TEST_GENERATE(LoadObjectTrue, assembler) {
4003 EnterTestFrame(assembler);
4004 __ LoadObject(R0, Bool::True());
4005 LeaveTestFrame(assembler);
4006 __ ret();
4007}
4008
4009ASSEMBLER_TEST_RUN(LoadObjectTrue, test) {
4010 EXPECT_EQ(static_cast<uword>(Bool::True().ptr()),
4011 test->InvokeWithCodeAndThread<uword>());
4012}
4013
4014ASSEMBLER_TEST_GENERATE(LoadObjectFalse, assembler) {
4015 EnterTestFrame(assembler);
4016 __ LoadObject(R0, Bool::False());
4017 LeaveTestFrame(assembler);
4018 __ ret();
4019}
4020
4021ASSEMBLER_TEST_RUN(LoadObjectFalse, test) {
4022 EXPECT_EQ(static_cast<uword>(Bool::False().ptr()),
4023 test->InvokeWithCodeAndThread<uword>());
4024}
4025
4026ASSEMBLER_TEST_GENERATE(CSelTrue, assembler) {
4027 __ LoadImmediate(R1, 42);
4028 __ LoadImmediate(R2, 1234);
4029 __ CompareRegisters(R1, R2);
4030 __ csel(R0, R1, R2, LT);
4031 __ ret();
4032}
4033
4034ASSEMBLER_TEST_RUN(CSelTrue, test) {
4035 typedef int64_t (*Int64Return)() DART_UNUSED;
4036 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4037 EXPECT_DISASSEMBLY(
4038 "movz r1, #0x2a\n"
4039 "movz r2, #0x4d2\n"
4040 "cmp r1, r2\n"
4041 "csel r0, r1, r2, lt\n"
4042 "ret\n");
4043}
4044
4045ASSEMBLER_TEST_GENERATE(CSelFalse, assembler) {
4046 __ LoadImmediate(R1, 42);
4047 __ LoadImmediate(R2, 1234);
4048 __ CompareRegisters(R1, R2);
4049 __ csel(R0, R1, R2, GE);
4050 __ ret();
4051}
4052
4053ASSEMBLER_TEST_RUN(CSelFalse, test) {
4054 typedef int64_t (*Int64Return)() DART_UNUSED;
4055 EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4056 EXPECT_DISASSEMBLY(
4057 "movz r1, #0x2a\n"
4058 "movz r2, #0x4d2\n"
4059 "cmp r1, r2\n"
4060 "csel r0, r1, r2, ge\n"
4061 "ret\n");
4062}
4063
4064ASSEMBLER_TEST_GENERATE(CsincFalse, assembler) {
4065 __ LoadImmediate(R1, 42);
4066 __ LoadImmediate(R2, 1234);
4067 __ CompareRegisters(R1, R2);
4068 __ csinc(R0, R2, R1, GE);
4069 __ ret();
4070}
4071
4072ASSEMBLER_TEST_RUN(CsincFalse, test) {
4073 typedef int64_t (*Int64Return)() DART_UNUSED;
4074 EXPECT_EQ(43, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4075}
4076
4077ASSEMBLER_TEST_GENERATE(CsincTrue, assembler) {
4078 __ LoadImmediate(R1, 42);
4079 __ LoadImmediate(R2, 1234);
4080 __ CompareRegisters(R1, R2);
4081 __ csinc(R0, R2, R1, LT);
4082 __ ret();
4083}
4084
4085ASSEMBLER_TEST_RUN(CsincTrue, test) {
4086 typedef int64_t (*Int64Return)() DART_UNUSED;
4087 EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4088 EXPECT_DISASSEMBLY(
4089 "movz r1, #0x2a\n"
4090 "movz r2, #0x4d2\n"
4091 "cmp r1, r2\n"
4092 "cinc r0, r2, ge\n"
4093 "ret\n");
4094}
4095
4096ASSEMBLER_TEST_GENERATE(CsinvFalse, assembler) {
4097 __ LoadImmediate(R1, 42);
4098 __ LoadImmediate(R2, 1234);
4099 __ CompareRegisters(R1, R2);
4100 __ csinv(R0, R2, R1, GE);
4101 __ ret();
4102}
4103
4104ASSEMBLER_TEST_RUN(CsinvFalse, test) {
4105 typedef int64_t (*Int64Return)() DART_UNUSED;
4106 EXPECT_EQ(~42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4107 EXPECT_DISASSEMBLY(
4108 "movz r1, #0x2a\n"
4109 "movz r2, #0x4d2\n"
4110 "cmp r1, r2\n"
4111 "csinv r0, r2, r1, ge\n"
4112 "ret\n");
4113}
4114
4115ASSEMBLER_TEST_GENERATE(CsinvTrue, assembler) {
4116 __ LoadImmediate(R1, 42);
4117 __ LoadImmediate(R2, 1234);
4118 __ CompareRegisters(R1, R2);
4119 __ csinv(R0, R2, R1, LT);
4120 __ ret();
4121}
4122
4123ASSEMBLER_TEST_RUN(CsinvTrue, test) {
4124 typedef int64_t (*Int64Return)() DART_UNUSED;
4125 EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4126 EXPECT_DISASSEMBLY(
4127 "movz r1, #0x2a\n"
4128 "movz r2, #0x4d2\n"
4129 "cmp r1, r2\n"
4130 "csinv r0, r2, r1, lt\n"
4131 "ret\n");
4132}
4133
4134ASSEMBLER_TEST_GENERATE(CsnegFalse, assembler) {
4135 __ LoadImmediate(R1, 42);
4136 __ LoadImmediate(R2, 1234);
4137 __ CompareRegisters(R1, R2);
4138 __ csneg(R0, R2, R1, GE);
4139 __ ret();
4140}
4141
4142ASSEMBLER_TEST_RUN(CsnegFalse, test) {
4143 typedef int64_t (*Int64Return)() DART_UNUSED;
4144 EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4145 EXPECT_DISASSEMBLY(
4146 "movz r1, #0x2a\n"
4147 "movz r2, #0x4d2\n"
4148 "cmp r1, r2\n"
4149 "csneg r0, r2, r1, ge\n"
4150 "ret\n");
4151}
4152
4153ASSEMBLER_TEST_GENERATE(CsnegTrue, assembler) {
4154 __ LoadImmediate(R1, 42);
4155 __ LoadImmediate(R2, 1234);
4156 __ CompareRegisters(R1, R2);
4157 __ csneg(R0, R2, R1, LT);
4158 __ ret();
4159}
4160
4161ASSEMBLER_TEST_RUN(CsnegTrue, test) {
4162 typedef int64_t (*Int64Return)() DART_UNUSED;
4163 EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4164 EXPECT_DISASSEMBLY(
4165 "movz r1, #0x2a\n"
4166 "movz r2, #0x4d2\n"
4167 "cmp r1, r2\n"
4168 "csneg r0, r2, r1, lt\n"
4169 "ret\n");
4170}
4171
4172ASSEMBLER_TEST_GENERATE(Ubfx, assembler) {
4173 __ LoadImmediate(R1, 0x819);
4174 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4175 __ ubfx(R0, R1, 4, 8);
4176 __ ret();
4177}
4178
4179ASSEMBLER_TEST_RUN(Ubfx, test) {
4180 typedef int64_t (*Int64Return)() DART_UNUSED;
4181 EXPECT_EQ(0x81, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4182 EXPECT_DISASSEMBLY(
4183 "movz r1, #0x819\n"
4184 "movz r0, #0x5a5a\n"
4185 "movk r0, #0x5a5a lsl 16\n"
4186 "ubfm r0, r1, #4, #11\n"
4187 "ret\n");
4188}
4189
4190ASSEMBLER_TEST_GENERATE(Sbfx, assembler) {
4191 __ LoadImmediate(R1, 0x819);
4192 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4193 __ sbfx(R0, R1, 4, 8);
4194 __ ret();
4195}
4196
4197ASSEMBLER_TEST_RUN(Sbfx, test) {
4198 typedef int64_t (*Int64Return)() DART_UNUSED;
4199 EXPECT_EQ(-0x7f, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4200 EXPECT_DISASSEMBLY(
4201 "movz r1, #0x819\n"
4202 "movz r0, #0x5a5a\n"
4203 "movk r0, #0x5a5a lsl 16\n"
4204 "sbfm r0, r1, #4, #11\n"
4205 "ret\n");
4206}
4207
4208ASSEMBLER_TEST_GENERATE(Bfi, assembler) {
4209 __ LoadImmediate(R1, 0x819);
4210 __ LoadImmediate(R0, 0x5a5a5a5a);
4211 __ bfi(R0, R1, 12, 5);
4212 __ ret();
4213}
4214
4216 typedef int64_t (*Int64Return)() DART_UNUSED;
4217 EXPECT_EQ(0x5a5b9a5a, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4218 EXPECT_DISASSEMBLY(
4219 "movz r1, #0x819\n"
4220 "movz r0, #0x5a5a\n"
4221 "movk r0, #0x5a5a lsl 16\n"
4222 "bfm r0, r1, #52, #4\n"
4223 "ret\n");
4224}
4225
4226ASSEMBLER_TEST_GENERATE(Ubfiz, assembler) {
4227 __ LoadImmediate(R1, 0xff1248ff);
4228 __ LoadImmediate(R0, 0x5a5a5a5a);
4229 // Take 30 low bits and place at position 1 in R0, zeroing the rest.
4230 __ ubfiz(R0, R1, 1, 30);
4231 __ ret();
4232}
4233
4234ASSEMBLER_TEST_RUN(Ubfiz, test) {
4235 typedef int64_t (*Int64Return)() DART_UNUSED;
4236 EXPECT_EQ(0x7e2491fe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4237 EXPECT_DISASSEMBLY(
4238 "movz r1, #0x48ff\n"
4239 "movk r1, #0xff12 lsl 16\n"
4240 "movz r0, #0x5a5a\n"
4241 "movk r0, #0x5a5a lsl 16\n"
4242 "ubfm r0, r1, #63, #29\n"
4243 "ret\n");
4244}
4245
4246ASSEMBLER_TEST_GENERATE(Bfxil, assembler) {
4247 __ LoadImmediate(R1, 0x819);
4248 __ LoadImmediate(R0, 0x5a5a5a5a);
4249 __ bfxil(R0, R1, 4, 8);
4250 __ ret();
4251}
4252
4253ASSEMBLER_TEST_RUN(Bfxil, test) {
4254 typedef int64_t (*Int64Return)() DART_UNUSED;
4255 EXPECT_EQ(0x5a5a5a81, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4256 EXPECT_DISASSEMBLY(
4257 "movz r1, #0x819\n"
4258 "movz r0, #0x5a5a\n"
4259 "movk r0, #0x5a5a lsl 16\n"
4260 "bfm r0, r1, #4, #11\n"
4261 "ret\n");
4262}
4263
4264ASSEMBLER_TEST_GENERATE(Sbfiz, assembler) {
4265 __ LoadImmediate(R1, 0x819);
4266 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4267 __ sbfiz(R0, R1, 4, 12);
4268 __ ret();
4269}
4270
4271ASSEMBLER_TEST_RUN(Sbfiz, test) {
4272 typedef int64_t (*Int64Return)() DART_UNUSED;
4273 EXPECT_EQ(-0x7e70, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4274 EXPECT_DISASSEMBLY(
4275 "movz r1, #0x819\n"
4276 "movz r0, #0x5a5a\n"
4277 "movk r0, #0x5a5a lsl 16\n"
4278 "sbfm r0, r1, #60, #11\n"
4279 "ret\n");
4280}
4281
4282ASSEMBLER_TEST_GENERATE(Sxtb, assembler) {
4283 __ LoadImmediate(R1, 0xff);
4284 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4285 __ sxtb(R0, R1);
4286 __ LoadImmediate(R2, 0x2a);
4287 __ LoadImmediate(R1, 0x5a5a5a5a); // Overwritten.
4288 __ sxtb(R1, R2);
4289 __ add(R0, R0, Operand(R1));
4290 __ ret();
4291}
4292
4293ASSEMBLER_TEST_RUN(Sxtb, test) {
4294 typedef int64_t (*Int64Return)() DART_UNUSED;
4295 EXPECT_EQ(0x29, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4296 EXPECT_DISASSEMBLY(
4297 "movz r1, #0xff\n"
4298 "movz r0, #0x5a5a\n"
4299 "movk r0, #0x5a5a lsl 16\n"
4300 "sxtb r0, r1\n"
4301 "movz r2, #0x2a\n"
4302 "movz r1, #0x5a5a\n"
4303 "movk r1, #0x5a5a lsl 16\n"
4304 "sxtb r1, r2\n"
4305 "add r0, r0, r1\n"
4306 "ret\n");
4307}
4308
4309ASSEMBLER_TEST_GENERATE(Sxth, assembler) {
4310 __ LoadImmediate(R1, 0xffff);
4311 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4312 __ sxth(R0, R1);
4313 __ LoadImmediate(R2, 0x1002a);
4314 __ LoadImmediate(R1, 0x5a5a5a5a); // Overwritten.
4315 __ sxth(R1, R2);
4316 __ add(R0, R0, Operand(R1));
4317 __ ret();
4318}
4319
4320ASSEMBLER_TEST_RUN(Sxth, test) {
4321 typedef int64_t (*Int64Return)() DART_UNUSED;
4322 EXPECT_EQ(0x29, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4323 EXPECT_DISASSEMBLY(
4324 "mov r1, 0xffff\n"
4325 "movz r0, #0x5a5a\n"
4326 "movk r0, #0x5a5a lsl 16\n"
4327 "sxth r0, r1\n"
4328 "movz r2, #0x2a\n"
4329 "movk r2, #0x1 lsl 16\n"
4330 "movz r1, #0x5a5a\n"
4331 "movk r1, #0x5a5a lsl 16\n"
4332 "sxth r1, r2\n"
4333 "add r0, r0, r1\n"
4334 "ret\n");
4335}
4336
4337ASSEMBLER_TEST_GENERATE(Sxtw, assembler) {
4338 __ LoadImmediate(R1, 0xffffffffll);
4339 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4340 __ sxtw(R0, R1);
4341 __ LoadImmediate(R2, 0x10000002all);
4342 __ LoadImmediate(R1, 0x5a5a5a5a); // Overwritten.
4343 __ sxtw(R1, R2);
4344 __ add(R0, R0, Operand(R1));
4345 __ ret();
4346}
4347
4348ASSEMBLER_TEST_RUN(Sxtw, test) {
4349 typedef int64_t (*Int64Return)() DART_UNUSED;
4350 EXPECT_EQ(0x29, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4351 EXPECT_DISASSEMBLY(
4352 "mov r1, 0xffffffff\n"
4353 "movz r0, #0x5a5a\n"
4354 "movk r0, #0x5a5a lsl 16\n"
4355 "sxtw r0, r1\n"
4356 "movz r2, #0x2a\n"
4357 "movk r2, #0x1 lsl 32\n"
4358 "movz r1, #0x5a5a\n"
4359 "movk r1, #0x5a5a lsl 16\n"
4360 "sxtw r1, r2\n"
4361 "add r0, r0, r1\n"
4362 "ret\n");
4363}
4364
4365ASSEMBLER_TEST_GENERATE(Uxtw, assembler) {
4366 __ LoadImmediate(R1, 0xffffffffll);
4367 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4368 __ ubfiz(R0, R1, 0, 32); // Zero extend word.
4369 __ LoadImmediate(R2, 0x10000002all);
4370 __ LoadImmediate(R1, 0x5a5a5a5a); // Overwritten.
4371 __ ubfiz(R1, R2, 0, 32); // Zero extend word.
4372 __ add(R0, R0, Operand(R1));
4373 __ ret();
4374}
4375
4376ASSEMBLER_TEST_RUN(Uxtw, test) {
4377 typedef int64_t (*Int64Return)() DART_UNUSED;
4378 EXPECT_EQ(0xffffffffll + 42,
4379 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4380 EXPECT_DISASSEMBLY(
4381 "mov r1, 0xffffffff\n"
4382 "movz r0, #0x5a5a\n"
4383 "movk r0, #0x5a5a lsl 16\n"
4384 "ubfm r0, r1, #0, #31\n"
4385 "movz r2, #0x2a\n"
4386 "movk r2, #0x1 lsl 32\n"
4387 "movz r1, #0x5a5a\n"
4388 "movk r1, #0x5a5a lsl 16\n"
4389 "ubfm r1, r2, #0, #31\n"
4390 "add r0, r0, r1\n"
4391 "ret\n");
4392}
4393
4394ASSEMBLER_TEST_GENERATE(Uxtb, assembler) {
4395 __ LoadImmediate(R1, -1);
4396 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4397 __ uxtb(R0, R1);
4398 __ LoadImmediate(R2, 0x12a);
4399 __ LoadImmediate(R1, 0x5a5a5a5a); // Overwritten.
4400 __ uxtb(R1, R2);
4401 __ add(R0, R0, Operand(R1));
4402 __ ret();
4403}
4404
4405ASSEMBLER_TEST_RUN(Uxtb, test) {
4406 typedef int64_t (*Int64Return)() DART_UNUSED;
4407 EXPECT_EQ(0xff + 0x2a, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4408 EXPECT_DISASSEMBLY(
4409 "movn r1, #0x0\n"
4410 "movz r0, #0x5a5a\n"
4411 "movk r0, #0x5a5a lsl 16\n"
4412 "uxtb r0, r1\n"
4413 "movz r2, #0x12a\n"
4414 "movz r1, #0x5a5a\n"
4415 "movk r1, #0x5a5a lsl 16\n"
4416 "uxtb r1, r2\n"
4417 "add r0, r0, r1\n"
4418 "ret\n");
4419}
4420
4421ASSEMBLER_TEST_GENERATE(Uxth, assembler) {
4422 __ LoadImmediate(R1, -1);
4423 __ LoadImmediate(R0, 0x5a5a5a5a); // Overwritten.
4424 __ uxth(R0, R1);
4425 __ LoadImmediate(R2, 0x1002a);
4426 __ LoadImmediate(R1, 0x5a5a5a5a); // Overwritten.
4427 __ uxth(R1, R2);
4428 __ add(R0, R0, Operand(R1));
4429 __ ret();
4430}
4431
4432ASSEMBLER_TEST_RUN(Uxth, test) {
4433 typedef int64_t (*Int64Return)() DART_UNUSED;
4434 EXPECT_EQ(0xffff + 0x2a, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4435 EXPECT_DISASSEMBLY(
4436 "movn r1, #0x0\n"
4437 "movz r0, #0x5a5a\n"
4438 "movk r0, #0x5a5a lsl 16\n"
4439 "uxth r0, r1\n"
4440 "movz r2, #0x2a\n"
4441 "movk r2, #0x1 lsl 16\n"
4442 "movz r1, #0x5a5a\n"
4443 "movk r1, #0x5a5a lsl 16\n"
4444 "uxth r1, r2\n"
4445 "add r0, r0, r1\n"
4446 "ret\n");
4447}
4448
4449// Floating point move immediate, to/from integer register.
4450ASSEMBLER_TEST_GENERATE(Fmovdi, assembler) {
4451 __ LoadDImmediate(V0, 1.0);
4452 __ ret();
4453}
4454
4455ASSEMBLER_TEST_RUN(Fmovdi, test) {
4456 typedef double (*DoubleReturn)() DART_UNUSED;
4457 EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
4458 EXPECT_DISASSEMBLY(
4459 "fmovd v0, 1.000000\n"
4460 "ret\n");
4461}
4462
4463ASSEMBLER_TEST_GENERATE(Fmovdi2, assembler) {
4464 __ LoadDImmediate(V0, 123412983.1324524315);
4465 __ ret();
4466}
4467
4468ASSEMBLER_TEST_RUN(Fmovdi2, test) {
4469 typedef double (*DoubleReturn)() DART_UNUSED;
4470 EXPECT_FLOAT_EQ(123412983.1324524315,
4471 EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()),
4472 0.0001f);
4473 EXPECT_DISASSEMBLY(
4474 "movz tmp, #0xa19c\n"
4475 "movk tmp, #0xdc87 lsl 16\n"
4476 "movk tmp, #0x6c87 lsl 32\n"
4477 "movk tmp, #0x419d lsl 48\n"
4478 "fmovdr v0, tmp\n"
4479 "ret\n");
4480}
4481
4482ASSEMBLER_TEST_GENERATE(Fmovrd, assembler) {
4483 __ LoadDImmediate(V1, 1.0);
4484 __ fmovrd(R0, V1);
4485 __ ret();
4486}
4487
4488ASSEMBLER_TEST_RUN(Fmovrd, test) {
4489 typedef int64_t (*Int64Return)() DART_UNUSED;
4490 const int64_t one = bit_cast<int64_t, double>(1.0);
4491 EXPECT_EQ(one, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4492 EXPECT_DISASSEMBLY(
4493 "fmovd v1, 1.000000\n"
4494 "fmovrd r0, v1\n"
4495 "ret\n");
4496}
4497
4498ASSEMBLER_TEST_GENERATE(Fmovdr, assembler) {
4499 __ LoadDImmediate(V1, 1.0);
4500 __ fmovrd(R1, V1);
4501 __ fmovdr(V0, R1);
4502 __ ret();
4503}
4504
4505ASSEMBLER_TEST_RUN(Fmovdr, test) {
4506 typedef double (*DoubleReturn)() DART_UNUSED;
4507 EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
4508 EXPECT_DISASSEMBLY(
4509 "fmovd v1, 1.000000\n"
4510 "fmovrd r1, v1\n"
4511 "fmovdr v0, r1\n"
4512 "ret\n");
4513}
4514
4515ASSEMBLER_TEST_GENERATE(Fmovrs, assembler) {
4516 __ LoadDImmediate(V2, 1.0);
4517 __ fcvtsd(V1, V2);
4518 __ fmovrs(R0, V1);
4519 __ ret();
4520}
4521
4522ASSEMBLER_TEST_RUN(Fmovrs, test) {
4523 typedef int64_t (*Int64Return)() DART_UNUSED;
4524 int64_t result = EXECUTE_TEST_CODE_INT64(Int64Return, test->entry());
4525 const uint32_t one = bit_cast<uint32_t, float>(1.0f);
4526 EXPECT_EQ(one, static_cast<uint32_t>(result));
4527 EXPECT_DISASSEMBLY(
4528 "fmovd v2, 1.000000\n"
4529 "fcvtsd v1, v2\n"
4530 "fmovrsw r0, v1\n"
4531 "ret\n");
4532}
4533
4534ASSEMBLER_TEST_GENERATE(Fmovsr, assembler) {
4535 __ LoadImmediate(R2, bit_cast<uint32_t, float>(1.0f));
4536 __ fmovsr(V1, R2);
4537 __ fmovrs(R0, V1);
4538 __ ret();
4539}
4540
4541ASSEMBLER_TEST_RUN(Fmovsr, test) {
4542 typedef int64_t (*Int64Return)() DART_UNUSED;
4543 int64_t result = EXECUTE_TEST_CODE_INT64(Int64Return, test->entry());
4544 const uint32_t one = bit_cast<uint32_t, float>(1.0f);
4545 EXPECT_EQ(one, static_cast<uint32_t>(result));
4546 EXPECT_DISASSEMBLY(
4547 "mov r2, 0x3f800000\n"
4548 "fmovsrw v1, r2\n"
4549 "fmovrsw r0, v1\n"
4550 "ret\n");
4551}
4552
4553ASSEMBLER_TEST_GENERATE(FldrdFstrdPrePostIndex, assembler) {
4554 __ SetupDartSP();
4555
4556 __ sub(CSP, CSP,
4557 Operand(2 * target::kWordSize)); // Must not access beyond CSP.
4558
4559 __ LoadDImmediate(V1, 42.0);
4560 __ fstrd(V1, Address(SP, -1 * target::kWordSize, Address::PreIndex));
4561 __ fldrd(V0, Address(SP, 1 * target::kWordSize, Address::PostIndex));
4562 __ RestoreCSP();
4563 __ ret();
4564}
4565
4566ASSEMBLER_TEST_RUN(FldrdFstrdPrePostIndex, test) {
4567 typedef double (*DoubleReturn)() DART_UNUSED;
4568 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
4569 EXPECT_DISASSEMBLY(
4570 "mov sp, csp\n"
4571 "sub csp, csp, #0x1000\n"
4572 "sub csp, csp, #0x10\n"
4573 "movz tmp, #0x4045 lsl 48\n"
4574 "fmovdr v1, tmp\n"
4575 "fstrd v1, [sp, #-8]!\n"
4576 "fldrd v0, [sp], #8 !\n"
4577 "mov csp, sp\n"
4578 "ret\n");
4579}
4580
4581ASSEMBLER_TEST_GENERATE(FldrsFstrsPrePostIndex, assembler) {
4582 __ SetupDartSP();
4583
4584 __ sub(CSP, CSP,
4585 Operand(2 * target::kWordSize)); // Must not access beyond CSP.
4586
4587 __ LoadDImmediate(V1, 42.0);
4588 __ fcvtsd(V2, V1);
4589 __ fstrs(V2, Address(SP, -1 * target::kWordSize, Address::PreIndex));
4590 __ fldrs(V3, Address(SP, 1 * target::kWordSize, Address::PostIndex));
4591 __ fcvtds(V0, V3);
4592 __ RestoreCSP();
4593 __ ret();
4594}
4595
4596ASSEMBLER_TEST_RUN(FldrsFstrsPrePostIndex, test) {
4597 typedef double (*DoubleReturn)() DART_UNUSED;
4598 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
4599 EXPECT_DISASSEMBLY(
4600 "mov sp, csp\n"
4601 "sub csp, csp, #0x1000\n"
4602 "sub csp, csp, #0x10\n"
4603 "movz tmp, #0x4045 lsl 48\n"
4604 "fmovdr v1, tmp\n"
4605 "fcvtsd v2, v1\n"
4606 "fstrs v2, [sp, #-8]!\n"
4607 "fldrs v3, [sp], #8 !\n"
4608 "fcvtds v0, v3\n"
4609 "mov csp, sp\n"
4610 "ret\n");
4611}
4612
4613ASSEMBLER_TEST_GENERATE(FldrqFstrqPrePostIndex, assembler) {
4614 __ SetupDartSP();
4615
4616 __ sub(CSP, CSP,
4617 Operand(2 * target::kWordSize)); // Must not access beyond CSP.
4618
4619 __ LoadDImmediate(V1, 21.0);
4620 __ LoadDImmediate(V2, 21.0);
4621 __ LoadImmediate(R1, 42);
4622 __ Push(R1);
4623 __ PushDouble(V1);
4624 __ PushDouble(V2);
4625 __ fldrq(V3, Address(SP, 2 * target::kWordSize, Address::PostIndex));
4626 __ Pop(R0);
4627 __ fstrq(V3, Address(SP, -2 * target::kWordSize, Address::PreIndex));
4628 __ PopDouble(V0);
4629 __ PopDouble(V1);
4630 __ faddd(V0, V0, V1);
4631 __ RestoreCSP();
4632 __ ret();
4633}
4634
4635ASSEMBLER_TEST_RUN(FldrqFstrqPrePostIndex, test) {
4636 typedef double (*DoubleReturn)() DART_UNUSED;
4637 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
4638 EXPECT_DISASSEMBLY(
4639 "mov sp, csp\n"
4640 "sub csp, csp, #0x1000\n"
4641 "sub csp, csp, #0x10\n"
4642 "fmovd v1, 21.000000\n"
4643 "fmovd v2, 21.000000\n"
4644 "movz r1, #0x2a\n"
4645 "str r1, [sp, #-8]!\n"
4646 "fstrd v1, [sp, #-8]!\n"
4647 "fstrd v2, [sp, #-8]!\n"
4648 "fldrq v3, [sp], #16 !\n"
4649 "ldr r0, [sp], #8 !\n"
4650 "fstrq v3, [sp, #-16]!\n"
4651 "fldrd v0, [sp], #8 !\n"
4652 "fldrd v1, [sp], #8 !\n"
4653 "faddd v0, v0, v1\n"
4654 "mov csp, sp\n"
4655 "ret\n");
4656}
4657
4658ASSEMBLER_TEST_GENERATE(Fcvtzsxd, assembler) {
4659 __ LoadDImmediate(V0, 42.5);
4660 __ fcvtzsxd(R0, V0);
4661 __ ret();
4662}
4663
4664ASSEMBLER_TEST_RUN(Fcvtzsxd, test) {
4665 typedef int64_t (*Int64Return)() DART_UNUSED;
4666 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4667 EXPECT_DISASSEMBLY(
4668 "movz tmp, #0x4000 lsl 32\n"
4669 "movk tmp, #0x4045 lsl 48\n"
4670 "fmovdr v0, tmp\n"
4671 "fcvtzs r0, v0\n"
4672 "ret\n");
4673}
4674
4675ASSEMBLER_TEST_GENERATE(Fcvtzswd, assembler) {
4676 __ LoadDImmediate(V0, -42.5);
4677 __ fcvtzswd(R0, V0);
4678 __ sxtw(R0, R0);
4679 __ ret();
4680}
4681
4682ASSEMBLER_TEST_RUN(Fcvtzswd, test) {
4683 typedef int64_t (*Int64Return)() DART_UNUSED;
4684 EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4685 EXPECT_DISASSEMBLY(
4686 "movz tmp, #0x4000 lsl 32\n"
4687 "movk tmp, #0xc045 lsl 48\n"
4688 "fmovdr v0, tmp\n"
4689 "fcvtzsw r0, v0\n"
4690 "sxtw r0, r0\n"
4691 "ret\n");
4692}
4693
4694ASSEMBLER_TEST_GENERATE(Fcvtzsxd_overflow, assembler) {
4695 __ LoadDImmediate(V0, 1e20);
4696 __ fcvtzsxd(R0, V0);
4697 __ ret();
4698}
4699
4700ASSEMBLER_TEST_RUN(Fcvtzsxd_overflow, test) {
4701 typedef int64_t (*Int64Return)() DART_UNUSED;
4702 EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4703}
4704
4705ASSEMBLER_TEST_GENERATE(Fcvtzsxd_overflow_negative, assembler) {
4706 __ LoadDImmediate(V0, -1e20);
4707 __ fcvtzsxd(R0, V0);
4708 __ ret();
4709}
4710
4711ASSEMBLER_TEST_RUN(Fcvtzsxd_overflow_negative, test) {
4712 typedef int64_t (*Int64Return)() DART_UNUSED;
4713 EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4714 EXPECT_DISASSEMBLY(
4715 "movz tmp, #0x8c40\n"
4716 "movk tmp, #0x78b5 lsl 16\n"
4717 "movk tmp, #0xaf1d lsl 32\n"
4718 "movk tmp, #0xc415 lsl 48\n"
4719 "fmovdr v0, tmp\n"
4720 "fcvtzs r0, v0\n"
4721 "ret\n");
4722}
4723
4724ASSEMBLER_TEST_GENERATE(Fcvtzswd_overflow, assembler) {
4725 __ LoadDImmediate(V0, 1e10);
4726 __ fcvtzswd(R0, V0);
4727 __ ret();
4728}
4729
4730ASSEMBLER_TEST_RUN(Fcvtzswd_overflow, test) {
4731 typedef int64_t (*Int64Return)() DART_UNUSED;
4732 EXPECT_EQ(kMaxInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4733 EXPECT_DISASSEMBLY(
4734 "movz tmp, #0x2000 lsl 16\n"
4735 "movk tmp, #0xa05f lsl 32\n"
4736 "movk tmp, #0x4202 lsl 48\n"
4737 "fmovdr v0, tmp\n"
4738 "fcvtzsw r0, v0\n"
4739 "ret\n");
4740}
4741
4742ASSEMBLER_TEST_GENERATE(Fcvtzswd_overflow_negative, assembler) {
4743 __ LoadDImmediate(V0, -1e10);
4744 __ fcvtzswd(R0, V0);
4745 __ sxtw(R0, R0);
4746 __ ret();
4747}
4748
4749ASSEMBLER_TEST_RUN(Fcvtzswd_overflow_negative, test) {
4750 typedef int64_t (*Int64Return)() DART_UNUSED;
4751 EXPECT_EQ(kMinInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4752 EXPECT_DISASSEMBLY(
4753 "movz tmp, #0x2000 lsl 16\n"
4754 "movk tmp, #0xa05f lsl 32\n"
4755 "movk tmp, #0xc202 lsl 48\n"
4756 "fmovdr v0, tmp\n"
4757 "fcvtzsw r0, v0\n"
4758 "sxtw r0, r0\n"
4759 "ret\n");
4760}
4761
4762ASSEMBLER_TEST_GENERATE(Fcvtpsxd, assembler) {
4763 __ LoadDImmediate(V0, 42.5);
4764 __ fcvtpsxd(R0, V0);
4765 __ ret();
4766}
4767
4768ASSEMBLER_TEST_RUN(Fcvtpsxd, test) {
4769 typedef int64_t (*Int64Return)() DART_UNUSED;
4770 EXPECT_EQ(43, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4771 EXPECT_DISASSEMBLY(
4772 "movz tmp, #0x4000 lsl 32\n"
4773 "movk tmp, #0x4045 lsl 48\n"
4774 "fmovdr v0, tmp\n"
4775 "fcvtps r0, v0\n"
4776 "ret\n");
4777}
4778
4779ASSEMBLER_TEST_GENERATE(Fcvtpswd, assembler) {
4780 __ LoadDImmediate(V0, -42.5);
4781 __ fcvtpswd(R0, V0);
4782 __ sxtw(R0, R0);
4783 __ ret();
4784}
4785
4786ASSEMBLER_TEST_RUN(Fcvtpswd, test) {
4787 typedef int64_t (*Int64Return)() DART_UNUSED;
4788 EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4789 EXPECT_DISASSEMBLY(
4790 "movz tmp, #0x4000 lsl 32\n"
4791 "movk tmp, #0xc045 lsl 48\n"
4792 "fmovdr v0, tmp\n"
4793 "fcvtpsw r0, v0\n"
4794 "sxtw r0, r0\n"
4795 "ret\n");
4796}
4797
4798ASSEMBLER_TEST_GENERATE(Fcvtpsxd_overflow, assembler) {
4799 __ LoadDImmediate(V0, 1e20);
4800 __ fcvtpsxd(R0, V0);
4801 __ ret();
4802}
4803
4804ASSEMBLER_TEST_RUN(Fcvtpsxd_overflow, test) {
4805 typedef int64_t (*Int64Return)() DART_UNUSED;
4806 EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4807 EXPECT_DISASSEMBLY(
4808 "movz tmp, #0x8c40\n"
4809 "movk tmp, #0x78b5 lsl 16\n"
4810 "movk tmp, #0xaf1d lsl 32\n"
4811 "movk tmp, #0x4415 lsl 48\n"
4812 "fmovdr v0, tmp\n"
4813 "fcvtps r0, v0\n"
4814 "ret\n");
4815}
4816
4817ASSEMBLER_TEST_GENERATE(Fcvtpsxd_overflow_negative, assembler) {
4818 __ LoadDImmediate(V0, -1e20);
4819 __ fcvtpsxd(R0, V0);
4820 __ ret();
4821}
4822
4823ASSEMBLER_TEST_RUN(Fcvtpsxd_overflow_negative, test) {
4824 typedef int64_t (*Int64Return)() DART_UNUSED;
4825 EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4826 EXPECT_DISASSEMBLY(
4827 "movz tmp, #0x8c40\n"
4828 "movk tmp, #0x78b5 lsl 16\n"
4829 "movk tmp, #0xaf1d lsl 32\n"
4830 "movk tmp, #0xc415 lsl 48\n"
4831 "fmovdr v0, tmp\n"
4832 "fcvtps r0, v0\n"
4833 "ret\n");
4834}
4835
4836ASSEMBLER_TEST_GENERATE(Fcvtpswd_overflow, assembler) {
4837 __ LoadDImmediate(V0, 1e10);
4838 __ fcvtpswd(R0, V0);
4839 __ ret();
4840}
4841
4842ASSEMBLER_TEST_RUN(Fcvtpswd_overflow, test) {
4843 typedef int64_t (*Int64Return)() DART_UNUSED;
4844 EXPECT_EQ(kMaxInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4845 EXPECT_DISASSEMBLY(
4846 "movz tmp, #0x2000 lsl 16\n"
4847 "movk tmp, #0xa05f lsl 32\n"
4848 "movk tmp, #0x4202 lsl 48\n"
4849 "fmovdr v0, tmp\n"
4850 "fcvtpsw r0, v0\n"
4851 "ret\n");
4852}
4853
4854ASSEMBLER_TEST_GENERATE(Fcvtpswd_overflow_negative, assembler) {
4855 __ LoadDImmediate(V0, -1e10);
4856 __ fcvtpswd(R0, V0);
4857 __ sxtw(R0, R0);
4858 __ ret();
4859}
4860
4861ASSEMBLER_TEST_RUN(Fcvtpswd_overflow_negative, test) {
4862 typedef int64_t (*Int64Return)() DART_UNUSED;
4863 EXPECT_EQ(kMinInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4864 EXPECT_DISASSEMBLY(
4865 "movz tmp, #0x2000 lsl 16\n"
4866 "movk tmp, #0xa05f lsl 32\n"
4867 "movk tmp, #0xc202 lsl 48\n"
4868 "fmovdr v0, tmp\n"
4869 "fcvtpsw r0, v0\n"
4870 "sxtw r0, r0\n"
4871 "ret\n");
4872}
4873
4874ASSEMBLER_TEST_GENERATE(Fcvtmsxd, assembler) {
4875 __ LoadDImmediate(V0, 42.5);
4876 __ fcvtmsxd(R0, V0);
4877 __ ret();
4878}
4879
4880ASSEMBLER_TEST_RUN(Fcvtmsxd, test) {
4881 typedef int64_t (*Int64Return)() DART_UNUSED;
4882 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4883 EXPECT_DISASSEMBLY(
4884 "movz tmp, #0x4000 lsl 32\n"
4885 "movk tmp, #0x4045 lsl 48\n"
4886 "fmovdr v0, tmp\n"
4887 "fcvtms r0, v0\n"
4888 "ret\n");
4889}
4890
4891ASSEMBLER_TEST_GENERATE(Fcvtmswd, assembler) {
4892 __ LoadDImmediate(V0, -42.5);
4893 __ fcvtmswd(R0, V0);
4894 __ sxtw(R0, R0);
4895 __ ret();
4896}
4897
4898ASSEMBLER_TEST_RUN(Fcvtmswd, test) {
4899 typedef int64_t (*Int64Return)() DART_UNUSED;
4900 EXPECT_EQ(-43, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4901 EXPECT_DISASSEMBLY(
4902 "movz tmp, #0x4000 lsl 32\n"
4903 "movk tmp, #0xc045 lsl 48\n"
4904 "fmovdr v0, tmp\n"
4905 "fcvtmsw r0, v0\n"
4906 "sxtw r0, r0\n"
4907 "ret\n");
4908}
4909
4910ASSEMBLER_TEST_GENERATE(Fcvtmsxd_overflow, assembler) {
4911 __ LoadDImmediate(V0, 1e20);
4912 __ fcvtmsxd(R0, V0);
4913 __ ret();
4914}
4915
4916ASSEMBLER_TEST_RUN(Fcvtmsxd_overflow, test) {
4917 typedef int64_t (*Int64Return)() DART_UNUSED;
4918 EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4919 EXPECT_DISASSEMBLY(
4920 "movz tmp, #0x8c40\n"
4921 "movk tmp, #0x78b5 lsl 16\n"
4922 "movk tmp, #0xaf1d lsl 32\n"
4923 "movk tmp, #0x4415 lsl 48\n"
4924 "fmovdr v0, tmp\n"
4925 "fcvtms r0, v0\n"
4926 "ret\n");
4927}
4928
4929ASSEMBLER_TEST_GENERATE(Fcvtmsxd_overflow_negative, assembler) {
4930 __ LoadDImmediate(V0, -1e20);
4931 __ fcvtmsxd(R0, V0);
4932 __ ret();
4933}
4934
4935ASSEMBLER_TEST_RUN(Fcvtmsxd_overflow_negative, test) {
4936 typedef int64_t (*Int64Return)() DART_UNUSED;
4937 EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4938 EXPECT_DISASSEMBLY(
4939 "movz tmp, #0x8c40\n"
4940 "movk tmp, #0x78b5 lsl 16\n"
4941 "movk tmp, #0xaf1d lsl 32\n"
4942 "movk tmp, #0xc415 lsl 48\n"
4943 "fmovdr v0, tmp\n"
4944 "fcvtms r0, v0\n"
4945 "ret\n");
4946}
4947
4948ASSEMBLER_TEST_GENERATE(Fcvtmswd_overflow, assembler) {
4949 __ LoadDImmediate(V0, 1e10);
4950 __ fcvtmswd(R0, V0);
4951 __ ret();
4952}
4953
4954ASSEMBLER_TEST_RUN(Fcvtmswd_overflow, test) {
4955 typedef int64_t (*Int64Return)() DART_UNUSED;
4956 EXPECT_EQ(kMaxInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4957 EXPECT_DISASSEMBLY(
4958 "movz tmp, #0x2000 lsl 16\n"
4959 "movk tmp, #0xa05f lsl 32\n"
4960 "movk tmp, #0x4202 lsl 48\n"
4961 "fmovdr v0, tmp\n"
4962 "fcvtmsw r0, v0\n"
4963 "ret\n");
4964}
4965
4966ASSEMBLER_TEST_GENERATE(Fcvtmswd_overflow_negative, assembler) {
4967 __ LoadDImmediate(V0, -1e10);
4968 __ fcvtmswd(R0, V0);
4969 __ sxtw(R0, R0);
4970 __ ret();
4971}
4972
4973ASSEMBLER_TEST_RUN(Fcvtmswd_overflow_negative, test) {
4974 typedef int64_t (*Int64Return)() DART_UNUSED;
4975 EXPECT_EQ(kMinInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
4976 EXPECT_DISASSEMBLY(
4977 "movz tmp, #0x2000 lsl 16\n"
4978 "movk tmp, #0xa05f lsl 32\n"
4979 "movk tmp, #0xc202 lsl 48\n"
4980 "fmovdr v0, tmp\n"
4981 "fcvtmsw r0, v0\n"
4982 "sxtw r0, r0\n"
4983 "ret\n");
4984}
4985
4986ASSEMBLER_TEST_GENERATE(Scvtfdx, assembler) {
4987 __ LoadImmediate(R0, 42);
4988 __ scvtfdx(V0, R0);
4989 __ ret();
4990}
4991
4992ASSEMBLER_TEST_RUN(Scvtfdx, test) {
4993 typedef double (*DoubleReturn)() DART_UNUSED;
4994 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
4995 EXPECT_DISASSEMBLY(
4996 "movz r0, #0x2a\n"
4997 "scvtfd v0, r0\n"
4998 "ret\n");
4999}
5000
5001ASSEMBLER_TEST_GENERATE(Scvtfdw, assembler) {
5002 // Fill upper 32-bits with garbage.
5003 __ LoadImmediate(R0, 0x111111110000002A);
5004 __ scvtfdw(V0, R0);
5005 __ ret();
5006}
5007
5008ASSEMBLER_TEST_RUN(Scvtfdw, test) {
5009 typedef double (*DoubleReturn)() DART_UNUSED;
5010 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5011 EXPECT_DISASSEMBLY(
5012 "movz r0, #0x2a\n"
5013 "movk r0, #0x1111 lsl 32\n"
5014 "movk r0, #0x1111 lsl 48\n"
5015 "scvtfdw v0, r0\n"
5016 "ret\n");
5017}
5018
5019ASSEMBLER_TEST_GENERATE(FabsdPos, assembler) {
5020 __ LoadDImmediate(V1, 42.0);
5021 __ fabsd(V0, V1);
5022 __ ret();
5023}
5024
5025ASSEMBLER_TEST_RUN(FabsdPos, test) {
5026 typedef double (*DoubleReturn)() DART_UNUSED;
5027 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5028 EXPECT_DISASSEMBLY(
5029 "movz tmp, #0x4045 lsl 48\n"
5030 "fmovdr v1, tmp\n"
5031 "fabsd v0, v1\n"
5032 "ret\n");
5033}
5034
5035ASSEMBLER_TEST_GENERATE(FabsdNeg, assembler) {
5036 __ LoadDImmediate(V1, -42.0);
5037 __ fabsd(V0, V1);
5038 __ ret();
5039}
5040
5041ASSEMBLER_TEST_RUN(FabsdNeg, test) {
5042 typedef double (*DoubleReturn)() DART_UNUSED;
5043 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5044 EXPECT_DISASSEMBLY(
5045 "movz tmp, #0xc045 lsl 48\n"
5046 "fmovdr v1, tmp\n"
5047 "fabsd v0, v1\n"
5048 "ret\n");
5049}
5050
5051ASSEMBLER_TEST_GENERATE(FnegdPos, assembler) {
5052 __ LoadDImmediate(V1, 42.0);
5053 __ fnegd(V0, V1);
5054 __ ret();
5055}
5056
5057ASSEMBLER_TEST_RUN(FnegdPos, test) {
5058 typedef double (*DoubleReturn)() DART_UNUSED;
5059 EXPECT_EQ(-42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5060 EXPECT_DISASSEMBLY(
5061 "movz tmp, #0x4045 lsl 48\n"
5062 "fmovdr v1, tmp\n"
5063 "fnegd v0, v1\n"
5064 "ret\n");
5065}
5066
5067ASSEMBLER_TEST_GENERATE(FnegdNeg, assembler) {
5068 __ LoadDImmediate(V1, -42.0);
5069 __ fnegd(V0, V1);
5070 __ ret();
5071}
5072
5073ASSEMBLER_TEST_RUN(FnegdNeg, test) {
5074 typedef double (*DoubleReturn)() DART_UNUSED;
5075 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5076 EXPECT_DISASSEMBLY(
5077 "movz tmp, #0xc045 lsl 48\n"
5078 "fmovdr v1, tmp\n"
5079 "fnegd v0, v1\n"
5080 "ret\n");
5081}
5082
5083ASSEMBLER_TEST_GENERATE(Fsqrtd, assembler) {
5084 __ LoadDImmediate(V1, 64.0);
5085 __ fsqrtd(V0, V1);
5086 __ ret();
5087}
5088
5089ASSEMBLER_TEST_RUN(Fsqrtd, test) {
5090 typedef double (*DoubleReturn)() DART_UNUSED;
5091 EXPECT_EQ(8.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5092 EXPECT_DISASSEMBLY(
5093 "movz tmp, #0x4050 lsl 48\n"
5094 "fmovdr v1, tmp\n"
5095 "fsqrtd v0, v1\n"
5096 "ret\n");
5097}
5098
5099ASSEMBLER_TEST_GENERATE(Fmuld, assembler) {
5100 __ LoadDImmediate(V1, 84.0);
5101 __ LoadDImmediate(V2, 0.5);
5102 __ fmuld(V0, V1, V2);
5103 __ ret();
5104}
5105
5106ASSEMBLER_TEST_RUN(Fmuld, test) {
5107 typedef double (*DoubleReturn)() DART_UNUSED;
5108 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5109 EXPECT_DISASSEMBLY(
5110 "movz tmp, #0x4055 lsl 48\n"
5111 "fmovdr v1, tmp\n"
5112 "fmovd v2, 0.500000\n"
5113 "fmuld v0, v1, v2\n"
5114 "ret\n");
5115}
5116
5117ASSEMBLER_TEST_GENERATE(Fdivd, assembler) {
5118 __ LoadDImmediate(V1, 84.0);
5119 __ LoadDImmediate(V2, 2.0);
5120 __ fdivd(V0, V1, V2);
5121 __ ret();
5122}
5123
5124ASSEMBLER_TEST_RUN(Fdivd, test) {
5125 typedef double (*DoubleReturn)() DART_UNUSED;
5126 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5127 EXPECT_DISASSEMBLY(
5128 "movz tmp, #0x4055 lsl 48\n"
5129 "fmovdr v1, tmp\n"
5130 "fmovd v2, 2.000000\n"
5131 "fdivd v0, v1, v2\n"
5132 "ret\n");
5133}
5134
5135ASSEMBLER_TEST_GENERATE(Faddd, assembler) {
5136 __ LoadDImmediate(V1, 41.5);
5137 __ LoadDImmediate(V2, 0.5);
5138 __ faddd(V0, V1, V2);
5139 __ ret();
5140}
5141
5142ASSEMBLER_TEST_RUN(Faddd, test) {
5143 typedef double (*DoubleReturn)() DART_UNUSED;
5144 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5145 EXPECT_DISASSEMBLY(
5146 "movz tmp, #0xc000 lsl 32\n"
5147 "movk tmp, #0x4044 lsl 48\n"
5148 "fmovdr v1, tmp\n"
5149 "fmovd v2, 0.500000\n"
5150 "faddd v0, v1, v2\n"
5151 "ret\n");
5152}
5153
5154ASSEMBLER_TEST_GENERATE(Fsubd, assembler) {
5155 __ LoadDImmediate(V1, 42.5);
5156 __ LoadDImmediate(V2, 0.5);
5157 __ fsubd(V0, V1, V2);
5158 __ ret();
5159}
5160
5161ASSEMBLER_TEST_RUN(Fsubd, test) {
5162 typedef double (*DoubleReturn)() DART_UNUSED;
5163 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5164 EXPECT_DISASSEMBLY(
5165 "movz tmp, #0x4000 lsl 32\n"
5166 "movk tmp, #0x4045 lsl 48\n"
5167 "fmovdr v1, tmp\n"
5168 "fmovd v2, 0.500000\n"
5169 "fsubd v0, v1, v2\n"
5170 "ret\n");
5171}
5172
5173ASSEMBLER_TEST_GENERATE(FldrdFstrdHeapTag, assembler) {
5174 __ SetupDartSP();
5175 __ LoadDImmediate(V0, 43.0);
5176 __ LoadDImmediate(V1, 42.0);
5177 __ AddImmediate(SP, SP, -1 * target::kWordSize);
5178 __ add(R2, SP, Operand(1));
5179 __ fstrd(V1, Address(R2, -1));
5180 __ fldrd(V0, Address(R2, -1));
5181 __ AddImmediate(SP, 1 * target::kWordSize);
5182 __ RestoreCSP();
5183 __ ret();
5184}
5185
5186ASSEMBLER_TEST_RUN(FldrdFstrdHeapTag, test) {
5187 typedef double (*DoubleReturn)() DART_UNUSED;
5188 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5189 EXPECT_DISASSEMBLY(
5190 "mov sp, csp\n"
5191 "sub csp, csp, #0x1000\n"
5192 "movz tmp, #0x8000 lsl 32\n"
5193 "movk tmp, #0x4045 lsl 48\n"
5194 "fmovdr v0, tmp\n"
5195 "movz tmp, #0x4045 lsl 48\n"
5196 "fmovdr v1, tmp\n"
5197 "sub sp, sp, #0x8\n"
5198 "add r2, sp, #0x1\n"
5199 "fstrd v1, [r2, #-1]\n"
5200 "fldrd v0, [r2, #-1]\n"
5201 "add sp, sp, #0x8\n"
5202 "mov csp, sp\n"
5203 "ret\n");
5204}
5205
5206ASSEMBLER_TEST_GENERATE(FldrdFstrdLargeIndex, assembler) {
5207 __ SetupDartSP();
5208
5209 __ sub(CSP, CSP,
5210 Operand(32 * target::kWordSize)); // Must not access beyond CSP.
5211
5212 __ LoadDImmediate(V0, 43.0);
5213 __ LoadDImmediate(V1, 42.0);
5214 // Largest negative offset that can fit in the signed 9-bit immediate field.
5215 __ fstrd(V1, Address(SP, -32 * target::kWordSize, Address::PreIndex));
5216 // Largest positive kWordSize aligned offset that we can fit.
5217 __ fldrd(V0, Address(SP, 31 * target::kWordSize, Address::PostIndex));
5218 // Correction.
5219 __ add(SP, SP, Operand(target::kWordSize)); // Restore SP.
5220 __ RestoreCSP();
5221 __ ret();
5222}
5223
5224ASSEMBLER_TEST_RUN(FldrdFstrdLargeIndex, test) {
5225 typedef double (*DoubleReturn)() DART_UNUSED;
5226 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5227 EXPECT_DISASSEMBLY(
5228 "mov sp, csp\n"
5229 "sub csp, csp, #0x1000\n"
5230 "sub csp, csp, #0x100\n"
5231 "movz tmp, #0x8000 lsl 32\n"
5232 "movk tmp, #0x4045 lsl 48\n"
5233 "fmovdr v0, tmp\n"
5234 "movz tmp, #0x4045 lsl 48\n"
5235 "fmovdr v1, tmp\n"
5236 "fstrd v1, [sp, #-256]!\n"
5237 "fldrd v0, [sp], #248 !\n"
5238 "add sp, sp, #0x8\n"
5239 "mov csp, sp\n"
5240 "ret\n");
5241}
5242
5243ASSEMBLER_TEST_GENERATE(FldrdFstrdLargeOffset, assembler) {
5244 __ SetupDartSP();
5245 __ LoadDImmediate(V0, 43.0);
5246 __ LoadDImmediate(V1, 42.0);
5247 __ sub(SP, SP, Operand(512 * target::kWordSize));
5248 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
5249 __ fstrd(V1, Address(SP, 512 * target::kWordSize));
5250 __ add(SP, SP, Operand(512 * target::kWordSize));
5251 __ fldrd(V0, Address(SP));
5252 __ RestoreCSP();
5253 __ ret();
5254}
5255
5256ASSEMBLER_TEST_RUN(FldrdFstrdLargeOffset, test) {
5257 typedef double (*DoubleReturn)() DART_UNUSED;
5258 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5259 EXPECT_DISASSEMBLY(
5260 "mov sp, csp\n"
5261 "sub csp, csp, #0x1000\n"
5262 "movz tmp, #0x8000 lsl 32\n"
5263 "movk tmp, #0x4045 lsl 48\n"
5264 "fmovdr v0, tmp\n"
5265 "movz tmp, #0x4045 lsl 48\n"
5266 "fmovdr v1, tmp\n"
5267 "sub sp, sp, #0x1000\n"
5268 "and csp, sp, 0xfffffffffffffff0\n"
5269 "fstrd v1, [sp, #4096]\n"
5270 "add sp, sp, #0x1000\n"
5271 "fldrd v0, [sp]\n"
5272 "mov csp, sp\n"
5273 "ret\n");
5274}
5275
5276ASSEMBLER_TEST_GENERATE(FldrdFstrdExtReg, assembler) {
5277 __ SetupDartSP();
5278 __ LoadDImmediate(V0, 43.0);
5279 __ LoadDImmediate(V1, 42.0);
5280 __ movz(R2, Immediate(0xfff8), 0);
5281 __ movk(R2, Immediate(0xffff), 1); // R2 <- -8 (int32_t).
5282 // This should sign extend R2, and add to SP to get address,
5283 // i.e. SP - kWordSize.
5284 __ fstrd(V1, Address(SP, R2, SXTW));
5285 __ sub(SP, SP, Operand(target::kWordSize));
5286 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
5287 __ fldrd(V0, Address(SP));
5288 __ add(SP, SP, Operand(target::kWordSize));
5289 __ RestoreCSP();
5290 __ ret();
5291}
5292
5293ASSEMBLER_TEST_RUN(FldrdFstrdExtReg, test) {
5294 typedef double (*DoubleReturn)() DART_UNUSED;
5295 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5296 EXPECT_DISASSEMBLY(
5297 "mov sp, csp\n"
5298 "sub csp, csp, #0x1000\n"
5299 "movz tmp, #0x8000 lsl 32\n"
5300 "movk tmp, #0x4045 lsl 48\n"
5301 "fmovdr v0, tmp\n"
5302 "movz tmp, #0x4045 lsl 48\n"
5303 "fmovdr v1, tmp\n"
5304 "movz r2, #0xfff8\n"
5305 "movk r2, #0xffff lsl 16\n"
5306 "fstrd v1, [sp, r2 sxtw]\n"
5307 "sub sp, sp, #0x8\n"
5308 "and csp, sp, 0xfffffffffffffff0\n"
5309 "fldrd v0, [sp]\n"
5310 "add sp, sp, #0x8\n"
5311 "mov csp, sp\n"
5312 "ret\n");
5313}
5314
5315ASSEMBLER_TEST_GENERATE(FldrdFstrdScaledReg, assembler) {
5316 __ SetupDartSP();
5317 __ LoadDImmediate(V0, 43.0);
5318 __ LoadDImmediate(V1, 42.0);
5319 __ movz(R2, Immediate(10), 0);
5320 __ sub(SP, SP, Operand(10 * target::kWordSize));
5321 __ andi(CSP, SP, Immediate(~15)); // Must not access beyond CSP.
5322 // Store V1 into SP + R2 * kWordSize.
5323 __ fstrd(V1, Address(SP, R2, UXTX, Address::Scaled));
5324 __ fldrd(V0, Address(SP, R2, UXTX, Address::Scaled));
5325 __ add(SP, SP, Operand(10 * target::kWordSize));
5326 __ RestoreCSP();
5327 __ ret();
5328}
5329
5330ASSEMBLER_TEST_RUN(FldrdFstrdScaledReg, test) {
5331 typedef double (*DoubleReturn)() DART_UNUSED;
5332 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5333 EXPECT_DISASSEMBLY(
5334 "mov sp, csp\n"
5335 "sub csp, csp, #0x1000\n"
5336 "movz tmp, #0x8000 lsl 32\n"
5337 "movk tmp, #0x4045 lsl 48\n"
5338 "fmovdr v0, tmp\n"
5339 "movz tmp, #0x4045 lsl 48\n"
5340 "fmovdr v1, tmp\n"
5341 "movz r2, #0xa\n"
5342 "sub sp, sp, #0x50\n"
5343 "and csp, sp, 0xfffffffffffffff0\n"
5344 "fstrd v1, [sp, r2 uxtx scaled]\n"
5345 "fldrd v0, [sp, r2 uxtx scaled]\n"
5346 "add sp, sp, #0x50\n"
5347 "mov csp, sp\n"
5348 "ret\n");
5349}
5350
5351ASSEMBLER_TEST_GENERATE(VinswVmovrs, assembler) {
5352 __ LoadImmediate(R0, 42);
5353 __ LoadImmediate(R1, 43);
5354 __ LoadImmediate(R2, 44);
5355 __ LoadImmediate(R3, 45);
5356
5357 __ vinsw(V0, 0, R0);
5358 __ vinsw(V0, 1, R1);
5359 __ vinsw(V0, 2, R2);
5360 __ vinsw(V0, 3, R3);
5361
5362 __ vmovrs(R4, V0, 0);
5363 __ vmovrs(R5, V0, 1);
5364 __ vmovrs(R6, V0, 2);
5365 __ vmovrs(R7, V0, 3);
5366
5367 __ add(R0, R4, Operand(R5));
5368 __ add(R0, R0, Operand(R6));
5369 __ add(R0, R0, Operand(R7));
5370 __ ret();
5371}
5372
5373ASSEMBLER_TEST_RUN(VinswVmovrs, test) {
5374 EXPECT(test != nullptr);
5375 typedef int64_t (*Int64Return)() DART_UNUSED;
5376 EXPECT_EQ(174, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
5377 EXPECT_DISASSEMBLY(
5378 "movz r0, #0x2a\n"
5379 "movz r1, #0x2b\n"
5380 "movz r2, #0x2c\n"
5381 "movz r3, #0x2d\n"
5382 "vinss v0[0], r0\n"
5383 "vinss v0[1], r1\n"
5384 "vinss v0[2], r2\n"
5385 "vinss v0[3], r3\n"
5386 "vmovrs r4, v0[0]\n"
5387 "vmovrs r5, v0[1]\n"
5388 "vmovrs r6, v0[2]\n"
5389 "vmovrs r7, v0[3]\n"
5390 "add r0, r4, r5\n"
5391 "add r0, r0, r6\n"
5392 "add r0, r0, r7\n"
5393 "ret\n");
5394}
5395
5396ASSEMBLER_TEST_GENERATE(VinsxVmovrd, assembler) {
5397 __ LoadImmediate(R0, 42);
5398 __ LoadImmediate(R1, 43);
5399
5400 __ vinsx(V0, 0, R0);
5401 __ vinsx(V0, 1, R1);
5402
5403 __ vmovrd(R2, V0, 0);
5404 __ vmovrd(R3, V0, 1);
5405
5406 __ add(R0, R2, Operand(R3));
5407 __ ret();
5408}
5409
5410ASSEMBLER_TEST_RUN(VinsxVmovrd, test) {
5411 EXPECT(test != nullptr);
5412 typedef int64_t (*Int64Return)() DART_UNUSED;
5413 EXPECT_EQ(85, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
5414 EXPECT_DISASSEMBLY(
5415 "movz r0, #0x2a\n"
5416 "movz r1, #0x2b\n"
5417 "vinsd v0[0], r0\n"
5418 "vinsd v0[1], r1\n"
5419 "vmovrd r2, v0[0]\n"
5420 "vmovrd r3, v0[1]\n"
5421 "add r0, r2, r3\n"
5422 "ret\n");
5423}
5424
5425ASSEMBLER_TEST_GENERATE(Vnot, assembler) {
5426 __ LoadImmediate(R0, 0xfffffffe);
5427 __ LoadImmediate(R1, 0xffffffff);
5428 __ vinsw(V1, 0, R1);
5429 __ vinsw(V1, 1, R0);
5430 __ vinsw(V1, 2, R1);
5431 __ vinsw(V1, 3, R0);
5432
5433 __ vnot(V0, V1);
5434
5435 __ vmovrs(R2, V0, 0);
5436 __ vmovrs(R3, V0, 1);
5437 __ vmovrs(R4, V0, 2);
5438 __ vmovrs(R5, V0, 3);
5439 __ add(R0, R2, Operand(R3));
5440 __ add(R0, R0, Operand(R4));
5441 __ add(R0, R0, Operand(R5));
5442 __ ret();
5443}
5444
5445ASSEMBLER_TEST_RUN(Vnot, test) {
5446 EXPECT(test != nullptr);
5447 typedef int64_t (*Int64Return)() DART_UNUSED;
5448 EXPECT_EQ(2, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
5449 EXPECT_DISASSEMBLY(
5450 "mov r0, 0xfffffffe\n"
5451 "mov r1, 0xffffffff\n"
5452 "vinss v1[0], r1\n"
5453 "vinss v1[1], r0\n"
5454 "vinss v1[2], r1\n"
5455 "vinss v1[3], r0\n"
5456 "vnot v0, v1\n"
5457 "vmovrs r2, v0[0]\n"
5458 "vmovrs r3, v0[1]\n"
5459 "vmovrs r4, v0[2]\n"
5460 "vmovrs r5, v0[3]\n"
5461 "add r0, r2, r3\n"
5462 "add r0, r0, r4\n"
5463 "add r0, r0, r5\n"
5464 "ret\n");
5465}
5466
5467ASSEMBLER_TEST_GENERATE(Vabss, assembler) {
5468 __ LoadDImmediate(V1, 21.0);
5469 __ LoadDImmediate(V2, -21.0);
5470
5471 __ fcvtsd(V1, V1);
5472 __ fcvtsd(V2, V2);
5473
5474 __ veor(V3, V3, V3);
5475 __ vinss(V3, 1, V1, 0);
5476 __ vinss(V3, 3, V2, 0);
5477
5478 __ vabss(V4, V3);
5479
5480 __ vinss(V5, 0, V4, 1);
5481 __ vinss(V6, 0, V4, 3);
5482
5483 __ fcvtds(V5, V5);
5484 __ fcvtds(V6, V6);
5485
5486 __ faddd(V0, V5, V6);
5487 __ ret();
5488}
5489
5490ASSEMBLER_TEST_RUN(Vabss, test) {
5491 typedef double (*DoubleReturn)() DART_UNUSED;
5492 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5493 EXPECT_DISASSEMBLY(
5494 "fmovd v1, 21.000000\n"
5495 "fmovd v2, -21.000000\n"
5496 "fcvtsd v1, v1\n"
5497 "fcvtsd v2, v2\n"
5498 "veor v3, v3, v3\n"
5499 "vinss v3[1], v1[0]\n"
5500 "vinss v3[3], v2[0]\n"
5501 "vabss v4, v3\n"
5502 "vinss v5[0], v4[1]\n"
5503 "vinss v6[0], v4[3]\n"
5504 "fcvtds v5, v5\n"
5505 "fcvtds v6, v6\n"
5506 "faddd v0, v5, v6\n"
5507 "ret\n");
5508}
5509
5510ASSEMBLER_TEST_GENERATE(Vabsd, assembler) {
5511 __ LoadDImmediate(V1, 21.0);
5512 __ LoadDImmediate(V2, -21.0);
5513
5514 __ vinsd(V3, 0, V1, 0);
5515 __ vinsd(V3, 1, V2, 0);
5516
5517 __ vabsd(V4, V3);
5518
5519 __ vinsd(V5, 0, V4, 0);
5520 __ vinsd(V6, 0, V4, 1);
5521
5522 __ faddd(V0, V5, V6);
5523 __ ret();
5524}
5525
5526ASSEMBLER_TEST_RUN(Vabsd, test) {
5527 typedef double (*DoubleReturn)() DART_UNUSED;
5528 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5529 EXPECT_DISASSEMBLY(
5530 "fmovd v1, 21.000000\n"
5531 "fmovd v2, -21.000000\n"
5532 "vinsd v3[0], v1[0]\n"
5533 "vinsd v3[1], v2[0]\n"
5534 "vabsd v4, v3\n"
5535 "vinsd v5[0], v4[0]\n"
5536 "vinsd v6[0], v4[1]\n"
5537 "faddd v0, v5, v6\n"
5538 "ret\n");
5539}
5540
5541ASSEMBLER_TEST_GENERATE(Vnegs, assembler) {
5542 __ LoadDImmediate(V1, 42.0);
5543 __ LoadDImmediate(V2, -84.0);
5544
5545 __ fcvtsd(V1, V1);
5546 __ fcvtsd(V2, V2);
5547
5548 __ veor(V3, V3, V3);
5549 __ vinss(V3, 1, V1, 0);
5550 __ vinss(V3, 3, V2, 0);
5551
5552 __ vnegs(V4, V3);
5553
5554 __ vinss(V5, 0, V4, 1);
5555 __ vinss(V6, 0, V4, 3);
5556
5557 __ fcvtds(V5, V5);
5558 __ fcvtds(V6, V6);
5559 __ faddd(V0, V5, V6);
5560 __ ret();
5561}
5562
5563ASSEMBLER_TEST_RUN(Vnegs, test) {
5564 typedef double (*DoubleReturn)() DART_UNUSED;
5565 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5566 EXPECT_DISASSEMBLY(
5567 "movz tmp, #0x4045 lsl 48\n"
5568 "fmovdr v1, tmp\n"
5569 "movz tmp, #0xc055 lsl 48\n"
5570 "fmovdr v2, tmp\n"
5571 "fcvtsd v1, v1\n"
5572 "fcvtsd v2, v2\n"
5573 "veor v3, v3, v3\n"
5574 "vinss v3[1], v1[0]\n"
5575 "vinss v3[3], v2[0]\n"
5576 "vnegs v4, v3\n"
5577 "vinss v5[0], v4[1]\n"
5578 "vinss v6[0], v4[3]\n"
5579 "fcvtds v5, v5\n"
5580 "fcvtds v6, v6\n"
5581 "faddd v0, v5, v6\n"
5582 "ret\n");
5583}
5584
5585ASSEMBLER_TEST_GENERATE(Vnegd, assembler) {
5586 __ LoadDImmediate(V1, 42.0);
5587 __ LoadDImmediate(V2, -84.0);
5588
5589 __ vinsd(V3, 0, V1, 0);
5590 __ vinsd(V3, 1, V2, 0);
5591
5592 __ vnegd(V4, V3);
5593
5594 __ vinsd(V5, 0, V4, 0);
5595 __ vinsd(V6, 0, V4, 1);
5596
5597 __ faddd(V0, V5, V6);
5598 __ ret();
5599}
5600
5601ASSEMBLER_TEST_RUN(Vnegd, test) {
5602 typedef double (*DoubleReturn)() DART_UNUSED;
5603 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5604 EXPECT_DISASSEMBLY(
5605 ""
5606 "movz tmp, #0x4045 lsl 48\n"
5607 "fmovdr v1, tmp\n"
5608 "movz tmp, #0xc055 lsl 48\n"
5609 "fmovdr v2, tmp\n"
5610 "vinsd v3[0], v1[0]\n"
5611 "vinsd v3[1], v2[0]\n"
5612 "vnegd v4, v3\n"
5613 "vinsd v5[0], v4[0]\n"
5614 "vinsd v6[0], v4[1]\n"
5615 "faddd v0, v5, v6\n"
5616 "ret\n");
5617}
5618
5619ASSEMBLER_TEST_GENERATE(Vadds, assembler) {
5620 __ LoadDImmediate(V0, 0.0);
5621 __ LoadDImmediate(V1, 1.0);
5622 __ LoadDImmediate(V2, 2.0);
5623 __ LoadDImmediate(V3, 3.0);
5624
5625 __ fcvtsd(V0, V0);
5626 __ fcvtsd(V1, V1);
5627 __ fcvtsd(V2, V2);
5628 __ fcvtsd(V3, V3);
5629
5630 __ vinss(V4, 0, V0, 0);
5631 __ vinss(V4, 1, V1, 0);
5632 __ vinss(V4, 2, V2, 0);
5633 __ vinss(V4, 3, V3, 0);
5634
5635 __ vadds(V5, V4, V4);
5636
5637 __ vinss(V0, 0, V5, 0);
5638 __ vinss(V1, 0, V5, 1);
5639 __ vinss(V2, 0, V5, 2);
5640 __ vinss(V3, 0, V5, 3);
5641
5642 __ fcvtds(V0, V0);
5643 __ fcvtds(V1, V1);
5644 __ fcvtds(V2, V2);
5645 __ fcvtds(V3, V3);
5646
5647 __ faddd(V0, V0, V1);
5648 __ faddd(V0, V0, V2);
5649 __ faddd(V0, V0, V3);
5650 __ ret();
5651}
5652
5653ASSEMBLER_TEST_RUN(Vadds, test) {
5654 typedef double (*DoubleReturn)() DART_UNUSED;
5655 EXPECT_EQ(12.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5656 EXPECT_DISASSEMBLY(
5657 "veor v0, v0, v0\n"
5658 "fmovd v1, 1.000000\n"
5659 "fmovd v2, 2.000000\n"
5660 "fmovd v3, 3.000000\n"
5661 "fcvtsd v0, v0\n"
5662 "fcvtsd v1, v1\n"
5663 "fcvtsd v2, v2\n"
5664 "fcvtsd v3, v3\n"
5665 "vinss v4[0], v0[0]\n"
5666 "vinss v4[1], v1[0]\n"
5667 "vinss v4[2], v2[0]\n"
5668 "vinss v4[3], v3[0]\n"
5669 "vadds v5, v4, v4\n"
5670 "vinss v0[0], v5[0]\n"
5671 "vinss v1[0], v5[1]\n"
5672 "vinss v2[0], v5[2]\n"
5673 "vinss v3[0], v5[3]\n"
5674 "fcvtds v0, v0\n"
5675 "fcvtds v1, v1\n"
5676 "fcvtds v2, v2\n"
5677 "fcvtds v3, v3\n"
5678 "faddd v0, v0, v1\n"
5679 "faddd v0, v0, v2\n"
5680 "faddd v0, v0, v3\n"
5681 "ret\n");
5682}
5683
5684ASSEMBLER_TEST_GENERATE(Vsubs, assembler) {
5685 __ LoadDImmediate(V0, 0.0);
5686 __ LoadDImmediate(V1, 1.0);
5687 __ LoadDImmediate(V2, 2.0);
5688 __ LoadDImmediate(V3, 3.0);
5689 __ LoadDImmediate(V5, 0.0);
5690
5691 __ fcvtsd(V0, V0);
5692 __ fcvtsd(V1, V1);
5693 __ fcvtsd(V2, V2);
5694 __ fcvtsd(V3, V3);
5695
5696 __ vinss(V4, 0, V0, 0);
5697 __ vinss(V4, 1, V1, 0);
5698 __ vinss(V4, 2, V2, 0);
5699 __ vinss(V4, 3, V3, 0);
5700
5701 __ vsubs(V5, V5, V4);
5702
5703 __ vinss(V0, 0, V5, 0);
5704 __ vinss(V1, 0, V5, 1);
5705 __ vinss(V2, 0, V5, 2);
5706 __ vinss(V3, 0, V5, 3);
5707
5708 __ fcvtds(V0, V0);
5709 __ fcvtds(V1, V1);
5710 __ fcvtds(V2, V2);
5711 __ fcvtds(V3, V3);
5712
5713 __ faddd(V0, V0, V1);
5714 __ faddd(V0, V0, V2);
5715 __ faddd(V0, V0, V3);
5716 __ ret();
5717}
5718
5719ASSEMBLER_TEST_RUN(Vsubs, test) {
5720 typedef double (*DoubleReturn)() DART_UNUSED;
5721 EXPECT_EQ(-6.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5722 EXPECT_DISASSEMBLY(
5723 "veor v0, v0, v0\n"
5724 "fmovd v1, 1.000000\n"
5725 "fmovd v2, 2.000000\n"
5726 "fmovd v3, 3.000000\n"
5727 "veor v5, v5, v5\n"
5728 "fcvtsd v0, v0\n"
5729 "fcvtsd v1, v1\n"
5730 "fcvtsd v2, v2\n"
5731 "fcvtsd v3, v3\n"
5732 "vinss v4[0], v0[0]\n"
5733 "vinss v4[1], v1[0]\n"
5734 "vinss v4[2], v2[0]\n"
5735 "vinss v4[3], v3[0]\n"
5736 "vsubs v5, v5, v4\n"
5737 "vinss v0[0], v5[0]\n"
5738 "vinss v1[0], v5[1]\n"
5739 "vinss v2[0], v5[2]\n"
5740 "vinss v3[0], v5[3]\n"
5741 "fcvtds v0, v0\n"
5742 "fcvtds v1, v1\n"
5743 "fcvtds v2, v2\n"
5744 "fcvtds v3, v3\n"
5745 "faddd v0, v0, v1\n"
5746 "faddd v0, v0, v2\n"
5747 "faddd v0, v0, v3\n"
5748 "ret\n");
5749}
5750
5751ASSEMBLER_TEST_GENERATE(Vmuls, assembler) {
5752 __ LoadDImmediate(V0, 0.0);
5753 __ LoadDImmediate(V1, 1.0);
5754 __ LoadDImmediate(V2, 2.0);
5755 __ LoadDImmediate(V3, 3.0);
5756
5757 __ fcvtsd(V0, V0);
5758 __ fcvtsd(V1, V1);
5759 __ fcvtsd(V2, V2);
5760 __ fcvtsd(V3, V3);
5761
5762 __ vinss(V4, 0, V0, 0);
5763 __ vinss(V4, 1, V1, 0);
5764 __ vinss(V4, 2, V2, 0);
5765 __ vinss(V4, 3, V3, 0);
5766
5767 __ vmuls(V5, V4, V4);
5768
5769 __ vinss(V0, 0, V5, 0);
5770 __ vinss(V1, 0, V5, 1);
5771 __ vinss(V2, 0, V5, 2);
5772 __ vinss(V3, 0, V5, 3);
5773
5774 __ fcvtds(V0, V0);
5775 __ fcvtds(V1, V1);
5776 __ fcvtds(V2, V2);
5777 __ fcvtds(V3, V3);
5778
5779 __ faddd(V0, V0, V1);
5780 __ faddd(V0, V0, V2);
5781 __ faddd(V0, V0, V3);
5782 __ ret();
5783}
5784
5785ASSEMBLER_TEST_RUN(Vmuls, test) {
5786 typedef double (*DoubleReturn)() DART_UNUSED;
5787 EXPECT_EQ(14.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5788 EXPECT_DISASSEMBLY(
5789 "veor v0, v0, v0\n"
5790 "fmovd v1, 1.000000\n"
5791 "fmovd v2, 2.000000\n"
5792 "fmovd v3, 3.000000\n"
5793 "fcvtsd v0, v0\n"
5794 "fcvtsd v1, v1\n"
5795 "fcvtsd v2, v2\n"
5796 "fcvtsd v3, v3\n"
5797 "vinss v4[0], v0[0]\n"
5798 "vinss v4[1], v1[0]\n"
5799 "vinss v4[2], v2[0]\n"
5800 "vinss v4[3], v3[0]\n"
5801 "vmuls v5, v4, v4\n"
5802 "vinss v0[0], v5[0]\n"
5803 "vinss v1[0], v5[1]\n"
5804 "vinss v2[0], v5[2]\n"
5805 "vinss v3[0], v5[3]\n"
5806 "fcvtds v0, v0\n"
5807 "fcvtds v1, v1\n"
5808 "fcvtds v2, v2\n"
5809 "fcvtds v3, v3\n"
5810 "faddd v0, v0, v1\n"
5811 "faddd v0, v0, v2\n"
5812 "faddd v0, v0, v3\n"
5813 "ret\n");
5814}
5815
5816ASSEMBLER_TEST_GENERATE(Vdivs, assembler) {
5817 __ LoadDImmediate(V0, 0.0);
5818 __ LoadDImmediate(V1, 1.0);
5819 __ LoadDImmediate(V2, 2.0);
5820 __ LoadDImmediate(V3, 3.0);
5821
5822 __ fcvtsd(V0, V0);
5823 __ fcvtsd(V1, V1);
5824 __ fcvtsd(V2, V2);
5825 __ fcvtsd(V3, V3);
5826
5827 __ vinss(V4, 0, V0, 0);
5828 __ vinss(V4, 1, V1, 0);
5829 __ vinss(V4, 2, V2, 0);
5830 __ vinss(V4, 3, V3, 0);
5831
5832 __ vdivs(V5, V4, V4);
5833
5834 __ vinss(V0, 0, V5, 0);
5835 __ vinss(V1, 0, V5, 1);
5836 __ vinss(V2, 0, V5, 2);
5837 __ vinss(V3, 0, V5, 3);
5838
5839 __ fcvtds(V0, V0);
5840 __ fcvtds(V1, V1);
5841 __ fcvtds(V2, V2);
5842 __ fcvtds(V3, V3);
5843
5844 __ faddd(V0, V1, V1);
5845 __ faddd(V0, V0, V2);
5846 __ faddd(V0, V0, V3);
5847 __ ret();
5848}
5849
5850ASSEMBLER_TEST_RUN(Vdivs, test) {
5851 typedef double (*DoubleReturn)() DART_UNUSED;
5852 EXPECT_EQ(4.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5853 EXPECT_DISASSEMBLY(
5854 "veor v0, v0, v0\n"
5855 "fmovd v1, 1.000000\n"
5856 "fmovd v2, 2.000000\n"
5857 "fmovd v3, 3.000000\n"
5858 "fcvtsd v0, v0\n"
5859 "fcvtsd v1, v1\n"
5860 "fcvtsd v2, v2\n"
5861 "fcvtsd v3, v3\n"
5862 "vinss v4[0], v0[0]\n"
5863 "vinss v4[1], v1[0]\n"
5864 "vinss v4[2], v2[0]\n"
5865 "vinss v4[3], v3[0]\n"
5866 "vdivs v5, v4, v4\n"
5867 "vinss v0[0], v5[0]\n"
5868 "vinss v1[0], v5[1]\n"
5869 "vinss v2[0], v5[2]\n"
5870 "vinss v3[0], v5[3]\n"
5871 "fcvtds v0, v0\n"
5872 "fcvtds v1, v1\n"
5873 "fcvtds v2, v2\n"
5874 "fcvtds v3, v3\n"
5875 "faddd v0, v1, v1\n"
5876 "faddd v0, v0, v2\n"
5877 "faddd v0, v0, v3\n"
5878 "ret\n");
5879}
5880
5881ASSEMBLER_TEST_GENERATE(Vaddd, assembler) {
5882 __ LoadDImmediate(V0, 2.0);
5883 __ LoadDImmediate(V1, 3.0);
5884
5885 __ vinsd(V4, 0, V0, 0);
5886 __ vinsd(V4, 1, V1, 0);
5887
5888 __ vaddd(V5, V4, V4);
5889
5890 __ vinsd(V0, 0, V5, 0);
5891 __ vinsd(V1, 0, V5, 1);
5892
5893 __ faddd(V0, V0, V1);
5894 __ ret();
5895}
5896
5897ASSEMBLER_TEST_RUN(Vaddd, test) {
5898 typedef double (*DoubleReturn)() DART_UNUSED;
5899 EXPECT_EQ(10.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5900 EXPECT_DISASSEMBLY(
5901 ""
5902 "fmovd v0, 2.000000\n"
5903 "fmovd v1, 3.000000\n"
5904 "vinsd v4[0], v0[0]\n"
5905 "vinsd v4[1], v1[0]\n"
5906 "vaddd v5, v4, v4\n"
5907 "vinsd v0[0], v5[0]\n"
5908 "vinsd v1[0], v5[1]\n"
5909 "faddd v0, v0, v1\n"
5910 "ret\n");
5911}
5912
5913ASSEMBLER_TEST_GENERATE(Vsubd, assembler) {
5914 __ LoadDImmediate(V0, 2.0);
5915 __ LoadDImmediate(V1, 3.0);
5916 __ LoadDImmediate(V5, 0.0);
5917
5918 __ vinsd(V4, 0, V0, 0);
5919 __ vinsd(V4, 1, V1, 0);
5920
5921 __ vsubd(V5, V5, V4);
5922
5923 __ vinsd(V0, 0, V5, 0);
5924 __ vinsd(V1, 0, V5, 1);
5925
5926 __ faddd(V0, V0, V1);
5927 __ ret();
5928}
5929
5930ASSEMBLER_TEST_RUN(Vsubd, test) {
5931 typedef double (*DoubleReturn)() DART_UNUSED;
5932 EXPECT_EQ(-5.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5933 EXPECT_DISASSEMBLY(
5934 "fmovd v0, 2.000000\n"
5935 "fmovd v1, 3.000000\n"
5936 "veor v5, v5, v5\n"
5937 "vinsd v4[0], v0[0]\n"
5938 "vinsd v4[1], v1[0]\n"
5939 "vsubd v5, v5, v4\n"
5940 "vinsd v0[0], v5[0]\n"
5941 "vinsd v1[0], v5[1]\n"
5942 "faddd v0, v0, v1\n"
5943 "ret\n");
5944}
5945
5946ASSEMBLER_TEST_GENERATE(Vmuld, assembler) {
5947 __ LoadDImmediate(V0, 2.0);
5948 __ LoadDImmediate(V1, 3.0);
5949
5950 __ vinsd(V4, 0, V0, 0);
5951 __ vinsd(V4, 1, V1, 0);
5952
5953 __ vmuld(V5, V4, V4);
5954
5955 __ vinsd(V0, 0, V5, 0);
5956 __ vinsd(V1, 0, V5, 1);
5957
5958 __ faddd(V0, V0, V1);
5959 __ ret();
5960}
5961
5962ASSEMBLER_TEST_RUN(Vmuld, test) {
5963 typedef double (*DoubleReturn)() DART_UNUSED;
5964 EXPECT_EQ(13.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5965 EXPECT_DISASSEMBLY(
5966 ""
5967 "fmovd v0, 2.000000\n"
5968 "fmovd v1, 3.000000\n"
5969 "vinsd v4[0], v0[0]\n"
5970 "vinsd v4[1], v1[0]\n"
5971 "vmuld v5, v4, v4\n"
5972 "vinsd v0[0], v5[0]\n"
5973 "vinsd v1[0], v5[1]\n"
5974 "faddd v0, v0, v1\n"
5975 "ret\n");
5976}
5977
5978ASSEMBLER_TEST_GENERATE(Vdivd, assembler) {
5979 __ LoadDImmediate(V0, 2.0);
5980 __ LoadDImmediate(V1, 3.0);
5981
5982 __ vinsd(V4, 0, V0, 0);
5983 __ vinsd(V4, 1, V1, 0);
5984
5985 __ vdivd(V5, V4, V4);
5986
5987 __ vinsd(V0, 0, V5, 0);
5988 __ vinsd(V1, 0, V5, 1);
5989
5990 __ faddd(V0, V0, V1);
5991 __ ret();
5992}
5993
5994ASSEMBLER_TEST_RUN(Vdivd, test) {
5995 typedef double (*DoubleReturn)() DART_UNUSED;
5996 EXPECT_EQ(2.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
5997 EXPECT_DISASSEMBLY(
5998 "fmovd v0, 2.000000\n"
5999 "fmovd v1, 3.000000\n"
6000 "vinsd v4[0], v0[0]\n"
6001 "vinsd v4[1], v1[0]\n"
6002 "vdivd v5, v4, v4\n"
6003 "vinsd v0[0], v5[0]\n"
6004 "vinsd v1[0], v5[1]\n"
6005 "faddd v0, v0, v1\n"
6006 "ret\n");
6007}
6008
6009ASSEMBLER_TEST_GENERATE(Vdupd, assembler) {
6010 __ SetupDartSP();
6011 __ LoadDImmediate(V0, 21.0);
6012 __ vdupd(V1, V0, 0);
6013
6014 const int dword_bytes = 1 << Log2OperandSizeBytes(kDWord);
6015 const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord);
6016
6017 __ sub(CSP, CSP, Operand(qword_bytes)); // Must not access beyond CSP.
6018
6019 __ fstrq(V1, Address(SP, -1 * qword_bytes, Address::PreIndex));
6020
6021 __ fldrd(V2, Address(SP, 1 * dword_bytes, Address::PostIndex));
6022 __ fldrd(V3, Address(SP, 1 * dword_bytes, Address::PostIndex));
6023
6024 __ faddd(V0, V2, V3);
6025 __ RestoreCSP();
6026 __ ret();
6027}
6028
6029ASSEMBLER_TEST_RUN(Vdupd, test) {
6030 typedef double (*DoubleReturn)() DART_UNUSED;
6031 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6032 EXPECT_DISASSEMBLY(
6033 ""
6034 "mov sp, csp\n"
6035 "sub csp, csp, #0x1000\n"
6036 "fmovd v0, 21.000000\n"
6037 "vdupd v1, v0[0]\n"
6038 "sub csp, csp, #0x10\n"
6039 "fstrq v1, [sp, #-16]!\n"
6040 "fldrd v2, [sp], #8 !\n"
6041 "fldrd v3, [sp], #8 !\n"
6042 "faddd v0, v2, v3\n"
6043 "mov csp, sp\n"
6044 "ret\n");
6045}
6046
6047ASSEMBLER_TEST_GENERATE(Vdups, assembler) {
6048 __ SetupDartSP();
6049 __ LoadDImmediate(V0, 21.0);
6050 __ fcvtsd(V0, V0);
6051 __ vdups(V1, V0, 0);
6052
6053 const int sword_bytes = 1 << Log2OperandSizeBytes(kSWord);
6054 const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord);
6055
6056 __ sub(CSP, CSP, Operand(qword_bytes)); // Must not access beyond CSP.
6057
6058 __ fstrq(V1, Address(SP, -1 * qword_bytes, Address::PreIndex));
6059
6060 __ fldrs(V3, Address(SP, 1 * sword_bytes, Address::PostIndex));
6061 __ fldrs(V2, Address(SP, 1 * sword_bytes, Address::PostIndex));
6062 __ fldrs(V1, Address(SP, 1 * sword_bytes, Address::PostIndex));
6063 __ fldrs(V0, Address(SP, 1 * sword_bytes, Address::PostIndex));
6064
6065 __ fcvtds(V0, V0);
6066 __ fcvtds(V1, V1);
6067 __ fcvtds(V2, V2);
6068 __ fcvtds(V3, V3);
6069
6070 __ faddd(V0, V1, V1);
6071 __ faddd(V0, V0, V2);
6072 __ faddd(V0, V0, V3);
6073 __ RestoreCSP();
6074 __ ret();
6075}
6076
6077ASSEMBLER_TEST_RUN(Vdups, test) {
6078 typedef double (*DoubleReturn)() DART_UNUSED;
6079 EXPECT_EQ(84.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6080 EXPECT_DISASSEMBLY(
6081 ""
6082 "mov sp, csp\n"
6083 "sub csp, csp, #0x1000\n"
6084 "fmovd v0, 21.000000\n"
6085 "fcvtsd v0, v0\n"
6086 "vdups v1, v0[0]\n"
6087 "sub csp, csp, #0x10\n"
6088 "fstrq v1, [sp, #-16]!\n"
6089 "fldrs v3, [sp], #4 !\n"
6090 "fldrs v2, [sp], #4 !\n"
6091 "fldrs v1, [sp], #4 !\n"
6092 "fldrs v0, [sp], #4 !\n"
6093 "fcvtds v0, v0\n"
6094 "fcvtds v1, v1\n"
6095 "fcvtds v2, v2\n"
6096 "fcvtds v3, v3\n"
6097 "faddd v0, v1, v1\n"
6098 "faddd v0, v0, v2\n"
6099 "faddd v0, v0, v3\n"
6100 "mov csp, sp\n"
6101 "ret\n");
6102}
6103
6104ASSEMBLER_TEST_GENERATE(Vinsd, assembler) {
6105 __ SetupDartSP();
6106 __ LoadDImmediate(V5, 42.0);
6107 __ vinsd(V1, 1, V5, 0); // V1[1] <- V0[0].
6108
6109 const int dword_bytes = 1 << Log2OperandSizeBytes(kDWord);
6110 const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord);
6111
6112 __ sub(CSP, CSP, Operand(qword_bytes)); // Must not access beyond CSP.
6113
6114 __ fstrq(V1, Address(SP, -1 * qword_bytes, Address::PreIndex));
6115
6116 __ fldrd(V2, Address(SP, 1 * dword_bytes, Address::PostIndex));
6117 __ fldrd(V3, Address(SP, 1 * dword_bytes, Address::PostIndex));
6118
6119 __ fmovdd(V0, V3);
6120 __ RestoreCSP();
6121 __ ret();
6122}
6123
6124ASSEMBLER_TEST_RUN(Vinsd, test) {
6125 typedef double (*DoubleReturn)() DART_UNUSED;
6126 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6127 EXPECT_DISASSEMBLY(
6128 ""
6129 "mov sp, csp\n"
6130 "sub csp, csp, #0x1000\n"
6131 "movz tmp, #0x4045 lsl 48\n"
6132 "fmovdr v5, tmp\n"
6133 "vinsd v1[1], v5[0]\n"
6134 "sub csp, csp, #0x10\n"
6135 "fstrq v1, [sp, #-16]!\n"
6136 "fldrd v2, [sp], #8 !\n"
6137 "fldrd v3, [sp], #8 !\n"
6138 "fmovdd v0, v3\n"
6139 "mov csp, sp\n"
6140 "ret\n");
6141}
6142
6143ASSEMBLER_TEST_GENERATE(Vinss, assembler) {
6144 __ SetupDartSP();
6145 // Set V1 parts 1 and 3 to 21.0.
6146 __ LoadDImmediate(V0, 21.0);
6147 __ fcvtsd(V0, V0);
6148 __ vinss(V1, 3, V0, 0);
6149 __ vinss(V1, 1, V0, 0);
6150
6151 // Set V1 parts 0 and 2 to 0.0.
6152 __ LoadDImmediate(V0, 0.0);
6153 __ fcvtsd(V0, V0);
6154 __ vinss(V1, 2, V0, 0);
6155 __ vinss(V1, 0, V0, 0);
6156
6157 const int sword_bytes = 1 << Log2OperandSizeBytes(kSWord);
6158 const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord);
6159
6160 __ sub(CSP, CSP, Operand(qword_bytes)); // Must not access beyond CSP.
6161
6162 __ fstrq(V1, Address(SP, -1 * qword_bytes, Address::PreIndex));
6163
6164 __ fldrs(V3, Address(SP, 1 * sword_bytes, Address::PostIndex));
6165 __ fldrs(V2, Address(SP, 1 * sword_bytes, Address::PostIndex));
6166 __ fldrs(V1, Address(SP, 1 * sword_bytes, Address::PostIndex));
6167 __ fldrs(V0, Address(SP, 1 * sword_bytes, Address::PostIndex));
6168
6169 __ fcvtds(V0, V0);
6170 __ fcvtds(V1, V1);
6171 __ fcvtds(V2, V2);
6172 __ fcvtds(V3, V3);
6173
6174 __ faddd(V0, V0, V1);
6175 __ faddd(V0, V0, V2);
6176 __ faddd(V0, V0, V3);
6177 __ RestoreCSP();
6178 __ ret();
6179}
6180
6181ASSEMBLER_TEST_RUN(Vinss, test) {
6182 typedef double (*DoubleReturn)() DART_UNUSED;
6183 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6184 EXPECT_DISASSEMBLY(
6185 "mov sp, csp\n"
6186 "sub csp, csp, #0x1000\n"
6187 "fmovd v0, 21.000000\n"
6188 "fcvtsd v0, v0\n"
6189 "vinss v1[3], v0[0]\n"
6190 "vinss v1[1], v0[0]\n"
6191 "veor v0, v0, v0\n"
6192 "fcvtsd v0, v0\n"
6193 "vinss v1[2], v0[0]\n"
6194 "vinss v1[0], v0[0]\n"
6195 "sub csp, csp, #0x10\n"
6196 "fstrq v1, [sp, #-16]!\n"
6197 "fldrs v3, [sp], #4 !\n"
6198 "fldrs v2, [sp], #4 !\n"
6199 "fldrs v1, [sp], #4 !\n"
6200 "fldrs v0, [sp], #4 !\n"
6201 "fcvtds v0, v0\n"
6202 "fcvtds v1, v1\n"
6203 "fcvtds v2, v2\n"
6204 "fcvtds v3, v3\n"
6205 "faddd v0, v0, v1\n"
6206 "faddd v0, v0, v2\n"
6207 "faddd v0, v0, v3\n"
6208 "mov csp, sp\n"
6209 "ret\n");
6210}
6211
6212ASSEMBLER_TEST_GENERATE(Vand, assembler) {
6213 __ LoadDImmediate(V1, 21.0);
6214 __ LoadImmediate(R0, 0xffffffff);
6215
6216 // V0 <- (0, 0xffffffff, 0, 0xffffffff)
6217 __ fmovdr(V0, R0);
6218 __ vinss(V0, 2, V0, 0);
6219
6220 // V1 <- (21.0, 21.0, 21.0, 21.0)
6221 __ fcvtsd(V1, V1);
6222 __ vdups(V1, V1, 0);
6223
6224 __ vand(V2, V1, V0);
6225
6226 __ vinss(V3, 0, V2, 0);
6227 __ vinss(V4, 0, V2, 1);
6228 __ vinss(V5, 0, V2, 2);
6229 __ vinss(V6, 0, V2, 3);
6230
6231 __ fcvtds(V3, V3);
6232 __ fcvtds(V4, V4);
6233 __ fcvtds(V5, V5);
6234 __ fcvtds(V6, V6);
6235
6236 __ vaddd(V0, V3, V4);
6237 __ vaddd(V0, V0, V5);
6238 __ vaddd(V0, V0, V6);
6239 __ ret();
6240}
6241
6242ASSEMBLER_TEST_RUN(Vand, test) {
6243 typedef double (*DoubleReturn)() DART_UNUSED;
6244 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6245 EXPECT_DISASSEMBLY(
6246 "fmovd v1, 21.000000\n"
6247 "mov r0, 0xffffffff\n"
6248 "fmovdr v0, r0\n"
6249 "vinss v0[2], v0[0]\n"
6250 "fcvtsd v1, v1\n"
6251 "vdups v1, v1[0]\n"
6252 "vand v2, v1, v0\n"
6253 "vinss v3[0], v2[0]\n"
6254 "vinss v4[0], v2[1]\n"
6255 "vinss v5[0], v2[2]\n"
6256 "vinss v6[0], v2[3]\n"
6257 "fcvtds v3, v3\n"
6258 "fcvtds v4, v4\n"
6259 "fcvtds v5, v5\n"
6260 "fcvtds v6, v6\n"
6261 "vaddd v0, v3, v4\n"
6262 "vaddd v0, v0, v5\n"
6263 "vaddd v0, v0, v6\n"
6264 "ret\n");
6265}
6266
6267ASSEMBLER_TEST_GENERATE(Vorr, assembler) {
6268 __ LoadDImmediate(V1, 10.5);
6269 __ fcvtsd(V1, V1);
6270
6271 // V0 <- (0, 10.5, 0, 10.5)
6272 __ fmovdd(V0, V1);
6273 __ vinss(V0, 2, V0, 0);
6274
6275 // V1 <- (10.5, 0, 10.5, 0)
6276 __ veor(V1, V1, V1);
6277 __ vinss(V1, 1, V0, 0);
6278 __ vinss(V1, 3, V0, 0);
6279
6280 __ vorr(V2, V1, V0);
6281
6282 __ vinss(V3, 0, V2, 0);
6283 __ vinss(V4, 0, V2, 1);
6284 __ vinss(V5, 0, V2, 2);
6285 __ vinss(V6, 0, V2, 3);
6286
6287 __ fcvtds(V3, V3);
6288 __ fcvtds(V4, V4);
6289 __ fcvtds(V5, V5);
6290 __ fcvtds(V6, V6);
6291
6292 __ vaddd(V0, V3, V4);
6293 __ vaddd(V0, V0, V5);
6294 __ vaddd(V0, V0, V6);
6295 __ ret();
6296}
6297
6298ASSEMBLER_TEST_RUN(Vorr, test) {
6299 typedef double (*DoubleReturn)() DART_UNUSED;
6300 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6301 EXPECT_DISASSEMBLY(
6302 "fmovd v1, 10.500000\n"
6303 "fcvtsd v1, v1\n"
6304 "fmovdd v0, v1\n"
6305 "vinss v0[2], v0[0]\n"
6306 "veor v1, v1, v1\n"
6307 "vinss v1[1], v0[0]\n"
6308 "vinss v1[3], v0[0]\n"
6309 "vorr v2, v1, v0\n"
6310 "vinss v3[0], v2[0]\n"
6311 "vinss v4[0], v2[1]\n"
6312 "vinss v5[0], v2[2]\n"
6313 "vinss v6[0], v2[3]\n"
6314 "fcvtds v3, v3\n"
6315 "fcvtds v4, v4\n"
6316 "fcvtds v5, v5\n"
6317 "fcvtds v6, v6\n"
6318 "vaddd v0, v3, v4\n"
6319 "vaddd v0, v0, v5\n"
6320 "vaddd v0, v0, v6\n"
6321 "ret\n");
6322}
6323
6324ASSEMBLER_TEST_GENERATE(Veor, assembler) {
6325 __ LoadImmediate(R1, 0xffffffff);
6326 __ LoadImmediate(R2, ~21);
6327
6328 __ vinsw(V1, 0, R1);
6329 __ vinsw(V1, 1, R2);
6330 __ vinsw(V1, 2, R1);
6331 __ vinsw(V1, 3, R2);
6332
6333 __ vinsw(V2, 0, R1);
6334 __ vinsw(V2, 1, R1);
6335 __ vinsw(V2, 2, R1);
6336 __ vinsw(V2, 3, R1);
6337
6338 __ veor(V0, V1, V2);
6339
6340 __ vmovrs(R3, V0, 0);
6341 __ vmovrs(R4, V0, 1);
6342 __ vmovrs(R5, V0, 2);
6343 __ vmovrs(R6, V0, 3);
6344
6345 __ add(R0, R3, Operand(R4));
6346 __ add(R0, R0, Operand(R5));
6347 __ add(R0, R0, Operand(R6));
6348 __ ret();
6349}
6350
6351ASSEMBLER_TEST_RUN(Veor, test) {
6352 typedef int64_t (*Int64Return)() DART_UNUSED;
6353 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6354 EXPECT_DISASSEMBLY(
6355 "mov r1, 0xffffffff\n"
6356 "movn r2, #0x15\n"
6357 "vinss v1[0], r1\n"
6358 "vinss v1[1], r2\n"
6359 "vinss v1[2], r1\n"
6360 "vinss v1[3], r2\n"
6361 "vinss v2[0], r1\n"
6362 "vinss v2[1], r1\n"
6363 "vinss v2[2], r1\n"
6364 "vinss v2[3], r1\n"
6365 "veor v0, v1, v2\n"
6366 "vmovrs r3, v0[0]\n"
6367 "vmovrs r4, v0[1]\n"
6368 "vmovrs r5, v0[2]\n"
6369 "vmovrs r6, v0[3]\n"
6370 "add r0, r3, r4\n"
6371 "add r0, r0, r5\n"
6372 "add r0, r0, r6\n"
6373 "ret\n");
6374}
6375
6376ASSEMBLER_TEST_GENERATE(Vaddw, assembler) {
6377 __ LoadImmediate(R4, 21);
6378
6379 __ vdupw(V1, R4);
6380 __ vdupw(V2, R4);
6381
6382 __ vaddw(V0, V1, V2);
6383
6384 __ vmovrs(R0, V0, 0);
6385 __ vmovrs(R1, V0, 1);
6386 __ vmovrs(R2, V0, 2);
6387 __ vmovrs(R3, V0, 3);
6388 __ add(R0, R0, Operand(R1));
6389 __ add(R0, R0, Operand(R2));
6390 __ add(R0, R0, Operand(R3));
6391 __ ret();
6392}
6393
6394ASSEMBLER_TEST_RUN(Vaddw, test) {
6395 typedef int64_t (*Int64Return)() DART_UNUSED;
6396 EXPECT_EQ(168, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6397 EXPECT_DISASSEMBLY(
6398 "movz r4, #0x15\n"
6399 "vdups v1, r4\n"
6400 "vdups v2, r4\n"
6401 "vaddw v0, v1, v2\n"
6402 "vmovrs r0, v0[0]\n"
6403 "vmovrs r1, v0[1]\n"
6404 "vmovrs r2, v0[2]\n"
6405 "vmovrs r3, v0[3]\n"
6406 "add r0, r0, r1\n"
6407 "add r0, r0, r2\n"
6408 "add r0, r0, r3\n"
6409 "ret\n");
6410}
6411
6412ASSEMBLER_TEST_GENERATE(Vsubw, assembler) {
6413 __ LoadImmediate(R4, 31);
6414 __ LoadImmediate(R5, 10);
6415
6416 __ vdupw(V1, R4);
6417 __ vdupw(V2, R5);
6418
6419 __ vsubw(V0, V1, V2);
6420
6421 __ vmovrs(R0, V0, 0);
6422 __ vmovrs(R1, V0, 1);
6423 __ vmovrs(R2, V0, 2);
6424 __ vmovrs(R3, V0, 3);
6425 __ add(R0, R0, Operand(R1));
6426 __ add(R0, R0, Operand(R2));
6427 __ add(R0, R0, Operand(R3));
6428 __ ret();
6429}
6430
6431ASSEMBLER_TEST_RUN(Vsubw, test) {
6432 typedef int64_t (*Int64Return)() DART_UNUSED;
6433 EXPECT_EQ(84, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6434 EXPECT_DISASSEMBLY(
6435 "movz r4, #0x1f\n"
6436 "movz r5, #0xa\n"
6437 "vdups v1, r4\n"
6438 "vdups v2, r5\n"
6439 "vsubw v0, v1, v2\n"
6440 "vmovrs r0, v0[0]\n"
6441 "vmovrs r1, v0[1]\n"
6442 "vmovrs r2, v0[2]\n"
6443 "vmovrs r3, v0[3]\n"
6444 "add r0, r0, r1\n"
6445 "add r0, r0, r2\n"
6446 "add r0, r0, r3\n"
6447 "ret\n");
6448}
6449
6450ASSEMBLER_TEST_GENERATE(Vaddx, assembler) {
6451 __ LoadImmediate(R4, 21);
6452
6453 __ vdupx(V1, R4);
6454 __ vdupx(V2, R4);
6455
6456 __ vaddx(V0, V1, V2);
6457
6458 __ vmovrd(R0, V0, 0);
6459 __ vmovrd(R1, V0, 1);
6460 __ add(R0, R0, Operand(R1));
6461 __ ret();
6462}
6463
6464ASSEMBLER_TEST_RUN(Vaddx, test) {
6465 typedef int64_t (*Int64Return)() DART_UNUSED;
6466 EXPECT_EQ(84, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6467 EXPECT_DISASSEMBLY(
6468 "movz r4, #0x15\n"
6469 "vdupd v1, r4\n"
6470 "vdupd v2, r4\n"
6471 "vaddx v0, v1, v2\n"
6472 "vmovrd r0, v0[0]\n"
6473 "vmovrd r1, v0[1]\n"
6474 "add r0, r0, r1\n"
6475 "ret\n");
6476}
6477
6478ASSEMBLER_TEST_GENERATE(Vsubx, assembler) {
6479 __ LoadImmediate(R4, 31);
6480 __ LoadImmediate(R5, 10);
6481
6482 __ vdupx(V1, R4);
6483 __ vdupx(V2, R5);
6484
6485 __ vsubx(V0, V1, V2);
6486
6487 __ vmovrd(R0, V0, 0);
6488 __ vmovrd(R1, V0, 1);
6489 __ add(R0, R0, Operand(R1));
6490 __ ret();
6491}
6492
6493ASSEMBLER_TEST_RUN(Vsubx, test) {
6494 typedef int64_t (*Int64Return)() DART_UNUSED;
6495 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6496 EXPECT_DISASSEMBLY(
6497 "movz r4, #0x1f\n"
6498 "movz r5, #0xa\n"
6499 "vdupd v1, r4\n"
6500 "vdupd v2, r5\n"
6501 "vsubx v0, v1, v2\n"
6502 "vmovrd r0, v0[0]\n"
6503 "vmovrd r1, v0[1]\n"
6504 "add r0, r0, r1\n"
6505 "ret\n");
6506}
6507
6508ASSEMBLER_TEST_GENERATE(Vceqs, assembler) {
6509 __ LoadDImmediate(V0, 42.0);
6510 __ LoadDImmediate(V1, -42.0);
6511
6512 __ fcvtsd(V0, V0);
6513 __ fcvtsd(V1, V1);
6514
6515 __ vdups(V2, V0, 0);
6516 __ vinss(V3, 0, V0, 0);
6517 __ vinss(V3, 1, V1, 0);
6518 __ vinss(V3, 2, V0, 0);
6519 __ vinss(V3, 3, V1, 0);
6520
6521 __ vceqs(V4, V2, V3);
6522
6523 __ vmovrs(R1, V4, 0);
6524 __ vmovrs(R2, V4, 1);
6525 __ vmovrs(R3, V4, 2);
6526 __ vmovrs(R4, V4, 3);
6527
6528 __ addw(R0, R1, Operand(R2));
6529 __ addw(R0, R0, Operand(R3));
6530 __ addw(R0, R0, Operand(R4));
6531 __ ret();
6532}
6533
6534ASSEMBLER_TEST_RUN(Vceqs, test) {
6535 typedef int64_t (*Int64Return)() DART_UNUSED;
6536 EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6537 EXPECT_DISASSEMBLY(
6538 "movz tmp, #0x4045 lsl 48\n"
6539 "fmovdr v0, tmp\n"
6540 "movz tmp, #0xc045 lsl 48\n"
6541 "fmovdr v1, tmp\n"
6542 "fcvtsd v0, v0\n"
6543 "fcvtsd v1, v1\n"
6544 "vdups v2, v0[0]\n"
6545 "vinss v3[0], v0[0]\n"
6546 "vinss v3[1], v1[0]\n"
6547 "vinss v3[2], v0[0]\n"
6548 "vinss v3[3], v1[0]\n"
6549 "vceqs v4, v2, v3\n"
6550 "vmovrs r1, v4[0]\n"
6551 "vmovrs r2, v4[1]\n"
6552 "vmovrs r3, v4[2]\n"
6553 "vmovrs r4, v4[3]\n"
6554 "addw r0, r1, r2\n"
6555 "addw r0, r0, r3\n"
6556 "addw r0, r0, r4\n"
6557 "ret\n");
6558}
6559
6560ASSEMBLER_TEST_GENERATE(Vceqd, assembler) {
6561 __ LoadDImmediate(V0, 42.0);
6562 __ LoadDImmediate(V1, -42.0);
6563
6564 __ vdupd(V2, V0, 0);
6565 __ vinsd(V3, 0, V0, 0);
6566 __ vinsd(V3, 1, V1, 0);
6567
6568 __ vceqd(V4, V2, V3);
6569
6570 __ vmovrd(R1, V4, 0);
6571 __ vmovrd(R2, V4, 1);
6572
6573 __ add(R0, R1, Operand(R2));
6574 __ ret();
6575}
6576
6577ASSEMBLER_TEST_RUN(Vceqd, test) {
6578 typedef int64_t (*Int64Return)() DART_UNUSED;
6579 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6580 EXPECT_DISASSEMBLY(
6581 "movz tmp, #0x4045 lsl 48\n"
6582 "fmovdr v0, tmp\n"
6583 "movz tmp, #0xc045 lsl 48\n"
6584 "fmovdr v1, tmp\n"
6585 "vdupd v2, v0[0]\n"
6586 "vinsd v3[0], v0[0]\n"
6587 "vinsd v3[1], v1[0]\n"
6588 "vceqd v4, v2, v3\n"
6589 "vmovrd r1, v4[0]\n"
6590 "vmovrd r2, v4[1]\n"
6591 "add r0, r1, r2\n"
6592 "ret\n");
6593}
6594
6595ASSEMBLER_TEST_GENERATE(Vcgts, assembler) {
6596 __ LoadDImmediate(V0, 42.0);
6597 __ LoadDImmediate(V1, -42.0);
6598
6599 __ fcvtsd(V0, V0);
6600 __ fcvtsd(V1, V1);
6601
6602 __ vdups(V2, V0, 0);
6603 __ vinss(V3, 0, V0, 0);
6604 __ vinss(V3, 1, V1, 0);
6605 __ vinss(V3, 2, V0, 0);
6606 __ vinss(V3, 3, V1, 0);
6607
6608 __ vcgts(V4, V2, V3);
6609
6610 __ vmovrs(R1, V4, 0);
6611 __ vmovrs(R2, V4, 1);
6612 __ vmovrs(R3, V4, 2);
6613 __ vmovrs(R4, V4, 3);
6614
6615 __ addw(R0, R1, Operand(R2));
6616 __ addw(R0, R0, Operand(R3));
6617 __ addw(R0, R0, Operand(R4));
6618 __ ret();
6619}
6620
6621ASSEMBLER_TEST_RUN(Vcgts, test) {
6622 typedef int64_t (*Int64Return)() DART_UNUSED;
6623 EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6624 EXPECT_DISASSEMBLY(
6625 "movz tmp, #0x4045 lsl 48\n"
6626 "fmovdr v0, tmp\n"
6627 "movz tmp, #0xc045 lsl 48\n"
6628 "fmovdr v1, tmp\n"
6629 "fcvtsd v0, v0\n"
6630 "fcvtsd v1, v1\n"
6631 "vdups v2, v0[0]\n"
6632 "vinss v3[0], v0[0]\n"
6633 "vinss v3[1], v1[0]\n"
6634 "vinss v3[2], v0[0]\n"
6635 "vinss v3[3], v1[0]\n"
6636 "vcgts v4, v2, v3\n"
6637 "vmovrs r1, v4[0]\n"
6638 "vmovrs r2, v4[1]\n"
6639 "vmovrs r3, v4[2]\n"
6640 "vmovrs r4, v4[3]\n"
6641 "addw r0, r1, r2\n"
6642 "addw r0, r0, r3\n"
6643 "addw r0, r0, r4\n"
6644 "ret\n");
6645}
6646
6647ASSEMBLER_TEST_GENERATE(Vcgtd, assembler) {
6648 __ LoadDImmediate(V0, 42.0);
6649 __ LoadDImmediate(V1, -42.0);
6650
6651 __ vdupd(V2, V0, 0);
6652 __ vinsd(V3, 0, V0, 0);
6653 __ vinsd(V3, 1, V1, 0);
6654
6655 __ vcgtd(V4, V2, V3);
6656
6657 __ vmovrd(R1, V4, 0);
6658 __ vmovrd(R2, V4, 1);
6659
6660 __ add(R0, R1, Operand(R2));
6661 __ ret();
6662}
6663
6664ASSEMBLER_TEST_RUN(Vcgtd, test) {
6665 typedef int64_t (*Int64Return)() DART_UNUSED;
6666 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6667 EXPECT_DISASSEMBLY(
6668 "movz tmp, #0x4045 lsl 48\n"
6669 "fmovdr v0, tmp\n"
6670 "movz tmp, #0xc045 lsl 48\n"
6671 "fmovdr v1, tmp\n"
6672 "vdupd v2, v0[0]\n"
6673 "vinsd v3[0], v0[0]\n"
6674 "vinsd v3[1], v1[0]\n"
6675 "vcgtd v4, v2, v3\n"
6676 "vmovrd r1, v4[0]\n"
6677 "vmovrd r2, v4[1]\n"
6678 "add r0, r1, r2\n"
6679 "ret\n");
6680}
6681
6682ASSEMBLER_TEST_GENERATE(Vcges, assembler) {
6683 __ LoadDImmediate(V0, 42.0);
6684 __ LoadDImmediate(V1, 43.0);
6685
6686 __ fcvtsd(V0, V0);
6687 __ fcvtsd(V1, V1);
6688
6689 __ vdups(V2, V0, 0);
6690 __ vinss(V3, 0, V0, 0);
6691 __ vinss(V3, 1, V1, 0);
6692 __ vinss(V3, 2, V0, 0);
6693 __ vinss(V3, 3, V1, 0);
6694
6695 __ vcges(V4, V2, V3);
6696
6697 __ vmovrs(R1, V4, 0);
6698 __ vmovrs(R2, V4, 1);
6699 __ vmovrs(R3, V4, 2);
6700 __ vmovrs(R4, V4, 3);
6701
6702 __ addw(R0, R1, Operand(R2));
6703 __ addw(R0, R0, Operand(R3));
6704 __ addw(R0, R0, Operand(R4));
6705 __ ret();
6706}
6707
6708ASSEMBLER_TEST_RUN(Vcges, test) {
6709 typedef int64_t (*Int64Return)() DART_UNUSED;
6710 EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6711 EXPECT_DISASSEMBLY(
6712 "movz tmp, #0x4045 lsl 48\n"
6713 "fmovdr v0, tmp\n"
6714 "movz tmp, #0x8000 lsl 32\n"
6715 "movk tmp, #0x4045 lsl 48\n"
6716 "fmovdr v1, tmp\n"
6717 "fcvtsd v0, v0\n"
6718 "fcvtsd v1, v1\n"
6719 "vdups v2, v0[0]\n"
6720 "vinss v3[0], v0[0]\n"
6721 "vinss v3[1], v1[0]\n"
6722 "vinss v3[2], v0[0]\n"
6723 "vinss v3[3], v1[0]\n"
6724 "vcges v4, v2, v3\n"
6725 "vmovrs r1, v4[0]\n"
6726 "vmovrs r2, v4[1]\n"
6727 "vmovrs r3, v4[2]\n"
6728 "vmovrs r4, v4[3]\n"
6729 "addw r0, r1, r2\n"
6730 "addw r0, r0, r3\n"
6731 "addw r0, r0, r4\n"
6732 "ret\n");
6733}
6734
6735ASSEMBLER_TEST_GENERATE(Vcged, assembler) {
6736 __ LoadDImmediate(V0, 42.0);
6737 __ LoadDImmediate(V1, 43.0);
6738
6739 __ vdupd(V2, V0, 0);
6740 __ vinsd(V3, 0, V0, 0);
6741 __ vinsd(V3, 1, V1, 0);
6742
6743 __ vcged(V4, V2, V3);
6744
6745 __ vmovrd(R1, V4, 0);
6746 __ vmovrd(R2, V4, 1);
6747
6748 __ add(R0, R1, Operand(R2));
6749 __ ret();
6750}
6751
6752ASSEMBLER_TEST_RUN(Vcged, test) {
6753 typedef int64_t (*Int64Return)() DART_UNUSED;
6754 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
6755 EXPECT_DISASSEMBLY(
6756 "movz tmp, #0x4045 lsl 48\n"
6757 "fmovdr v0, tmp\n"
6758 "movz tmp, #0x8000 lsl 32\n"
6759 "movk tmp, #0x4045 lsl 48\n"
6760 "fmovdr v1, tmp\n"
6761 "vdupd v2, v0[0]\n"
6762 "vinsd v3[0], v0[0]\n"
6763 "vinsd v3[1], v1[0]\n"
6764 "vcged v4, v2, v3\n"
6765 "vmovrd r1, v4[0]\n"
6766 "vmovrd r2, v4[1]\n"
6767 "add r0, r1, r2\n"
6768 "ret\n");
6769}
6770
6771// Verify that vmaxs(-0.0, 0.0) = 0.0
6772ASSEMBLER_TEST_GENERATE(Vmaxs_zero, assembler) {
6773 __ veor(V1, V1, V1);
6774 __ vnegd(V2, V1);
6775 __ vmaxs(V0, V2, V1);
6776 __ ret();
6777}
6778
6779ASSEMBLER_TEST_RUN(Vmaxs_zero, test) {
6780 typedef double (*DoubleReturn)() DART_UNUSED;
6781 double d = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
6782 EXPECT_EQ(true, !signbit(d) && (d == 0.0));
6783 EXPECT_DISASSEMBLY(
6784 "veor v1, v1, v1\n"
6785 "vnegd v2, v1\n"
6786 "vmaxs v0, v2, v1\n"
6787 "ret\n");
6788}
6789
6790ASSEMBLER_TEST_GENERATE(Vmaxs, assembler) {
6791 __ LoadDImmediate(V0, 10.5);
6792 __ LoadDImmediate(V1, 10.0);
6793
6794 __ fcvtsd(V0, V0);
6795 __ fcvtsd(V1, V1);
6796
6797 __ vdups(V2, V0, 0);
6798 __ vinss(V3, 0, V0, 0);
6799 __ vinss(V3, 1, V1, 0);
6800 __ vinss(V3, 2, V0, 0);
6801 __ vinss(V3, 3, V1, 0);
6802
6803 __ vmaxs(V4, V2, V3);
6804
6805 __ vinss(V0, 0, V4, 0);
6806 __ vinss(V1, 0, V4, 1);
6807 __ vinss(V2, 0, V4, 2);
6808 __ vinss(V3, 0, V4, 3);
6809
6810 __ fcvtds(V0, V0);
6811 __ fcvtds(V1, V1);
6812 __ fcvtds(V2, V2);
6813 __ fcvtds(V3, V3);
6814
6815 __ faddd(V0, V0, V1);
6816 __ faddd(V0, V0, V2);
6817 __ faddd(V0, V0, V3);
6818 __ ret();
6819}
6820
6821ASSEMBLER_TEST_RUN(Vmaxs, test) {
6822 typedef double (*DoubleReturn)() DART_UNUSED;
6823 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6824 EXPECT_DISASSEMBLY(
6825 "fmovd v0, 10.500000\n"
6826 "fmovd v1, 10.000000\n"
6827 "fcvtsd v0, v0\n"
6828 "fcvtsd v1, v1\n"
6829 "vdups v2, v0[0]\n"
6830 "vinss v3[0], v0[0]\n"
6831 "vinss v3[1], v1[0]\n"
6832 "vinss v3[2], v0[0]\n"
6833 "vinss v3[3], v1[0]\n"
6834 "vmaxs v4, v2, v3\n"
6835 "vinss v0[0], v4[0]\n"
6836 "vinss v1[0], v4[1]\n"
6837 "vinss v2[0], v4[2]\n"
6838 "vinss v3[0], v4[3]\n"
6839 "fcvtds v0, v0\n"
6840 "fcvtds v1, v1\n"
6841 "fcvtds v2, v2\n"
6842 "fcvtds v3, v3\n"
6843 "faddd v0, v0, v1\n"
6844 "faddd v0, v0, v2\n"
6845 "faddd v0, v0, v3\n"
6846 "ret\n");
6847}
6848
6849// Verify that vmaxd(-0.0, 0.0) = 0.0
6850ASSEMBLER_TEST_GENERATE(Vmaxd_zero, assembler) {
6851 __ veor(V1, V1, V1);
6852 __ vnegd(V2, V1);
6853 __ vmaxd(V0, V2, V1);
6854 __ ret();
6855}
6856
6857ASSEMBLER_TEST_RUN(Vmaxd_zero, test) {
6858 typedef double (*DoubleReturn)() DART_UNUSED;
6859 double d = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
6860 EXPECT_EQ(true, !signbit(d) && (d == 0.0));
6861 EXPECT_DISASSEMBLY(
6862 "veor v1, v1, v1\n"
6863 "vnegd v2, v1\n"
6864 "vmaxd v0, v2, v1\n"
6865 "ret\n");
6866}
6867
6868ASSEMBLER_TEST_GENERATE(Vmaxd, assembler) {
6869 __ LoadDImmediate(V0, 21.0);
6870 __ LoadDImmediate(V1, 20.5);
6871
6872 __ vdupd(V2, V0, 0);
6873 __ vinsd(V3, 0, V0, 0);
6874 __ vinsd(V3, 1, V1, 0);
6875
6876 __ vmaxd(V4, V2, V3);
6877
6878 __ vinsd(V0, 0, V4, 0);
6879 __ vinsd(V1, 0, V4, 1);
6880
6881 __ faddd(V0, V0, V1);
6882 __ ret();
6883}
6884
6885ASSEMBLER_TEST_RUN(Vmaxd, test) {
6886 typedef double (*DoubleReturn)() DART_UNUSED;
6887 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6888 EXPECT_DISASSEMBLY(
6889 "fmovd v0, 21.000000\n"
6890 "movz tmp, #0x8000 lsl 32\n"
6891 "movk tmp, #0x4034 lsl 48\n"
6892 "fmovdr v1, tmp\n"
6893 "vdupd v2, v0[0]\n"
6894 "vinsd v3[0], v0[0]\n"
6895 "vinsd v3[1], v1[0]\n"
6896 "vmaxd v4, v2, v3\n"
6897 "vinsd v0[0], v4[0]\n"
6898 "vinsd v1[0], v4[1]\n"
6899 "faddd v0, v0, v1\n"
6900 "ret\n");
6901}
6902
6903// Verify that vmins(-0.0, 0.0) = -0.0
6904ASSEMBLER_TEST_GENERATE(Vmins_zero, assembler) {
6905 __ veor(V1, V1, V1);
6906 __ vnegd(V2, V1);
6907 __ vmins(V0, V1, V2);
6908 __ ret();
6909}
6910
6911ASSEMBLER_TEST_RUN(Vmins_zero, test) {
6912 typedef double (*DoubleReturn)() DART_UNUSED;
6913 double d = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
6914 fprintf(stderr, "d: %f\n", d);
6915 EXPECT_EQ(true, signbit(d) && (d == 0.0));
6916 EXPECT_DISASSEMBLY(
6917 "veor v1, v1, v1\n"
6918 "vnegd v2, v1\n"
6919 "vmins v0, v1, v2\n"
6920 "ret\n");
6921}
6922
6923ASSEMBLER_TEST_GENERATE(Vmins, assembler) {
6924 __ LoadDImmediate(V0, 10.5);
6925 __ LoadDImmediate(V1, 11.0);
6926
6927 __ fcvtsd(V0, V0);
6928 __ fcvtsd(V1, V1);
6929
6930 __ vdups(V2, V0, 0);
6931 __ vinss(V3, 0, V0, 0);
6932 __ vinss(V3, 1, V1, 0);
6933 __ vinss(V3, 2, V0, 0);
6934 __ vinss(V3, 3, V1, 0);
6935
6936 __ vmins(V4, V2, V3);
6937
6938 __ vinss(V0, 0, V4, 0);
6939 __ vinss(V1, 0, V4, 1);
6940 __ vinss(V2, 0, V4, 2);
6941 __ vinss(V3, 0, V4, 3);
6942
6943 __ fcvtds(V0, V0);
6944 __ fcvtds(V1, V1);
6945 __ fcvtds(V2, V2);
6946 __ fcvtds(V3, V3);
6947
6948 __ faddd(V0, V0, V1);
6949 __ faddd(V0, V0, V2);
6950 __ faddd(V0, V0, V3);
6951 __ ret();
6952}
6953
6954ASSEMBLER_TEST_RUN(Vmins, test) {
6955 typedef double (*DoubleReturn)() DART_UNUSED;
6956 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
6957 EXPECT_DISASSEMBLY(
6958 "fmovd v0, 10.500000\n"
6959 "fmovd v1, 11.000000\n"
6960 "fcvtsd v0, v0\n"
6961 "fcvtsd v1, v1\n"
6962 "vdups v2, v0[0]\n"
6963 "vinss v3[0], v0[0]\n"
6964 "vinss v3[1], v1[0]\n"
6965 "vinss v3[2], v0[0]\n"
6966 "vinss v3[3], v1[0]\n"
6967 "vmins v4, v2, v3\n"
6968 "vinss v0[0], v4[0]\n"
6969 "vinss v1[0], v4[1]\n"
6970 "vinss v2[0], v4[2]\n"
6971 "vinss v3[0], v4[3]\n"
6972 "fcvtds v0, v0\n"
6973 "fcvtds v1, v1\n"
6974 "fcvtds v2, v2\n"
6975 "fcvtds v3, v3\n"
6976 "faddd v0, v0, v1\n"
6977 "faddd v0, v0, v2\n"
6978 "faddd v0, v0, v3\n"
6979 "ret\n");
6980}
6981
6982// Verify that vmind(-0.0, 0.0) = -0.0
6983ASSEMBLER_TEST_GENERATE(Vmind_zero, assembler) {
6984 __ veor(V1, V1, V1);
6985 __ vnegd(V2, V1);
6986 __ vmind(V0, V1, V2);
6987 __ ret();
6988}
6989
6990ASSEMBLER_TEST_RUN(Vmind_zero, test) {
6991 typedef double (*DoubleReturn)() DART_UNUSED;
6992 double d = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
6993 fprintf(stderr, "d: %f\n", d);
6994 EXPECT_EQ(true, signbit(d) && (d == 0.0));
6995 EXPECT_DISASSEMBLY(
6996 "veor v1, v1, v1\n"
6997 "vnegd v2, v1\n"
6998 "vmind v0, v1, v2\n"
6999 "ret\n");
7000}
7001
7002ASSEMBLER_TEST_GENERATE(Vmind, assembler) {
7003 __ LoadDImmediate(V0, 21.0);
7004 __ LoadDImmediate(V1, 21.5);
7005
7006 __ vdupd(V2, V0, 0);
7007 __ vinsd(V3, 0, V0, 0);
7008 __ vinsd(V3, 1, V1, 0);
7009
7010 __ vmind(V4, V2, V3);
7011
7012 __ vinsd(V0, 0, V4, 0);
7013 __ vinsd(V1, 0, V4, 1);
7014
7015 __ faddd(V0, V0, V1);
7016 __ ret();
7017}
7018
7019ASSEMBLER_TEST_RUN(Vmind, test) {
7020 typedef double (*DoubleReturn)() DART_UNUSED;
7021 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
7022 EXPECT_DISASSEMBLY(
7023 "fmovd v0, 21.000000\n"
7024 "movz tmp, #0x8000 lsl 32\n"
7025 "movk tmp, #0x4035 lsl 48\n"
7026 "fmovdr v1, tmp\n"
7027 "vdupd v2, v0[0]\n"
7028 "vinsd v3[0], v0[0]\n"
7029 "vinsd v3[1], v1[0]\n"
7030 "vmind v4, v2, v3\n"
7031 "vinsd v0[0], v4[0]\n"
7032 "vinsd v1[0], v4[1]\n"
7033 "faddd v0, v0, v1\n"
7034 "ret\n");
7035}
7036
7037ASSEMBLER_TEST_GENERATE(Vsqrts, assembler) {
7038 __ LoadDImmediate(V0, 64.0);
7039 __ LoadDImmediate(V1, 49.0);
7040
7041 __ fcvtsd(V0, V0);
7042 __ fcvtsd(V1, V1);
7043
7044 __ veor(V3, V3, V3);
7045 __ vinss(V3, 1, V0, 0);
7046 __ vinss(V3, 3, V1, 0);
7047
7048 __ vsqrts(V4, V3);
7049
7050 __ vinss(V5, 0, V4, 1);
7051 __ vinss(V6, 0, V4, 3);
7052
7053 __ fcvtds(V5, V5);
7054 __ fcvtds(V6, V6);
7055
7056 __ faddd(V0, V5, V6);
7057 __ ret();
7058}
7059
7060ASSEMBLER_TEST_RUN(Vsqrts, test) {
7061 typedef double (*DoubleReturn)() DART_UNUSED;
7062 EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
7063 EXPECT_DISASSEMBLY(
7064 "movz tmp, #0x4050 lsl 48\n"
7065 "fmovdr v0, tmp\n"
7066 "movz tmp, #0x8000 lsl 32\n"
7067 "movk tmp, #0x4048 lsl 48\n"
7068 "fmovdr v1, tmp\n"
7069 "fcvtsd v0, v0\n"
7070 "fcvtsd v1, v1\n"
7071 "veor v3, v3, v3\n"
7072 "vinss v3[1], v0[0]\n"
7073 "vinss v3[3], v1[0]\n"
7074 "vsqrts v4, v3\n"
7075 "vinss v5[0], v4[1]\n"
7076 "vinss v6[0], v4[3]\n"
7077 "fcvtds v5, v5\n"
7078 "fcvtds v6, v6\n"
7079 "faddd v0, v5, v6\n"
7080 "ret\n");
7081}
7082
7083ASSEMBLER_TEST_GENERATE(Vsqrtd, assembler) {
7084 __ LoadDImmediate(V0, 64.0);
7085 __ LoadDImmediate(V1, 49.0);
7086
7087 __ vinsd(V3, 0, V0, 0);
7088 __ vinsd(V3, 1, V1, 0);
7089
7090 __ vsqrtd(V4, V3);
7091
7092 __ vinsd(V5, 0, V4, 0);
7093 __ vinsd(V6, 0, V4, 1);
7094
7095 __ faddd(V0, V5, V6);
7096 __ ret();
7097}
7098
7099ASSEMBLER_TEST_RUN(Vsqrtd, test) {
7100 typedef double (*DoubleReturn)() DART_UNUSED;
7101 EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
7102 EXPECT_DISASSEMBLY(
7103 "movz tmp, #0x4050 lsl 48\n"
7104 "fmovdr v0, tmp\n"
7105 "movz tmp, #0x8000 lsl 32\n"
7106 "movk tmp, #0x4048 lsl 48\n"
7107 "fmovdr v1, tmp\n"
7108 "vinsd v3[0], v0[0]\n"
7109 "vinsd v3[1], v1[0]\n"
7110 "vsqrtd v4, v3\n"
7111 "vinsd v5[0], v4[0]\n"
7112 "vinsd v6[0], v4[1]\n"
7113 "faddd v0, v5, v6\n"
7114 "ret\n");
7115}
7116
7117// This is the same function as in the Simulator.
7118static float arm_recip_estimate(float a) {
7119 // From the ARM Architecture Reference Manual A2-85.
7120 if (isinf(a) || (fabs(a) >= exp2f(126)))
7121 return 0.0;
7122 else if (a == 0.0)
7123 return kPosInfinity;
7124 else if (isnan(a))
7125 return a;
7126
7127 uint32_t a_bits = bit_cast<uint32_t, float>(a);
7128 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29)
7129 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) |
7130 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29);
7131 // result_exp = 253 - UInt(a<30:23>)
7132 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff);
7133 ASSERT((result_exp >= 1) && (result_exp <= 252));
7134
7135 double scaled_d = bit_cast<double, uint64_t>(scaled);
7136 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0));
7137
7138 // a in units of 1/512 rounded down.
7139 int32_t q = static_cast<int32_t>(scaled_d * 512.0);
7140 // reciprocal r.
7141 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0);
7142 // r in units of 1/256 rounded to nearest.
7143 int32_t s = static_cast<int32_t>(256.0 * r + 0.5);
7144 double estimate = static_cast<double>(s) / 256.0;
7145 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0)));
7146
7147 // result = sign : result_exp<7:0> : estimate<51:29>
7148 int32_t result_bits =
7149 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) |
7150 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
7151 return bit_cast<float, int32_t>(result_bits);
7152}
7153
7154ASSEMBLER_TEST_GENERATE(Vrecpes, assembler) {
7155 __ LoadDImmediate(V1, 147.0);
7156 __ fcvtsd(V1, V1);
7157 __ vinss(V2, 0, V1, 0);
7158 __ vinss(V2, 1, V1, 0);
7159 __ vinss(V2, 2, V1, 0);
7160 __ vinss(V2, 3, V1, 0);
7161 __ vrecpes(V0, V2);
7162 __ fcvtds(V0, V0);
7163 __ ret();
7164}
7165
7166ASSEMBLER_TEST_RUN(Vrecpes, test) {
7167 EXPECT(test != nullptr);
7168 typedef double (*DoubleReturn)() DART_UNUSED;
7169 float res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
7170 EXPECT_FLOAT_EQ(arm_recip_estimate(147.0), res, 0.0001);
7171 EXPECT_DISASSEMBLY(
7172 "movz tmp, #0x6000 lsl 32\n"
7173 "movk tmp, #0x4062 lsl 48\n"
7174 "fmovdr v1, tmp\n"
7175 "fcvtsd v1, v1\n"
7176 "vinss v2[0], v1[0]\n"
7177 "vinss v2[1], v1[0]\n"
7178 "vinss v2[2], v1[0]\n"
7179 "vinss v2[3], v1[0]\n"
7180 "vrecpes v0, v2\n"
7181 "fcvtds v0, v0\n"
7182 "ret\n");
7183}
7184
7185ASSEMBLER_TEST_GENERATE(Vrecpss, assembler) {
7186 __ LoadDImmediate(V1, 5.0);
7187 __ LoadDImmediate(V2, 10.0);
7188
7189 __ fcvtsd(V1, V1);
7190 __ fcvtsd(V2, V2);
7191
7192 __ vrecpss(V0, V1, V2);
7193
7194 __ fcvtds(V0, V0);
7195 __ ret();
7196}
7197
7198ASSEMBLER_TEST_RUN(Vrecpss, test) {
7199 EXPECT(test != nullptr);
7200 typedef double (*DoubleReturn)() DART_UNUSED;
7201 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
7202 EXPECT_FLOAT_EQ(2.0 - 10.0 * 5.0, res, 0.0001);
7203 EXPECT_DISASSEMBLY(
7204 "fmovd v1, 5.000000\n"
7205 "fmovd v2, 10.000000\n"
7206 "fcvtsd v1, v1\n"
7207 "fcvtsd v2, v2\n"
7208 "vrecpss v0, v1, v2\n"
7209 "fcvtds v0, v0\n"
7210 "ret\n");
7211}
7212
7213ASSEMBLER_TEST_GENERATE(VRecps, assembler) {
7214 __ LoadDImmediate(V0, 1.0 / 10.5);
7215 __ fcvtsd(V0, V0);
7216
7217 __ vdups(V1, V0, 0);
7218
7219 __ VRecps(V2, V1);
7220
7221 __ vinss(V0, 0, V2, 0);
7222 __ vinss(V1, 0, V2, 1);
7223 __ vinss(V2, 0, V2, 2);
7224 __ vinss(V3, 0, V2, 3);
7225
7226 __ fcvtds(V0, V0);
7227 __ fcvtds(V1, V1);
7228 __ fcvtds(V2, V2);
7229 __ fcvtds(V3, V3);
7230
7231 __ faddd(V0, V0, V1);
7232 __ faddd(V0, V0, V2);
7233 __ faddd(V0, V0, V3);
7234 __ ret();
7235}
7236
7237ASSEMBLER_TEST_RUN(VRecps, test) {
7238 typedef double (*DoubleReturn)() DART_UNUSED;
7239 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
7240 EXPECT_FLOAT_EQ(42.0, res, 0.0001);
7241 EXPECT_DISASSEMBLY(
7242 "movz tmp, #0x8618\n"
7243 "movk tmp, #0x1861 lsl 16\n"
7244 "movk tmp, #0x6186 lsl 32\n"
7245 "movk tmp, #0x3fb8 lsl 48\n"
7246 "fmovdr v0, tmp\n"
7247 "fcvtsd v0, v0\n"
7248 "vdups v1, v0[0]\n"
7249 "vrecpes v2, v1\n"
7250 "vrecpss v31, v1, v2\n"
7251 "vmuls v2, v2, v31\n"
7252 "vrecpss v31, v1, v2\n"
7253 "vmuls v2, v2, v31\n"
7254 "vinss v0[0], v2[0]\n"
7255 "vinss v1[0], v2[1]\n"
7256 "vinss v2[0], v2[2]\n"
7257 "vinss v3[0], v2[3]\n"
7258 "fcvtds v0, v0\n"
7259 "fcvtds v1, v1\n"
7260 "fcvtds v2, v2\n"
7261 "fcvtds v3, v3\n"
7262 "faddd v0, v0, v1\n"
7263 "faddd v0, v0, v2\n"
7264 "faddd v0, v0, v3\n"
7265 "ret\n");
7266}
7267
7268static float arm_reciprocal_sqrt_estimate(float a) {
7269 // From the ARM Architecture Reference Manual A2-87.
7270 if (isinf(a) || (fabs(a) >= exp2f(126)))
7271 return 0.0;
7272 else if (a == 0.0)
7273 return kPosInfinity;
7274 else if (isnan(a))
7275 return a;
7276
7277 uint32_t a_bits = bit_cast<uint32_t, float>(a);
7278 uint64_t scaled;
7279 if (((a_bits >> 23) & 1) != 0) {
7280 // scaled = '0 01111111101' : operand<22:0> : Zeros(29)
7281 scaled = (static_cast<uint64_t>(0x3fd) << 52) |
7282 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29);
7283 } else {
7284 // scaled = '0 01111111110' : operand<22:0> : Zeros(29)
7285 scaled = (static_cast<uint64_t>(0x3fe) << 52) |
7286 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29);
7287 }
7288 // result_exp = (380 - UInt(operand<30:23>) DIV 2;
7289 int32_t result_exp = (380 - ((a_bits >> 23) & 0xff)) / 2;
7290
7291 double scaled_d = bit_cast<double, uint64_t>(scaled);
7292 ASSERT((scaled_d >= 0.25) && (scaled_d < 1.0));
7293
7294 double r;
7295 if (scaled_d < 0.5) {
7296 // range 0.25 <= a < 0.5
7297
7298 // a in units of 1/512 rounded down.
7299 int32_t q0 = static_cast<int32_t>(scaled_d * 512.0);
7300 // reciprocal root r.
7301 r = 1.0 / sqrt((static_cast<double>(q0) + 0.5) / 512.0);
7302 } else {
7303 // range 0.5 <= a < 1.0
7304
7305 // a in units of 1/256 rounded down.
7306 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0);
7307 // reciprocal root r.
7308 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0);
7309 }
7310 // r in units of 1/256 rounded to nearest.
7311 int32_t s = static_cast<int>(256.0 * r + 0.5);
7312 double estimate = static_cast<double>(s) / 256.0;
7313 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0)));
7314
7315 // result = 0 : result_exp<7:0> : estimate<51:29>
7316 int32_t result_bits =
7317 ((result_exp & 0xff) << 23) |
7318 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
7319 return bit_cast<float, int32_t>(result_bits);
7320}
7321
7322ASSEMBLER_TEST_GENERATE(Vrsqrtes, assembler) {
7323 __ LoadDImmediate(V1, 147.0);
7324 __ fcvtsd(V1, V1);
7325
7326 __ vrsqrtes(V0, V1);
7327
7328 __ fcvtds(V0, V0);
7329 __ ret();
7330}
7331
7332ASSEMBLER_TEST_RUN(Vrsqrtes, test) {
7333 EXPECT(test != nullptr);
7334 typedef double (*DoubleReturn)() DART_UNUSED;
7335 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
7336 EXPECT_FLOAT_EQ(arm_reciprocal_sqrt_estimate(147.0), res, 0.0001);
7337 EXPECT_DISASSEMBLY(
7338 "movz tmp, #0x6000 lsl 32\n"
7339 "movk tmp, #0x4062 lsl 48\n"
7340 "fmovdr v1, tmp\n"
7341 "fcvtsd v1, v1\n"
7342 "vrsqrtes v0, v1\n"
7343 "fcvtds v0, v0\n"
7344 "ret\n");
7345}
7346
7347ASSEMBLER_TEST_GENERATE(Vrsqrtss, assembler) {
7348 __ LoadDImmediate(V1, 5.0);
7349 __ LoadDImmediate(V2, 10.0);
7350
7351 __ fcvtsd(V1, V1);
7352 __ fcvtsd(V2, V2);
7353
7354 __ vrsqrtss(V0, V1, V2);
7355
7356 __ fcvtds(V0, V0);
7357 __ ret();
7358}
7359
7360ASSEMBLER_TEST_RUN(Vrsqrtss, test) {
7361 EXPECT(test != nullptr);
7362 typedef double (*DoubleReturn)() DART_UNUSED;
7363 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
7364 EXPECT_FLOAT_EQ((3.0 - 10.0 * 5.0) / 2.0, res, 0.0001);
7365 EXPECT_DISASSEMBLY(
7366 "fmovd v1, 5.000000\n"
7367 "fmovd v2, 10.000000\n"
7368 "fcvtsd v1, v1\n"
7369 "fcvtsd v2, v2\n"
7370 "vrsqrts v0, v1, v2\n"
7371 "fcvtds v0, v0\n"
7372 "ret\n");
7373}
7374
7375ASSEMBLER_TEST_GENERATE(ReciprocalSqrt, assembler) {
7376 __ LoadDImmediate(V1, 147000.0);
7377 __ fcvtsd(V1, V1);
7378
7379 __ VRSqrts(V0, V1);
7380
7381 __ fcvtds(V0, V0);
7382 __ ret();
7383}
7384
7385ASSEMBLER_TEST_RUN(ReciprocalSqrt, test) {
7386 EXPECT(test != nullptr);
7387 typedef double (*DoubleReturn)() DART_UNUSED;
7388 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
7389 EXPECT_FLOAT_EQ(1.0 / sqrt(147000.0), res, 0.0001);
7390 EXPECT_DISASSEMBLY(
7391 "movz tmp, #0xf1c0 lsl 32\n"
7392 "movk tmp, #0x4101 lsl 48\n"
7393 "fmovdr v1, tmp\n"
7394 "fcvtsd v1, v1\n"
7395 "vrsqrtes v0, v1\n"
7396 "vmuls v31, v0, v0\n"
7397 "vrsqrts v31, v1, v31\n"
7398 "vmuls v0, v0, v31\n"
7399 "vmuls v31, v0, v0\n"
7400 "vrsqrts v31, v1, v31\n"
7401 "vmuls v0, v0, v31\n"
7402 "fcvtds v0, v0\n"
7403 "ret\n");
7404}
7405
7406// Called from assembler_test.cc.
7407// LR: return address.
7408// R0: value.
7409// R1: growable array.
7410// R2: current thread.
7411ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
7412 __ SetupDartSP();
7413 __ Push(CODE_REG);
7414 __ Push(THR);
7415 __ Push(HEAP_BITS);
7416 SPILLS_LR_TO_FRAME(__ Push(LR));
7417 __ mov(THR, R2);
7419 __ LslImmediate(HEAP_BITS, HEAP_BITS, 32);
7420 __ StoreCompressedIntoObject(
7421 R1, FieldAddress(R1, GrowableObjectArray::data_offset()), R0);
7422 RESTORES_LR_FROM_FRAME(__ Pop(LR));
7423 __ Pop(HEAP_BITS);
7424 __ Pop(THR);
7425 __ Pop(CODE_REG);
7426 __ RestoreCSP();
7427 __ ret();
7428}
7429
7430// Push numbers from kMaxPushedNumber to 0 to the stack then drop top
7431// kMaxPushedNumber elements. This should leave just kMaxPushedNumber on the
7432// stack.
7433const intptr_t kMaxPushedNumber = 913;
7434
7435ASSEMBLER_TEST_GENERATE(Drop, assembler) {
7436 __ SetupDartSP((kMaxPushedNumber + 1) * target::kWordSize);
7437 for (intptr_t i = kMaxPushedNumber; i >= 0; i--) {
7438 __ PushImmediate(i);
7439 }
7440 __ Drop(kMaxPushedNumber);
7441 __ PopRegister(R0);
7442 __ RestoreCSP();
7443 __ ret();
7444}
7445
7446ASSEMBLER_TEST_RUN(Drop, test) {
7447 EXPECT(test != nullptr);
7448 typedef int64_t (*Int64Return)() DART_UNUSED;
7449 EXPECT_EQ(kMaxPushedNumber,
7450 EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
7451}
7452
7453ASSEMBLER_TEST_GENERATE(AndImmediate32Negative, assembler) {
7454 __ AndImmediate(R0, R0, -512, kFourBytes);
7455 __ ret();
7456}
7457
7458ASSEMBLER_TEST_RUN(AndImmediate32Negative, test) {
7459 typedef intptr_t (*IntPtrReturn)(intptr_t) DART_UNUSED;
7460 EXPECT_EQ(0xfffffe00,
7461 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -42));
7462 EXPECT_EQ(0, EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 0));
7463 EXPECT_EQ(0,
7464 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 42));
7465 EXPECT_DISASSEMBLY(
7466 "andw r0, r0, 0xfffffe00\n"
7467 "ret\n");
7468}
7469
7470ASSEMBLER_TEST_GENERATE(OrImmediate32Negative, assembler) {
7471 __ OrImmediate(R0, R0, -512, kFourBytes);
7472 __ ret();
7473}
7474
7475ASSEMBLER_TEST_RUN(OrImmediate32Negative, test) {
7476 typedef intptr_t (*IntPtrReturn)(intptr_t) DART_UNUSED;
7477 EXPECT_EQ(0xffffffd6,
7478 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -42));
7479 EXPECT_EQ(0xfffffe00,
7480 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 0));
7481 EXPECT_EQ(0xfffffe2a,
7482 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 42));
7483 EXPECT_DISASSEMBLY(
7484 "orrw r0, r0, 0xfffffe00\n"
7485 "ret\n");
7486}
7487
7488ASSEMBLER_TEST_GENERATE(XorImmediate32Negative, assembler) {
7489 __ XorImmediate(R0, R0, -512, kFourBytes);
7490 __ ret();
7491}
7492
7493ASSEMBLER_TEST_RUN(XorImmediate32Negative, test) {
7494 typedef intptr_t (*IntPtrReturn)(intptr_t) DART_UNUSED;
7495 EXPECT_EQ(0x1d6,
7496 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -42));
7497 EXPECT_EQ(0xfffffe00,
7498 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 0));
7499 EXPECT_EQ(0xfffffe2a,
7500 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 42));
7501 EXPECT_DISASSEMBLY(
7502 "eorw r0, r0, 0xfffffe00\n"
7503 "ret\n");
7504}
7505
7506ASSEMBLER_TEST_GENERATE(TestImmediate32Negative, assembler) {
7507 Label on_zero;
7508 __ TestImmediate(R0, -512, kFourBytes);
7509 __ b(&on_zero, EQ);
7510 __ LoadImmediate(R0, 1);
7511 __ ret();
7512 __ Bind(&on_zero);
7513 __ LoadImmediate(R0, 0);
7514 __ ret();
7515}
7516
7517ASSEMBLER_TEST_RUN(TestImmediate32Negative, test) {
7518 typedef intptr_t (*IntPtrReturn)(intptr_t) DART_UNUSED;
7519 EXPECT_EQ(1,
7520 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -42));
7521 EXPECT_EQ(0, EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 0));
7522 EXPECT_EQ(0,
7523 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), 42));
7524 EXPECT_DISASSEMBLY(
7525 "tstw r0, 0xfffffe00\n"
7526 "beq +12\n"
7527 "movz r0, #0x1\n"
7528 "ret\n"
7529 "movz r0, #0x0\n"
7530 "ret\n");
7531}
7532
7533ASSEMBLER_TEST_GENERATE(CompareImmediate32Negative, assembler) {
7534 Label on_zero;
7535 __ CompareImmediate(R0, -512, kFourBytes);
7536 __ b(&on_zero, LT);
7537 __ LoadImmediate(R0, 0);
7538 __ ret();
7539 __ Bind(&on_zero);
7540 __ LoadImmediate(R0, 1);
7541 __ ret();
7542}
7543
7544ASSEMBLER_TEST_RUN(CompareImmediate32Negative, test) {
7545 typedef intptr_t (*IntPtrReturn)(intptr_t) DART_UNUSED;
7546 EXPECT_EQ(1,
7547 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -513));
7548 EXPECT_EQ(0,
7549 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -512));
7550 EXPECT_EQ(0,
7551 EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -511));
7552 EXPECT_DISASSEMBLY(
7553 "cmnw r0, #0x200\n"
7554 "blt +12\n"
7555 "movz r0, #0x0\n"
7556 "ret\n"
7557 "movz r0, #0x1\n"
7558 "ret\n");
7559}
7560
7561// can't call (tsan) runtime methods
7562#if !defined(TARGET_USES_THREAD_SANITIZER)
7563
7564ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire, assembler) {
7565 __ SetupDartSP();
7566 __ Push(R1);
7567 __ LoadImmediate(R1, 0);
7568 __ Push(R1);
7569 __ mov(R1, R0);
7570 __ LoadImmediate(R0, 0);
7571 __ StoreReleaseToOffset(R1, SP, 0);
7572 __ LoadAcquireFromOffset(R0, SP, 0);
7573 __ Pop(R1);
7574 __ Pop(R1);
7575 __ RestoreCSP();
7576 __ ret();
7577}
7578
7579ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire, test) {
7580 typedef intptr_t (*StoreReleaseLoadAcquire)(intptr_t) DART_UNUSED;
7581 EXPECT_EQ(123, EXECUTE_TEST_CODE_INTPTR_INTPTR(StoreReleaseLoadAcquire,
7582 test->entry(), 123));
7583 EXPECT_DISASSEMBLY(
7584 "mov sp, csp\n"
7585 "sub csp, csp, #0x1000\n"
7586 "str r1, [sp, #-8]!\n"
7587 "movz r1, #0x0\n"
7588 "str r1, [sp, #-8]!\n"
7589 "mov r1, r0\n"
7590 "movz r0, #0x0\n"
7591 "stlr r1, sp\n"
7592 "ldar r0, sp\n"
7593 "ldr r1, [sp], #8 !\n"
7594 "ldr r1, [sp], #8 !\n"
7595 "mov csp, sp\n"
7596 "ret\n");
7597}
7598
7599ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire1024, assembler) {
7600 __ SetupDartSP();
7601 __ Push(R1);
7602 __ LoadImmediate(R1, 0);
7603 __ Push(R1);
7604 __ mov(R1, R0);
7605 __ LoadImmediate(R0, 0);
7606 __ sub(SP, SP, Operand(1024 * target::kWordSize));
7607 __ StoreReleaseToOffset(R1, SP, 1024);
7608 __ LoadAcquireFromOffset(R0, SP, 1024);
7609 __ add(SP, SP, Operand(1024 * target::kWordSize));
7610 __ Pop(R1);
7611 __ Pop(R1);
7612 __ RestoreCSP();
7613 __ ret();
7614}
7615
7616ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire1024, test) {
7617 typedef intptr_t (*StoreReleaseLoadAcquire1024)(intptr_t) DART_UNUSED;
7618 EXPECT_EQ(123, EXECUTE_TEST_CODE_INTPTR_INTPTR(StoreReleaseLoadAcquire1024,
7619 test->entry(), 123));
7620 EXPECT_DISASSEMBLY(
7621 "mov sp, csp\n"
7622 "sub csp, csp, #0x1000\n"
7623 "str r1, [sp, #-8]!\n"
7624 "movz r1, #0x0\n"
7625 "str r1, [sp, #-8]!\n"
7626 "mov r1, r0\n"
7627 "movz r0, #0x0\n"
7628 "sub sp, sp, #0x2000\n"
7629 "add tmp2, sp, #0x400\n"
7630 "stlr r1, tmp2\n"
7631 "add tmp2, sp, #0x400\n"
7632 "ldar r0, tmp2\n"
7633 "add sp, sp, #0x2000\n"
7634 "ldr r1, [sp], #8 !\n"
7635 "ldr r1, [sp], #8 !\n"
7636 "mov csp, sp\n"
7637 "ret\n");
7638}
7639#endif // !defined(TARGET_USES_THREAD_SANITIZER)
7640
7641static void RangeCheck(Assembler* assembler, Register value, Register temp) {
7642 const Register return_reg = CallingConventions::kReturnReg;
7643 Label in_range;
7644 __ RangeCheck(value, temp, kFirstErrorCid, kLastErrorCid,
7645 AssemblerBase::kIfInRange, &in_range);
7646 __ LoadImmediate(return_reg, Immediate(0));
7647 __ Ret();
7648 __ Bind(&in_range);
7649 __ LoadImmediate(return_reg, Immediate(1));
7650 __ Ret();
7651}
7652
7653ASSEMBLER_TEST_GENERATE(RangeCheckNoTemp, assembler) {
7655 const Register temp = kNoRegister;
7656 RangeCheck(assembler, value, temp);
7657}
7658
7659ASSEMBLER_TEST_RUN(RangeCheckNoTemp, test) {
7660 intptr_t result;
7661 result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
7662 EXPECT_EQ(1, result);
7663 result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
7664 EXPECT_EQ(1, result);
7665 result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
7666 EXPECT_EQ(0, result);
7667 result = test->Invoke<intptr_t, intptr_t>(kMintCid);
7668 EXPECT_EQ(0, result);
7669}
7670
7671ASSEMBLER_TEST_GENERATE(RangeCheckWithTemp, assembler) {
7674 RangeCheck(assembler, value, temp);
7675}
7676
7677ASSEMBLER_TEST_RUN(RangeCheckWithTemp, test) {
7678 intptr_t result;
7679 result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
7680 EXPECT_EQ(1, result);
7681 result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
7682 EXPECT_EQ(1, result);
7683 result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
7684 EXPECT_EQ(0, result);
7685 result = test->Invoke<intptr_t, intptr_t>(kMintCid);
7686 EXPECT_EQ(0, result);
7687}
7688
7689ASSEMBLER_TEST_GENERATE(RangeCheckWithTempReturnValue, assembler) {
7692 const Register return_reg = CallingConventions::kReturnReg;
7693 Label in_range;
7694 __ RangeCheck(value, temp, kFirstErrorCid, kLastErrorCid,
7695 AssemblerBase::kIfInRange, &in_range);
7696 __ Bind(&in_range);
7697 __ mov(return_reg, value);
7698 __ Ret();
7699}
7700
7701ASSEMBLER_TEST_RUN(RangeCheckWithTempReturnValue, test) {
7702 intptr_t result;
7703 result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
7704 EXPECT_EQ(kErrorCid, result);
7705 result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
7706 EXPECT_EQ(kUnwindErrorCid, result);
7707 result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
7708 EXPECT_EQ(kFunctionCid, result);
7709 result = test->Invoke<intptr_t, intptr_t>(kMintCid);
7710 EXPECT_EQ(kMintCid, result);
7711}
7712
7713// Tests that BranchLink only clobbers CODE_REG in JIT mode and does not
7714// clobber any allocatable registers in AOT mode.
7715ASSEMBLER_TEST_GENERATE(BranchLinkPreservesRegisters, assembler) {
7716 const auto& do_nothing_just_return =
7717 AssemblerTest::Generate("DoNothing", [](auto assembler) { __ Ret(); });
7718
7719 EnterTestFrame(assembler);
7720 SPILLS_LR_TO_FRAME({ __ PushRegister(LR); });
7721
7722 const RegisterSet clobbered_regs(
7723 kDartAvailableCpuRegs & ~(static_cast<RegList>(1) << R0),
7724 /*fpu_register_mask=*/0);
7725 __ PushRegisters(clobbered_regs);
7726
7727 Label done;
7728
7729 const auto check_all_allocatable_registers_are_preserved_by_call = [&]() {
7730 for (auto reg : RegisterRange(kDartAvailableCpuRegs)) {
7731 __ LoadImmediate(reg, static_cast<int32_t>(reg));
7732 }
7733 __ BranchLink(do_nothing_just_return);
7734 for (auto reg : RegisterRange(kDartAvailableCpuRegs)) {
7735 // We expect CODE_REG to be clobbered in JIT mode.
7736 if (!FLAG_precompiled_mode && reg == CODE_REG) continue;
7737
7738 Label ok;
7739 __ CompareImmediate(reg, static_cast<int32_t>(reg));
7740 __ b(&ok, EQ);
7741 __ LoadImmediate(R0, reg);
7742 __ b(&done);
7743 __ Bind(&ok);
7744 }
7745 };
7746
7747 check_all_allocatable_registers_are_preserved_by_call();
7748
7749 FLAG_precompiled_mode = true;
7750 check_all_allocatable_registers_are_preserved_by_call();
7751 FLAG_precompiled_mode = false;
7752
7753 __ LoadImmediate(R0, 42); // 42 is SUCCESS.
7754 __ Bind(&done);
7755 __ PopRegisters(clobbered_regs);
7756 RESTORES_LR_FROM_FRAME({ __ PopRegister(LR); });
7757 LeaveTestFrame(assembler);
7758 __ Ret();
7759}
7760
7761ASSEMBLER_TEST_RUN(BranchLinkPreservesRegisters, test) {
7762 const intptr_t result = test->InvokeWithCodeAndThread<int64_t>();
7763 EXPECT_EQ(42, result);
7764}
7765
7766} // namespace compiler
7767} // namespace dart
7768
7769#endif // defined(TARGET_ARCH_ARM64)
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition DM.cpp:263
static bool ok(int result)
#define EXPECT(type, expectedAlignment, expectedSize)
#define __
Type::kYUV Type::kRGBA() int(0.7 *637)
static const Code & Generate(const char *name, const std::function< void(compiler::Assembler *assembler)> &generator)
Definition unit_test.cc:756
static const Bool & False()
Definition object.h:10778
static const Bool & True()
Definition object.h:10776
static const Register ArgumentRegisters[]
static constexpr Register kReturnReg
static intptr_t data_offset()
Definition object.h:11110
static ObjectPtr null()
Definition object.h:433
static intptr_t write_barrier_mask_offset()
Definition thread.h:436
static Address Pair(Register rn, int32_t offset=0, AddressType at=PairOffset)
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static bool b
struct MyStruct s
struct MyStruct a[10]
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
double x
static int Log2OperandSizeBytes(OperandSize os)
void LeaveTestFrame(Assembler *assembler)
void EnterTestFrame(Assembler *assembler)
constexpr int64_t kMaxInt64
Definition globals.h:486
constexpr int64_t kMinInt64
Definition globals.h:485
const Register THR
static Utils::BitsRange< Register > RegisterRange(uint32_t regs)
Definition constants.h:110
const Register NULL_REG
constexpr int32_t kMinInt32
Definition globals.h:482
uint16_t RegList
static const ClassId kLastErrorCid
Definition class_id.h:311
static const ClassId kFirstErrorCid
Definition class_id.h:310
uintptr_t uword
Definition globals.h:501
const Register CODE_REG
const Register TMP2
@ kNoRegister
constexpr RegList kDartAvailableCpuRegs
const Register TMP
const Register HEAP_BITS
constexpr int32_t kMaxInt32
Definition globals.h:483
const Register PP
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition SkVx.h:706
#define DART_UNUSED
Definition globals.h:269
#define DART_INT64_C(x)
Definition globals.h:433
#define ASSEMBLER_TEST_GENERATE(name, assembler)
Definition unit_test.h:89
#define ASSEMBLER_TEST_RUN(name, test)
Definition unit_test.h:127
#define kPosInfinity
Definition globals.h:65