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