1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include "test-assembler-aarch64.h"
28
29 #include <cfloat>
30 #include <cmath>
31 #include <cstdio>
32 #include <cstdlib>
33 #include <cstring>
34 #include <sys/mman.h>
35
36 #include "test-runner.h"
37 #include "test-utils.h"
38
39 #include "aarch64/cpu-aarch64.h"
40 #include "aarch64/disasm-aarch64.h"
41 #include "aarch64/macro-assembler-aarch64.h"
42 #include "aarch64/simulator-aarch64.h"
43 #include "aarch64/test-utils-aarch64.h"
44
45 namespace vixl {
46 namespace aarch64 {
47
TEST(preshift_immediates)48 TEST(preshift_immediates) {
49 SETUP();
50
51 START();
52 // Test operations involving immediates that could be generated using a
53 // pre-shifted encodable immediate followed by a post-shift applied to
54 // the arithmetic or logical operation.
55
56 // Save sp.
57 __ Mov(x29, sp);
58
59 // Set the registers to known values.
60 __ Mov(x0, 0x1000);
61 __ Mov(sp, 0x1004);
62
63 // Arithmetic ops.
64 __ Add(x1, x0, 0x1f7de);
65 __ Add(w2, w0, 0xffffff1);
66 __ Adds(x3, x0, 0x18001);
67 __ Adds(w4, w0, 0xffffff1);
68 __ Sub(x5, x0, 0x1f7de);
69 __ Sub(w6, w0, 0xffffff1);
70 __ Subs(x7, x0, 0x18001);
71 __ Subs(w8, w0, 0xffffff1);
72
73 // Logical ops.
74 __ And(x9, x0, 0x1f7de);
75 __ Orr(w10, w0, 0xffffff1);
76 __ Eor(x11, x0, 0x18001);
77
78 // Ops using the stack pointer.
79 __ Add(sp, sp, 0x18001);
80 __ Mov(x12, sp);
81 __ Mov(sp, 0x1004);
82
83 __ Add(sp, sp, 0x1f7de);
84 __ Mov(x13, sp);
85 __ Mov(sp, 0x1004);
86
87 __ Adds(x14, sp, 0x1f7de);
88
89 __ Orr(sp, x0, 0x1f7de);
90 __ Mov(x15, sp);
91
92 // Restore sp.
93 __ Mov(sp, x29);
94 END();
95
96 if (CAN_RUN()) {
97 RUN();
98
99 ASSERT_EQUAL_64(0x1000, x0);
100 ASSERT_EQUAL_64(0x207de, x1);
101 ASSERT_EQUAL_64(0x10000ff1, x2);
102 ASSERT_EQUAL_64(0x19001, x3);
103 ASSERT_EQUAL_64(0x10000ff1, x4);
104 ASSERT_EQUAL_64(0xfffffffffffe1822, x5);
105 ASSERT_EQUAL_64(0xf000100f, x6);
106 ASSERT_EQUAL_64(0xfffffffffffe8fff, x7);
107 ASSERT_EQUAL_64(0xf000100f, x8);
108 ASSERT_EQUAL_64(0x1000, x9);
109 ASSERT_EQUAL_64(0xffffff1, x10);
110 ASSERT_EQUAL_64(0x19001, x11);
111 ASSERT_EQUAL_64(0x19005, x12);
112 ASSERT_EQUAL_64(0x207e2, x13);
113 ASSERT_EQUAL_64(0x207e2, x14);
114 ASSERT_EQUAL_64(0x1f7de, x15);
115 }
116 }
117
118
TEST(stack_ops)119 TEST(stack_ops) {
120 SETUP();
121
122 START();
123 // save sp.
124 __ Mov(x29, sp);
125
126 // Set the sp to a known value.
127 __ Mov(sp, 0x1004);
128 __ Mov(x0, sp);
129
130 // Add immediate to the sp, and move the result to a normal register.
131 __ Add(sp, sp, 0x50);
132 __ Mov(x1, sp);
133
134 // Add extended to the sp, and move the result to a normal register.
135 __ Mov(x17, 0xfff);
136 __ Add(sp, sp, Operand(x17, SXTB));
137 __ Mov(x2, sp);
138
139 // Create an sp using a logical instruction, and move to normal register.
140 __ Orr(sp, xzr, 0x1fff);
141 __ Mov(x3, sp);
142
143 // Write wsp using a logical instruction.
144 __ Orr(wsp, wzr, 0xfffffff8);
145 __ Mov(x4, sp);
146
147 // Write sp, and read back wsp.
148 __ Orr(sp, xzr, 0xfffffff8);
149 __ Mov(w5, wsp);
150
151 // Test writing into wsp in cases where the immediate isn't encodable.
152 VIXL_ASSERT(!Assembler::IsImmLogical(0x1234, kWRegSize));
153 __ Orr(wsp, w5, 0x1234);
154 __ Mov(w6, wsp);
155
156 // restore sp.
157 __ Mov(sp, x29);
158 END();
159
160 if (CAN_RUN()) {
161 RUN();
162
163 ASSERT_EQUAL_64(0x1004, x0);
164 ASSERT_EQUAL_64(0x1054, x1);
165 ASSERT_EQUAL_64(0x1053, x2);
166 ASSERT_EQUAL_64(0x1fff, x3);
167 ASSERT_EQUAL_64(0xfffffff8, x4);
168 ASSERT_EQUAL_64(0xfffffff8, x5);
169 ASSERT_EQUAL_64(0xfffffffc, x6);
170 }
171 }
172
173
TEST(mvn)174 TEST(mvn) {
175 SETUP();
176
177 START();
178 __ Mvn(w0, 0xfff);
179 __ Mvn(x1, 0xfff);
180 __ Mvn(w2, Operand(w0, LSL, 1));
181 __ Mvn(x3, Operand(x1, LSL, 2));
182 __ Mvn(w4, Operand(w0, LSR, 3));
183 __ Mvn(x5, Operand(x1, LSR, 4));
184 __ Mvn(w6, Operand(w0, ASR, 11));
185 __ Mvn(x7, Operand(x1, ASR, 12));
186 __ Mvn(w8, Operand(w0, ROR, 13));
187 __ Mvn(x9, Operand(x1, ROR, 14));
188 __ Mvn(w10, Operand(w2, UXTB));
189 __ Mvn(x11, Operand(x2, SXTB, 1));
190 __ Mvn(w12, Operand(w2, UXTH, 2));
191 __ Mvn(x13, Operand(x2, SXTH, 3));
192 __ Mvn(x14, Operand(w2, UXTW, 4));
193 __ Mvn(x15, Operand(w2, SXTW, 4));
194 END();
195
196 if (CAN_RUN()) {
197 RUN();
198
199 ASSERT_EQUAL_64(0xfffff000, x0);
200 ASSERT_EQUAL_64(0xfffffffffffff000, x1);
201 ASSERT_EQUAL_64(0x00001fff, x2);
202 ASSERT_EQUAL_64(0x0000000000003fff, x3);
203 ASSERT_EQUAL_64(0xe00001ff, x4);
204 ASSERT_EQUAL_64(0xf0000000000000ff, x5);
205 ASSERT_EQUAL_64(0x00000001, x6);
206 ASSERT_EQUAL_64(0x0000000000000000, x7);
207 ASSERT_EQUAL_64(0x7ff80000, x8);
208 ASSERT_EQUAL_64(0x3ffc000000000000, x9);
209 ASSERT_EQUAL_64(0xffffff00, x10);
210 ASSERT_EQUAL_64(0x0000000000000001, x11);
211 ASSERT_EQUAL_64(0xffff8003, x12);
212 ASSERT_EQUAL_64(0xffffffffffff0007, x13);
213 ASSERT_EQUAL_64(0xfffffffffffe000f, x14);
214 ASSERT_EQUAL_64(0xfffffffffffe000f, x15);
215 }
216 }
217
218
TEST(mov_imm_w)219 TEST(mov_imm_w) {
220 SETUP();
221
222 START();
223 __ Mov(w0, 0xffffffff);
224 __ Mov(w1, 0xffff1234);
225 __ Mov(w2, 0x1234ffff);
226 __ Mov(w3, 0x00000000);
227 __ Mov(w4, 0x00001234);
228 __ Mov(w5, 0x12340000);
229 __ Mov(w6, 0x12345678);
230 __ Mov(w7, (int32_t)0x80000000);
231 __ Mov(w8, (int32_t)0xffff0000);
232 __ Mov(w9, kWMinInt);
233 END();
234
235 if (CAN_RUN()) {
236 RUN();
237
238 ASSERT_EQUAL_64(0xffffffff, x0);
239 ASSERT_EQUAL_64(0xffff1234, x1);
240 ASSERT_EQUAL_64(0x1234ffff, x2);
241 ASSERT_EQUAL_64(0x00000000, x3);
242 ASSERT_EQUAL_64(0x00001234, x4);
243 ASSERT_EQUAL_64(0x12340000, x5);
244 ASSERT_EQUAL_64(0x12345678, x6);
245 ASSERT_EQUAL_64(0x80000000, x7);
246 ASSERT_EQUAL_64(0xffff0000, x8);
247 ASSERT_EQUAL_32(kWMinInt, w9);
248 }
249 }
250
251
TEST(mov_imm_x)252 TEST(mov_imm_x) {
253 SETUP();
254
255 START();
256 __ Mov(x0, 0xffffffffffffffff);
257 __ Mov(x1, 0xffffffffffff1234);
258 __ Mov(x2, 0xffffffff12345678);
259 __ Mov(x3, 0xffff1234ffff5678);
260 __ Mov(x4, 0x1234ffffffff5678);
261 __ Mov(x5, 0x1234ffff5678ffff);
262 __ Mov(x6, 0x12345678ffffffff);
263 __ Mov(x7, 0x1234ffffffffffff);
264 __ Mov(x8, 0x123456789abcffff);
265 __ Mov(x9, 0x12345678ffff9abc);
266 __ Mov(x10, 0x1234ffff56789abc);
267 __ Mov(x11, 0xffff123456789abc);
268 __ Mov(x12, 0x0000000000000000);
269 __ Mov(x13, 0x0000000000001234);
270 __ Mov(x14, 0x0000000012345678);
271 __ Mov(x15, 0x0000123400005678);
272 __ Mov(x18, 0x1234000000005678);
273 __ Mov(x19, 0x1234000056780000);
274 __ Mov(x20, 0x1234567800000000);
275 __ Mov(x21, 0x1234000000000000);
276 __ Mov(x22, 0x123456789abc0000);
277 __ Mov(x23, 0x1234567800009abc);
278 __ Mov(x24, 0x1234000056789abc);
279 __ Mov(x25, 0x0000123456789abc);
280 __ Mov(x26, 0x123456789abcdef0);
281 __ Mov(x27, 0xffff000000000001);
282 __ Mov(x28, 0x8000ffff00000000);
283 END();
284
285 if (CAN_RUN()) {
286 RUN();
287
288 ASSERT_EQUAL_64(0xffffffffffff1234, x1);
289 ASSERT_EQUAL_64(0xffffffff12345678, x2);
290 ASSERT_EQUAL_64(0xffff1234ffff5678, x3);
291 ASSERT_EQUAL_64(0x1234ffffffff5678, x4);
292 ASSERT_EQUAL_64(0x1234ffff5678ffff, x5);
293 ASSERT_EQUAL_64(0x12345678ffffffff, x6);
294 ASSERT_EQUAL_64(0x1234ffffffffffff, x7);
295 ASSERT_EQUAL_64(0x123456789abcffff, x8);
296 ASSERT_EQUAL_64(0x12345678ffff9abc, x9);
297 ASSERT_EQUAL_64(0x1234ffff56789abc, x10);
298 ASSERT_EQUAL_64(0xffff123456789abc, x11);
299 ASSERT_EQUAL_64(0x0000000000000000, x12);
300 ASSERT_EQUAL_64(0x0000000000001234, x13);
301 ASSERT_EQUAL_64(0x0000000012345678, x14);
302 ASSERT_EQUAL_64(0x0000123400005678, x15);
303 ASSERT_EQUAL_64(0x1234000000005678, x18);
304 ASSERT_EQUAL_64(0x1234000056780000, x19);
305 ASSERT_EQUAL_64(0x1234567800000000, x20);
306 ASSERT_EQUAL_64(0x1234000000000000, x21);
307 ASSERT_EQUAL_64(0x123456789abc0000, x22);
308 ASSERT_EQUAL_64(0x1234567800009abc, x23);
309 ASSERT_EQUAL_64(0x1234000056789abc, x24);
310 ASSERT_EQUAL_64(0x0000123456789abc, x25);
311 ASSERT_EQUAL_64(0x123456789abcdef0, x26);
312 ASSERT_EQUAL_64(0xffff000000000001, x27);
313 ASSERT_EQUAL_64(0x8000ffff00000000, x28);
314 }
315 }
316
317
TEST(mov)318 TEST(mov) {
319 SETUP();
320
321 START();
322 __ Mov(x0, 0xffffffffffffffff);
323 __ Mov(x1, 0xffffffffffffffff);
324 __ Mov(x2, 0xffffffffffffffff);
325 __ Mov(x3, 0xffffffffffffffff);
326
327 __ Mov(x0, 0x0123456789abcdef);
328
329 {
330 ExactAssemblyScope scope(&masm, 3 * kInstructionSize);
331 __ movz(x1, UINT64_C(0xabcd) << 16);
332 __ movk(x2, UINT64_C(0xabcd) << 32);
333 __ movn(x3, UINT64_C(0xabcd) << 48);
334 }
335
336 __ Mov(x4, 0x0123456789abcdef);
337 __ Mov(x5, x4);
338
339 __ Mov(w6, -1);
340
341 // Test that moves back to the same register have the desired effect. This
342 // is a no-op for X registers, and a truncation for W registers.
343 __ Mov(x7, 0x0123456789abcdef);
344 __ Mov(x7, x7);
345 __ Mov(x8, 0x0123456789abcdef);
346 __ Mov(w8, w8);
347 __ Mov(x9, 0x0123456789abcdef);
348 __ Mov(x9, Operand(x9));
349 __ Mov(x10, 0x0123456789abcdef);
350 __ Mov(w10, Operand(w10));
351
352 __ Mov(w11, 0xfff);
353 __ Mov(x12, 0xfff);
354 __ Mov(w13, Operand(w11, LSL, 1));
355 __ Mov(x14, Operand(x12, LSL, 2));
356 __ Mov(w15, Operand(w11, LSR, 3));
357 __ Mov(x18, Operand(x12, LSR, 4));
358 __ Mov(w19, Operand(w11, ASR, 11));
359 __ Mov(x20, Operand(x12, ASR, 12));
360 __ Mov(w21, Operand(w11, ROR, 13));
361 __ Mov(x22, Operand(x12, ROR, 14));
362 __ Mov(w23, Operand(w13, UXTB));
363 __ Mov(x24, Operand(x13, SXTB, 1));
364 __ Mov(w25, Operand(w13, UXTH, 2));
365 __ Mov(x26, Operand(x13, SXTH, 3));
366 __ Mov(x27, Operand(w13, UXTW, 4));
367
368 __ Mov(x28, 0x0123456789abcdef);
369 __ Mov(w28, w28, kDiscardForSameWReg);
370 END();
371
372 if (CAN_RUN()) {
373 RUN();
374
375 ASSERT_EQUAL_64(0x0123456789abcdef, x0);
376 ASSERT_EQUAL_64(0x00000000abcd0000, x1);
377 ASSERT_EQUAL_64(0xffffabcdffffffff, x2);
378 ASSERT_EQUAL_64(0x5432ffffffffffff, x3);
379 ASSERT_EQUAL_64(x4, x5);
380 ASSERT_EQUAL_32(-1, w6);
381 ASSERT_EQUAL_64(0x0123456789abcdef, x7);
382 ASSERT_EQUAL_32(0x89abcdef, w8);
383 ASSERT_EQUAL_64(0x0123456789abcdef, x9);
384 ASSERT_EQUAL_32(0x89abcdef, w10);
385 ASSERT_EQUAL_64(0x00000fff, x11);
386 ASSERT_EQUAL_64(0x0000000000000fff, x12);
387 ASSERT_EQUAL_64(0x00001ffe, x13);
388 ASSERT_EQUAL_64(0x0000000000003ffc, x14);
389 ASSERT_EQUAL_64(0x000001ff, x15);
390 ASSERT_EQUAL_64(0x00000000000000ff, x18);
391 ASSERT_EQUAL_64(0x00000001, x19);
392 ASSERT_EQUAL_64(0x0000000000000000, x20);
393 ASSERT_EQUAL_64(0x7ff80000, x21);
394 ASSERT_EQUAL_64(0x3ffc000000000000, x22);
395 ASSERT_EQUAL_64(0x000000fe, x23);
396 ASSERT_EQUAL_64(0xfffffffffffffffc, x24);
397 ASSERT_EQUAL_64(0x00007ff8, x25);
398 ASSERT_EQUAL_64(0x000000000000fff0, x26);
399 ASSERT_EQUAL_64(0x000000000001ffe0, x27);
400 ASSERT_EQUAL_64(0x0123456789abcdef, x28);
401 }
402 }
403
404
TEST(mov_negative)405 TEST(mov_negative) {
406 SETUP();
407
408 START();
409 __ Mov(w11, 0xffffffff);
410 __ Mov(x12, 0xffffffffffffffff);
411
412 __ Mov(w13, Operand(w11, LSL, 1));
413 __ Mov(w14, Operand(w11, LSR, 1));
414 __ Mov(w15, Operand(w11, ASR, 1));
415 __ Mov(w18, Operand(w11, ROR, 1));
416 __ Mov(w19, Operand(w11, UXTB, 1));
417 __ Mov(w20, Operand(w11, SXTB, 1));
418 __ Mov(w21, Operand(w11, UXTH, 1));
419 __ Mov(w22, Operand(w11, SXTH, 1));
420
421 __ Mov(x23, Operand(x12, LSL, 1));
422 __ Mov(x24, Operand(x12, LSR, 1));
423 __ Mov(x25, Operand(x12, ASR, 1));
424 __ Mov(x26, Operand(x12, ROR, 1));
425 __ Mov(x27, Operand(x12, UXTH, 1));
426 __ Mov(x28, Operand(x12, SXTH, 1));
427 __ Mov(x29, Operand(x12, UXTW, 1));
428 __ Mov(x30, Operand(x12, SXTW, 1));
429 END();
430
431 if (CAN_RUN()) {
432 RUN();
433
434 ASSERT_EQUAL_64(0xfffffffe, x13);
435 ASSERT_EQUAL_64(0x7fffffff, x14);
436 ASSERT_EQUAL_64(0xffffffff, x15);
437 ASSERT_EQUAL_64(0xffffffff, x18);
438 ASSERT_EQUAL_64(0x000001fe, x19);
439 ASSERT_EQUAL_64(0xfffffffe, x20);
440 ASSERT_EQUAL_64(0x0001fffe, x21);
441 ASSERT_EQUAL_64(0xfffffffe, x22);
442
443 ASSERT_EQUAL_64(0xfffffffffffffffe, x23);
444 ASSERT_EQUAL_64(0x7fffffffffffffff, x24);
445 ASSERT_EQUAL_64(0xffffffffffffffff, x25);
446 ASSERT_EQUAL_64(0xffffffffffffffff, x26);
447 ASSERT_EQUAL_64(0x000000000001fffe, x27);
448 ASSERT_EQUAL_64(0xfffffffffffffffe, x28);
449 ASSERT_EQUAL_64(0x00000001fffffffe, x29);
450 ASSERT_EQUAL_64(0xfffffffffffffffe, x30);
451 }
452 }
453
454
TEST(orr)455 TEST(orr) {
456 SETUP();
457
458 START();
459 __ Mov(x0, 0xf0f0);
460 __ Mov(x1, 0xf00000ff);
461
462 __ Orr(x2, x0, Operand(x1));
463 __ Orr(w3, w0, Operand(w1, LSL, 28));
464 __ Orr(x4, x0, Operand(x1, LSL, 32));
465 __ Orr(x5, x0, Operand(x1, LSR, 4));
466 __ Orr(w6, w0, Operand(w1, ASR, 4));
467 __ Orr(x7, x0, Operand(x1, ASR, 4));
468 __ Orr(w8, w0, Operand(w1, ROR, 12));
469 __ Orr(x9, x0, Operand(x1, ROR, 12));
470 __ Orr(w10, w0, 0xf);
471 __ Orr(x11, x0, 0xf0000000f0000000);
472 END();
473
474 if (CAN_RUN()) {
475 RUN();
476
477 ASSERT_EQUAL_64(0x00000000f000f0ff, x2);
478 ASSERT_EQUAL_64(0xf000f0f0, x3);
479 ASSERT_EQUAL_64(0xf00000ff0000f0f0, x4);
480 ASSERT_EQUAL_64(0x000000000f00f0ff, x5);
481 ASSERT_EQUAL_64(0xff00f0ff, x6);
482 ASSERT_EQUAL_64(0x000000000f00f0ff, x7);
483 ASSERT_EQUAL_64(0x0ffff0f0, x8);
484 ASSERT_EQUAL_64(0x0ff00000000ff0f0, x9);
485 ASSERT_EQUAL_64(0x0000f0ff, x10);
486 ASSERT_EQUAL_64(0xf0000000f000f0f0, x11);
487 }
488 }
489
490
TEST(orr_extend)491 TEST(orr_extend) {
492 SETUP();
493
494 START();
495 __ Mov(x0, 1);
496 __ Mov(x1, 0x8000000080008080);
497 __ Orr(w6, w0, Operand(w1, UXTB));
498 __ Orr(x7, x0, Operand(x1, UXTH, 1));
499 __ Orr(w8, w0, Operand(w1, UXTW, 2));
500 __ Orr(x9, x0, Operand(x1, UXTX, 3));
501 __ Orr(w10, w0, Operand(w1, SXTB));
502 __ Orr(x11, x0, Operand(x1, SXTH, 1));
503 __ Orr(x12, x0, Operand(x1, SXTW, 2));
504 __ Orr(x13, x0, Operand(x1, SXTX, 3));
505 END();
506
507 if (CAN_RUN()) {
508 RUN();
509
510 ASSERT_EQUAL_64(0x00000081, x6);
511 ASSERT_EQUAL_64(0x0000000000010101, x7);
512 ASSERT_EQUAL_64(0x00020201, x8);
513 ASSERT_EQUAL_64(0x0000000400040401, x9);
514 ASSERT_EQUAL_64(0xffffff81, x10);
515 ASSERT_EQUAL_64(0xffffffffffff0101, x11);
516 ASSERT_EQUAL_64(0xfffffffe00020201, x12);
517 ASSERT_EQUAL_64(0x0000000400040401, x13);
518 }
519 }
520
521
TEST(bitwise_wide_imm)522 TEST(bitwise_wide_imm) {
523 SETUP();
524
525 START();
526 __ Mov(x0, 0);
527 __ Mov(x1, 0xf0f0f0f0f0f0f0f0);
528
529 __ Orr(x10, x0, 0x1234567890abcdef);
530 __ Orr(w11, w1, 0x90abcdef);
531
532 __ Orr(w12, w0, kWMinInt);
533 __ Eor(w13, w0, kWMinInt);
534 END();
535
536 if (CAN_RUN()) {
537 RUN();
538
539 ASSERT_EQUAL_64(0, x0);
540 ASSERT_EQUAL_64(0xf0f0f0f0f0f0f0f0, x1);
541 ASSERT_EQUAL_64(0x1234567890abcdef, x10);
542 ASSERT_EQUAL_64(0x00000000f0fbfdff, x11);
543 ASSERT_EQUAL_32(kWMinInt, w12);
544 ASSERT_EQUAL_32(kWMinInt, w13);
545 }
546 }
547
548
TEST(orn)549 TEST(orn) {
550 SETUP();
551
552 START();
553 __ Mov(x0, 0xf0f0);
554 __ Mov(x1, 0xf00000ff);
555
556 __ Orn(x2, x0, Operand(x1));
557 __ Orn(w3, w0, Operand(w1, LSL, 4));
558 __ Orn(x4, x0, Operand(x1, LSL, 4));
559 __ Orn(x5, x0, Operand(x1, LSR, 1));
560 __ Orn(w6, w0, Operand(w1, ASR, 1));
561 __ Orn(x7, x0, Operand(x1, ASR, 1));
562 __ Orn(w8, w0, Operand(w1, ROR, 16));
563 __ Orn(x9, x0, Operand(x1, ROR, 16));
564 __ Orn(w10, w0, 0x0000ffff);
565 __ Orn(x11, x0, 0x0000ffff0000ffff);
566 END();
567
568 if (CAN_RUN()) {
569 RUN();
570
571 ASSERT_EQUAL_64(0xffffffff0ffffff0, x2);
572 ASSERT_EQUAL_64(0xfffff0ff, x3);
573 ASSERT_EQUAL_64(0xfffffff0fffff0ff, x4);
574 ASSERT_EQUAL_64(0xffffffff87fffff0, x5);
575 ASSERT_EQUAL_64(0x07fffff0, x6);
576 ASSERT_EQUAL_64(0xffffffff87fffff0, x7);
577 ASSERT_EQUAL_64(0xff00ffff, x8);
578 ASSERT_EQUAL_64(0xff00ffffffffffff, x9);
579 ASSERT_EQUAL_64(0xfffff0f0, x10);
580 ASSERT_EQUAL_64(0xffff0000fffff0f0, x11);
581 }
582 }
583
584
TEST(orn_extend)585 TEST(orn_extend) {
586 SETUP();
587
588 START();
589 __ Mov(x0, 1);
590 __ Mov(x1, 0x8000000080008081);
591 __ Orn(w6, w0, Operand(w1, UXTB));
592 __ Orn(x7, x0, Operand(x1, UXTH, 1));
593 __ Orn(w8, w0, Operand(w1, UXTW, 2));
594 __ Orn(x9, x0, Operand(x1, UXTX, 3));
595 __ Orn(w10, w0, Operand(w1, SXTB));
596 __ Orn(x11, x0, Operand(x1, SXTH, 1));
597 __ Orn(x12, x0, Operand(x1, SXTW, 2));
598 __ Orn(x13, x0, Operand(x1, SXTX, 3));
599 END();
600
601 if (CAN_RUN()) {
602 RUN();
603
604 ASSERT_EQUAL_64(0xffffff7f, x6);
605 ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
606 ASSERT_EQUAL_64(0xfffdfdfb, x8);
607 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
608 ASSERT_EQUAL_64(0x0000007f, x10);
609 ASSERT_EQUAL_64(0x000000000000fefd, x11);
610 ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
611 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
612 }
613 }
614
615
TEST(and_)616 TEST(and_) {
617 SETUP();
618
619 START();
620 __ Mov(x0, 0xfff0);
621 __ Mov(x1, 0xf00000ff);
622
623 __ And(x2, x0, Operand(x1));
624 __ And(w3, w0, Operand(w1, LSL, 4));
625 __ And(x4, x0, Operand(x1, LSL, 4));
626 __ And(x5, x0, Operand(x1, LSR, 1));
627 __ And(w6, w0, Operand(w1, ASR, 20));
628 __ And(x7, x0, Operand(x1, ASR, 20));
629 __ And(w8, w0, Operand(w1, ROR, 28));
630 __ And(x9, x0, Operand(x1, ROR, 28));
631 __ And(w10, w0, Operand(0xff00));
632 __ And(x11, x0, Operand(0xff));
633 END();
634
635 if (CAN_RUN()) {
636 RUN();
637
638 ASSERT_EQUAL_64(0x000000f0, x2);
639 ASSERT_EQUAL_64(0x00000ff0, x3);
640 ASSERT_EQUAL_64(0x00000ff0, x4);
641 ASSERT_EQUAL_64(0x00000070, x5);
642 ASSERT_EQUAL_64(0x0000ff00, x6);
643 ASSERT_EQUAL_64(0x00000f00, x7);
644 ASSERT_EQUAL_64(0x00000ff0, x8);
645 ASSERT_EQUAL_64(0x00000000, x9);
646 ASSERT_EQUAL_64(0x0000ff00, x10);
647 ASSERT_EQUAL_64(0x000000f0, x11);
648 }
649 }
650
651
TEST(and_extend)652 TEST(and_extend) {
653 SETUP();
654
655 START();
656 __ Mov(x0, 0xffffffffffffffff);
657 __ Mov(x1, 0x8000000080008081);
658 __ And(w6, w0, Operand(w1, UXTB));
659 __ And(x7, x0, Operand(x1, UXTH, 1));
660 __ And(w8, w0, Operand(w1, UXTW, 2));
661 __ And(x9, x0, Operand(x1, UXTX, 3));
662 __ And(w10, w0, Operand(w1, SXTB));
663 __ And(x11, x0, Operand(x1, SXTH, 1));
664 __ And(x12, x0, Operand(x1, SXTW, 2));
665 __ And(x13, x0, Operand(x1, SXTX, 3));
666 END();
667
668 if (CAN_RUN()) {
669 RUN();
670
671 ASSERT_EQUAL_64(0x00000081, x6);
672 ASSERT_EQUAL_64(0x0000000000010102, x7);
673 ASSERT_EQUAL_64(0x00020204, x8);
674 ASSERT_EQUAL_64(0x0000000400040408, x9);
675 ASSERT_EQUAL_64(0xffffff81, x10);
676 ASSERT_EQUAL_64(0xffffffffffff0102, x11);
677 ASSERT_EQUAL_64(0xfffffffe00020204, x12);
678 ASSERT_EQUAL_64(0x0000000400040408, x13);
679 }
680 }
681
682
TEST(ands)683 TEST(ands) {
684 SETUP();
685
686 START();
687 __ Mov(x1, 0xf00000ff);
688 __ Ands(w0, w1, Operand(w1));
689 END();
690
691 if (CAN_RUN()) {
692 RUN();
693
694 ASSERT_EQUAL_NZCV(NFlag);
695 ASSERT_EQUAL_64(0xf00000ff, x0);
696 }
697
698 START();
699 __ Mov(x0, 0xfff0);
700 __ Mov(x1, 0xf00000ff);
701 __ Ands(w0, w0, Operand(w1, LSR, 4));
702 END();
703
704 if (CAN_RUN()) {
705 RUN();
706
707 ASSERT_EQUAL_NZCV(ZFlag);
708 ASSERT_EQUAL_64(0x00000000, x0);
709 }
710
711 START();
712 __ Mov(x0, 0x8000000000000000);
713 __ Mov(x1, 0x00000001);
714 __ Ands(x0, x0, Operand(x1, ROR, 1));
715 END();
716
717 if (CAN_RUN()) {
718 RUN();
719
720 ASSERT_EQUAL_NZCV(NFlag);
721 ASSERT_EQUAL_64(0x8000000000000000, x0);
722 }
723
724 START();
725 __ Mov(x0, 0xfff0);
726 __ Ands(w0, w0, Operand(0xf));
727 END();
728
729 if (CAN_RUN()) {
730 RUN();
731
732 ASSERT_EQUAL_NZCV(ZFlag);
733 ASSERT_EQUAL_64(0x00000000, x0);
734 }
735
736 START();
737 __ Mov(x0, 0xff000000);
738 __ Ands(w0, w0, Operand(0x80000000));
739 END();
740
741 if (CAN_RUN()) {
742 RUN();
743
744 ASSERT_EQUAL_NZCV(NFlag);
745 ASSERT_EQUAL_64(0x80000000, x0);
746 }
747 }
748
749
TEST(bic)750 TEST(bic) {
751 SETUP();
752
753 START();
754 __ Mov(x0, 0xfff0);
755 __ Mov(x1, 0xf00000ff);
756
757 __ Bic(x2, x0, Operand(x1));
758 __ Bic(w3, w0, Operand(w1, LSL, 4));
759 __ Bic(x4, x0, Operand(x1, LSL, 4));
760 __ Bic(x5, x0, Operand(x1, LSR, 1));
761 __ Bic(w6, w0, Operand(w1, ASR, 20));
762 __ Bic(x7, x0, Operand(x1, ASR, 20));
763 __ Bic(w8, w0, Operand(w1, ROR, 28));
764 __ Bic(x9, x0, Operand(x1, ROR, 24));
765 __ Bic(x10, x0, Operand(0x1f));
766 __ Bic(x11, x0, Operand(0x100));
767
768 // Test bic into sp when the constant cannot be encoded in the immediate
769 // field.
770 // Use x20 to preserve sp. We check for the result via x21 because the
771 // test infrastructure requires that sp be restored to its original value.
772 __ Mov(x20, sp);
773 __ Mov(x0, 0xffffff);
774 __ Bic(sp, x0, Operand(0xabcdef));
775 __ Mov(x21, sp);
776 __ Mov(sp, x20);
777 END();
778
779 if (CAN_RUN()) {
780 RUN();
781
782 ASSERT_EQUAL_64(0x0000ff00, x2);
783 ASSERT_EQUAL_64(0x0000f000, x3);
784 ASSERT_EQUAL_64(0x0000f000, x4);
785 ASSERT_EQUAL_64(0x0000ff80, x5);
786 ASSERT_EQUAL_64(0x000000f0, x6);
787 ASSERT_EQUAL_64(0x0000f0f0, x7);
788 ASSERT_EQUAL_64(0x0000f000, x8);
789 ASSERT_EQUAL_64(0x0000ff00, x9);
790 ASSERT_EQUAL_64(0x0000ffe0, x10);
791 ASSERT_EQUAL_64(0x0000fef0, x11);
792
793 ASSERT_EQUAL_64(0x543210, x21);
794 }
795 }
796
797
TEST(bic_extend)798 TEST(bic_extend) {
799 SETUP();
800
801 START();
802 __ Mov(x0, 0xffffffffffffffff);
803 __ Mov(x1, 0x8000000080008081);
804 __ Bic(w6, w0, Operand(w1, UXTB));
805 __ Bic(x7, x0, Operand(x1, UXTH, 1));
806 __ Bic(w8, w0, Operand(w1, UXTW, 2));
807 __ Bic(x9, x0, Operand(x1, UXTX, 3));
808 __ Bic(w10, w0, Operand(w1, SXTB));
809 __ Bic(x11, x0, Operand(x1, SXTH, 1));
810 __ Bic(x12, x0, Operand(x1, SXTW, 2));
811 __ Bic(x13, x0, Operand(x1, SXTX, 3));
812 END();
813
814 if (CAN_RUN()) {
815 RUN();
816
817 ASSERT_EQUAL_64(0xffffff7e, x6);
818 ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
819 ASSERT_EQUAL_64(0xfffdfdfb, x8);
820 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
821 ASSERT_EQUAL_64(0x0000007e, x10);
822 ASSERT_EQUAL_64(0x000000000000fefd, x11);
823 ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
824 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
825 }
826 }
827
828
TEST(bics)829 TEST(bics) {
830 SETUP();
831
832 START();
833 __ Mov(x1, 0xffff);
834 __ Bics(w0, w1, Operand(w1));
835 END();
836
837 if (CAN_RUN()) {
838 RUN();
839
840 ASSERT_EQUAL_NZCV(ZFlag);
841 ASSERT_EQUAL_64(0x00000000, x0);
842 }
843
844 START();
845 __ Mov(x0, 0xffffffff);
846 __ Bics(w0, w0, Operand(w0, LSR, 1));
847 END();
848
849 if (CAN_RUN()) {
850 RUN();
851
852 ASSERT_EQUAL_NZCV(NFlag);
853 ASSERT_EQUAL_64(0x80000000, x0);
854 }
855
856 START();
857 __ Mov(x0, 0x8000000000000000);
858 __ Mov(x1, 0x00000001);
859 __ Bics(x0, x0, Operand(x1, ROR, 1));
860 END();
861
862 if (CAN_RUN()) {
863 RUN();
864
865 ASSERT_EQUAL_NZCV(ZFlag);
866 ASSERT_EQUAL_64(0x00000000, x0);
867 }
868
869 START();
870 __ Mov(x0, 0xffffffffffffffff);
871 __ Bics(x0, x0, 0x7fffffffffffffff);
872 END();
873
874 if (CAN_RUN()) {
875 RUN();
876
877 ASSERT_EQUAL_NZCV(NFlag);
878 ASSERT_EQUAL_64(0x8000000000000000, x0);
879 }
880
881 START();
882 __ Mov(w0, 0xffff0000);
883 __ Bics(w0, w0, 0xfffffff0);
884 END();
885
886 if (CAN_RUN()) {
887 RUN();
888
889 ASSERT_EQUAL_NZCV(ZFlag);
890 ASSERT_EQUAL_64(0x00000000, x0);
891 }
892 }
893
894
TEST(eor)895 TEST(eor) {
896 SETUP();
897
898 START();
899 __ Mov(x0, 0xfff0);
900 __ Mov(x1, 0xf00000ff);
901
902 __ Eor(x2, x0, Operand(x1));
903 __ Eor(w3, w0, Operand(w1, LSL, 4));
904 __ Eor(x4, x0, Operand(x1, LSL, 4));
905 __ Eor(x5, x0, Operand(x1, LSR, 1));
906 __ Eor(w6, w0, Operand(w1, ASR, 20));
907 __ Eor(x7, x0, Operand(x1, ASR, 20));
908 __ Eor(w8, w0, Operand(w1, ROR, 28));
909 __ Eor(x9, x0, Operand(x1, ROR, 28));
910 __ Eor(w10, w0, 0xff00ff00);
911 __ Eor(x11, x0, 0xff00ff00ff00ff00);
912 END();
913
914 if (CAN_RUN()) {
915 RUN();
916
917 ASSERT_EQUAL_64(0x00000000f000ff0f, x2);
918 ASSERT_EQUAL_64(0x0000f000, x3);
919 ASSERT_EQUAL_64(0x0000000f0000f000, x4);
920 ASSERT_EQUAL_64(0x000000007800ff8f, x5);
921 ASSERT_EQUAL_64(0xffff00f0, x6);
922 ASSERT_EQUAL_64(0x000000000000f0f0, x7);
923 ASSERT_EQUAL_64(0x0000f00f, x8);
924 ASSERT_EQUAL_64(0x00000ff00000ffff, x9);
925 ASSERT_EQUAL_64(0xff0000f0, x10);
926 ASSERT_EQUAL_64(0xff00ff00ff0000f0, x11);
927 }
928 }
929
TEST(eor_extend)930 TEST(eor_extend) {
931 SETUP();
932
933 START();
934 __ Mov(x0, 0x1111111111111111);
935 __ Mov(x1, 0x8000000080008081);
936 __ Eor(w6, w0, Operand(w1, UXTB));
937 __ Eor(x7, x0, Operand(x1, UXTH, 1));
938 __ Eor(w8, w0, Operand(w1, UXTW, 2));
939 __ Eor(x9, x0, Operand(x1, UXTX, 3));
940 __ Eor(w10, w0, Operand(w1, SXTB));
941 __ Eor(x11, x0, Operand(x1, SXTH, 1));
942 __ Eor(x12, x0, Operand(x1, SXTW, 2));
943 __ Eor(x13, x0, Operand(x1, SXTX, 3));
944 END();
945
946 if (CAN_RUN()) {
947 RUN();
948
949 ASSERT_EQUAL_64(0x11111190, x6);
950 ASSERT_EQUAL_64(0x1111111111101013, x7);
951 ASSERT_EQUAL_64(0x11131315, x8);
952 ASSERT_EQUAL_64(0x1111111511151519, x9);
953 ASSERT_EQUAL_64(0xeeeeee90, x10);
954 ASSERT_EQUAL_64(0xeeeeeeeeeeee1013, x11);
955 ASSERT_EQUAL_64(0xeeeeeeef11131315, x12);
956 ASSERT_EQUAL_64(0x1111111511151519, x13);
957 }
958 }
959
960
TEST(eon)961 TEST(eon) {
962 SETUP();
963
964 START();
965 __ Mov(x0, 0xfff0);
966 __ Mov(x1, 0xf00000ff);
967
968 __ Eon(x2, x0, Operand(x1));
969 __ Eon(w3, w0, Operand(w1, LSL, 4));
970 __ Eon(x4, x0, Operand(x1, LSL, 4));
971 __ Eon(x5, x0, Operand(x1, LSR, 1));
972 __ Eon(w6, w0, Operand(w1, ASR, 20));
973 __ Eon(x7, x0, Operand(x1, ASR, 20));
974 __ Eon(w8, w0, Operand(w1, ROR, 28));
975 __ Eon(x9, x0, Operand(x1, ROR, 28));
976 __ Eon(w10, w0, 0x03c003c0);
977 __ Eon(x11, x0, 0x0000100000001000);
978 END();
979
980 if (CAN_RUN()) {
981 RUN();
982
983 ASSERT_EQUAL_64(0xffffffff0fff00f0, x2);
984 ASSERT_EQUAL_64(0xffff0fff, x3);
985 ASSERT_EQUAL_64(0xfffffff0ffff0fff, x4);
986 ASSERT_EQUAL_64(0xffffffff87ff0070, x5);
987 ASSERT_EQUAL_64(0x0000ff0f, x6);
988 ASSERT_EQUAL_64(0xffffffffffff0f0f, x7);
989 ASSERT_EQUAL_64(0xffff0ff0, x8);
990 ASSERT_EQUAL_64(0xfffff00fffff0000, x9);
991 ASSERT_EQUAL_64(0xfc3f03cf, x10);
992 ASSERT_EQUAL_64(0xffffefffffff100f, x11);
993 }
994 }
995
996
TEST(eon_extend)997 TEST(eon_extend) {
998 SETUP();
999
1000 START();
1001 __ Mov(x0, 0x1111111111111111);
1002 __ Mov(x1, 0x8000000080008081);
1003 __ Eon(w6, w0, Operand(w1, UXTB));
1004 __ Eon(x7, x0, Operand(x1, UXTH, 1));
1005 __ Eon(w8, w0, Operand(w1, UXTW, 2));
1006 __ Eon(x9, x0, Operand(x1, UXTX, 3));
1007 __ Eon(w10, w0, Operand(w1, SXTB));
1008 __ Eon(x11, x0, Operand(x1, SXTH, 1));
1009 __ Eon(x12, x0, Operand(x1, SXTW, 2));
1010 __ Eon(x13, x0, Operand(x1, SXTX, 3));
1011 END();
1012
1013 if (CAN_RUN()) {
1014 RUN();
1015
1016 ASSERT_EQUAL_64(0xeeeeee6f, x6);
1017 ASSERT_EQUAL_64(0xeeeeeeeeeeefefec, x7);
1018 ASSERT_EQUAL_64(0xeeececea, x8);
1019 ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x9);
1020 ASSERT_EQUAL_64(0x1111116f, x10);
1021 ASSERT_EQUAL_64(0x111111111111efec, x11);
1022 ASSERT_EQUAL_64(0x11111110eeececea, x12);
1023 ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x13);
1024 }
1025 }
1026
1027
TEST(mul)1028 TEST(mul) {
1029 SETUP();
1030
1031 START();
1032 __ Mov(x25, 0);
1033 __ Mov(x26, 1);
1034 __ Mov(x18, 0xffffffff);
1035 __ Mov(x19, 0xffffffffffffffff);
1036
1037 __ Mul(w0, w25, w25);
1038 __ Mul(w1, w25, w26);
1039 __ Mul(w2, w26, w18);
1040 __ Mul(w3, w18, w19);
1041 __ Mul(x4, x25, x25);
1042 __ Mul(x5, x26, x18);
1043 __ Mul(x6, x18, x19);
1044 __ Mul(x7, x19, x19);
1045 __ Smull(x8, w26, w18);
1046 __ Smull(x9, w18, w18);
1047 __ Smull(x10, w19, w19);
1048 __ Mneg(w11, w25, w25);
1049 __ Mneg(w12, w25, w26);
1050 __ Mneg(w13, w26, w18);
1051 __ Mneg(w14, w18, w19);
1052 __ Mneg(x20, x25, x25);
1053 __ Mneg(x21, x26, x18);
1054 __ Mneg(x22, x18, x19);
1055 __ Mneg(x23, x19, x19);
1056 END();
1057
1058 if (CAN_RUN()) {
1059 RUN();
1060
1061 ASSERT_EQUAL_64(0, x0);
1062 ASSERT_EQUAL_64(0, x1);
1063 ASSERT_EQUAL_64(0xffffffff, x2);
1064 ASSERT_EQUAL_64(1, x3);
1065 ASSERT_EQUAL_64(0, x4);
1066 ASSERT_EQUAL_64(0xffffffff, x5);
1067 ASSERT_EQUAL_64(0xffffffff00000001, x6);
1068 ASSERT_EQUAL_64(1, x7);
1069 ASSERT_EQUAL_64(0xffffffffffffffff, x8);
1070 ASSERT_EQUAL_64(1, x9);
1071 ASSERT_EQUAL_64(1, x10);
1072 ASSERT_EQUAL_64(0, x11);
1073 ASSERT_EQUAL_64(0, x12);
1074 ASSERT_EQUAL_64(1, x13);
1075 ASSERT_EQUAL_64(0xffffffff, x14);
1076 ASSERT_EQUAL_64(0, x20);
1077 ASSERT_EQUAL_64(0xffffffff00000001, x21);
1078 ASSERT_EQUAL_64(0xffffffff, x22);
1079 ASSERT_EQUAL_64(0xffffffffffffffff, x23);
1080 }
1081 }
1082
1083
SmullHelper(int64_t expected, int64_t a, int64_t b)1084 static void SmullHelper(int64_t expected, int64_t a, int64_t b) {
1085 SETUP();
1086 START();
1087 __ Mov(w0, a);
1088 __ Mov(w1, b);
1089 __ Smull(x2, w0, w1);
1090 END();
1091 if (CAN_RUN()) {
1092 RUN();
1093 ASSERT_EQUAL_64(expected, x2);
1094 }
1095 }
1096
1097
TEST(smull)1098 TEST(smull) {
1099 SmullHelper(0, 0, 0);
1100 SmullHelper(1, 1, 1);
1101 SmullHelper(-1, -1, 1);
1102 SmullHelper(1, -1, -1);
1103 SmullHelper(0xffffffff80000000, 0x80000000, 1);
1104 SmullHelper(0x0000000080000000, 0x00010000, 0x00008000);
1105 }
1106
1107
TEST(madd)1108 TEST(madd) {
1109 SETUP();
1110
1111 START();
1112 __ Mov(x16, 0);
1113 __ Mov(x17, 1);
1114 __ Mov(x18, 0xffffffff);
1115 __ Mov(x19, 0xffffffffffffffff);
1116
1117 __ Madd(w0, w16, w16, w16);
1118 __ Madd(w1, w16, w16, w17);
1119 __ Madd(w2, w16, w16, w18);
1120 __ Madd(w3, w16, w16, w19);
1121 __ Madd(w4, w16, w17, w17);
1122 __ Madd(w5, w17, w17, w18);
1123 __ Madd(w6, w17, w17, w19);
1124 __ Madd(w7, w17, w18, w16);
1125 __ Madd(w8, w17, w18, w18);
1126 __ Madd(w9, w18, w18, w17);
1127 __ Madd(w10, w18, w19, w18);
1128 __ Madd(w11, w19, w19, w19);
1129
1130 __ Madd(x12, x16, x16, x16);
1131 __ Madd(x13, x16, x16, x17);
1132 __ Madd(x14, x16, x16, x18);
1133 __ Madd(x15, x16, x16, x19);
1134 __ Madd(x20, x16, x17, x17);
1135 __ Madd(x21, x17, x17, x18);
1136 __ Madd(x22, x17, x17, x19);
1137 __ Madd(x23, x17, x18, x16);
1138 __ Madd(x24, x17, x18, x18);
1139 __ Madd(x25, x18, x18, x17);
1140 __ Madd(x26, x18, x19, x18);
1141 __ Madd(x27, x19, x19, x19);
1142
1143 END();
1144
1145 if (CAN_RUN()) {
1146 RUN();
1147
1148 ASSERT_EQUAL_64(0, x0);
1149 ASSERT_EQUAL_64(1, x1);
1150 ASSERT_EQUAL_64(0xffffffff, x2);
1151 ASSERT_EQUAL_64(0xffffffff, x3);
1152 ASSERT_EQUAL_64(1, x4);
1153 ASSERT_EQUAL_64(0, x5);
1154 ASSERT_EQUAL_64(0, x6);
1155 ASSERT_EQUAL_64(0xffffffff, x7);
1156 ASSERT_EQUAL_64(0xfffffffe, x8);
1157 ASSERT_EQUAL_64(2, x9);
1158 ASSERT_EQUAL_64(0, x10);
1159 ASSERT_EQUAL_64(0, x11);
1160
1161 ASSERT_EQUAL_64(0, x12);
1162 ASSERT_EQUAL_64(1, x13);
1163 ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1164 ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1165 ASSERT_EQUAL_64(1, x20);
1166 ASSERT_EQUAL_64(0x0000000100000000, x21);
1167 ASSERT_EQUAL_64(0, x22);
1168 ASSERT_EQUAL_64(0x00000000ffffffff, x23);
1169 ASSERT_EQUAL_64(0x00000001fffffffe, x24);
1170 ASSERT_EQUAL_64(0xfffffffe00000002, x25);
1171 ASSERT_EQUAL_64(0, x26);
1172 ASSERT_EQUAL_64(0, x27);
1173 }
1174 }
1175
1176
TEST(msub)1177 TEST(msub) {
1178 SETUP();
1179
1180 START();
1181 __ Mov(x16, 0);
1182 __ Mov(x17, 1);
1183 __ Mov(x18, 0xffffffff);
1184 __ Mov(x19, 0xffffffffffffffff);
1185
1186 __ Msub(w0, w16, w16, w16);
1187 __ Msub(w1, w16, w16, w17);
1188 __ Msub(w2, w16, w16, w18);
1189 __ Msub(w3, w16, w16, w19);
1190 __ Msub(w4, w16, w17, w17);
1191 __ Msub(w5, w17, w17, w18);
1192 __ Msub(w6, w17, w17, w19);
1193 __ Msub(w7, w17, w18, w16);
1194 __ Msub(w8, w17, w18, w18);
1195 __ Msub(w9, w18, w18, w17);
1196 __ Msub(w10, w18, w19, w18);
1197 __ Msub(w11, w19, w19, w19);
1198
1199 __ Msub(x12, x16, x16, x16);
1200 __ Msub(x13, x16, x16, x17);
1201 __ Msub(x14, x16, x16, x18);
1202 __ Msub(x15, x16, x16, x19);
1203 __ Msub(x20, x16, x17, x17);
1204 __ Msub(x21, x17, x17, x18);
1205 __ Msub(x22, x17, x17, x19);
1206 __ Msub(x23, x17, x18, x16);
1207 __ Msub(x24, x17, x18, x18);
1208 __ Msub(x25, x18, x18, x17);
1209 __ Msub(x26, x18, x19, x18);
1210 __ Msub(x27, x19, x19, x19);
1211
1212 END();
1213
1214 if (CAN_RUN()) {
1215 RUN();
1216
1217 ASSERT_EQUAL_64(0, x0);
1218 ASSERT_EQUAL_64(1, x1);
1219 ASSERT_EQUAL_64(0xffffffff, x2);
1220 ASSERT_EQUAL_64(0xffffffff, x3);
1221 ASSERT_EQUAL_64(1, x4);
1222 ASSERT_EQUAL_64(0xfffffffe, x5);
1223 ASSERT_EQUAL_64(0xfffffffe, x6);
1224 ASSERT_EQUAL_64(1, x7);
1225 ASSERT_EQUAL_64(0, x8);
1226 ASSERT_EQUAL_64(0, x9);
1227 ASSERT_EQUAL_64(0xfffffffe, x10);
1228 ASSERT_EQUAL_64(0xfffffffe, x11);
1229
1230 ASSERT_EQUAL_64(0, x12);
1231 ASSERT_EQUAL_64(1, x13);
1232 ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1233 ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1234 ASSERT_EQUAL_64(1, x20);
1235 ASSERT_EQUAL_64(0x00000000fffffffe, x21);
1236 ASSERT_EQUAL_64(0xfffffffffffffffe, x22);
1237 ASSERT_EQUAL_64(0xffffffff00000001, x23);
1238 ASSERT_EQUAL_64(0, x24);
1239 ASSERT_EQUAL_64(0x0000000200000000, x25);
1240 ASSERT_EQUAL_64(0x00000001fffffffe, x26);
1241 ASSERT_EQUAL_64(0xfffffffffffffffe, x27);
1242 }
1243 }
1244
1245
TEST(smulh)1246 TEST(smulh) {
1247 SETUP();
1248
1249 START();
1250 __ Mov(x20, 0);
1251 __ Mov(x21, 1);
1252 __ Mov(x22, 0x0000000100000000);
1253 __ Mov(x23, 0x0000000012345678);
1254 __ Mov(x24, 0x0123456789abcdef);
1255 __ Mov(x25, 0x0000000200000000);
1256 __ Mov(x26, 0x8000000000000000);
1257 __ Mov(x27, 0xffffffffffffffff);
1258 __ Mov(x28, 0x5555555555555555);
1259 __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
1260
1261 __ Smulh(x0, x20, x24);
1262 __ Smulh(x1, x21, x24);
1263 __ Smulh(x2, x22, x23);
1264 __ Smulh(x3, x22, x24);
1265 __ Smulh(x4, x24, x25);
1266 __ Smulh(x5, x23, x27);
1267 __ Smulh(x6, x26, x26);
1268 __ Smulh(x7, x26, x27);
1269 __ Smulh(x8, x27, x27);
1270 __ Smulh(x9, x28, x28);
1271 __ Smulh(x10, x28, x29);
1272 __ Smulh(x11, x29, x29);
1273 END();
1274
1275 if (CAN_RUN()) {
1276 RUN();
1277
1278 ASSERT_EQUAL_64(0, x0);
1279 ASSERT_EQUAL_64(0, x1);
1280 ASSERT_EQUAL_64(0, x2);
1281 ASSERT_EQUAL_64(0x0000000001234567, x3);
1282 ASSERT_EQUAL_64(0x0000000002468acf, x4);
1283 ASSERT_EQUAL_64(0xffffffffffffffff, x5);
1284 ASSERT_EQUAL_64(0x4000000000000000, x6);
1285 ASSERT_EQUAL_64(0, x7);
1286 ASSERT_EQUAL_64(0, x8);
1287 ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1288 ASSERT_EQUAL_64(0xe38e38e38e38e38e, x10);
1289 ASSERT_EQUAL_64(0x1c71c71c71c71c72, x11);
1290 }
1291 }
1292
1293
TEST(umulh)1294 TEST(umulh) {
1295 SETUP();
1296
1297 START();
1298 __ Mov(x20, 0);
1299 __ Mov(x21, 1);
1300 __ Mov(x22, 0x0000000100000000);
1301 __ Mov(x23, 0x0000000012345678);
1302 __ Mov(x24, 0x0123456789abcdef);
1303 __ Mov(x25, 0x0000000200000000);
1304 __ Mov(x26, 0x8000000000000000);
1305 __ Mov(x27, 0xffffffffffffffff);
1306 __ Mov(x28, 0x5555555555555555);
1307 __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
1308
1309 __ Umulh(x0, x20, x24);
1310 __ Umulh(x1, x21, x24);
1311 __ Umulh(x2, x22, x23);
1312 __ Umulh(x3, x22, x24);
1313 __ Umulh(x4, x24, x25);
1314 __ Umulh(x5, x23, x27);
1315 __ Umulh(x6, x26, x26);
1316 __ Umulh(x7, x26, x27);
1317 __ Umulh(x8, x27, x27);
1318 __ Umulh(x9, x28, x28);
1319 __ Umulh(x10, x28, x29);
1320 __ Umulh(x11, x29, x29);
1321 END();
1322
1323 if (CAN_RUN()) {
1324 RUN();
1325
1326 ASSERT_EQUAL_64(0, x0);
1327 ASSERT_EQUAL_64(0, x1);
1328 ASSERT_EQUAL_64(0, x2);
1329 ASSERT_EQUAL_64(0x0000000001234567, x3);
1330 ASSERT_EQUAL_64(0x0000000002468acf, x4);
1331 ASSERT_EQUAL_64(0x0000000012345677, x5);
1332 ASSERT_EQUAL_64(0x4000000000000000, x6);
1333 ASSERT_EQUAL_64(0x7fffffffffffffff, x7);
1334 ASSERT_EQUAL_64(0xfffffffffffffffe, x8);
1335 ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1336 ASSERT_EQUAL_64(0x38e38e38e38e38e3, x10);
1337 ASSERT_EQUAL_64(0x71c71c71c71c71c6, x11);
1338 }
1339 }
1340
1341
TEST(smaddl_umaddl_umull)1342 TEST(smaddl_umaddl_umull) {
1343 SETUP();
1344
1345 START();
1346 __ Mov(x17, 1);
1347 __ Mov(x18, 0x00000000ffffffff);
1348 __ Mov(x19, 0xffffffffffffffff);
1349 __ Mov(x20, 4);
1350 __ Mov(x21, 0x0000000200000000);
1351
1352 __ Smaddl(x9, w17, w18, x20);
1353 __ Smaddl(x10, w18, w18, x20);
1354 __ Smaddl(x11, w19, w19, x20);
1355 __ Smaddl(x12, w19, w19, x21);
1356 __ Umaddl(x13, w17, w18, x20);
1357 __ Umaddl(x14, w18, w18, x20);
1358 __ Umaddl(x15, w19, w19, x20);
1359 __ Umaddl(x22, w19, w19, x21);
1360 __ Umull(x24, w19, w19);
1361 __ Umull(x25, w17, w18);
1362 END();
1363
1364 if (CAN_RUN()) {
1365 RUN();
1366
1367 ASSERT_EQUAL_64(3, x9);
1368 ASSERT_EQUAL_64(5, x10);
1369 ASSERT_EQUAL_64(5, x11);
1370 ASSERT_EQUAL_64(0x0000000200000001, x12);
1371 ASSERT_EQUAL_64(0x0000000100000003, x13);
1372 ASSERT_EQUAL_64(0xfffffffe00000005, x14);
1373 ASSERT_EQUAL_64(0xfffffffe00000005, x15);
1374 ASSERT_EQUAL_64(1, x22);
1375 ASSERT_EQUAL_64(0xfffffffe00000001, x24);
1376 ASSERT_EQUAL_64(0x00000000ffffffff, x25);
1377 }
1378 }
1379
1380
TEST(smsubl_umsubl)1381 TEST(smsubl_umsubl) {
1382 SETUP();
1383
1384 START();
1385 __ Mov(x17, 1);
1386 __ Mov(x18, 0x00000000ffffffff);
1387 __ Mov(x19, 0xffffffffffffffff);
1388 __ Mov(x20, 4);
1389 __ Mov(x21, 0x0000000200000000);
1390
1391 __ Smsubl(x9, w17, w18, x20);
1392 __ Smsubl(x10, w18, w18, x20);
1393 __ Smsubl(x11, w19, w19, x20);
1394 __ Smsubl(x12, w19, w19, x21);
1395 __ Umsubl(x13, w17, w18, x20);
1396 __ Umsubl(x14, w18, w18, x20);
1397 __ Umsubl(x15, w19, w19, x20);
1398 __ Umsubl(x22, w19, w19, x21);
1399 END();
1400
1401 if (CAN_RUN()) {
1402 RUN();
1403
1404 ASSERT_EQUAL_64(5, x9);
1405 ASSERT_EQUAL_64(3, x10);
1406 ASSERT_EQUAL_64(3, x11);
1407 ASSERT_EQUAL_64(0x00000001ffffffff, x12);
1408 ASSERT_EQUAL_64(0xffffffff00000005, x13);
1409 ASSERT_EQUAL_64(0x0000000200000003, x14);
1410 ASSERT_EQUAL_64(0x0000000200000003, x15);
1411 ASSERT_EQUAL_64(0x00000003ffffffff, x22);
1412 }
1413 }
1414
1415
TEST(div)1416 TEST(div) {
1417 SETUP();
1418
1419 START();
1420 __ Mov(x16, 1);
1421 __ Mov(x17, 0xffffffff);
1422 __ Mov(x18, 0xffffffffffffffff);
1423 __ Mov(x19, 0x80000000);
1424 __ Mov(x20, 0x8000000000000000);
1425 __ Mov(x21, 2);
1426
1427 __ Udiv(w0, w16, w16);
1428 __ Udiv(w1, w17, w16);
1429 __ Sdiv(w2, w16, w16);
1430 __ Sdiv(w3, w16, w17);
1431 __ Sdiv(w4, w17, w18);
1432
1433 __ Udiv(x5, x16, x16);
1434 __ Udiv(x6, x17, x18);
1435 __ Sdiv(x7, x16, x16);
1436 __ Sdiv(x8, x16, x17);
1437 __ Sdiv(x9, x17, x18);
1438
1439 __ Udiv(w10, w19, w21);
1440 __ Sdiv(w11, w19, w21);
1441 __ Udiv(x12, x19, x21);
1442 __ Sdiv(x13, x19, x21);
1443 __ Udiv(x14, x20, x21);
1444 __ Sdiv(x15, x20, x21);
1445
1446 __ Udiv(w22, w19, w17);
1447 __ Sdiv(w23, w19, w17);
1448 __ Udiv(x24, x20, x18);
1449 __ Sdiv(x25, x20, x18);
1450
1451 __ Udiv(x26, x16, x21);
1452 __ Sdiv(x27, x16, x21);
1453 __ Udiv(x28, x18, x21);
1454 __ Sdiv(x29, x18, x21);
1455
1456 __ Mov(x17, 0);
1457 __ Udiv(w18, w16, w17);
1458 __ Sdiv(w19, w16, w17);
1459 __ Udiv(x20, x16, x17);
1460 __ Sdiv(x21, x16, x17);
1461 END();
1462
1463 if (CAN_RUN()) {
1464 RUN();
1465
1466 ASSERT_EQUAL_64(1, x0);
1467 ASSERT_EQUAL_64(0xffffffff, x1);
1468 ASSERT_EQUAL_64(1, x2);
1469 ASSERT_EQUAL_64(0xffffffff, x3);
1470 ASSERT_EQUAL_64(1, x4);
1471 ASSERT_EQUAL_64(1, x5);
1472 ASSERT_EQUAL_64(0, x6);
1473 ASSERT_EQUAL_64(1, x7);
1474 ASSERT_EQUAL_64(0, x8);
1475 ASSERT_EQUAL_64(0xffffffff00000001, x9);
1476 ASSERT_EQUAL_64(0x40000000, x10);
1477 ASSERT_EQUAL_64(0xc0000000, x11);
1478 ASSERT_EQUAL_64(0x0000000040000000, x12);
1479 ASSERT_EQUAL_64(0x0000000040000000, x13);
1480 ASSERT_EQUAL_64(0x4000000000000000, x14);
1481 ASSERT_EQUAL_64(0xc000000000000000, x15);
1482 ASSERT_EQUAL_64(0, x22);
1483 ASSERT_EQUAL_64(0x80000000, x23);
1484 ASSERT_EQUAL_64(0, x24);
1485 ASSERT_EQUAL_64(0x8000000000000000, x25);
1486 ASSERT_EQUAL_64(0, x26);
1487 ASSERT_EQUAL_64(0, x27);
1488 ASSERT_EQUAL_64(0x7fffffffffffffff, x28);
1489 ASSERT_EQUAL_64(0, x29);
1490 ASSERT_EQUAL_64(0, x18);
1491 ASSERT_EQUAL_64(0, x19);
1492 ASSERT_EQUAL_64(0, x20);
1493 ASSERT_EQUAL_64(0, x21);
1494 }
1495 }
1496
1497
TEST(rbit_rev)1498 TEST(rbit_rev) {
1499 SETUP();
1500
1501 START();
1502 __ Mov(x24, 0xfedcba9876543210);
1503 __ Rbit(w0, w24);
1504 __ Rbit(x1, x24);
1505 __ Rev16(w2, w24);
1506 __ Rev16(x3, x24);
1507 __ Rev(w4, w24);
1508 __ Rev32(x5, x24);
1509 __ Rev64(x6, x24);
1510 __ Rev(x7, x24);
1511 END();
1512
1513 if (CAN_RUN()) {
1514 RUN();
1515
1516 ASSERT_EQUAL_64(0x084c2a6e, x0);
1517 ASSERT_EQUAL_64(0x084c2a6e195d3b7f, x1);
1518 ASSERT_EQUAL_64(0x54761032, x2);
1519 ASSERT_EQUAL_64(0xdcfe98ba54761032, x3);
1520 ASSERT_EQUAL_64(0x10325476, x4);
1521 ASSERT_EQUAL_64(0x98badcfe10325476, x5);
1522 ASSERT_EQUAL_64(0x1032547698badcfe, x6);
1523 ASSERT_EQUAL_64(0x1032547698badcfe, x7);
1524 }
1525 }
1526
1527 typedef void (MacroAssembler::*TestBranchSignature)(const Register& rt,
1528 unsigned bit_pos,
1529 Label* label);
1530
TbzRangePoolLimitHelper(TestBranchSignature test_branch)1531 static void TbzRangePoolLimitHelper(TestBranchSignature test_branch) {
1532 const int kTbzRange = 32768;
1533 const int kNumLdrLiteral = kTbzRange / 4;
1534 const int fuzz_range = 2;
1535 for (int n = kNumLdrLiteral - fuzz_range; n <= kNumLdrLiteral + fuzz_range;
1536 ++n) {
1537 for (int margin = -32; margin < 32; margin += 4) {
1538 SETUP();
1539
1540 START();
1541
1542 // Emit 32KB of literals (equal to the range of TBZ).
1543 for (int i = 0; i < n; ++i) {
1544 __ Ldr(w0, 0x12345678);
1545 }
1546
1547 const int kLiteralMargin = 128 * KBytes;
1548
1549 // Emit enough NOPs to be just about to emit the literal pool.
1550 ptrdiff_t end =
1551 masm.GetCursorOffset() + (kLiteralMargin - n * 4 + margin);
1552 while (masm.GetCursorOffset() < end) {
1553 __ Nop();
1554 }
1555
1556 // Add a TBZ instruction.
1557 Label label;
1558
1559 (masm.*test_branch)(x0, 2, &label);
1560
1561 // Add enough NOPs to surpass its range, to make sure we can encode the
1562 // veneer.
1563 end = masm.GetCursorOffset() + (kTbzRange - 4);
1564 {
1565 ExactAssemblyScope scope(&masm,
1566 kTbzRange,
1567 ExactAssemblyScope::kMaximumSize);
1568 while (masm.GetCursorOffset() < end) __ nop();
1569 }
1570
1571 // Finally, bind the label.
1572 __ Bind(&label);
1573
1574 END();
1575
1576 if (CAN_RUN()) {
1577 RUN();
1578 }
1579 }
1580 }
1581 }
1582
TEST(test_branch_limits_literal_pool_size_tbz)1583 TEST(test_branch_limits_literal_pool_size_tbz) {
1584 TbzRangePoolLimitHelper(&MacroAssembler::Tbz);
1585 }
1586
TEST(test_branch_limits_literal_pool_size_tbnz)1587 TEST(test_branch_limits_literal_pool_size_tbnz) {
1588 TbzRangePoolLimitHelper(&MacroAssembler::Tbnz);
1589 }
1590
TEST(clz_cls)1591 TEST(clz_cls) {
1592 SETUP();
1593
1594 START();
1595 __ Mov(x24, 0x0008000000800000);
1596 __ Mov(x25, 0xff800000fff80000);
1597 __ Mov(x26, 0);
1598 __ Clz(w0, w24);
1599 __ Clz(x1, x24);
1600 __ Clz(w2, w25);
1601 __ Clz(x3, x25);
1602 __ Clz(w4, w26);
1603 __ Clz(x5, x26);
1604 __ Cls(w6, w24);
1605 __ Cls(x7, x24);
1606 __ Cls(w8, w25);
1607 __ Cls(x9, x25);
1608 __ Cls(w10, w26);
1609 __ Cls(x11, x26);
1610 END();
1611
1612 if (CAN_RUN()) {
1613 RUN();
1614
1615 ASSERT_EQUAL_64(8, x0);
1616 ASSERT_EQUAL_64(12, x1);
1617 ASSERT_EQUAL_64(0, x2);
1618 ASSERT_EQUAL_64(0, x3);
1619 ASSERT_EQUAL_64(32, x4);
1620 ASSERT_EQUAL_64(64, x5);
1621 ASSERT_EQUAL_64(7, x6);
1622 ASSERT_EQUAL_64(11, x7);
1623 ASSERT_EQUAL_64(12, x8);
1624 ASSERT_EQUAL_64(8, x9);
1625 ASSERT_EQUAL_64(31, x10);
1626 ASSERT_EQUAL_64(63, x11);
1627 }
1628 }
1629
1630
TEST(pacia_pacib_autia_autib)1631 TEST(pacia_pacib_autia_autib) {
1632 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1633
1634 START();
1635
1636 Register pointer = x24;
1637 Register modifier = x25;
1638
1639 __ Mov(pointer, 0x0000000012345678);
1640 __ Mov(modifier, 0x477d469dec0b8760);
1641
1642 // Generate PACs using keys A and B.
1643 __ Mov(x0, pointer);
1644 __ Pacia(x0, modifier);
1645
1646 __ Mov(x1, pointer);
1647 __ Pacib(x1, modifier);
1648
1649 // Authenticate the pointers above.
1650 __ Mov(x2, x0);
1651 __ Autia(x2, modifier);
1652
1653 __ Mov(x3, x1);
1654 __ Autib(x3, modifier);
1655
1656 // Attempt to authenticate incorrect pointers.
1657 __ Mov(x4, x1);
1658 __ Autia(x4, modifier);
1659
1660 __ Mov(x5, x0);
1661 __ Autib(x5, modifier);
1662
1663 // Mask out just the PAC code bits.
1664 // TODO: use Simulator::CalculatePACMask in a nice way.
1665 __ And(x0, x0, 0x007f000000000000);
1666 __ And(x1, x1, 0x007f000000000000);
1667
1668 END();
1669
1670 if (CAN_RUN()) {
1671 RUN();
1672
1673 // Check PAC codes have been generated and aren't equal.
1674 // NOTE: with a different ComputePAC implementation, there may be a
1675 // collision.
1676 ASSERT_NOT_EQUAL_64(0, x0);
1677 ASSERT_NOT_EQUAL_64(0, x1);
1678 ASSERT_NOT_EQUAL_64(x0, x1);
1679
1680 // Pointers correctly authenticated.
1681 ASSERT_EQUAL_64(pointer, x2);
1682 ASSERT_EQUAL_64(pointer, x3);
1683
1684 // Pointers corrupted after failing to authenticate.
1685 ASSERT_EQUAL_64(0x0020000012345678, x4);
1686 ASSERT_EQUAL_64(0x0040000012345678, x5);
1687 }
1688 }
1689
1690
TEST(paciza_pacizb_autiza_autizb)1691 TEST(paciza_pacizb_autiza_autizb) {
1692 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1693
1694 START();
1695
1696 Register pointer = x24;
1697
1698 __ Mov(pointer, 0x0000000012345678);
1699
1700 // Generate PACs using keys A and B.
1701 __ Mov(x0, pointer);
1702 __ Paciza(x0);
1703
1704 __ Mov(x1, pointer);
1705 __ Pacizb(x1);
1706
1707 // Authenticate the pointers above.
1708 __ Mov(x2, x0);
1709 __ Autiza(x2);
1710
1711 __ Mov(x3, x1);
1712 __ Autizb(x3);
1713
1714 // Attempt to authenticate incorrect pointers.
1715 __ Mov(x4, x1);
1716 __ Autiza(x4);
1717
1718 __ Mov(x5, x0);
1719 __ Autizb(x5);
1720
1721 // Mask out just the PAC code bits.
1722 // TODO: use Simulator::CalculatePACMask in a nice way.
1723 __ And(x0, x0, 0x007f000000000000);
1724 __ And(x1, x1, 0x007f000000000000);
1725
1726 END();
1727
1728 if (CAN_RUN()) {
1729 RUN();
1730
1731 // Check PAC codes have been generated and aren't equal.
1732 // NOTE: with a different ComputePAC implementation, there may be a
1733 // collision.
1734 ASSERT_NOT_EQUAL_64(0, x0);
1735 ASSERT_NOT_EQUAL_64(0, x1);
1736 ASSERT_NOT_EQUAL_64(x0, x1);
1737
1738 // Pointers correctly authenticated.
1739 ASSERT_EQUAL_64(pointer, x2);
1740 ASSERT_EQUAL_64(pointer, x3);
1741
1742 // Pointers corrupted after failing to authenticate.
1743 ASSERT_EQUAL_64(0x0020000012345678, x4);
1744 ASSERT_EQUAL_64(0x0040000012345678, x5);
1745 }
1746 }
1747
1748
TEST(pacda_pacdb_autda_autdb)1749 TEST(pacda_pacdb_autda_autdb) {
1750 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1751
1752 START();
1753
1754 Register pointer = x24;
1755 Register modifier = x25;
1756
1757 __ Mov(pointer, 0x0000000012345678);
1758 __ Mov(modifier, 0x477d469dec0b8760);
1759
1760 // Generate PACs using keys A and B.
1761 __ Mov(x0, pointer);
1762 __ Pacda(x0, modifier);
1763
1764 __ Mov(x1, pointer);
1765 __ Pacdb(x1, modifier);
1766
1767 // Authenticate the pointers above.
1768 __ Mov(x2, x0);
1769 __ Autda(x2, modifier);
1770
1771 __ Mov(x3, x1);
1772 __ Autdb(x3, modifier);
1773
1774 // Attempt to authenticate incorrect pointers.
1775 __ Mov(x4, x1);
1776 __ Autda(x4, modifier);
1777
1778 __ Mov(x5, x0);
1779 __ Autdb(x5, modifier);
1780
1781 // Mask out just the PAC code bits.
1782 // TODO: use Simulator::CalculatePACMask in a nice way.
1783 __ And(x0, x0, 0x007f000000000000);
1784 __ And(x1, x1, 0x007f000000000000);
1785
1786 END();
1787
1788 if (CAN_RUN()) {
1789 RUN();
1790
1791 // Check PAC codes have been generated and aren't equal.
1792 // NOTE: with a different ComputePAC implementation, there may be a
1793 // collision.
1794 ASSERT_NOT_EQUAL_64(0, x0);
1795 ASSERT_NOT_EQUAL_64(0, x1);
1796 ASSERT_NOT_EQUAL_64(x0, x1);
1797
1798 // Pointers correctly authenticated.
1799 ASSERT_EQUAL_64(pointer, x2);
1800 ASSERT_EQUAL_64(pointer, x3);
1801
1802 // Pointers corrupted after failing to authenticate.
1803 ASSERT_EQUAL_64(0x0020000012345678, x4);
1804 ASSERT_EQUAL_64(0x0040000012345678, x5);
1805 }
1806 }
1807
1808
TEST(pacdza_pacdzb_autdza_autdzb)1809 TEST(pacdza_pacdzb_autdza_autdzb) {
1810 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1811
1812 START();
1813
1814 Register pointer = x24;
1815
1816 __ Mov(pointer, 0x0000000012345678);
1817
1818 // Generate PACs using keys A and B.
1819 __ Mov(x0, pointer);
1820 __ Pacdza(x0);
1821
1822 __ Mov(x1, pointer);
1823 __ Pacdzb(x1);
1824
1825 // Authenticate the pointers above.
1826 __ Mov(x2, x0);
1827 __ Autdza(x2);
1828
1829 __ Mov(x3, x1);
1830 __ Autdzb(x3);
1831
1832 // Attempt to authenticate incorrect pointers.
1833 __ Mov(x4, x1);
1834 __ Autdza(x4);
1835
1836 __ Mov(x5, x0);
1837 __ Autdzb(x5);
1838
1839 // Mask out just the PAC code bits.
1840 // TODO: use Simulator::CalculatePACMask in a nice way.
1841 __ And(x0, x0, 0x007f000000000000);
1842 __ And(x1, x1, 0x007f000000000000);
1843
1844 END();
1845
1846 if (CAN_RUN()) {
1847 RUN();
1848
1849 // Check PAC codes have been generated and aren't equal.
1850 // NOTE: with a different ComputePAC implementation, there may be a
1851 // collision.
1852 ASSERT_NOT_EQUAL_64(0, x0);
1853 ASSERT_NOT_EQUAL_64(0, x1);
1854 ASSERT_NOT_EQUAL_64(x0, x1);
1855
1856 // Pointers correctly authenticated.
1857 ASSERT_EQUAL_64(pointer, x2);
1858 ASSERT_EQUAL_64(pointer, x3);
1859
1860 // Pointers corrupted after failing to authenticate.
1861 ASSERT_EQUAL_64(0x0020000012345678, x4);
1862 ASSERT_EQUAL_64(0x0040000012345678, x5);
1863 }
1864 }
1865
1866
TEST(pacga_xpaci_xpacd)1867 TEST(pacga_xpaci_xpacd) {
1868 SETUP_WITH_FEATURES(CPUFeatures::kPAuth, CPUFeatures::kPAuthGeneric);
1869
1870 START();
1871
1872 Register pointer = x24;
1873 Register modifier = x25;
1874
1875 __ Mov(pointer, 0x0000000012345678);
1876 __ Mov(modifier, 0x477d469dec0b8760);
1877
1878 // Generate generic PAC.
1879 __ Pacga(x0, pointer, modifier);
1880
1881 // Generate PACs using key A.
1882 __ Mov(x1, pointer);
1883 __ Mov(x2, pointer);
1884 __ Pacia(x1, modifier);
1885 __ Pacda(x2, modifier);
1886
1887 // Strip PACs.
1888 __ Mov(x3, x1);
1889 __ Mov(x4, x2);
1890 __ Xpaci(x3);
1891 __ Xpacd(x4);
1892
1893 // Mask out just the PAC code bits.
1894 // TODO: use Simulator::CalculatePACMask in a nice way.
1895 __ And(x0, x0, 0xffffffff00000000);
1896 __ And(x1, x1, 0x007f000000000000);
1897 __ And(x2, x2, 0x007f000000000000);
1898
1899 END();
1900
1901 if (CAN_RUN()) {
1902 RUN();
1903
1904
1905 // Check PAC codes have been generated and aren't equal.
1906 // NOTE: with a different ComputePAC implementation, there may be a
1907 // collision.
1908 ASSERT_NOT_EQUAL_64(0, x0);
1909
1910 ASSERT_NOT_EQUAL_64(0, x1);
1911 ASSERT_NOT_EQUAL_64(0, x2);
1912 ASSERT_NOT_EQUAL_64(x1, x2);
1913
1914 ASSERT_EQUAL_64(pointer, x3);
1915 ASSERT_EQUAL_64(pointer, x4);
1916 }
1917 }
1918
TEST(pac_sp_modifier)1919 TEST(pac_sp_modifier) {
1920 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1921
1922 START();
1923
1924 __ Mov(x0, 0x0000000012345678);
1925 __ Mov(x1, x0);
1926 __ Mov(x10, sp);
1927
1928 // Generate PACs using sp and register containing a copy of sp.
1929 __ Pacia(x0, x10);
1930 __ Pacia(x1, sp);
1931
1932 // Authenticate the pointers, exchanging (equal) modifiers.
1933 __ Mov(x2, x0);
1934 __ Mov(x3, x1);
1935 __ Autia(x2, sp);
1936 __ Autia(x3, x10);
1937
1938 END();
1939
1940 if (CAN_RUN()) {
1941 RUN();
1942
1943 ASSERT_EQUAL_64(x0, x1);
1944 ASSERT_EQUAL_64(x2, x3);
1945 }
1946 }
1947
TEST(label)1948 TEST(label) {
1949 SETUP();
1950
1951 Label label_1, label_2, label_3, label_4;
1952
1953 START();
1954 __ Mov(x0, 0x1);
1955 __ Mov(x1, 0x0);
1956 __ Mov(x22, lr); // Save lr.
1957
1958 __ B(&label_1);
1959 __ B(&label_1);
1960 __ B(&label_1); // Multiple branches to the same label.
1961 __ Mov(x0, 0x0);
1962 __ Bind(&label_2);
1963 __ B(&label_3); // Forward branch.
1964 __ Mov(x0, 0x0);
1965 __ Bind(&label_1);
1966 __ B(&label_2); // Backward branch.
1967 __ Mov(x0, 0x0);
1968 __ Bind(&label_3);
1969 __ Bl(&label_4);
1970 END();
1971
1972 __ Bind(&label_4);
1973 __ Mov(x1, 0x1);
1974 __ Mov(lr, x22);
1975 END();
1976
1977 if (CAN_RUN()) {
1978 RUN();
1979
1980 ASSERT_EQUAL_64(0x1, x0);
1981 ASSERT_EQUAL_64(0x1, x1);
1982 }
1983 }
1984
1985
TEST(label_2)1986 TEST(label_2) {
1987 SETUP();
1988
1989 Label label_1, label_2, label_3;
1990 Label first_jump_to_3;
1991
1992 START();
1993 __ Mov(x0, 0x0);
1994
1995 __ B(&label_1);
1996 ptrdiff_t offset_2 = masm.GetCursorOffset();
1997 __ Orr(x0, x0, 1 << 1);
1998 __ B(&label_3);
1999 ptrdiff_t offset_1 = masm.GetCursorOffset();
2000 __ Orr(x0, x0, 1 << 0);
2001 __ B(&label_2);
2002 ptrdiff_t offset_3 = masm.GetCursorOffset();
2003 __ Tbz(x0, 2, &first_jump_to_3);
2004 __ Orr(x0, x0, 1 << 3);
2005 __ Bind(&first_jump_to_3);
2006 __ Orr(x0, x0, 1 << 2);
2007 __ Tbz(x0, 3, &label_3);
2008
2009 // Labels 1, 2, and 3 are bound before the current buffer offset. Branches to
2010 // label_1 and label_2 branch respectively forward and backward. Branches to
2011 // label 3 include both forward and backward branches.
2012 masm.BindToOffset(&label_1, offset_1);
2013 masm.BindToOffset(&label_2, offset_2);
2014 masm.BindToOffset(&label_3, offset_3);
2015
2016 END();
2017
2018 if (CAN_RUN()) {
2019 RUN();
2020
2021 ASSERT_EQUAL_64(0xf, x0);
2022 }
2023 }
2024
2025
TEST(adr)2026 TEST(adr) {
2027 SETUP();
2028
2029 Label label_1, label_2, label_3, label_4;
2030
2031 START();
2032 __ Mov(x0, 0x0); // Set to non-zero to indicate failure.
2033 __ Adr(x1, &label_3); // Set to zero to indicate success.
2034
2035 __ Adr(x2, &label_1); // Multiple forward references to the same label.
2036 __ Adr(x3, &label_1);
2037 __ Adr(x4, &label_1);
2038
2039 __ Bind(&label_2);
2040 __ Eor(x5, x2, Operand(x3)); // Ensure that x2,x3 and x4 are identical.
2041 __ Eor(x6, x2, Operand(x4));
2042 __ Orr(x0, x0, Operand(x5));
2043 __ Orr(x0, x0, Operand(x6));
2044 __ Br(x2); // label_1, label_3
2045
2046 __ Bind(&label_3);
2047 __ Adr(x2, &label_3); // Self-reference (offset 0).
2048 __ Eor(x1, x1, Operand(x2));
2049 __ Adr(x2, &label_4); // Simple forward reference.
2050 __ Br(x2); // label_4
2051
2052 __ Bind(&label_1);
2053 __ Adr(x2, &label_3); // Multiple reverse references to the same label.
2054 __ Adr(x3, &label_3);
2055 __ Adr(x4, &label_3);
2056 __ Adr(x5, &label_2); // Simple reverse reference.
2057 __ Br(x5); // label_2
2058
2059 __ Bind(&label_4);
2060 END();
2061
2062 if (CAN_RUN()) {
2063 RUN();
2064
2065 ASSERT_EQUAL_64(0x0, x0);
2066 ASSERT_EQUAL_64(0x0, x1);
2067 }
2068 }
2069
2070
2071 // Simple adrp tests: check that labels are linked and handled properly.
2072 // This is similar to the adr test, but all the adrp instructions are put on the
2073 // same page so that they return the same value.
TEST(adrp)2074 TEST(adrp) {
2075 Label start;
2076 Label label_1, label_2, label_3;
2077
2078 SETUP_CUSTOM(2 * kPageSize, PageOffsetDependentCode);
2079 START();
2080
2081 // Waste space until the start of a page.
2082 {
2083 ExactAssemblyScope scope(&masm,
2084 kPageSize,
2085 ExactAssemblyScope::kMaximumSize);
2086 const uintptr_t kPageOffsetMask = kPageSize - 1;
2087 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2088 __ b(&start);
2089 }
2090 __ bind(&start);
2091 }
2092
2093 // Simple forward reference.
2094 __ Adrp(x0, &label_2);
2095
2096 __ Bind(&label_1);
2097
2098 // Multiple forward references to the same label.
2099 __ Adrp(x1, &label_3);
2100 __ Adrp(x2, &label_3);
2101 __ Adrp(x3, &label_3);
2102
2103 __ Bind(&label_2);
2104
2105 // Self-reference (offset 0).
2106 __ Adrp(x4, &label_2);
2107
2108 __ Bind(&label_3);
2109
2110 // Simple reverse reference.
2111 __ Adrp(x5, &label_1);
2112
2113 // Multiple reverse references to the same label.
2114 __ Adrp(x6, &label_2);
2115 __ Adrp(x7, &label_2);
2116 __ Adrp(x8, &label_2);
2117
2118 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&start) < kPageSize);
2119 END();
2120 if (CAN_RUN()) {
2121 RUN();
2122
2123 uint64_t expected = reinterpret_cast<uint64_t>(
2124 AlignDown(masm.GetLabelAddress<uint64_t*>(&start), kPageSize));
2125 ASSERT_EQUAL_64(expected, x0);
2126 ASSERT_EQUAL_64(expected, x1);
2127 ASSERT_EQUAL_64(expected, x2);
2128 ASSERT_EQUAL_64(expected, x3);
2129 ASSERT_EQUAL_64(expected, x4);
2130 ASSERT_EQUAL_64(expected, x5);
2131 ASSERT_EQUAL_64(expected, x6);
2132 ASSERT_EQUAL_64(expected, x7);
2133 ASSERT_EQUAL_64(expected, x8);
2134 }
2135 }
2136
2137
AdrpPageBoundaryHelper(unsigned offset_into_page)2138 static void AdrpPageBoundaryHelper(unsigned offset_into_page) {
2139 VIXL_ASSERT(offset_into_page < kPageSize);
2140 VIXL_ASSERT((offset_into_page % kInstructionSize) == 0);
2141
2142 const uintptr_t kPageOffsetMask = kPageSize - 1;
2143
2144 // The test label is always bound on page 0. Adrp instructions are generated
2145 // on pages from kStartPage to kEndPage (inclusive).
2146 const int kStartPage = -16;
2147 const int kEndPage = 16;
2148 const int kMaxCodeSize = (kEndPage - kStartPage + 2) * kPageSize;
2149
2150 SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
2151 START();
2152
2153 Label test;
2154 Label start;
2155
2156 {
2157 ExactAssemblyScope scope(&masm,
2158 kMaxCodeSize,
2159 ExactAssemblyScope::kMaximumSize);
2160 // Initialize NZCV with `eq` flags.
2161 __ cmp(wzr, wzr);
2162 // Waste space until the start of a page.
2163 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2164 __ b(&start);
2165 }
2166
2167 // The first page.
2168 VIXL_STATIC_ASSERT(kStartPage < 0);
2169 {
2170 ExactAssemblyScope scope_page(&masm, kPageSize);
2171 __ bind(&start);
2172 __ adrp(x0, &test);
2173 __ adrp(x1, &test);
2174 for (size_t i = 2; i < (kPageSize / kInstructionSize); i += 2) {
2175 __ ccmp(x0, x1, NoFlag, eq);
2176 __ adrp(x1, &test);
2177 }
2178 }
2179
2180 // Subsequent pages.
2181 VIXL_STATIC_ASSERT(kEndPage >= 0);
2182 for (int page = (kStartPage + 1); page <= kEndPage; page++) {
2183 ExactAssemblyScope scope_page(&masm, kPageSize);
2184 if (page == 0) {
2185 for (size_t i = 0; i < (kPageSize / kInstructionSize);) {
2186 if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
2187 __ ccmp(x0, x1, NoFlag, eq);
2188 if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
2189 __ adrp(x1, &test);
2190 }
2191 } else {
2192 for (size_t i = 0; i < (kPageSize / kInstructionSize); i += 2) {
2193 __ ccmp(x0, x1, NoFlag, eq);
2194 __ adrp(x1, &test);
2195 }
2196 }
2197 }
2198 }
2199
2200 // Every adrp instruction pointed to the same label (`test`), so they should
2201 // all have produced the same result.
2202
2203 END();
2204 if (CAN_RUN()) {
2205 RUN();
2206
2207 uintptr_t expected =
2208 AlignDown(masm.GetLabelAddress<uintptr_t>(&test), kPageSize);
2209 ASSERT_EQUAL_64(expected, x0);
2210 ASSERT_EQUAL_64(expected, x1);
2211 ASSERT_EQUAL_NZCV(ZCFlag);
2212 }
2213 }
2214
2215
2216 // Test that labels are correctly referenced by adrp across page boundaries.
2217 TEST(adrp_page_boundaries) {
2218 VIXL_STATIC_ASSERT(kPageSize == 4096);
2219 AdrpPageBoundaryHelper(kInstructionSize * 0);
2220 AdrpPageBoundaryHelper(kInstructionSize * 1);
2221 AdrpPageBoundaryHelper(kInstructionSize * 512);
2222 AdrpPageBoundaryHelper(kInstructionSize * 1022);
2223 AdrpPageBoundaryHelper(kInstructionSize * 1023);
2224 }
2225
2226
2227 static void AdrpOffsetHelper(int64_t offset) {
2228 const size_t kPageOffsetMask = kPageSize - 1;
2229 const int kMaxCodeSize = 2 * kPageSize;
2230
2231 SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
2232 START();
2233
2234 Label page;
2235
2236 {
2237 ExactAssemblyScope scope(&masm,
2238 kMaxCodeSize,
2239 ExactAssemblyScope::kMaximumSize);
2240 // Initialize NZCV with `eq` flags.
2241 __ cmp(wzr, wzr);
2242 // Waste space until the start of a page.
2243 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2244 __ b(&page);
2245 }
2246 __ bind(&page);
2247
2248 {
2249 ExactAssemblyScope scope_page(&masm, kPageSize);
2250 // Every adrp instruction on this page should return the same value.
2251 __ adrp(x0, offset);
2252 __ adrp(x1, offset);
2253 for (size_t i = 2; i < kPageSize / kInstructionSize; i += 2) {
2254 __ ccmp(x0, x1, NoFlag, eq);
2255 __ adrp(x1, offset);
2256 }
2257 }
2258 }
2259
2260 END();
2261 if (CAN_RUN()) {
2262 RUN();
2263
2264 uintptr_t expected =
2265 masm.GetLabelAddress<uintptr_t>(&page) + (kPageSize * offset);
2266 ASSERT_EQUAL_64(expected, x0);
2267 ASSERT_EQUAL_64(expected, x1);
2268 ASSERT_EQUAL_NZCV(ZCFlag);
2269 }
2270 }
2271
2272
2273 // Check that adrp produces the correct result for a specific offset.
2274 TEST(adrp_offset) {
2275 AdrpOffsetHelper(0);
2276 AdrpOffsetHelper(1);
2277 AdrpOffsetHelper(-1);
2278 AdrpOffsetHelper(4);
2279 AdrpOffsetHelper(-4);
2280 AdrpOffsetHelper(0x000fffff);
2281 AdrpOffsetHelper(-0x000fffff);
2282 AdrpOffsetHelper(-0x00100000);
2283 }
2284
2285
2286 TEST(branch_cond) {
2287 SETUP();
2288
2289 Label done, wrong;
2290
2291 START();
2292 __ Mov(x0, 0x1);
2293 __ Mov(x1, 0x1);
2294 __ Mov(x2, 0x8000000000000000);
2295
2296 // For each 'cmp' instruction below, condition codes other than the ones
2297 // following it would branch.
2298
2299 __ Cmp(x1, 0);
2300 __ B(&wrong, eq);
2301 __ B(&wrong, lo);
2302 __ B(&wrong, mi);
2303 __ B(&wrong, vs);
2304 __ B(&wrong, ls);
2305 __ B(&wrong, lt);
2306 __ B(&wrong, le);
2307 Label ok_1;
2308 __ B(&ok_1, ne);
2309 __ Mov(x0, 0x0);
2310 __ Bind(&ok_1);
2311
2312 __ Cmp(x1, 1);
2313 __ B(&wrong, ne);
2314 __ B(&wrong, lo);
2315 __ B(&wrong, mi);
2316 __ B(&wrong, vs);
2317 __ B(&wrong, hi);
2318 __ B(&wrong, lt);
2319 __ B(&wrong, gt);
2320 Label ok_2;
2321 __ B(&ok_2, pl);
2322 __ Mov(x0, 0x0);
2323 __ Bind(&ok_2);
2324
2325 __ Cmp(x1, 2);
2326 __ B(&wrong, eq);
2327 __ B(&wrong, hs);
2328 __ B(&wrong, pl);
2329 __ B(&wrong, vs);
2330 __ B(&wrong, hi);
2331 __ B(&wrong, ge);
2332 __ B(&wrong, gt);
2333 Label ok_3;
2334 __ B(&ok_3, vc);
2335 __ Mov(x0, 0x0);
2336 __ Bind(&ok_3);
2337
2338 __ Cmp(x2, 1);
2339 __ B(&wrong, eq);
2340 __ B(&wrong, lo);
2341 __ B(&wrong, mi);
2342 __ B(&wrong, vc);
2343 __ B(&wrong, ls);
2344 __ B(&wrong, ge);
2345 __ B(&wrong, gt);
2346 Label ok_4;
2347 __ B(&ok_4, le);
2348 __ Mov(x0, 0x0);
2349 __ Bind(&ok_4);
2350
2351 // The MacroAssembler does not allow al as a branch condition.
2352 Label ok_5;
2353 {
2354 ExactAssemblyScope scope(&masm, kInstructionSize);
2355 __ b(&ok_5, al);
2356 }
2357 __ Mov(x0, 0x0);
2358 __ Bind(&ok_5);
2359
2360 // The MacroAssembler does not allow nv as a branch condition.
2361 Label ok_6;
2362 {
2363 ExactAssemblyScope scope(&masm, kInstructionSize);
2364 __ b(&ok_6, nv);
2365 }
2366 __ Mov(x0, 0x0);
2367 __ Bind(&ok_6);
2368
2369 __ B(&done);
2370
2371 __ Bind(&wrong);
2372 __ Mov(x0, 0x0);
2373
2374 __ Bind(&done);
2375 END();
2376
2377 if (CAN_RUN()) {
2378 RUN();
2379
2380 ASSERT_EQUAL_64(0x1, x0);
2381 }
2382 }
2383
2384
2385 TEST(branch_to_reg) {
2386 SETUP();
2387
2388 // Test br.
2389 Label fn1, after_fn1;
2390
2391 START();
2392 __ Mov(x29, lr);
2393
2394 __ Mov(x1, 0);
2395 __ B(&after_fn1);
2396
2397 __ Bind(&fn1);
2398 __ Mov(x0, lr);
2399 __ Mov(x1, 42);
2400 __ Br(x0);
2401
2402 __ Bind(&after_fn1);
2403 __ Bl(&fn1);
2404
2405 // Test blr.
2406 Label fn2, after_fn2, after_bl2;
2407
2408 __ Mov(x2, 0);
2409 __ B(&after_fn2);
2410
2411 __ Bind(&fn2);
2412 __ Mov(x0, lr);
2413 __ Mov(x2, 84);
2414 __ Blr(x0);
2415
2416 __ Bind(&after_fn2);
2417 __ Bl(&fn2);
2418 __ Bind(&after_bl2);
2419 __ Mov(x3, lr);
2420 __ Adr(x4, &after_bl2);
2421 __ Adr(x5, &after_fn2);
2422
2423 __ Mov(lr, x29);
2424 END();
2425
2426 if (CAN_RUN()) {
2427 RUN();
2428
2429 ASSERT_EQUAL_64(x4, x0);
2430 ASSERT_EQUAL_64(x5, x3);
2431 ASSERT_EQUAL_64(42, x1);
2432 ASSERT_EQUAL_64(84, x2);
2433 }
2434 }
2435
2436 TEST(branch_to_reg_auth_a) {
2437 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2438
2439 START();
2440
2441 Label fn1, after_fn1;
2442
2443 __ Mov(x28, 0x477d469dec0b8760);
2444 __ Mov(x29, lr);
2445
2446 __ Mov(x1, 0);
2447 __ B(&after_fn1);
2448
2449 __ Bind(&fn1);
2450 __ Mov(x0, lr);
2451 __ Mov(x1, 42);
2452 __ Pacia(x0, x28);
2453 __ Braa(x0, x28);
2454
2455 __ Bind(&after_fn1);
2456 __ Bl(&fn1);
2457
2458 Label fn2, after_fn2, after_bl2;
2459
2460 __ Mov(x2, 0);
2461 __ B(&after_fn2);
2462
2463 __ Bind(&fn2);
2464 __ Mov(x0, lr);
2465 __ Mov(x2, 84);
2466 __ Pacia(x0, x28);
2467 __ Blraa(x0, x28);
2468
2469 __ Bind(&after_fn2);
2470 __ Bl(&fn2);
2471 __ Bind(&after_bl2);
2472 __ Mov(x3, lr);
2473 __ Adr(x4, &after_bl2);
2474 __ Adr(x5, &after_fn2);
2475
2476 __ Xpaci(x0);
2477 __ Mov(lr, x29);
2478 END();
2479
2480 if (CAN_RUN()) {
2481 RUN();
2482
2483 ASSERT_EQUAL_64(x4, x0);
2484 ASSERT_EQUAL_64(x5, x3);
2485 ASSERT_EQUAL_64(42, x1);
2486 ASSERT_EQUAL_64(84, x2);
2487 }
2488 }
2489
2490 TEST(return_to_reg_auth) {
2491 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2492
2493 START();
2494
2495 Label fn1, after_fn1;
2496
2497 __ Mov(x28, sp);
2498 __ Mov(x29, lr);
2499 __ Mov(sp, 0x477d469dec0b8760);
2500
2501 __ Mov(x0, 0);
2502 __ B(&after_fn1);
2503
2504 __ Bind(&fn1);
2505 __ Mov(x0, 42);
2506 __ Paciasp();
2507 __ Retaa();
2508
2509 __ Bind(&after_fn1);
2510 __ Bl(&fn1);
2511
2512 Label fn2, after_fn2;
2513
2514 __ Mov(x1, 0);
2515 __ B(&after_fn2);
2516
2517 __ Bind(&fn2);
2518 __ Mov(x1, 84);
2519 __ Pacibsp();
2520 __ Retab();
2521
2522 __ Bind(&after_fn2);
2523 __ Bl(&fn2);
2524
2525 __ Mov(sp, x28);
2526 __ Mov(lr, x29);
2527 END();
2528
2529 if (CAN_RUN()) {
2530 RUN();
2531
2532 ASSERT_EQUAL_64(42, x0);
2533 ASSERT_EQUAL_64(84, x1);
2534 }
2535 }
2536
2537 TEST(return_to_reg_auth_guarded) {
2538 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2539
2540 START();
2541
2542 Label fn1, after_fn1;
2543
2544 __ Mov(x28, sp);
2545 __ Mov(x29, lr);
2546 __ Mov(sp, 0x477d469dec0b8760);
2547
2548 __ Mov(x0, 0);
2549 __ B(&after_fn1);
2550
2551 __ Bind(&fn1, EmitPACIASP);
2552 __ Mov(x0, 42);
2553 __ Retaa();
2554
2555 __ Bind(&after_fn1);
2556 __ Adr(x2, &fn1);
2557 __ Blr(x2);
2558
2559 Label fn2, after_fn2;
2560
2561 __ Mov(x1, 0);
2562 __ B(&after_fn2);
2563
2564 __ Bind(&fn2, EmitPACIBSP);
2565 __ Mov(x1, 84);
2566 __ Retab();
2567
2568 __ Bind(&after_fn2);
2569 __ Adr(x2, &fn2);
2570 __ Blr(x2);
2571
2572 __ Mov(sp, x28);
2573 __ Mov(lr, x29);
2574 END();
2575
2576 if (CAN_RUN()) {
2577 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
2578 simulator.SetGuardedPages(true);
2579 #else
2580 VIXL_UNIMPLEMENTED();
2581 #endif
2582 RUN();
2583
2584 ASSERT_EQUAL_64(42, x0);
2585 ASSERT_EQUAL_64(84, x1);
2586 }
2587 }
2588
2589 #ifdef VIXL_NEGATIVE_TESTING
2590 TEST(branch_to_reg_auth_fail) {
2591 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2592
2593 START();
2594
2595 Label fn1, after_fn1;
2596
2597 __ Mov(x29, lr);
2598
2599 __ B(&after_fn1);
2600
2601 __ Bind(&fn1);
2602 __ Mov(x0, lr);
2603 __ Pacizb(x0);
2604 __ Blraaz(x0);
2605
2606 __ Bind(&after_fn1);
2607 // There is a small but not negligible chance (1 in 127 runs) that the PAC
2608 // codes for keys A and B will collide and BLRAAZ won't abort. To mitigate
2609 // this, we simply repeat the test a few more times.
2610 for (unsigned i = 0; i < 32; i++) {
2611 __ Bl(&fn1);
2612 }
2613
2614 __ Mov(lr, x29);
2615 END();
2616
2617 if (CAN_RUN()) {
2618 MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
2619 }
2620 }
2621 #endif // VIXL_NEGATIVE_TESTING
2622
2623 #ifdef VIXL_NEGATIVE_TESTING
2624 TEST(return_to_reg_auth_fail) {
2625 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2626
2627 START();
2628
2629 Label fn1, after_fn1;
2630
2631 __ Mov(x28, sp);
2632 __ Mov(x29, lr);
2633 __ Mov(sp, 0x477d469dec0b8760);
2634
2635 __ B(&after_fn1);
2636
2637 __ Bind(&fn1);
2638 __ Paciasp();
2639 __ Retab();
2640
2641 __ Bind(&after_fn1);
2642 // There is a small but not negligible chance (1 in 127 runs) that the PAC
2643 // codes for keys A and B will collide and RETAB won't abort. To mitigate
2644 // this, we simply repeat the test a few more times.
2645 for (unsigned i = 0; i < 32; i++) {
2646 __ Bl(&fn1);
2647 }
2648
2649 __ Mov(sp, x28);
2650 __ Mov(lr, x29);
2651 END();
2652
2653 if (CAN_RUN()) {
2654 MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
2655 }
2656 }
2657 #endif // VIXL_NEGATIVE_TESTING
2658
2659 TEST(branch_to_reg_auth_a_zero) {
2660 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2661
2662 START();
2663
2664 Label fn1, after_fn1;
2665
2666 __ Mov(x29, lr);
2667
2668 __ Mov(x1, 0);
2669 __ B(&after_fn1);
2670
2671 __ Bind(&fn1);
2672 __ Mov(x0, lr);
2673 __ Mov(x1, 42);
2674 __ Paciza(x0);
2675 __ Braaz(x0);
2676
2677 __ Bind(&after_fn1);
2678 __ Bl(&fn1);
2679
2680 Label fn2, after_fn2, after_bl2;
2681
2682 __ Mov(x2, 0);
2683 __ B(&after_fn2);
2684
2685 __ Bind(&fn2);
2686 __ Mov(x0, lr);
2687 __ Mov(x2, 84);
2688 __ Paciza(x0);
2689 __ Blraaz(x0);
2690
2691 __ Bind(&after_fn2);
2692 __ Bl(&fn2);
2693 __ Bind(&after_bl2);
2694 __ Mov(x3, lr);
2695 __ Adr(x4, &after_bl2);
2696 __ Adr(x5, &after_fn2);
2697
2698 __ Xpaci(x0);
2699 __ Mov(lr, x29);
2700 END();
2701
2702 if (CAN_RUN()) {
2703 RUN();
2704
2705 ASSERT_EQUAL_64(x4, x0);
2706 ASSERT_EQUAL_64(x5, x3);
2707 ASSERT_EQUAL_64(42, x1);
2708 ASSERT_EQUAL_64(84, x2);
2709 }
2710 }
2711
2712
2713 TEST(compare_branch) {
2714 SETUP();
2715
2716 START();
2717 __ Mov(x0, 0);
2718 __ Mov(x1, 0);
2719 __ Mov(x2, 0);
2720 __ Mov(x3, 0);
2721 __ Mov(x4, 0);
2722 __ Mov(x5, 0);
2723 __ Mov(x16, 0);
2724 __ Mov(x17, 42);
2725
2726 Label zt, zt_end;
2727 __ Cbz(w16, &zt);
2728 __ B(&zt_end);
2729 __ Bind(&zt);
2730 __ Mov(x0, 1);
2731 __ Bind(&zt_end);
2732
2733 Label zf, zf_end;
2734 __ Cbz(x17, &zf);
2735 __ B(&zf_end);
2736 __ Bind(&zf);
2737 __ Mov(x1, 1);
2738 __ Bind(&zf_end);
2739
2740 Label nzt, nzt_end;
2741 __ Cbnz(w17, &nzt);
2742 __ B(&nzt_end);
2743 __ Bind(&nzt);
2744 __ Mov(x2, 1);
2745 __ Bind(&nzt_end);
2746
2747 Label nzf, nzf_end;
2748 __ Cbnz(x16, &nzf);
2749 __ B(&nzf_end);
2750 __ Bind(&nzf);
2751 __ Mov(x3, 1);
2752 __ Bind(&nzf_end);
2753
2754 __ Mov(x18, 0xffffffff00000000);
2755
2756 Label a, a_end;
2757 __ Cbz(w18, &a);
2758 __ B(&a_end);
2759 __ Bind(&a);
2760 __ Mov(x4, 1);
2761 __ Bind(&a_end);
2762
2763 Label b, b_end;
2764 __ Cbnz(w18, &b);
2765 __ B(&b_end);
2766 __ Bind(&b);
2767 __ Mov(x5, 1);
2768 __ Bind(&b_end);
2769
2770 END();
2771
2772 if (CAN_RUN()) {
2773 RUN();
2774
2775 ASSERT_EQUAL_64(1, x0);
2776 ASSERT_EQUAL_64(0, x1);
2777 ASSERT_EQUAL_64(1, x2);
2778 ASSERT_EQUAL_64(0, x3);
2779 ASSERT_EQUAL_64(1, x4);
2780 ASSERT_EQUAL_64(0, x5);
2781 }
2782 }
2783
2784
2785 TEST(test_branch) {
2786 SETUP();
2787
2788 START();
2789 __ Mov(x0, 0);
2790 __ Mov(x1, 0);
2791 __ Mov(x2, 0);
2792 __ Mov(x3, 0);
2793 __ Mov(x16, 0xaaaaaaaaaaaaaaaa);
2794
2795 Label bz, bz_end;
2796 __ Tbz(w16, 0, &bz);
2797 __ B(&bz_end);
2798 __ Bind(&bz);
2799 __ Mov(x0, 1);
2800 __ Bind(&bz_end);
2801
2802 Label bo, bo_end;
2803 __ Tbz(x16, 63, &bo);
2804 __ B(&bo_end);
2805 __ Bind(&bo);
2806 __ Mov(x1, 1);
2807 __ Bind(&bo_end);
2808
2809 Label nbz, nbz_end;
2810 __ Tbnz(x16, 61, &nbz);
2811 __ B(&nbz_end);
2812 __ Bind(&nbz);
2813 __ Mov(x2, 1);
2814 __ Bind(&nbz_end);
2815
2816 Label nbo, nbo_end;
2817 __ Tbnz(w16, 2, &nbo);
2818 __ B(&nbo_end);
2819 __ Bind(&nbo);
2820 __ Mov(x3, 1);
2821 __ Bind(&nbo_end);
2822 END();
2823
2824 if (CAN_RUN()) {
2825 RUN();
2826
2827 ASSERT_EQUAL_64(1, x0);
2828 ASSERT_EQUAL_64(0, x1);
2829 ASSERT_EQUAL_64(1, x2);
2830 ASSERT_EQUAL_64(0, x3);
2831 }
2832 }
2833
2834
2835 TEST(branch_type) {
2836 SETUP();
2837
2838 Label fail, done;
2839
2840 START();
2841 __ Mov(x0, 0x0);
2842 __ Mov(x10, 0x7);
2843 __ Mov(x11, 0x0);
2844
2845 // Test non taken branches.
2846 __ Cmp(x10, 0x7);
2847 __ B(&fail, ne);
2848 __ B(&fail, never);
2849 __ B(&fail, reg_zero, x10);
2850 __ B(&fail, reg_not_zero, x11);
2851 __ B(&fail, reg_bit_clear, x10, 0);
2852 __ B(&fail, reg_bit_set, x10, 3);
2853
2854 // Test taken branches.
2855 Label l1, l2, l3, l4, l5;
2856 __ Cmp(x10, 0x7);
2857 __ B(&l1, eq);
2858 __ B(&fail);
2859 __ Bind(&l1);
2860 __ B(&l2, always);
2861 __ B(&fail);
2862 __ Bind(&l2);
2863 __ B(&l3, reg_not_zero, x10);
2864 __ B(&fail);
2865 __ Bind(&l3);
2866 __ B(&l4, reg_bit_clear, x10, 15);
2867 __ B(&fail);
2868 __ Bind(&l4);
2869 __ B(&l5, reg_bit_set, x10, 1);
2870 __ B(&fail);
2871 __ Bind(&l5);
2872
2873 __ B(&done);
2874
2875 __ Bind(&fail);
2876 __ Mov(x0, 0x1);
2877
2878 __ Bind(&done);
2879
2880 END();
2881
2882 if (CAN_RUN()) {
2883 RUN();
2884
2885 ASSERT_EQUAL_64(0x0, x0);
2886 }
2887 }
2888
2889 enum MTEStgAttribute {
2890 StgNoSideEffect = 0,
2891 StgPairTag = 1,
2892 StgZeroing = 2,
2893 StgPairReg = 4
2894 };
2895
2896 // Support st2g, stg, stz2g and stzg.
2897 template <typename Op>
2898 static void MTEStoreTagHelper(Op op,
2899 AddrMode addr_mode,
2900 int attr = StgNoSideEffect) {
2901 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
2902 START();
2903
2904 // This method does nothing when the size is zero. i.e. stg and st2g.
2905 // Reserve x9 and x10.
2906 auto LoadDataAndSum = [&](Register reg, int off, unsigned size_in_bytes) {
2907 for (unsigned j = 0; j < size_in_bytes / kXRegSizeInBytes; j++) {
2908 __ Ldr(x9, MemOperand(reg, off));
2909 __ Add(x10, x9, x10);
2910 off += kXRegSizeInBytes;
2911 }
2912 };
2913
2914 // Initialize registers to zero.
2915 for (int i = 0; i < 29; i++) {
2916 __ Mov(XRegister(i), 0);
2917 }
2918
2919 Register base = x28;
2920 Register base_tag = x27;
2921 uint32_t* data_ptr = nullptr;
2922 const int data_size = 640;
2923 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
2924 data_ptr = reinterpret_cast<uint32_t*>(
2925 simulator.Mmap(NULL,
2926 data_size * sizeof(uint32_t),
2927 PROT_READ | PROT_WRITE | PROT_MTE,
2928 MAP_PRIVATE | MAP_ANONYMOUS,
2929 -1,
2930 0));
2931
2932 VIXL_ASSERT(data_ptr != nullptr);
2933 uint32_t* untagged_ptr = AddressUntag(data_ptr);
2934 memset(untagged_ptr, 0xae, data_size * sizeof(uint32_t));
2935 #else
2936 // TODO: Port the memory allocation to work on MTE supported platform natively.
2937 // Note that `CAN_RUN` prevents running in MTE-unsupported environments.
2938 #endif
2939
2940 __ Mov(base, reinterpret_cast<uint64_t>(&data_ptr[data_size / 2]));
2941
2942 VIXL_STATIC_ASSERT(kMTETagGranuleInBytes == 16);
2943 const int tag_granule = kMTETagGranuleInBytes;
2944 int size = ((attr & StgZeroing) != 0) ? tag_granule : 0;
2945 // lsb of MTE tag field.
2946 const int tag_lsb = 56;
2947
2948 for (int i = 1; i < 7; i++) {
2949 uint64_t tag = static_cast<uint64_t>(i) << tag_lsb;
2950 int offset = 2 * i * tag_granule;
2951 __ Mov(XRegister(i), tag);
2952 (masm.*op)(XRegister(i), MemOperand(base, offset, addr_mode));
2953
2954 // The address tag has been changed after the execution of store tag
2955 // instructions, so update the pointer tag as well.
2956 __ Bic(base_tag, base, 0x0f00000000000000);
2957 __ Orr(base_tag, base_tag, XRegister(i));
2958
2959 switch (addr_mode) {
2960 case Offset:
2961 __ Ldg(XRegister(i + 10), MemOperand(base_tag, offset));
2962 LoadDataAndSum(base_tag, offset, size);
2963 if ((attr & StgPairTag) != 0) {
2964 __ Ldg(XRegister(i + 20), MemOperand(base_tag, offset + tag_granule));
2965 LoadDataAndSum(base_tag, offset + tag_granule, size);
2966 }
2967 break;
2968
2969 case PreIndex:
2970 __ Ldg(XRegister(i + 10), MemOperand(base_tag));
2971 LoadDataAndSum(base_tag, 0, size);
2972 if ((attr & StgPairTag) != 0) {
2973 __ Ldg(XRegister(i + 20), MemOperand(base_tag, tag_granule));
2974 LoadDataAndSum(base_tag, tag_granule, size);
2975 }
2976 break;
2977
2978 case PostIndex:
2979 __ Ldg(XRegister(i + 10), MemOperand(base_tag, -offset));
2980 LoadDataAndSum(base_tag, -offset, size);
2981 if ((attr & StgPairTag) != 0) {
2982 __ Ldg(XRegister(i + 20),
2983 MemOperand(base_tag, -offset + tag_granule));
2984 LoadDataAndSum(base_tag, -offset + tag_granule, size);
2985 }
2986 break;
2987
2988 default:
2989 VIXL_UNIMPLEMENTED();
2990 break;
2991 }
2992
2993 // Switch the sign to test both positive and negative offsets.
2994 offset = -offset;
2995 }
2996
2997 int pos_offset = 304;
2998 int neg_offset = -256;
2999
3000 // Backup stack pointer and others.
3001 __ Mov(x7, sp);
3002 __ Mov(base_tag, base);
3003
3004 // Test the cases where operand is the stack pointer.
3005 __ Mov(x8, 11UL << tag_lsb);
3006 __ Mov(sp, x8);
3007 (masm.*op)(sp, MemOperand(base, neg_offset, addr_mode));
3008
3009 // Synthesise a new address with new tag and assign to the stack pointer.
3010 __ Add(sp, base_tag, 32);
3011 (masm.*op)(x8, MemOperand(sp, pos_offset, addr_mode));
3012
3013 switch (addr_mode) {
3014 case Offset:
3015 __ Ldg(x17, MemOperand(base, neg_offset));
3016 __ Ldg(x19, MemOperand(sp, pos_offset));
3017 if ((attr & StgPairTag) != 0) {
3018 __ Ldg(x18, MemOperand(base, neg_offset + tag_granule));
3019 __ Ldg(x20, MemOperand(sp, pos_offset + tag_granule));
3020 }
3021 break;
3022 case PreIndex:
3023 __ Ldg(x17, MemOperand(base));
3024 __ Ldg(x19, MemOperand(sp));
3025 if ((attr & StgPairTag) != 0) {
3026 __ Ldg(x18, MemOperand(base, tag_granule));
3027 __ Ldg(x20, MemOperand(sp, tag_granule));
3028 }
3029 break;
3030 case PostIndex:
3031 __ Ldg(x17, MemOperand(base, -neg_offset));
3032 __ Ldg(x19, MemOperand(sp, -pos_offset));
3033 if ((attr & StgPairTag) != 0) {
3034 __ Ldg(x18, MemOperand(base, -neg_offset + tag_granule));
3035 __ Ldg(x20, MemOperand(sp, -pos_offset + tag_granule));
3036 }
3037 break;
3038 default:
3039 VIXL_UNIMPLEMENTED();
3040 break;
3041 }
3042
3043 // Restore stack pointer.
3044 __ Mov(sp, x7);
3045
3046 END();
3047
3048 if (CAN_RUN()) {
3049 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
3050 VIXL_UNIMPLEMENTED();
3051 #endif
3052 RUN();
3053
3054 ASSERT_EQUAL_64(1UL << tag_lsb, x11);
3055 ASSERT_EQUAL_64(2UL << tag_lsb, x12);
3056 ASSERT_EQUAL_64(3UL << tag_lsb, x13);
3057 ASSERT_EQUAL_64(4UL << tag_lsb, x14);
3058 ASSERT_EQUAL_64(5UL << tag_lsb, x15);
3059 ASSERT_EQUAL_64(6UL << tag_lsb, x16);
3060 ASSERT_EQUAL_64(11UL << tag_lsb, x17);
3061 ASSERT_EQUAL_64(11UL << tag_lsb, x19);
3062
3063 if ((attr & StgPairTag) != 0) {
3064 ASSERT_EQUAL_64(1UL << tag_lsb, x21);
3065 ASSERT_EQUAL_64(2UL << tag_lsb, x22);
3066 ASSERT_EQUAL_64(3UL << tag_lsb, x23);
3067 ASSERT_EQUAL_64(4UL << tag_lsb, x24);
3068 ASSERT_EQUAL_64(5UL << tag_lsb, x25);
3069 ASSERT_EQUAL_64(6UL << tag_lsb, x26);
3070 ASSERT_EQUAL_64(11UL << tag_lsb, x18);
3071 ASSERT_EQUAL_64(11UL << tag_lsb, x20);
3072 }
3073
3074 if ((attr & StgZeroing) != 0) {
3075 ASSERT_EQUAL_64(0, x10);
3076 }
3077 }
3078
3079 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3080 simulator.Munmap(data_ptr, data_size, PROT_MTE);
3081 #endif
3082 }
3083
3084 TEST(st2g_ldg) {
3085 MTEStoreTagHelper(&MacroAssembler::St2g, Offset, StgPairTag);
3086 MTEStoreTagHelper(&MacroAssembler::St2g, PreIndex, StgPairTag);
3087 MTEStoreTagHelper(&MacroAssembler::St2g, PostIndex, StgPairTag);
3088 }
3089
3090 TEST(stg_ldg) {
3091 MTEStoreTagHelper(&MacroAssembler::Stg, Offset);
3092 MTEStoreTagHelper(&MacroAssembler::Stg, PreIndex);
3093 MTEStoreTagHelper(&MacroAssembler::Stg, PostIndex);
3094 }
3095
3096 TEST(stz2g_ldg) {
3097 MTEStoreTagHelper(&MacroAssembler::Stz2g, Offset, StgPairTag | StgZeroing);
3098 MTEStoreTagHelper(&MacroAssembler::Stz2g, PreIndex, StgPairTag | StgZeroing);
3099 MTEStoreTagHelper(&MacroAssembler::Stz2g, PostIndex, StgPairTag | StgZeroing);
3100 }
3101
3102 TEST(stzg_ldg) {
3103 MTEStoreTagHelper(&MacroAssembler::Stzg, Offset, StgZeroing);
3104 MTEStoreTagHelper(&MacroAssembler::Stzg, PreIndex, StgZeroing);
3105 MTEStoreTagHelper(&MacroAssembler::Stzg, PostIndex, StgZeroing);
3106 }
3107
3108 TEST(stgp_ldg) {
3109 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
3110 START();
3111
3112 // Initialize registers to zero.
3113 for (int i = 0; i < 29; i++) {
3114 __ Mov(XRegister(i), 0);
3115 }
3116
3117 // Reserve x14 and x15.
3118 auto LoadDataAndSum = [&](Register reg, int off) {
3119 __ Ldr(x14, MemOperand(reg, off));
3120 __ Add(x15, x14, x15);
3121 __ Ldr(x14, MemOperand(reg, off + static_cast<int>(kXRegSizeInBytes)));
3122 __ Add(x15, x14, x15);
3123 };
3124
3125 Register base = x28;
3126 uint32_t* data_ptr = nullptr;
3127 const int data_size = 640;
3128 uint64_t init_tag = 17;
3129 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3130 data_ptr = reinterpret_cast<uint32_t*>(
3131 simulator.Mmap(NULL,
3132 data_size * sizeof(uint32_t),
3133 PROT_READ | PROT_WRITE | PROT_MTE,
3134 MAP_PRIVATE | MAP_ANONYMOUS,
3135 -1,
3136 0));
3137
3138 VIXL_ASSERT(data_ptr != nullptr);
3139 init_tag = CPU::GetPointerTag(data_ptr);
3140 uint32_t* untagged_ptr = AddressUntag(data_ptr);
3141 memset(untagged_ptr, 0xc9, data_size * sizeof(uint32_t));
3142 #else
3143 // TODO: Port the memory allocation to work on MTE supported platform natively.
3144 // Note that `CAN_RUN` prevents running in MTE-unsupported environments.
3145 #endif
3146
3147 __ Mov(base, reinterpret_cast<uint64_t>(&data_ptr[data_size / 2]));
3148
3149 // lsb of MTE tag field.
3150 const int tag_lsb = 56;
3151 for (int i = 0; i < 11; i++) {
3152 // <63..60> <59..56> <55........5> <4..0>
3153 // 0 i 0 i
3154 __ Mov(XRegister(i), i | (static_cast<uint64_t>(i) << tag_lsb));
3155 }
3156
3157 // Backup stack pointer.
3158 __ Mov(x0, sp);
3159
3160 int offset = -16;
3161 __ Addg(base, base, 0, 1);
3162 __ Stgp(x1, x2, MemOperand(base, offset, Offset));
3163 // Make sure `ldg` works well with address that isn't tag-granule aligned.
3164 __ Add(x29, base, 8);
3165 __ Ldg(x18, MemOperand(x29, offset));
3166 LoadDataAndSum(base, offset);
3167
3168 offset = -304;
3169 __ Addg(base, base, 0, 1);
3170 __ Stgp(x2, x3, MemOperand(base, offset, Offset));
3171 __ Add(x29, base, 4);
3172 __ Ldg(x19, MemOperand(x29, offset));
3173 LoadDataAndSum(base, offset);
3174
3175 offset = 128;
3176 __ Addg(base, base, 0, 1);
3177 __ Stgp(x3, x4, MemOperand(base, offset, Offset));
3178 __ Mov(sp, base);
3179 __ Ldg(x20, MemOperand(sp, offset));
3180 LoadDataAndSum(base, offset);
3181
3182 offset = -48;
3183 __ Addg(base, base, 0, 1);
3184 __ Stgp(x4, x5, MemOperand(base, offset, PreIndex));
3185 __ Add(x29, base, 8);
3186 __ Ldg(x21, MemOperand(x29));
3187 LoadDataAndSum(base, 0);
3188
3189 offset = 64;
3190 __ Addg(base, base, 0, 1);
3191 __ Stgp(x5, x6, MemOperand(base, offset, PreIndex));
3192 __ Add(x29, base, 4);
3193 __ Ldg(x22, MemOperand(x29));
3194 LoadDataAndSum(base, 0);
3195
3196 offset = -288;
3197 __ Addg(base, base, 0, 1);
3198 __ Stgp(x6, x7, MemOperand(base, offset, PreIndex));
3199 __ Mov(sp, base);
3200 __ Ldg(x23, MemOperand(sp));
3201 LoadDataAndSum(base, 0);
3202
3203 offset = -96;
3204 __ Addg(base, base, 0, 1);
3205 __ Stgp(x7, x8, MemOperand(base, offset, PostIndex));
3206 __ Add(x29, base, 8);
3207 __ Ldg(x24, MemOperand(x29, -offset));
3208 LoadDataAndSum(base, -offset);
3209
3210 offset = 80;
3211 __ Addg(base, base, 0, 1);
3212 __ Stgp(x8, x9, MemOperand(base, offset, PostIndex));
3213 __ Add(x29, base, 4);
3214 __ Ldg(x25, MemOperand(x29, -offset));
3215 LoadDataAndSum(base, -offset);
3216
3217 offset = -224;
3218 __ Addg(base, base, 0, 1);
3219 __ Stgp(x9, x10, MemOperand(base, offset, PostIndex));
3220 __ Mov(sp, base);
3221 __ Ldg(x26, MemOperand(sp, -offset));
3222 LoadDataAndSum(base, -offset);
3223
3224 __ Mov(sp, x0);
3225
3226 END();
3227
3228 if (CAN_RUN()) {
3229 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
3230 VIXL_UNIMPLEMENTED();
3231 #endif
3232 RUN();
3233
3234 const uint64_t k = kMTETagGranuleInBytes;
3235 USE(k);
3236 ASSERT_EQUAL_64(((init_tag + 1) % k) << tag_lsb, x18);
3237 ASSERT_EQUAL_64(((init_tag + 2) % k) << tag_lsb, x19);
3238 ASSERT_EQUAL_64(((init_tag + 3) % k) << tag_lsb, x20);
3239 ASSERT_EQUAL_64(((init_tag + 4) % k) << tag_lsb, x21);
3240 ASSERT_EQUAL_64(((init_tag + 5) % k) << tag_lsb, x22);
3241 ASSERT_EQUAL_64(((init_tag + 6) % k) << tag_lsb, x23);
3242 ASSERT_EQUAL_64(((init_tag + 7) % k) << tag_lsb, x24);
3243 ASSERT_EQUAL_64(((init_tag + 8) % k) << tag_lsb, x25);
3244 ASSERT_EQUAL_64(((init_tag + 9) % k) << tag_lsb, x26);
3245
3246 // We store 1, 2, 2, 3, 3, 4, ....9, 9, 10 to memory, so the total sum of
3247 // these values is 1 + (2 * (2 + 9) * 8 / 2) + 10 = 99.
3248 ASSERT_EQUAL_64((99UL << tag_lsb | 99UL), x15);
3249 }
3250
3251 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3252 simulator.Munmap(data_ptr, data_size, PROT_MTE);
3253 #endif
3254 }
3255
3256 TEST(ldr_str_offset) {
3257 SETUP();
3258
3259 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3260 uint64_t dst[5] = {0, 0, 0, 0, 0};
3261 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3262 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3263
3264 START();
3265 __ Mov(x17, src_base);
3266 __ Mov(x18, dst_base);
3267 __ Ldr(w0, MemOperand(x17));
3268 __ Str(w0, MemOperand(x18));
3269 __ Ldr(w1, MemOperand(x17, 4));
3270 __ Str(w1, MemOperand(x18, 12));
3271 __ Ldr(x2, MemOperand(x17, 8));
3272 __ Str(x2, MemOperand(x18, 16));
3273 __ Ldrb(w3, MemOperand(x17, 1));
3274 __ Strb(w3, MemOperand(x18, 25));
3275 __ Ldrh(w4, MemOperand(x17, 2));
3276 __ Strh(w4, MemOperand(x18, 33));
3277 END();
3278
3279 if (CAN_RUN()) {
3280 RUN();
3281
3282 ASSERT_EQUAL_64(0x76543210, x0);
3283 ASSERT_EQUAL_64(0x76543210, dst[0]);
3284 ASSERT_EQUAL_64(0xfedcba98, x1);
3285 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3286 ASSERT_EQUAL_64(0x0123456789abcdef, x2);
3287 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3288 ASSERT_EQUAL_64(0x32, x3);
3289 ASSERT_EQUAL_64(0x3200, dst[3]);
3290 ASSERT_EQUAL_64(0x7654, x4);
3291 ASSERT_EQUAL_64(0x765400, dst[4]);
3292 ASSERT_EQUAL_64(src_base, x17);
3293 ASSERT_EQUAL_64(dst_base, x18);
3294 }
3295 }
3296
3297
3298 TEST(ldr_str_wide) {
3299 SETUP();
3300
3301 uint32_t src[8192];
3302 uint32_t dst[8192];
3303 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3304 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3305 memset(src, 0xaa, 8192 * sizeof(src[0]));
3306 memset(dst, 0xaa, 8192 * sizeof(dst[0]));
3307 src[0] = 0;
3308 src[6144] = 6144;
3309 src[8191] = 8191;
3310
3311 START();
3312 __ Mov(x22, src_base);
3313 __ Mov(x23, dst_base);
3314 __ Mov(x24, src_base);
3315 __ Mov(x25, dst_base);
3316 __ Mov(x26, src_base);
3317 __ Mov(x27, dst_base);
3318
3319 __ Ldr(w0, MemOperand(x22, 8191 * sizeof(src[0])));
3320 __ Str(w0, MemOperand(x23, 8191 * sizeof(dst[0])));
3321 __ Ldr(w1, MemOperand(x24, 4096 * sizeof(src[0]), PostIndex));
3322 __ Str(w1, MemOperand(x25, 4096 * sizeof(dst[0]), PostIndex));
3323 __ Ldr(w2, MemOperand(x26, 6144 * sizeof(src[0]), PreIndex));
3324 __ Str(w2, MemOperand(x27, 6144 * sizeof(dst[0]), PreIndex));
3325 END();
3326
3327 if (CAN_RUN()) {
3328 RUN();
3329
3330 ASSERT_EQUAL_32(8191, w0);
3331 ASSERT_EQUAL_32(8191, dst[8191]);
3332 ASSERT_EQUAL_64(src_base, x22);
3333 ASSERT_EQUAL_64(dst_base, x23);
3334 ASSERT_EQUAL_32(0, w1);
3335 ASSERT_EQUAL_32(0, dst[0]);
3336 ASSERT_EQUAL_64(src_base + 4096 * sizeof(src[0]), x24);
3337 ASSERT_EQUAL_64(dst_base + 4096 * sizeof(dst[0]), x25);
3338 ASSERT_EQUAL_32(6144, w2);
3339 ASSERT_EQUAL_32(6144, dst[6144]);
3340 ASSERT_EQUAL_64(src_base + 6144 * sizeof(src[0]), x26);
3341 ASSERT_EQUAL_64(dst_base + 6144 * sizeof(dst[0]), x27);
3342 }
3343 }
3344
3345
3346 TEST(ldr_str_preindex) {
3347 SETUP();
3348
3349 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3350 uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
3351 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3352 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3353
3354 START();
3355 __ Mov(x17, src_base);
3356 __ Mov(x18, dst_base);
3357 __ Mov(x19, src_base);
3358 __ Mov(x20, dst_base);
3359 __ Mov(x21, src_base + 16);
3360 __ Mov(x22, dst_base + 40);
3361 __ Mov(x23, src_base);
3362 __ Mov(x24, dst_base);
3363 __ Mov(x25, src_base);
3364 __ Mov(x26, dst_base);
3365 __ Ldr(w0, MemOperand(x17, 4, PreIndex));
3366 __ Str(w0, MemOperand(x18, 12, PreIndex));
3367 __ Ldr(x1, MemOperand(x19, 8, PreIndex));
3368 __ Str(x1, MemOperand(x20, 16, PreIndex));
3369 __ Ldr(w2, MemOperand(x21, -4, PreIndex));
3370 __ Str(w2, MemOperand(x22, -4, PreIndex));
3371 __ Ldrb(w3, MemOperand(x23, 1, PreIndex));
3372 __ Strb(w3, MemOperand(x24, 25, PreIndex));
3373 __ Ldrh(w4, MemOperand(x25, 3, PreIndex));
3374 __ Strh(w4, MemOperand(x26, 41, PreIndex));
3375 END();
3376
3377 if (CAN_RUN()) {
3378 RUN();
3379
3380 ASSERT_EQUAL_64(0xfedcba98, x0);
3381 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3382 ASSERT_EQUAL_64(0x0123456789abcdef, x1);
3383 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3384 ASSERT_EQUAL_64(0x01234567, x2);
3385 ASSERT_EQUAL_64(0x0123456700000000, dst[4]);
3386 ASSERT_EQUAL_64(0x32, x3);
3387 ASSERT_EQUAL_64(0x3200, dst[3]);
3388 ASSERT_EQUAL_64(0x9876, x4);
3389 ASSERT_EQUAL_64(0x987600, dst[5]);
3390 ASSERT_EQUAL_64(src_base + 4, x17);
3391 ASSERT_EQUAL_64(dst_base + 12, x18);
3392 ASSERT_EQUAL_64(src_base + 8, x19);
3393 ASSERT_EQUAL_64(dst_base + 16, x20);
3394 ASSERT_EQUAL_64(src_base + 12, x21);
3395 ASSERT_EQUAL_64(dst_base + 36, x22);
3396 ASSERT_EQUAL_64(src_base + 1, x23);
3397 ASSERT_EQUAL_64(dst_base + 25, x24);
3398 ASSERT_EQUAL_64(src_base + 3, x25);
3399 ASSERT_EQUAL_64(dst_base + 41, x26);
3400 }
3401 }
3402
3403
3404 TEST(ldr_str_postindex) {
3405 SETUP();
3406
3407 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3408 uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
3409 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3410 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3411
3412 START();
3413 __ Mov(x17, src_base + 4);
3414 __ Mov(x18, dst_base + 12);
3415 __ Mov(x19, src_base + 8);
3416 __ Mov(x20, dst_base + 16);
3417 __ Mov(x21, src_base + 8);
3418 __ Mov(x22, dst_base + 32);
3419 __ Mov(x23, src_base + 1);
3420 __ Mov(x24, dst_base + 25);
3421 __ Mov(x25, src_base + 3);
3422 __ Mov(x26, dst_base + 41);
3423 __ Ldr(w0, MemOperand(x17, 4, PostIndex));
3424 __ Str(w0, MemOperand(x18, 12, PostIndex));
3425 __ Ldr(x1, MemOperand(x19, 8, PostIndex));
3426 __ Str(x1, MemOperand(x20, 16, PostIndex));
3427 __ Ldr(x2, MemOperand(x21, -8, PostIndex));
3428 __ Str(x2, MemOperand(x22, -32, PostIndex));
3429 __ Ldrb(w3, MemOperand(x23, 1, PostIndex));
3430 __ Strb(w3, MemOperand(x24, 5, PostIndex));
3431 __ Ldrh(w4, MemOperand(x25, -3, PostIndex));
3432 __ Strh(w4, MemOperand(x26, -41, PostIndex));
3433 END();
3434
3435 if (CAN_RUN()) {
3436 RUN();
3437
3438 ASSERT_EQUAL_64(0xfedcba98, x0);
3439 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3440 ASSERT_EQUAL_64(0x0123456789abcdef, x1);
3441 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3442 ASSERT_EQUAL_64(0x0123456789abcdef, x2);
3443 ASSERT_EQUAL_64(0x0123456789abcdef, dst[4]);
3444 ASSERT_EQUAL_64(0x32, x3);
3445 ASSERT_EQUAL_64(0x3200, dst[3]);
3446 ASSERT_EQUAL_64(0x9876, x4);
3447 ASSERT_EQUAL_64(0x987600, dst[5]);
3448 ASSERT_EQUAL_64(src_base + 8, x17);
3449 ASSERT_EQUAL_64(dst_base + 24, x18);
3450 ASSERT_EQUAL_64(src_base + 16, x19);
3451 ASSERT_EQUAL_64(dst_base + 32, x20);
3452 ASSERT_EQUAL_64(src_base, x21);
3453 ASSERT_EQUAL_64(dst_base, x22);
3454 ASSERT_EQUAL_64(src_base + 2, x23);
3455 ASSERT_EQUAL_64(dst_base + 30, x24);
3456 ASSERT_EQUAL_64(src_base, x25);
3457 ASSERT_EQUAL_64(dst_base, x26);
3458 }
3459 }
3460
3461
3462 TEST(ldr_str_largeindex) {
3463 SETUP();
3464
3465 // This value won't fit in the immediate offset field of ldr/str instructions.
3466 int largeoffset = 0xabcdef;
3467
3468 int64_t data[3] = {0x1122334455667788, 0, 0};
3469 uint64_t base_addr = reinterpret_cast<uintptr_t>(data);
3470 uint64_t drifted_addr = base_addr - largeoffset;
3471
3472 // This test checks that we we can use large immediate offsets when
3473 // using PreIndex or PostIndex addressing mode of the MacroAssembler
3474 // Ldr/Str instructions.
3475
3476 START();
3477 __ Mov(x19, drifted_addr);
3478 __ Ldr(x0, MemOperand(x19, largeoffset, PreIndex));
3479
3480 __ Mov(x20, base_addr);
3481 __ Ldr(x1, MemOperand(x20, largeoffset, PostIndex));
3482
3483 __ Mov(x21, drifted_addr);
3484 __ Str(x0, MemOperand(x21, largeoffset + 8, PreIndex));
3485
3486 __ Mov(x22, base_addr + 16);
3487 __ Str(x0, MemOperand(x22, largeoffset, PostIndex));
3488 END();
3489
3490 if (CAN_RUN()) {
3491 RUN();
3492
3493 ASSERT_EQUAL_64(0x1122334455667788, data[0]);
3494 ASSERT_EQUAL_64(0x1122334455667788, data[1]);
3495 ASSERT_EQUAL_64(0x1122334455667788, data[2]);
3496 ASSERT_EQUAL_64(0x1122334455667788, x0);
3497 ASSERT_EQUAL_64(0x1122334455667788, x1);
3498
3499 ASSERT_EQUAL_64(base_addr, x19);
3500 ASSERT_EQUAL_64(base_addr + largeoffset, x20);
3501 ASSERT_EQUAL_64(base_addr + 8, x21);
3502 ASSERT_EQUAL_64(base_addr + 16 + largeoffset, x22);
3503 }
3504 }
3505
3506
3507 TEST(load_signed) {
3508 SETUP();
3509
3510 uint32_t src[2] = {0x80008080, 0x7fff7f7f};
3511 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3512
3513 START();
3514 __ Mov(x24, src_base);
3515 __ Ldrsb(w0, MemOperand(x24));
3516 __ Ldrsb(w1, MemOperand(x24, 4));
3517 __ Ldrsh(w2, MemOperand(x24));
3518 __ Ldrsh(w3, MemOperand(x24, 4));
3519 __ Ldrsb(x4, MemOperand(x24));
3520 __ Ldrsb(x5, MemOperand(x24, 4));
3521 __ Ldrsh(x6, MemOperand(x24));
3522 __ Ldrsh(x7, MemOperand(x24, 4));
3523 __ Ldrsw(x8, MemOperand(x24));
3524 __ Ldrsw(x9, MemOperand(x24, 4));
3525 END();
3526
3527 if (CAN_RUN()) {
3528 RUN();
3529
3530 ASSERT_EQUAL_64(0xffffff80, x0);
3531 ASSERT_EQUAL_64(0x0000007f, x1);
3532 ASSERT_EQUAL_64(0xffff8080, x2);
3533 ASSERT_EQUAL_64(0x00007f7f, x3);
3534 ASSERT_EQUAL_64(0xffffffffffffff80, x4);
3535 ASSERT_EQUAL_64(0x000000000000007f, x5);
3536 ASSERT_EQUAL_64(0xffffffffffff8080, x6);
3537 ASSERT_EQUAL_64(0x0000000000007f7f, x7);
3538 ASSERT_EQUAL_64(0xffffffff80008080, x8);
3539 ASSERT_EQUAL_64(0x000000007fff7f7f, x9);
3540 }
3541 }
3542
3543
3544 TEST(load_store_regoffset) {
3545 SETUP();
3546
3547 uint32_t src[3] = {1, 2, 3};
3548 uint32_t dst[4] = {0, 0, 0, 0};
3549 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3550 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3551
3552 START();
3553 __ Mov(x16, src_base);
3554 __ Mov(x17, dst_base);
3555 __ Mov(x18, src_base + 3 * sizeof(src[0]));
3556 __ Mov(x19, dst_base + 3 * sizeof(dst[0]));
3557 __ Mov(x20, dst_base + 4 * sizeof(dst[0]));
3558 __ Mov(x24, 0);
3559 __ Mov(x25, 4);
3560 __ Mov(x26, -4);
3561 __ Mov(x27, 0xfffffffc); // 32-bit -4.
3562 __ Mov(x28, 0xfffffffe); // 32-bit -2.
3563 __ Mov(x29, 0xffffffff); // 32-bit -1.
3564
3565 __ Ldr(w0, MemOperand(x16, x24));
3566 __ Ldr(x1, MemOperand(x16, x25));
3567 __ Ldr(w2, MemOperand(x18, x26));
3568 __ Ldr(w3, MemOperand(x18, x27, SXTW));
3569 __ Ldr(w4, MemOperand(x18, x28, SXTW, 2));
3570 __ Str(w0, MemOperand(x17, x24));
3571 __ Str(x1, MemOperand(x17, x25));
3572 __ Str(w2, MemOperand(x20, x29, SXTW, 2));
3573 END();
3574
3575 if (CAN_RUN()) {
3576 RUN();
3577
3578 ASSERT_EQUAL_64(1, x0);
3579 ASSERT_EQUAL_64(0x0000000300000002, x1);
3580 ASSERT_EQUAL_64(3, x2);
3581 ASSERT_EQUAL_64(3, x3);
3582 ASSERT_EQUAL_64(2, x4);
3583 ASSERT_EQUAL_32(1, dst[0]);
3584 ASSERT_EQUAL_32(2, dst[1]);
3585 ASSERT_EQUAL_32(3, dst[2]);
3586 ASSERT_EQUAL_32(3, dst[3]);
3587 }
3588 }
3589
3590
3591 TEST(load_pauth) {
3592 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
3593
3594 uint64_t src[4] = {1, 2, 3, 4};
3595 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3596
3597 START();
3598 __ Mov(x16, src_base);
3599 __ Mov(x17, src_base);
3600 __ Mov(x18, src_base + 4 * sizeof(src[0]));
3601 __ Mov(x19, src_base + 4 * sizeof(src[0]));
3602
3603 // Add PAC codes to addresses
3604 __ Pacdza(x16);
3605 __ Pacdzb(x17);
3606 __ Pacdza(x18);
3607 __ Pacdzb(x19);
3608
3609 __ Ldraa(x0, MemOperand(x16));
3610 __ Ldraa(x1, MemOperand(x16, sizeof(src[0])));
3611 __ Ldraa(x2, MemOperand(x16, 2 * sizeof(src[0]), PreIndex));
3612 __ Ldraa(x3, MemOperand(x18, -sizeof(src[0])));
3613 __ Ldrab(x4, MemOperand(x17));
3614 __ Ldrab(x5, MemOperand(x17, sizeof(src[0])));
3615 __ Ldrab(x6, MemOperand(x17, 2 * sizeof(src[0]), PreIndex));
3616 __ Ldrab(x7, MemOperand(x19, -sizeof(src[0])));
3617 END();
3618
3619 if (CAN_RUN()) {
3620 RUN();
3621
3622 ASSERT_EQUAL_64(1, x0);
3623 ASSERT_EQUAL_64(2, x1);
3624 ASSERT_EQUAL_64(3, x2);
3625 ASSERT_EQUAL_64(4, x3);
3626 ASSERT_EQUAL_64(1, x4);
3627 ASSERT_EQUAL_64(2, x5);
3628 ASSERT_EQUAL_64(3, x6);
3629 ASSERT_EQUAL_64(4, x7);
3630 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x16);
3631 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x17);
3632 }
3633 }
3634
3635
3636 #ifdef VIXL_NEGATIVE_TESTING
3637 TEST(load_pauth_negative_test) {
3638 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
3639
3640 uint64_t src[4] = {1, 2, 3, 4};
3641 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3642
3643 START();
3644 __ Mov(x16, src_base);
3645
3646 // There is a small but not negligible chance (1 in 127 runs) that the PAC
3647 // codes for keys A and B will collide and LDRAB won't abort. To mitigate
3648 // this, we simply repeat the test a few more times.
3649 for (unsigned i = 0; i < 32; i++) {
3650 __ Add(x17, x16, i);
3651 __ Pacdza(x17);
3652 __ Ldrab(x0, MemOperand(x17));
3653 }
3654 END();
3655
3656 if (CAN_RUN()) {
3657 MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
3658 }
3659 }
3660 #endif // VIXL_NEGATIVE_TESTING
3661
3662
3663 TEST(ldp_stp_offset) {
3664 SETUP();
3665
3666 uint64_t src[3] = {0x0011223344556677,
3667 0x8899aabbccddeeff,
3668 0xffeeddccbbaa9988};
3669 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
3670 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3671 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3672
3673 START();
3674 __ Mov(x16, src_base);
3675 __ Mov(x17, dst_base);
3676 __ Mov(x18, src_base + 24);
3677 __ Mov(x19, dst_base + 56);
3678 __ Ldp(w0, w1, MemOperand(x16));
3679 __ Ldp(w2, w3, MemOperand(x16, 4));
3680 __ Ldp(x4, x5, MemOperand(x16, 8));
3681 __ Ldp(w6, w7, MemOperand(x18, -12));
3682 __ Ldp(x8, x9, MemOperand(x18, -16));
3683 __ Stp(w0, w1, MemOperand(x17));
3684 __ Stp(w2, w3, MemOperand(x17, 8));
3685 __ Stp(x4, x5, MemOperand(x17, 16));
3686 __ Stp(w6, w7, MemOperand(x19, -24));
3687 __ Stp(x8, x9, MemOperand(x19, -16));
3688 END();
3689
3690 if (CAN_RUN()) {
3691 RUN();
3692
3693 ASSERT_EQUAL_64(0x44556677, x0);
3694 ASSERT_EQUAL_64(0x00112233, x1);
3695 ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3696 ASSERT_EQUAL_64(0x00112233, x2);
3697 ASSERT_EQUAL_64(0xccddeeff, x3);
3698 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3699 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3700 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3701 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3702 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3703 ASSERT_EQUAL_64(0x8899aabb, x6);
3704 ASSERT_EQUAL_64(0xbbaa9988, x7);
3705 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3706 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3707 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3708 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3709 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3710 ASSERT_EQUAL_64(src_base, x16);
3711 ASSERT_EQUAL_64(dst_base, x17);
3712 ASSERT_EQUAL_64(src_base + 24, x18);
3713 ASSERT_EQUAL_64(dst_base + 56, x19);
3714 }
3715 }
3716
3717
3718 TEST(ldp_stp_offset_wide) {
3719 SETUP();
3720
3721 uint64_t src[3] = {0x0011223344556677,
3722 0x8899aabbccddeeff,
3723 0xffeeddccbbaa9988};
3724 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
3725 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3726 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3727 // Move base too far from the array to force multiple instructions
3728 // to be emitted.
3729 const int64_t base_offset = 1024;
3730
3731 START();
3732 __ Mov(x20, src_base - base_offset);
3733 __ Mov(x21, dst_base - base_offset);
3734 __ Mov(x18, src_base + base_offset + 24);
3735 __ Mov(x19, dst_base + base_offset + 56);
3736 __ Ldp(w0, w1, MemOperand(x20, base_offset));
3737 __ Ldp(w2, w3, MemOperand(x20, base_offset + 4));
3738 __ Ldp(x4, x5, MemOperand(x20, base_offset + 8));
3739 __ Ldp(w6, w7, MemOperand(x18, -12 - base_offset));
3740 __ Ldp(x8, x9, MemOperand(x18, -16 - base_offset));
3741 __ Stp(w0, w1, MemOperand(x21, base_offset));
3742 __ Stp(w2, w3, MemOperand(x21, base_offset + 8));
3743 __ Stp(x4, x5, MemOperand(x21, base_offset + 16));
3744 __ Stp(w6, w7, MemOperand(x19, -24 - base_offset));
3745 __ Stp(x8, x9, MemOperand(x19, -16 - base_offset));
3746 END();
3747
3748 if (CAN_RUN()) {
3749 RUN();
3750
3751 ASSERT_EQUAL_64(0x44556677, x0);
3752 ASSERT_EQUAL_64(0x00112233, x1);
3753 ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3754 ASSERT_EQUAL_64(0x00112233, x2);
3755 ASSERT_EQUAL_64(0xccddeeff, x3);
3756 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3757 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3758 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3759 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3760 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3761 ASSERT_EQUAL_64(0x8899aabb, x6);
3762 ASSERT_EQUAL_64(0xbbaa9988, x7);
3763 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3764 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3765 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3766 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3767 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3768 ASSERT_EQUAL_64(src_base - base_offset, x20);
3769 ASSERT_EQUAL_64(dst_base - base_offset, x21);
3770 ASSERT_EQUAL_64(src_base + base_offset + 24, x18);
3771 ASSERT_EQUAL_64(dst_base + base_offset + 56, x19);
3772 }
3773 }
3774
3775
3776 TEST(ldnp_stnp_offset) {
3777 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3778
3779 uint64_t src[4] = {0x0011223344556677,
3780 0x8899aabbccddeeff,
3781 0xffeeddccbbaa9988,
3782 0x7766554433221100};
3783 uint64_t dst[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3784 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3785 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3786
3787 START();
3788 __ Mov(x16, src_base);
3789 __ Mov(x17, dst_base);
3790 __ Mov(x18, src_base + 24);
3791 __ Mov(x19, dst_base + 64);
3792 __ Mov(x20, src_base + 32);
3793
3794 // Ensure address set up has happened before executing non-temporal ops.
3795 __ Dmb(InnerShareable, BarrierAll);
3796
3797 __ Ldnp(w0, w1, MemOperand(x16));
3798 __ Ldnp(w2, w3, MemOperand(x16, 4));
3799 __ Ldnp(x4, x5, MemOperand(x16, 8));
3800 __ Ldnp(w6, w7, MemOperand(x18, -12));
3801 __ Ldnp(x8, x9, MemOperand(x18, -16));
3802 __ Ldnp(q16, q17, MemOperand(x16));
3803 __ Ldnp(q19, q18, MemOperand(x20, -32));
3804 __ Stnp(w0, w1, MemOperand(x17));
3805 __ Stnp(w2, w3, MemOperand(x17, 8));
3806 __ Stnp(x4, x5, MemOperand(x17, 16));
3807 __ Stnp(w6, w7, MemOperand(x19, -32));
3808 __ Stnp(x8, x9, MemOperand(x19, -24));
3809 __ Stnp(q17, q16, MemOperand(x19));
3810 __ Stnp(q18, q19, MemOperand(x19, 32));
3811 END();
3812
3813 if (CAN_RUN()) {
3814 RUN();
3815
3816 ASSERT_EQUAL_64(0x44556677, x0);
3817 ASSERT_EQUAL_64(0x00112233, x1);
3818 ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3819 ASSERT_EQUAL_64(0x00112233, x2);
3820 ASSERT_EQUAL_64(0xccddeeff, x3);
3821 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3822 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3823 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3824 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3825 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3826 ASSERT_EQUAL_64(0x8899aabb, x6);
3827 ASSERT_EQUAL_64(0xbbaa9988, x7);
3828 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3829 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3830 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3831 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3832 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3833 ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q16);
3834 ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q17);
3835 ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q18);
3836 ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q19);
3837 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[8]);
3838 ASSERT_EQUAL_64(0x7766554433221100, dst[9]);
3839 ASSERT_EQUAL_64(0x0011223344556677, dst[10]);
3840 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[11]);
3841 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[12]);
3842 ASSERT_EQUAL_64(0x7766554433221100, dst[13]);
3843 ASSERT_EQUAL_64(0x0011223344556677, dst[14]);
3844 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[15]);
3845 ASSERT_EQUAL_64(src_base, x16);
3846 ASSERT_EQUAL_64(dst_base, x17);
3847 ASSERT_EQUAL_64(src_base + 24, x18);
3848 ASSERT_EQUAL_64(dst_base + 64, x19);
3849 ASSERT_EQUAL_64(src_base + 32, x20);
3850 }
3851 }
3852
3853 TEST(ldp_stp_preindex) {
3854 SETUP();
3855
3856 uint64_t src[3] = {0x0011223344556677,
3857 0x8899aabbccddeeff,
3858 0xffeeddccbbaa9988};
3859 uint64_t dst[5] = {0, 0, 0, 0, 0};
3860 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3861 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3862
3863 START();
3864 __ Mov(x16, src_base);
3865 __ Mov(x17, dst_base);
3866 __ Mov(x18, dst_base + 16);
3867 __ Ldp(w0, w1, MemOperand(x16, 4, PreIndex));
3868 __ Mov(x19, x16);
3869 __ Ldp(w2, w3, MemOperand(x16, -4, PreIndex));
3870 __ Stp(w2, w3, MemOperand(x17, 4, PreIndex));
3871 __ Mov(x20, x17);
3872 __ Stp(w0, w1, MemOperand(x17, -4, PreIndex));
3873 __ Ldp(x4, x5, MemOperand(x16, 8, PreIndex));
3874 __ Mov(x21, x16);
3875 __ Ldp(x6, x7, MemOperand(x16, -8, PreIndex));
3876 __ Stp(x7, x6, MemOperand(x18, 8, PreIndex));
3877 __ Mov(x22, x18);
3878 __ Stp(x5, x4, MemOperand(x18, -8, PreIndex));
3879 END();
3880
3881 if (CAN_RUN()) {
3882 RUN();
3883
3884 ASSERT_EQUAL_64(0x00112233, x0);
3885 ASSERT_EQUAL_64(0xccddeeff, x1);
3886 ASSERT_EQUAL_64(0x44556677, x2);
3887 ASSERT_EQUAL_64(0x00112233, x3);
3888 ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
3889 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3890 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3891 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3892 ASSERT_EQUAL_64(0x0011223344556677, x6);
3893 ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
3894 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3895 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3896 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3897 ASSERT_EQUAL_64(src_base, x16);
3898 ASSERT_EQUAL_64(dst_base, x17);
3899 ASSERT_EQUAL_64(dst_base + 16, x18);
3900 ASSERT_EQUAL_64(src_base + 4, x19);
3901 ASSERT_EQUAL_64(dst_base + 4, x20);
3902 ASSERT_EQUAL_64(src_base + 8, x21);
3903 ASSERT_EQUAL_64(dst_base + 24, x22);
3904 }
3905 }
3906
3907
3908 TEST(ldp_stp_preindex_wide) {
3909 SETUP();
3910
3911 uint64_t src[3] = {0x0011223344556677,
3912 0x8899aabbccddeeff,
3913 0xffeeddccbbaa9988};
3914 uint64_t dst[5] = {0, 0, 0, 0, 0};
3915 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3916 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3917 // Move base too far from the array to force multiple instructions
3918 // to be emitted.
3919 const int64_t base_offset = 1024;
3920
3921 START();
3922 __ Mov(x24, src_base - base_offset);
3923 __ Mov(x25, dst_base + base_offset);
3924 __ Mov(x18, dst_base + base_offset + 16);
3925 __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PreIndex));
3926 __ Mov(x19, x24);
3927 __ Mov(x24, src_base - base_offset + 4);
3928 __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PreIndex));
3929 __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PreIndex));
3930 __ Mov(x20, x25);
3931 __ Mov(x25, dst_base + base_offset + 4);
3932 __ Mov(x24, src_base - base_offset);
3933 __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PreIndex));
3934 __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PreIndex));
3935 __ Mov(x21, x24);
3936 __ Mov(x24, src_base - base_offset + 8);
3937 __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PreIndex));
3938 __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PreIndex));
3939 __ Mov(x22, x18);
3940 __ Mov(x18, dst_base + base_offset + 16 + 8);
3941 __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PreIndex));
3942 END();
3943
3944 if (CAN_RUN()) {
3945 RUN();
3946
3947 ASSERT_EQUAL_64(0x00112233, x0);
3948 ASSERT_EQUAL_64(0xccddeeff, x1);
3949 ASSERT_EQUAL_64(0x44556677, x2);
3950 ASSERT_EQUAL_64(0x00112233, x3);
3951 ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
3952 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3953 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3954 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3955 ASSERT_EQUAL_64(0x0011223344556677, x6);
3956 ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
3957 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3958 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3959 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3960 ASSERT_EQUAL_64(src_base, x24);
3961 ASSERT_EQUAL_64(dst_base, x25);
3962 ASSERT_EQUAL_64(dst_base + 16, x18);
3963 ASSERT_EQUAL_64(src_base + 4, x19);
3964 ASSERT_EQUAL_64(dst_base + 4, x20);
3965 ASSERT_EQUAL_64(src_base + 8, x21);
3966 ASSERT_EQUAL_64(dst_base + 24, x22);
3967 }
3968 }
3969
3970
3971 TEST(ldp_stp_postindex) {
3972 SETUP();
3973
3974 uint64_t src[4] = {0x0011223344556677,
3975 0x8899aabbccddeeff,
3976 0xffeeddccbbaa9988,
3977 0x7766554433221100};
3978 uint64_t dst[5] = {0, 0, 0, 0, 0};
3979 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3980 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3981
3982 START();
3983 __ Mov(x16, src_base);
3984 __ Mov(x17, dst_base);
3985 __ Mov(x18, dst_base + 16);
3986 __ Ldp(w0, w1, MemOperand(x16, 4, PostIndex));
3987 __ Mov(x19, x16);
3988 __ Ldp(w2, w3, MemOperand(x16, -4, PostIndex));
3989 __ Stp(w2, w3, MemOperand(x17, 4, PostIndex));
3990 __ Mov(x20, x17);
3991 __ Stp(w0, w1, MemOperand(x17, -4, PostIndex));
3992 __ Ldp(x4, x5, MemOperand(x16, 8, PostIndex));
3993 __ Mov(x21, x16);
3994 __ Ldp(x6, x7, MemOperand(x16, -8, PostIndex));
3995 __ Stp(x7, x6, MemOperand(x18, 8, PostIndex));
3996 __ Mov(x22, x18);
3997 __ Stp(x5, x4, MemOperand(x18, -8, PostIndex));
3998 END();
3999
4000 if (CAN_RUN()) {
4001 RUN();
4002
4003 ASSERT_EQUAL_64(0x44556677, x0);
4004 ASSERT_EQUAL_64(0x00112233, x1);
4005 ASSERT_EQUAL_64(0x00112233, x2);
4006 ASSERT_EQUAL_64(0xccddeeff, x3);
4007 ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
4008 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
4009 ASSERT_EQUAL_64(0x0011223344556677, x4);
4010 ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
4011 ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
4012 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
4013 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
4014 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
4015 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
4016 ASSERT_EQUAL_64(src_base, x16);
4017 ASSERT_EQUAL_64(dst_base, x17);
4018 ASSERT_EQUAL_64(dst_base + 16, x18);
4019 ASSERT_EQUAL_64(src_base + 4, x19);
4020 ASSERT_EQUAL_64(dst_base + 4, x20);
4021 ASSERT_EQUAL_64(src_base + 8, x21);
4022 ASSERT_EQUAL_64(dst_base + 24, x22);
4023 }
4024 }
4025
4026
4027 TEST(ldp_stp_postindex_wide) {
4028 SETUP();
4029
4030 uint64_t src[4] = {0x0011223344556677,
4031 0x8899aabbccddeeff,
4032 0xffeeddccbbaa9988,
4033 0x7766554433221100};
4034 uint64_t dst[5] = {0, 0, 0, 0, 0};
4035 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4036 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4037 // Move base too far from the array to force multiple instructions
4038 // to be emitted.
4039 const int64_t base_offset = 1024;
4040
4041 START();
4042 __ Mov(x24, src_base);
4043 __ Mov(x25, dst_base);
4044 __ Mov(x18, dst_base + 16);
4045 __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PostIndex));
4046 __ Mov(x19, x24);
4047 __ Sub(x24, x24, base_offset);
4048 __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PostIndex));
4049 __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PostIndex));
4050 __ Mov(x20, x25);
4051 __ Sub(x24, x24, base_offset);
4052 __ Add(x25, x25, base_offset);
4053 __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PostIndex));
4054 __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PostIndex));
4055 __ Mov(x21, x24);
4056 __ Sub(x24, x24, base_offset);
4057 __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PostIndex));
4058 __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PostIndex));
4059 __ Mov(x22, x18);
4060 __ Add(x18, x18, base_offset);
4061 __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PostIndex));
4062 END();
4063
4064 if (CAN_RUN()) {
4065 RUN();
4066
4067 ASSERT_EQUAL_64(0x44556677, x0);
4068 ASSERT_EQUAL_64(0x00112233, x1);
4069 ASSERT_EQUAL_64(0x00112233, x2);
4070 ASSERT_EQUAL_64(0xccddeeff, x3);
4071 ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
4072 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
4073 ASSERT_EQUAL_64(0x0011223344556677, x4);
4074 ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
4075 ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
4076 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
4077 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
4078 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
4079 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
4080 ASSERT_EQUAL_64(src_base + base_offset, x24);
4081 ASSERT_EQUAL_64(dst_base - base_offset, x25);
4082 ASSERT_EQUAL_64(dst_base - base_offset + 16, x18);
4083 ASSERT_EQUAL_64(src_base + base_offset + 4, x19);
4084 ASSERT_EQUAL_64(dst_base - base_offset + 4, x20);
4085 ASSERT_EQUAL_64(src_base + base_offset + 8, x21);
4086 ASSERT_EQUAL_64(dst_base - base_offset + 24, x22);
4087 }
4088 }
4089
4090
4091 TEST(ldp_sign_extend) {
4092 SETUP();
4093
4094 uint32_t src[2] = {0x80000000, 0x7fffffff};
4095 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4096
4097 START();
4098 __ Mov(x24, src_base);
4099 __ Ldpsw(x0, x1, MemOperand(x24));
4100 END();
4101
4102 if (CAN_RUN()) {
4103 RUN();
4104
4105 ASSERT_EQUAL_64(0xffffffff80000000, x0);
4106 ASSERT_EQUAL_64(0x000000007fffffff, x1);
4107 }
4108 }
4109
4110
4111 TEST(ldur_stur) {
4112 SETUP();
4113
4114 int64_t src[2] = {0x0123456789abcdef, 0x0123456789abcdef};
4115 int64_t dst[5] = {0, 0, 0, 0, 0};
4116 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4117 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4118
4119 START();
4120 __ Mov(x17, src_base);
4121 __ Mov(x18, dst_base);
4122 __ Mov(x19, src_base + 16);
4123 __ Mov(x20, dst_base + 32);
4124 __ Mov(x21, dst_base + 40);
4125 __ Ldr(w0, MemOperand(x17, 1));
4126 __ Str(w0, MemOperand(x18, 2));
4127 __ Ldr(x1, MemOperand(x17, 3));
4128 __ Str(x1, MemOperand(x18, 9));
4129 __ Ldr(w2, MemOperand(x19, -9));
4130 __ Str(w2, MemOperand(x20, -5));
4131 __ Ldrb(w3, MemOperand(x19, -1));
4132 __ Strb(w3, MemOperand(x21, -1));
4133 END();
4134
4135 if (CAN_RUN()) {
4136 RUN();
4137
4138 ASSERT_EQUAL_64(0x6789abcd, x0);
4139 ASSERT_EQUAL_64(0x00006789abcd0000, dst[0]);
4140 ASSERT_EQUAL_64(0xabcdef0123456789, x1);
4141 ASSERT_EQUAL_64(0xcdef012345678900, dst[1]);
4142 ASSERT_EQUAL_64(0x000000ab, dst[2]);
4143 ASSERT_EQUAL_64(0xabcdef01, x2);
4144 ASSERT_EQUAL_64(0x00abcdef01000000, dst[3]);
4145 ASSERT_EQUAL_64(0x00000001, x3);
4146 ASSERT_EQUAL_64(0x0100000000000000, dst[4]);
4147 ASSERT_EQUAL_64(src_base, x17);
4148 ASSERT_EQUAL_64(dst_base, x18);
4149 ASSERT_EQUAL_64(src_base + 16, x19);
4150 ASSERT_EQUAL_64(dst_base + 32, x20);
4151 }
4152 }
4153
4154
4155 TEST(ldur_stur_neon) {
4156 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4157
4158 int64_t src[3] = {0x0123456789abcdef, 0x0123456789abcdef, 0x0123456789abcdef};
4159 int64_t dst[5] = {0, 0, 0, 0, 0};
4160 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4161 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4162
4163 START();
4164 __ Mov(x17, src_base);
4165 __ Mov(x18, dst_base);
4166 __ Ldr(b0, MemOperand(x17));
4167 __ Str(b0, MemOperand(x18));
4168 __ Ldr(h1, MemOperand(x17, 1));
4169 __ Str(h1, MemOperand(x18, 1));
4170 __ Ldr(s2, MemOperand(x17, 2));
4171 __ Str(s2, MemOperand(x18, 3));
4172 __ Ldr(d3, MemOperand(x17, 3));
4173 __ Str(d3, MemOperand(x18, 7));
4174 __ Ldr(q4, MemOperand(x17, 4));
4175 __ Str(q4, MemOperand(x18, 15));
4176 END();
4177
4178 if (CAN_RUN()) {
4179 RUN();
4180
4181 ASSERT_EQUAL_128(0, 0xef, q0);
4182 ASSERT_EQUAL_128(0, 0xabcd, q1);
4183 ASSERT_EQUAL_128(0, 0x456789ab, q2);
4184 ASSERT_EQUAL_128(0, 0xabcdef0123456789, q3);
4185 ASSERT_EQUAL_128(0x89abcdef01234567, 0x89abcdef01234567, q4);
4186 ASSERT_EQUAL_64(0x89456789ababcdef, dst[0]);
4187 ASSERT_EQUAL_64(0x67abcdef01234567, dst[1]);
4188 ASSERT_EQUAL_64(0x6789abcdef012345, dst[2]);
4189 ASSERT_EQUAL_64(0x0089abcdef012345, dst[3]);
4190 }
4191 }
4192
4193
4194 TEST(ldr_literal) {
4195 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4196
4197 START();
4198 __ Ldr(x2, 0x1234567890abcdef);
4199 __ Ldr(w3, 0xfedcba09);
4200 __ Ldrsw(x4, 0x7fffffff);
4201 __ Ldrsw(x5, 0x80000000);
4202 __ Ldr(q11, 0x1234000056780000, 0xabcd0000ef000000);
4203 __ Ldr(d13, 1.234);
4204 __ Ldr(s25, 2.5);
4205 END();
4206
4207 if (CAN_RUN()) {
4208 RUN();
4209
4210 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4211 ASSERT_EQUAL_64(0xfedcba09, x3);
4212 ASSERT_EQUAL_64(0x7fffffff, x4);
4213 ASSERT_EQUAL_64(0xffffffff80000000, x5);
4214 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4215 ASSERT_EQUAL_FP64(1.234, d13);
4216 ASSERT_EQUAL_FP32(2.5, s25);
4217 }
4218 }
4219
4220
4221 TEST(ldr_literal_range) {
4222 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4223
4224 START();
4225 // Make sure the pool is empty;
4226 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
4227 ASSERT_LITERAL_POOL_SIZE(0);
4228
4229 // Create some literal pool entries.
4230 __ Ldr(x0, 0x1234567890abcdef);
4231 __ Ldr(w1, 0xfedcba09);
4232 __ Ldrsw(x2, 0x7fffffff);
4233 __ Ldrsw(x3, 0x80000000);
4234 __ Ldr(q2, 0x1234000056780000, 0xabcd0000ef000000);
4235 __ Ldr(d0, 1.234);
4236 __ Ldr(s1, 2.5);
4237 ASSERT_LITERAL_POOL_SIZE(48);
4238
4239 // Emit more code than the maximum literal load range to ensure the pool
4240 // should be emitted.
4241 const ptrdiff_t end = masm.GetCursorOffset() + 2 * kMaxLoadLiteralRange;
4242 while (masm.GetCursorOffset() < end) {
4243 __ Nop();
4244 }
4245
4246 // The pool should have been emitted.
4247 ASSERT_LITERAL_POOL_SIZE(0);
4248
4249 // These loads should be after the pool (and will require a new one).
4250 __ Ldr(x4, 0x34567890abcdef12);
4251 __ Ldr(w5, 0xdcba09fe);
4252 __ Ldrsw(x6, 0x7fffffff);
4253 __ Ldrsw(x7, 0x80000000);
4254 __ Ldr(q6, 0x1234000056780000, 0xabcd0000ef000000);
4255 __ Ldr(d4, 123.4);
4256 __ Ldr(s5, 250.0);
4257 ASSERT_LITERAL_POOL_SIZE(48);
4258 END();
4259
4260 if (CAN_RUN()) {
4261 RUN();
4262
4263 // Check that the literals loaded correctly.
4264 ASSERT_EQUAL_64(0x1234567890abcdef, x0);
4265 ASSERT_EQUAL_64(0xfedcba09, x1);
4266 ASSERT_EQUAL_64(0x7fffffff, x2);
4267 ASSERT_EQUAL_64(0xffffffff80000000, x3);
4268 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q2);
4269 ASSERT_EQUAL_FP64(1.234, d0);
4270 ASSERT_EQUAL_FP32(2.5, s1);
4271 ASSERT_EQUAL_64(0x34567890abcdef12, x4);
4272 ASSERT_EQUAL_64(0xdcba09fe, x5);
4273 ASSERT_EQUAL_64(0x7fffffff, x6);
4274 ASSERT_EQUAL_64(0xffffffff80000000, x7);
4275 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q6);
4276 ASSERT_EQUAL_FP64(123.4, d4);
4277 ASSERT_EQUAL_FP32(250.0, s5);
4278 }
4279 }
4280
4281
4282 template <typename T>
4283 void LoadIntValueHelper(T values[], int card) {
4284 SETUP();
4285
4286 const bool is_32bit = (sizeof(T) == 4);
4287 Register tgt1 = is_32bit ? Register(w1) : Register(x1);
4288 Register tgt2 = is_32bit ? Register(w2) : Register(x2);
4289
4290 START();
4291 __ Mov(x0, 0);
4292
4293 // If one of the values differ then x0 will be one.
4294 for (int i = 0; i < card; ++i) {
4295 __ Mov(tgt1, values[i]);
4296 __ Ldr(tgt2, values[i]);
4297 __ Cmp(tgt1, tgt2);
4298 __ Cset(x0, ne);
4299 }
4300 END();
4301
4302 if (CAN_RUN()) {
4303 RUN();
4304
4305 // If one of the values differs, the trace can be used to identify which
4306 // one.
4307 ASSERT_EQUAL_64(0, x0);
4308 }
4309 }
4310
4311
4312 TEST(ldr_literal_values_x) {
4313 static const uint64_t kValues[] = {0x8000000000000000,
4314 0x7fffffffffffffff,
4315 0x0000000000000000,
4316 0xffffffffffffffff,
4317 0x00ff00ff00ff00ff,
4318 0x1234567890abcdef};
4319
4320 LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
4321 }
4322
4323
4324 TEST(ldr_literal_values_w) {
4325 static const uint32_t kValues[] = {0x80000000,
4326 0x7fffffff,
4327 0x00000000,
4328 0xffffffff,
4329 0x00ff00ff,
4330 0x12345678,
4331 0x90abcdef};
4332
4333 LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
4334 }
4335
4336 TEST(ldr_literal_custom) {
4337 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4338
4339 Label end_of_pool_before;
4340 Label end_of_pool_after;
4341
4342 const size_t kSizeOfPoolInBytes = 44;
4343
4344 Literal<uint64_t> before_x(0x1234567890abcdef);
4345 Literal<uint32_t> before_w(0xfedcba09);
4346 Literal<uint32_t> before_sx(0x80000000);
4347 Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000);
4348 Literal<double> before_d(1.234);
4349 Literal<float> before_s(2.5);
4350
4351 Literal<uint64_t> after_x(0x1234567890abcdef);
4352 Literal<uint32_t> after_w(0xfedcba09);
4353 Literal<uint32_t> after_sx(0x80000000);
4354 Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000);
4355 Literal<double> after_d(1.234);
4356 Literal<float> after_s(2.5);
4357
4358 START();
4359
4360 // Manually generate a pool.
4361 __ B(&end_of_pool_before);
4362 {
4363 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4364 __ place(&before_x);
4365 __ place(&before_w);
4366 __ place(&before_sx);
4367 __ place(&before_q);
4368 __ place(&before_d);
4369 __ place(&before_s);
4370 }
4371 __ Bind(&end_of_pool_before);
4372
4373 {
4374 ExactAssemblyScope scope(&masm, 12 * kInstructionSize);
4375 __ ldr(x2, &before_x);
4376 __ ldr(w3, &before_w);
4377 __ ldrsw(x5, &before_sx);
4378 __ ldr(q11, &before_q);
4379 __ ldr(d13, &before_d);
4380 __ ldr(s25, &before_s);
4381
4382 __ ldr(x6, &after_x);
4383 __ ldr(w7, &after_w);
4384 __ ldrsw(x8, &after_sx);
4385 __ ldr(q18, &after_q);
4386 __ ldr(d14, &after_d);
4387 __ ldr(s26, &after_s);
4388 }
4389
4390 // Manually generate a pool.
4391 __ B(&end_of_pool_after);
4392 {
4393 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4394 __ place(&after_x);
4395 __ place(&after_w);
4396 __ place(&after_sx);
4397 __ place(&after_q);
4398 __ place(&after_d);
4399 __ place(&after_s);
4400 }
4401 __ Bind(&end_of_pool_after);
4402
4403 END();
4404
4405 if (CAN_RUN()) {
4406 RUN();
4407
4408 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4409 ASSERT_EQUAL_64(0xfedcba09, x3);
4410 ASSERT_EQUAL_64(0xffffffff80000000, x5);
4411 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4412 ASSERT_EQUAL_FP64(1.234, d13);
4413 ASSERT_EQUAL_FP32(2.5, s25);
4414
4415 ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4416 ASSERT_EQUAL_64(0xfedcba09, x7);
4417 ASSERT_EQUAL_64(0xffffffff80000000, x8);
4418 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18);
4419 ASSERT_EQUAL_FP64(1.234, d14);
4420 ASSERT_EQUAL_FP32(2.5, s26);
4421 }
4422 }
4423
4424
4425 TEST(ldr_literal_custom_shared) {
4426 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4427
4428 Label end_of_pool_before;
4429 Label end_of_pool_after;
4430
4431 const size_t kSizeOfPoolInBytes = 40;
4432
4433 Literal<uint64_t> before_x(0x1234567890abcdef);
4434 Literal<uint32_t> before_w(0xfedcba09);
4435 Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000);
4436 Literal<double> before_d(1.234);
4437 Literal<float> before_s(2.5);
4438
4439 Literal<uint64_t> after_x(0x1234567890abcdef);
4440 Literal<uint32_t> after_w(0xfedcba09);
4441 Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000);
4442 Literal<double> after_d(1.234);
4443 Literal<float> after_s(2.5);
4444
4445 START();
4446
4447 // Manually generate a pool.
4448 __ B(&end_of_pool_before);
4449 {
4450 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4451 __ place(&before_x);
4452 __ place(&before_w);
4453 __ place(&before_q);
4454 __ place(&before_d);
4455 __ place(&before_s);
4456 }
4457 __ Bind(&end_of_pool_before);
4458
4459 // Load the entries several times to test that literals can be shared.
4460 for (int i = 0; i < 50; i++) {
4461 ExactAssemblyScope scope(&masm, 12 * kInstructionSize);
4462 __ ldr(x2, &before_x);
4463 __ ldr(w3, &before_w);
4464 __ ldrsw(x5, &before_w); // Re-use before_w.
4465 __ ldr(q11, &before_q);
4466 __ ldr(d13, &before_d);
4467 __ ldr(s25, &before_s);
4468
4469 __ ldr(x6, &after_x);
4470 __ ldr(w7, &after_w);
4471 __ ldrsw(x8, &after_w); // Re-use after_w.
4472 __ ldr(q18, &after_q);
4473 __ ldr(d14, &after_d);
4474 __ ldr(s26, &after_s);
4475 }
4476
4477 // Manually generate a pool.
4478 __ B(&end_of_pool_after);
4479 {
4480 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4481 __ place(&after_x);
4482 __ place(&after_w);
4483 __ place(&after_q);
4484 __ place(&after_d);
4485 __ place(&after_s);
4486 }
4487 __ Bind(&end_of_pool_after);
4488
4489 END();
4490
4491 if (CAN_RUN()) {
4492 RUN();
4493
4494 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4495 ASSERT_EQUAL_64(0xfedcba09, x3);
4496 ASSERT_EQUAL_64(0xfffffffffedcba09, x5);
4497 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4498 ASSERT_EQUAL_FP64(1.234, d13);
4499 ASSERT_EQUAL_FP32(2.5, s25);
4500
4501 ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4502 ASSERT_EQUAL_64(0xfedcba09, x7);
4503 ASSERT_EQUAL_64(0xfffffffffedcba09, x8);
4504 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18);
4505 ASSERT_EQUAL_FP64(1.234, d14);
4506 ASSERT_EQUAL_FP32(2.5, s26);
4507 }
4508 }
4509
4510 static const PrefetchOperation kPrfmOperations[] = {PLDL1KEEP,
4511 PLDL1STRM,
4512 PLDL2KEEP,
4513 PLDL2STRM,
4514 PLDL3KEEP,
4515 PLDL3STRM,
4516
4517 PLIL1KEEP,
4518 PLIL1STRM,
4519 PLIL2KEEP,
4520 PLIL2STRM,
4521 PLIL3KEEP,
4522 PLIL3STRM,
4523
4524 PSTL1KEEP,
4525 PSTL1STRM,
4526 PSTL2KEEP,
4527 PSTL2STRM,
4528 PSTL3KEEP,
4529 PSTL3STRM};
4530
4531 TEST(prfm_offset) {
4532 SETUP();
4533
4534 START();
4535 // The address used in prfm doesn't have to be valid.
4536 __ Mov(x0, 0x0123456789abcdef);
4537
4538 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4539 // Unallocated prefetch operations are ignored, so test all of them.
4540 // We have to use the Assembler directly for this.
4541 ExactAssemblyScope guard(&masm, 3 * kInstructionSize);
4542 __ prfm(op, MemOperand(x0));
4543 __ prfm(op, MemOperand(x0, 8));
4544 __ prfm(op, MemOperand(x0, 32760));
4545 }
4546
4547 for (PrefetchOperation op : kPrfmOperations) {
4548 // Also test named operations.
4549 __ Prfm(op, MemOperand(x0, 32768));
4550 __ Prfm(op, MemOperand(x0, 1));
4551 __ Prfm(op, MemOperand(x0, 9));
4552 __ Prfm(op, MemOperand(x0, 255));
4553 __ Prfm(op, MemOperand(x0, 257));
4554 __ Prfm(op, MemOperand(x0, -1));
4555 __ Prfm(op, MemOperand(x0, -9));
4556 __ Prfm(op, MemOperand(x0, -255));
4557 __ Prfm(op, MemOperand(x0, -257));
4558
4559 __ Prfm(op, MemOperand(x0, 0xfedcba9876543210));
4560 }
4561
4562 END();
4563 if (CAN_RUN()) {
4564 RUN();
4565 }
4566 }
4567
4568
4569 TEST(prfm_regoffset) {
4570 SETUP();
4571
4572 START();
4573 // The address used in prfm doesn't have to be valid.
4574 __ Mov(x0, 0x0123456789abcdef);
4575
4576 CPURegList inputs(CPURegister::kRegister, kXRegSize, 10, 18);
4577 __ Mov(x10, 0);
4578 __ Mov(x11, 1);
4579 __ Mov(x12, 8);
4580 __ Mov(x13, 255);
4581 __ Mov(x14, -0);
4582 __ Mov(x15, -1);
4583 __ Mov(x16, -8);
4584 __ Mov(x17, -255);
4585 __ Mov(x18, 0xfedcba9876543210);
4586
4587 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4588 // Unallocated prefetch operations are ignored, so test all of them.
4589 // We have to use the Assembler directly for this.
4590
4591 // Prefetch operations of the form 0b11xxx are allocated to another
4592 // instruction.
4593 if (op >= 0b11000) continue;
4594
4595 ExactAssemblyScope guard(&masm, inputs.GetCount() * kInstructionSize);
4596 CPURegList loop = inputs;
4597 while (!loop.IsEmpty()) {
4598 __ prfm(op, MemOperand(x0, Register(loop.PopLowestIndex())));
4599 }
4600 }
4601
4602 for (PrefetchOperation op : kPrfmOperations) {
4603 // Also test named operations.
4604 CPURegList loop = inputs;
4605 while (!loop.IsEmpty()) {
4606 Register input(loop.PopLowestIndex());
4607 __ Prfm(op, MemOperand(x0, input, UXTW));
4608 __ Prfm(op, MemOperand(x0, input, UXTW, 3));
4609 __ Prfm(op, MemOperand(x0, input, LSL));
4610 __ Prfm(op, MemOperand(x0, input, LSL, 3));
4611 __ Prfm(op, MemOperand(x0, input, SXTW));
4612 __ Prfm(op, MemOperand(x0, input, SXTW, 3));
4613 __ Prfm(op, MemOperand(x0, input, SXTX));
4614 __ Prfm(op, MemOperand(x0, input, SXTX, 3));
4615 }
4616 }
4617
4618 END();
4619 if (CAN_RUN()) {
4620 RUN();
4621 }
4622 }
4623
4624
4625 TEST(prfm_literal_imm19) {
4626 SETUP();
4627 START();
4628
4629 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4630 // Unallocated prefetch operations are ignored, so test all of them.
4631 // We have to use the Assembler directly for this.
4632 ExactAssemblyScope guard(&masm, 3 * kInstructionSize);
4633 __ prfm(op, INT64_C(0));
4634 __ prfm(op, 1);
4635 __ prfm(op, -1);
4636 }
4637
4638 for (PrefetchOperation op : kPrfmOperations) {
4639 // Also test named operations.
4640 ExactAssemblyScope guard(&masm, 4 * kInstructionSize);
4641 // The address used in prfm doesn't have to be valid.
4642 __ prfm(op, 1000);
4643 __ prfm(op, -1000);
4644 __ prfm(op, 0x3ffff);
4645 __ prfm(op, -0x40000);
4646 }
4647
4648 END();
4649 if (CAN_RUN()) {
4650 RUN();
4651 }
4652 }
4653
4654
4655 TEST(prfm_literal) {
4656 SETUP();
4657
4658 Label end_of_pool_before;
4659 Label end_of_pool_after;
4660 Literal<uint64_t> before(0);
4661 Literal<uint64_t> after(0);
4662
4663 START();
4664
4665 // Manually generate a pool.
4666 __ B(&end_of_pool_before);
4667 {
4668 ExactAssemblyScope scope(&masm, before.GetSize());
4669 __ place(&before);
4670 }
4671 __ Bind(&end_of_pool_before);
4672
4673 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4674 // Unallocated prefetch operations are ignored, so test all of them.
4675 // We have to use the Assembler directly for this.
4676 ExactAssemblyScope guard(&masm, 2 * kInstructionSize);
4677 __ prfm(op, &before);
4678 __ prfm(op, &after);
4679 }
4680
4681 for (PrefetchOperation op : kPrfmOperations) {
4682 // Also test named operations.
4683 ExactAssemblyScope guard(&masm, 2 * kInstructionSize);
4684 __ prfm(op, &before);
4685 __ prfm(op, &after);
4686 }
4687
4688 // Manually generate a pool.
4689 __ B(&end_of_pool_after);
4690 {
4691 ExactAssemblyScope scope(&masm, after.GetSize());
4692 __ place(&after);
4693 }
4694 __ Bind(&end_of_pool_after);
4695
4696 END();
4697 if (CAN_RUN()) {
4698 RUN();
4699 }
4700 }
4701
4702
4703 TEST(prfm_wide) {
4704 SETUP();
4705
4706 START();
4707 // The address used in prfm doesn't have to be valid.
4708 __ Mov(x0, 0x0123456789abcdef);
4709
4710 for (PrefetchOperation op : kPrfmOperations) {
4711 __ Prfm(op, MemOperand(x0, 0x40000));
4712 __ Prfm(op, MemOperand(x0, -0x40001));
4713 __ Prfm(op, MemOperand(x0, UINT64_C(0x5555555555555555)));
4714 __ Prfm(op, MemOperand(x0, UINT64_C(0xfedcba9876543210)));
4715 }
4716
4717 END();
4718 if (CAN_RUN()) {
4719 RUN();
4720 }
4721 }
4722
4723
4724 TEST(load_prfm_literal) {
4725 // Test literals shared between both prfm and ldr.
4726 SETUP_WITH_FEATURES(CPUFeatures::kFP);
4727
4728 Label end_of_pool_before;
4729 Label end_of_pool_after;
4730
4731 const size_t kSizeOfPoolInBytes = 28;
4732
4733 Literal<uint64_t> before_x(0x1234567890abcdef);
4734 Literal<uint32_t> before_w(0xfedcba09);
4735 Literal<uint32_t> before_sx(0x80000000);
4736 Literal<double> before_d(1.234);
4737 Literal<float> before_s(2.5);
4738 Literal<uint64_t> after_x(0x1234567890abcdef);
4739 Literal<uint32_t> after_w(0xfedcba09);
4740 Literal<uint32_t> after_sx(0x80000000);
4741 Literal<double> after_d(1.234);
4742 Literal<float> after_s(2.5);
4743
4744 START();
4745
4746 // Manually generate a pool.
4747 __ B(&end_of_pool_before);
4748 {
4749 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4750 __ place(&before_x);
4751 __ place(&before_w);
4752 __ place(&before_sx);
4753 __ place(&before_d);
4754 __ place(&before_s);
4755 }
4756 __ Bind(&end_of_pool_before);
4757
4758 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4759 // Unallocated prefetch operations are ignored, so test all of them.
4760 ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4761
4762 __ prfm(op, &before_x);
4763 __ prfm(op, &before_w);
4764 __ prfm(op, &before_sx);
4765 __ prfm(op, &before_d);
4766 __ prfm(op, &before_s);
4767
4768 __ prfm(op, &after_x);
4769 __ prfm(op, &after_w);
4770 __ prfm(op, &after_sx);
4771 __ prfm(op, &after_d);
4772 __ prfm(op, &after_s);
4773 }
4774
4775 for (PrefetchOperation op : kPrfmOperations) {
4776 // Also test named operations.
4777 ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4778
4779 __ prfm(op, &before_x);
4780 __ prfm(op, &before_w);
4781 __ prfm(op, &before_sx);
4782 __ prfm(op, &before_d);
4783 __ prfm(op, &before_s);
4784
4785 __ prfm(op, &after_x);
4786 __ prfm(op, &after_w);
4787 __ prfm(op, &after_sx);
4788 __ prfm(op, &after_d);
4789 __ prfm(op, &after_s);
4790 }
4791
4792 {
4793 ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4794 __ ldr(x2, &before_x);
4795 __ ldr(w3, &before_w);
4796 __ ldrsw(x5, &before_sx);
4797 __ ldr(d13, &before_d);
4798 __ ldr(s25, &before_s);
4799
4800 __ ldr(x6, &after_x);
4801 __ ldr(w7, &after_w);
4802 __ ldrsw(x8, &after_sx);
4803 __ ldr(d14, &after_d);
4804 __ ldr(s26, &after_s);
4805 }
4806
4807 // Manually generate a pool.
4808 __ B(&end_of_pool_after);
4809 {
4810 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4811 __ place(&after_x);
4812 __ place(&after_w);
4813 __ place(&after_sx);
4814 __ place(&after_d);
4815 __ place(&after_s);
4816 }
4817 __ Bind(&end_of_pool_after);
4818
4819 END();
4820
4821 if (CAN_RUN()) {
4822 RUN();
4823
4824 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4825 ASSERT_EQUAL_64(0xfedcba09, x3);
4826 ASSERT_EQUAL_64(0xffffffff80000000, x5);
4827 ASSERT_EQUAL_FP64(1.234, d13);
4828 ASSERT_EQUAL_FP32(2.5, s25);
4829
4830 ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4831 ASSERT_EQUAL_64(0xfedcba09, x7);
4832 ASSERT_EQUAL_64(0xffffffff80000000, x8);
4833 ASSERT_EQUAL_FP64(1.234, d14);
4834 ASSERT_EQUAL_FP32(2.5, s26);
4835 }
4836 }
4837
4838
4839 TEST(add_sub_imm) {
4840 SETUP();
4841
4842 START();
4843 __ Mov(x0, 0x0);
4844 __ Mov(x1, 0x1111);
4845 __ Mov(x2, 0xffffffffffffffff);
4846 __ Mov(x3, 0x8000000000000000);
4847
4848 __ Add(x10, x0, Operand(0x123));
4849 __ Add(x11, x1, Operand(0x122000));
4850 __ Add(x12, x0, Operand(0xabc << 12));
4851 __ Add(x13, x2, Operand(1));
4852
4853 __ Add(w14, w0, Operand(0x123));
4854 __ Add(w15, w1, Operand(0x122000));
4855 __ Add(w16, w0, Operand(0xabc << 12));
4856 __ Add(w17, w2, Operand(1));
4857
4858 __ Sub(x20, x0, Operand(0x1));
4859 __ Sub(x21, x1, Operand(0x111));
4860 __ Sub(x22, x1, Operand(0x1 << 12));
4861 __ Sub(x23, x3, Operand(1));
4862
4863 __ Sub(w24, w0, Operand(0x1));
4864 __ Sub(w25, w1, Operand(0x111));
4865 __ Sub(w26, w1, Operand(0x1 << 12));
4866 __ Sub(w27, w3, Operand(1));
4867 END();
4868
4869 if (CAN_RUN()) {
4870 RUN();
4871
4872 ASSERT_EQUAL_64(0x123, x10);
4873 ASSERT_EQUAL_64(0x123111, x11);
4874 ASSERT_EQUAL_64(0xabc000, x12);
4875 ASSERT_EQUAL_64(0x0, x13);
4876
4877 ASSERT_EQUAL_32(0x123, w14);
4878 ASSERT_EQUAL_32(0x123111, w15);
4879 ASSERT_EQUAL_32(0xabc000, w16);
4880 ASSERT_EQUAL_32(0x0, w17);
4881
4882 ASSERT_EQUAL_64(0xffffffffffffffff, x20);
4883 ASSERT_EQUAL_64(0x1000, x21);
4884 ASSERT_EQUAL_64(0x111, x22);
4885 ASSERT_EQUAL_64(0x7fffffffffffffff, x23);
4886
4887 ASSERT_EQUAL_32(0xffffffff, w24);
4888 ASSERT_EQUAL_32(0x1000, w25);
4889 ASSERT_EQUAL_32(0x111, w26);
4890 ASSERT_EQUAL_32(0xffffffff, w27);
4891 }
4892 }
4893
4894
4895 TEST(add_sub_wide_imm) {
4896 SETUP();
4897
4898 START();
4899 __ Mov(x0, 0x0);
4900 __ Mov(x1, 0x1);
4901
4902 __ Add(x10, x0, Operand(0x1234567890abcdef));
4903 __ Add(x11, x1, Operand(0xffffffff));
4904
4905 __ Add(w12, w0, Operand(0x12345678));
4906 __ Add(w13, w1, Operand(0xffffffff));
4907
4908 __ Add(w18, w0, Operand(kWMinInt));
4909 __ Sub(w19, w0, Operand(kWMinInt));
4910
4911 __ Sub(x20, x0, Operand(0x1234567890abcdef));
4912 __ Sub(w21, w0, Operand(0x12345678));
4913
4914 END();
4915
4916 if (CAN_RUN()) {
4917 RUN();
4918
4919 ASSERT_EQUAL_64(0x1234567890abcdef, x10);
4920 ASSERT_EQUAL_64(0x100000000, x11);
4921
4922 ASSERT_EQUAL_32(0x12345678, w12);
4923 ASSERT_EQUAL_64(0x0, x13);
4924
4925 ASSERT_EQUAL_32(kWMinInt, w18);
4926 ASSERT_EQUAL_32(kWMinInt, w19);
4927
4928 ASSERT_EQUAL_64(-0x1234567890abcdef, x20);
4929 ASSERT_EQUAL_32(-0x12345678, w21);
4930 }
4931 }
4932
4933
4934 TEST(add_sub_shifted) {
4935 SETUP();
4936
4937 START();
4938 __ Mov(x0, 0);
4939 __ Mov(x1, 0x0123456789abcdef);
4940 __ Mov(x2, 0xfedcba9876543210);
4941 __ Mov(x3, 0xffffffffffffffff);
4942
4943 __ Add(x10, x1, Operand(x2));
4944 __ Add(x11, x0, Operand(x1, LSL, 8));
4945 __ Add(x12, x0, Operand(x1, LSR, 8));
4946 __ Add(x13, x0, Operand(x1, ASR, 8));
4947 __ Add(x14, x0, Operand(x2, ASR, 8));
4948 __ Add(w15, w0, Operand(w1, ASR, 8));
4949 __ Add(w18, w3, Operand(w1, ROR, 8));
4950 __ Add(x19, x3, Operand(x1, ROR, 8));
4951
4952 __ Sub(x20, x3, Operand(x2));
4953 __ Sub(x21, x3, Operand(x1, LSL, 8));
4954 __ Sub(x22, x3, Operand(x1, LSR, 8));
4955 __ Sub(x23, x3, Operand(x1, ASR, 8));
4956 __ Sub(x24, x3, Operand(x2, ASR, 8));
4957 __ Sub(w25, w3, Operand(w1, ASR, 8));
4958 __ Sub(w26, w3, Operand(w1, ROR, 8));
4959 __ Sub(x27, x3, Operand(x1, ROR, 8));
4960 END();
4961
4962 if (CAN_RUN()) {
4963 RUN();
4964
4965 ASSERT_EQUAL_64(0xffffffffffffffff, x10);
4966 ASSERT_EQUAL_64(0x23456789abcdef00, x11);
4967 ASSERT_EQUAL_64(0x000123456789abcd, x12);
4968 ASSERT_EQUAL_64(0x000123456789abcd, x13);
4969 ASSERT_EQUAL_64(0xfffedcba98765432, x14);
4970 ASSERT_EQUAL_64(0xff89abcd, x15);
4971 ASSERT_EQUAL_64(0xef89abcc, x18);
4972 ASSERT_EQUAL_64(0xef0123456789abcc, x19);
4973
4974 ASSERT_EQUAL_64(0x0123456789abcdef, x20);
4975 ASSERT_EQUAL_64(0xdcba9876543210ff, x21);
4976 ASSERT_EQUAL_64(0xfffedcba98765432, x22);
4977 ASSERT_EQUAL_64(0xfffedcba98765432, x23);
4978 ASSERT_EQUAL_64(0x000123456789abcd, x24);
4979 ASSERT_EQUAL_64(0x00765432, x25);
4980 ASSERT_EQUAL_64(0x10765432, x26);
4981 ASSERT_EQUAL_64(0x10fedcba98765432, x27);
4982 }
4983 }
4984
4985
4986 TEST(add_sub_extended) {
4987 SETUP();
4988
4989 START();
4990 __ Mov(x0, 0);
4991 __ Mov(x1, 0x0123456789abcdef);
4992 __ Mov(x2, 0xfedcba9876543210);
4993 __ Mov(w3, 0x80);
4994
4995 __ Add(x10, x0, Operand(x1, UXTB, 0));
4996 __ Add(x11, x0, Operand(x1, UXTB, 1));
4997 __ Add(x12, x0, Operand(x1, UXTH, 2));
4998 __ Add(x13, x0, Operand(x1, UXTW, 4));
4999
5000 __ Add(x14, x0, Operand(x1, SXTB, 0));
5001 __ Add(x15, x0, Operand(x1, SXTB, 1));
5002 __ Add(x16, x0, Operand(x1, SXTH, 2));
5003 __ Add(x17, x0, Operand(x1, SXTW, 3));
5004 __ Add(x18, x0, Operand(x2, SXTB, 0));
5005 __ Add(x19, x0, Operand(x2, SXTB, 1));
5006 __ Add(x20, x0, Operand(x2, SXTH, 2));
5007 __ Add(x21, x0, Operand(x2, SXTW, 3));
5008
5009 __ Add(x22, x1, Operand(x2, SXTB, 1));
5010 __ Sub(x23, x1, Operand(x2, SXTB, 1));
5011
5012 __ Add(w24, w1, Operand(w2, UXTB, 2));
5013 __ Add(w25, w0, Operand(w1, SXTB, 0));
5014 __ Add(w26, w0, Operand(w1, SXTB, 1));
5015 __ Add(w27, w2, Operand(w1, SXTW, 3));
5016
5017 __ Add(w28, w0, Operand(w1, SXTW, 3));
5018 __ Add(x29, x0, Operand(w1, SXTW, 3));
5019
5020 __ Sub(x30, x0, Operand(w3, SXTB, 1));
5021 END();
5022
5023 if (CAN_RUN()) {
5024 RUN();
5025
5026 ASSERT_EQUAL_64(0xef, x10);
5027 ASSERT_EQUAL_64(0x1de, x11);
5028 ASSERT_EQUAL_64(0x337bc, x12);
5029 ASSERT_EQUAL_64(0x89abcdef0, x13);
5030
5031 ASSERT_EQUAL_64(0xffffffffffffffef, x14);
5032 ASSERT_EQUAL_64(0xffffffffffffffde, x15);
5033 ASSERT_EQUAL_64(0xffffffffffff37bc, x16);
5034 ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x17);
5035 ASSERT_EQUAL_64(0x10, x18);
5036 ASSERT_EQUAL_64(0x20, x19);
5037 ASSERT_EQUAL_64(0xc840, x20);
5038 ASSERT_EQUAL_64(0x3b2a19080, x21);
5039
5040 ASSERT_EQUAL_64(0x0123456789abce0f, x22);
5041 ASSERT_EQUAL_64(0x0123456789abcdcf, x23);
5042
5043 ASSERT_EQUAL_32(0x89abce2f, w24);
5044 ASSERT_EQUAL_32(0xffffffef, w25);
5045 ASSERT_EQUAL_32(0xffffffde, w26);
5046 ASSERT_EQUAL_32(0xc3b2a188, w27);
5047
5048 ASSERT_EQUAL_32(0x4d5e6f78, w28);
5049 ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x29);
5050
5051 ASSERT_EQUAL_64(256, x30);
5052 }
5053 }
5054
5055
5056 TEST(add_sub_negative) {
5057 SETUP();
5058
5059 START();
5060 __ Mov(x0, 0);
5061 __ Mov(x1, 4687);
5062 __ Mov(x2, 0x1122334455667788);
5063 __ Mov(w3, 0x11223344);
5064 __ Mov(w4, 400000);
5065
5066 __ Add(x10, x0, -42);
5067 __ Add(x11, x1, -687);
5068 __ Add(x12, x2, -0x88);
5069
5070 __ Sub(x13, x0, -600);
5071 __ Sub(x14, x1, -313);
5072 __ Sub(x15, x2, -0x555);
5073
5074 __ Add(w19, w3, -0x344);
5075 __ Add(w20, w4, -2000);
5076
5077 __ Sub(w21, w3, -0xbc);
5078 __ Sub(w22, w4, -2000);
5079 END();
5080
5081 if (CAN_RUN()) {
5082 RUN();
5083
5084 ASSERT_EQUAL_64(-42, x10);
5085 ASSERT_EQUAL_64(4000, x11);
5086 ASSERT_EQUAL_64(0x1122334455667700, x12);
5087
5088 ASSERT_EQUAL_64(600, x13);
5089 ASSERT_EQUAL_64(5000, x14);
5090 ASSERT_EQUAL_64(0x1122334455667cdd, x15);
5091
5092 ASSERT_EQUAL_32(0x11223000, w19);
5093 ASSERT_EQUAL_32(398000, w20);
5094
5095 ASSERT_EQUAL_32(0x11223400, w21);
5096 ASSERT_EQUAL_32(402000, w22);
5097 }
5098 }
5099
5100
5101 TEST(add_sub_zero) {
5102 SETUP();
5103
5104 START();
5105 __ Mov(x0, 0);
5106 __ Mov(x1, 0);
5107 __ Mov(x2, 0);
5108
5109 Label blob1;
5110 __ Bind(&blob1);
5111 __ Add(x0, x0, 0);
5112 __ Sub(x1, x1, 0);
5113 __ Sub(x2, x2, xzr);
5114 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob1) == 0);
5115
5116 Label blob2;
5117 __ Bind(&blob2);
5118 __ Add(w3, w3, 0);
5119 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob2) != 0);
5120
5121 Label blob3;
5122 __ Bind(&blob3);
5123 __ Sub(w3, w3, wzr);
5124 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob3) != 0);
5125
5126 END();
5127
5128 if (CAN_RUN()) {
5129 RUN();
5130
5131 ASSERT_EQUAL_64(0, x0);
5132 ASSERT_EQUAL_64(0, x1);
5133 ASSERT_EQUAL_64(0, x2);
5134 }
5135 }
5136
5137
5138 TEST(claim_drop_zero) {
5139 SETUP();
5140
5141 START();
5142
5143 Label start;
5144 __ Bind(&start);
5145 __ Claim(Operand(0));
5146 __ Drop(Operand(0));
5147 __ Claim(Operand(xzr));
5148 __ Drop(Operand(xzr));
5149 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
5150
5151 END();
5152
5153 if (CAN_RUN()) {
5154 RUN();
5155 }
5156 }
5157
5158
5159 TEST(neg) {
5160 SETUP();
5161
5162 START();
5163 __ Mov(x0, 0xf123456789abcdef);
5164
5165 // Immediate.
5166 __ Neg(x1, 0x123);
5167 __ Neg(w2, 0x123);
5168
5169 // Shifted.
5170 __ Neg(x3, Operand(x0, LSL, 1));
5171 __ Neg(w4, Operand(w0, LSL, 2));
5172 __ Neg(x5, Operand(x0, LSR, 3));
5173 __ Neg(w6, Operand(w0, LSR, 4));
5174 __ Neg(x7, Operand(x0, ASR, 5));
5175 __ Neg(w8, Operand(w0, ASR, 6));
5176
5177 // Extended.
5178 __ Neg(w9, Operand(w0, UXTB));
5179 __ Neg(x10, Operand(x0, SXTB, 1));
5180 __ Neg(w11, Operand(w0, UXTH, 2));
5181 __ Neg(x12, Operand(x0, SXTH, 3));
5182 __ Neg(w13, Operand(w0, UXTW, 4));
5183 __ Neg(x14, Operand(x0, SXTW, 4));
5184 END();
5185
5186 if (CAN_RUN()) {
5187 RUN();
5188
5189 ASSERT_EQUAL_64(0xfffffffffffffedd, x1);
5190 ASSERT_EQUAL_64(0xfffffedd, x2);
5191 ASSERT_EQUAL_64(0x1db97530eca86422, x3);
5192 ASSERT_EQUAL_64(0xd950c844, x4);
5193 ASSERT_EQUAL_64(0xe1db97530eca8643, x5);
5194 ASSERT_EQUAL_64(0xf7654322, x6);
5195 ASSERT_EQUAL_64(0x0076e5d4c3b2a191, x7);
5196 ASSERT_EQUAL_64(0x01d950c9, x8);
5197 ASSERT_EQUAL_64(0xffffff11, x9);
5198 ASSERT_EQUAL_64(0x0000000000000022, x10);
5199 ASSERT_EQUAL_64(0xfffcc844, x11);
5200 ASSERT_EQUAL_64(0x0000000000019088, x12);
5201 ASSERT_EQUAL_64(0x65432110, x13);
5202 ASSERT_EQUAL_64(0x0000000765432110, x14);
5203 }
5204 }
5205
5206
5207 template <typename T, typename Op>
5208 static void AdcsSbcsHelper(
5209 Op op, T left, T right, int carry, T expected, StatusFlags expected_flags) {
5210 int reg_size = sizeof(T) * 8;
5211 Register left_reg(0, reg_size);
5212 Register right_reg(1, reg_size);
5213 Register result_reg(2, reg_size);
5214
5215 SETUP();
5216 START();
5217
5218 __ Mov(left_reg, left);
5219 __ Mov(right_reg, right);
5220 __ Mov(x10, (carry ? CFlag : NoFlag));
5221
5222 __ Msr(NZCV, x10);
5223 (masm.*op)(result_reg, left_reg, right_reg);
5224
5225 END();
5226 if (CAN_RUN()) {
5227 RUN();
5228
5229 ASSERT_EQUAL_64(left, left_reg.X());
5230 ASSERT_EQUAL_64(right, right_reg.X());
5231 ASSERT_EQUAL_64(expected, result_reg.X());
5232 ASSERT_EQUAL_NZCV(expected_flags);
5233 }
5234 }
5235
5236
5237 TEST(adcs_sbcs_x) {
5238 uint64_t inputs[] = {
5239 0x0000000000000000,
5240 0x0000000000000001,
5241 0x7ffffffffffffffe,
5242 0x7fffffffffffffff,
5243 0x8000000000000000,
5244 0x8000000000000001,
5245 0xfffffffffffffffe,
5246 0xffffffffffffffff,
5247 };
5248 static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]);
5249
5250 struct Expected {
5251 uint64_t carry0_result;
5252 StatusFlags carry0_flags;
5253 uint64_t carry1_result;
5254 StatusFlags carry1_flags;
5255 };
5256
5257 static const Expected expected_adcs_x[input_count][input_count] =
5258 {{{0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag},
5259 {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
5260 {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
5261 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5262 {0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
5263 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5264 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5265 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}},
5266 {{0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
5267 {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag},
5268 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5269 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5270 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5271 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5272 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5273 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}},
5274 {{0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
5275 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5276 {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag},
5277 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5278 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5279 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5280 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5281 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}},
5282 {{0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5283 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5284 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5285 {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag},
5286 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5287 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5288 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5289 {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}},
5290 {{0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
5291 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5292 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5293 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5294 {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag},
5295 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5296 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5297 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}},
5298 {{0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5299 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5300 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5301 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5302 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5303 {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag},
5304 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5305 {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}},
5306 {{0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5307 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5308 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5309 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5310 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5311 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5312 {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag},
5313 {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}},
5314 {{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5315 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5316 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5317 {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
5318 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5319 {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
5320 {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
5321 {0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}}};
5322
5323 static const Expected expected_sbcs_x[input_count][input_count] =
5324 {{{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5325 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5326 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5327 {0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
5328 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5329 {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
5330 {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
5331 {0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}},
5332 {{0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5333 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5334 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5335 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5336 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5337 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5338 {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag},
5339 {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}},
5340 {{0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5341 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5342 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5343 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5344 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5345 {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag},
5346 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5347 {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}},
5348 {{0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
5349 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5350 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5351 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5352 {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag},
5353 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5354 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5355 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}},
5356 {{0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5357 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5358 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5359 {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag},
5360 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5361 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5362 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5363 {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}},
5364 {{0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
5365 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5366 {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag},
5367 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5368 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5369 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5370 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5371 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}},
5372 {{0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
5373 {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag},
5374 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5375 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5376 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5377 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5378 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5379 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}},
5380 {{0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag},
5381 {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
5382 {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
5383 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5384 {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
5385 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5386 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5387 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}}};
5388
5389 for (size_t left = 0; left < input_count; left++) {
5390 for (size_t right = 0; right < input_count; right++) {
5391 const Expected& expected = expected_adcs_x[left][right];
5392 AdcsSbcsHelper(&MacroAssembler::Adcs,
5393 inputs[left],
5394 inputs[right],
5395 0,
5396 expected.carry0_result,
5397 expected.carry0_flags);
5398 AdcsSbcsHelper(&MacroAssembler::Adcs,
5399 inputs[left],
5400 inputs[right],
5401 1,
5402 expected.carry1_result,
5403 expected.carry1_flags);
5404 }
5405 }
5406
5407 for (size_t left = 0; left < input_count; left++) {
5408 for (size_t right = 0; right < input_count; right++) {
5409 const Expected& expected = expected_sbcs_x[left][right];
5410 AdcsSbcsHelper(&MacroAssembler::Sbcs,
5411 inputs[left],
5412 inputs[right],
5413 0,
5414 expected.carry0_result,
5415 expected.carry0_flags);
5416 AdcsSbcsHelper(&MacroAssembler::Sbcs,
5417 inputs[left],
5418 inputs[right],
5419 1,
5420 expected.carry1_result,
5421 expected.carry1_flags);
5422 }
5423 }
5424 }
5425
5426
5427 TEST(adcs_sbcs_w) {
5428 uint32_t inputs[] = {
5429 0x00000000,
5430 0x00000001,
5431 0x7ffffffe,
5432 0x7fffffff,
5433 0x80000000,
5434 0x80000001,
5435 0xfffffffe,
5436 0xffffffff,
5437 };
5438 static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]);
5439
5440 struct Expected {
5441 uint32_t carry0_result;
5442 StatusFlags carry0_flags;
5443 uint32_t carry1_result;
5444 StatusFlags carry1_flags;
5445 };
5446
5447 static const Expected expected_adcs_w[input_count][input_count] =
5448 {{{0x00000000, ZFlag, 0x00000001, NoFlag},
5449 {0x00000001, NoFlag, 0x00000002, NoFlag},
5450 {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5451 {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5452 {0x80000000, NFlag, 0x80000001, NFlag},
5453 {0x80000001, NFlag, 0x80000002, NFlag},
5454 {0xfffffffe, NFlag, 0xffffffff, NFlag},
5455 {0xffffffff, NFlag, 0x00000000, ZCFlag}},
5456 {{0x00000001, NoFlag, 0x00000002, NoFlag},
5457 {0x00000002, NoFlag, 0x00000003, NoFlag},
5458 {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5459 {0x80000000, NVFlag, 0x80000001, NVFlag},
5460 {0x80000001, NFlag, 0x80000002, NFlag},
5461 {0x80000002, NFlag, 0x80000003, NFlag},
5462 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5463 {0x00000000, ZCFlag, 0x00000001, CFlag}},
5464 {{0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5465 {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5466 {0xfffffffc, NVFlag, 0xfffffffd, NVFlag},
5467 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5468 {0xfffffffe, NFlag, 0xffffffff, NFlag},
5469 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5470 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5471 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}},
5472 {{0x7fffffff, NoFlag, 0x80000000, NVFlag},
5473 {0x80000000, NVFlag, 0x80000001, NVFlag},
5474 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5475 {0xfffffffe, NVFlag, 0xffffffff, NVFlag},
5476 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5477 {0x00000000, ZCFlag, 0x00000001, CFlag},
5478 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5479 {0x7ffffffe, CFlag, 0x7fffffff, CFlag}},
5480 {{0x80000000, NFlag, 0x80000001, NFlag},
5481 {0x80000001, NFlag, 0x80000002, NFlag},
5482 {0xfffffffe, NFlag, 0xffffffff, NFlag},
5483 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5484 {0x00000000, ZCVFlag, 0x00000001, CVFlag},
5485 {0x00000001, CVFlag, 0x00000002, CVFlag},
5486 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5487 {0x7fffffff, CVFlag, 0x80000000, NCFlag}},
5488 {{0x80000001, NFlag, 0x80000002, NFlag},
5489 {0x80000002, NFlag, 0x80000003, NFlag},
5490 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5491 {0x00000000, ZCFlag, 0x00000001, CFlag},
5492 {0x00000001, CVFlag, 0x00000002, CVFlag},
5493 {0x00000002, CVFlag, 0x00000003, CVFlag},
5494 {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5495 {0x80000000, NCFlag, 0x80000001, NCFlag}},
5496 {{0xfffffffe, NFlag, 0xffffffff, NFlag},
5497 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5498 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5499 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5500 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5501 {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5502 {0xfffffffc, NCFlag, 0xfffffffd, NCFlag},
5503 {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}},
5504 {{0xffffffff, NFlag, 0x00000000, ZCFlag},
5505 {0x00000000, ZCFlag, 0x00000001, CFlag},
5506 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5507 {0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5508 {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5509 {0x80000000, NCFlag, 0x80000001, NCFlag},
5510 {0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5511 {0xfffffffe, NCFlag, 0xffffffff, NCFlag}}};
5512
5513 static const Expected expected_sbcs_w[input_count][input_count] =
5514 {{{0xffffffff, NFlag, 0x00000000, ZCFlag},
5515 {0xfffffffe, NFlag, 0xffffffff, NFlag},
5516 {0x80000001, NFlag, 0x80000002, NFlag},
5517 {0x80000000, NFlag, 0x80000001, NFlag},
5518 {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5519 {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5520 {0x00000001, NoFlag, 0x00000002, NoFlag},
5521 {0x00000000, ZFlag, 0x00000001, NoFlag}},
5522 {{0x00000000, ZCFlag, 0x00000001, CFlag},
5523 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5524 {0x80000002, NFlag, 0x80000003, NFlag},
5525 {0x80000001, NFlag, 0x80000002, NFlag},
5526 {0x80000000, NVFlag, 0x80000001, NVFlag},
5527 {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5528 {0x00000002, NoFlag, 0x00000003, NoFlag},
5529 {0x00000001, NoFlag, 0x00000002, NoFlag}},
5530 {{0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5531 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5532 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5533 {0xfffffffe, NFlag, 0xffffffff, NFlag},
5534 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5535 {0xfffffffc, NVFlag, 0xfffffffd, NVFlag},
5536 {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5537 {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}},
5538 {{0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5539 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5540 {0x00000000, ZCFlag, 0x00000001, CFlag},
5541 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5542 {0xfffffffe, NVFlag, 0xffffffff, NVFlag},
5543 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5544 {0x80000000, NVFlag, 0x80000001, NVFlag},
5545 {0x7fffffff, NoFlag, 0x80000000, NVFlag}},
5546 {{0x7fffffff, CVFlag, 0x80000000, NCFlag},
5547 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5548 {0x00000001, CVFlag, 0x00000002, CVFlag},
5549 {0x00000000, ZCVFlag, 0x00000001, CVFlag},
5550 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5551 {0xfffffffe, NFlag, 0xffffffff, NFlag},
5552 {0x80000001, NFlag, 0x80000002, NFlag},
5553 {0x80000000, NFlag, 0x80000001, NFlag}},
5554 {{0x80000000, NCFlag, 0x80000001, NCFlag},
5555 {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5556 {0x00000002, CVFlag, 0x00000003, CVFlag},
5557 {0x00000001, CVFlag, 0x00000002, CVFlag},
5558 {0x00000000, ZCFlag, 0x00000001, CFlag},
5559 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5560 {0x80000002, NFlag, 0x80000003, NFlag},
5561 {0x80000001, NFlag, 0x80000002, NFlag}},
5562 {{0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5563 {0xfffffffc, NCFlag, 0xfffffffd, NCFlag},
5564 {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5565 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5566 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5567 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5568 {0xffffffff, NFlag, 0x00000000, ZCFlag},
5569 {0xfffffffe, NFlag, 0xffffffff, NFlag}},
5570 {{0xfffffffe, NCFlag, 0xffffffff, NCFlag},
5571 {0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5572 {0x80000000, NCFlag, 0x80000001, NCFlag},
5573 {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5574 {0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5575 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5576 {0x00000000, ZCFlag, 0x00000001, CFlag},
5577 {0xffffffff, NFlag, 0x00000000, ZCFlag}}};
5578
5579 for (size_t left = 0; left < input_count; left++) {
5580 for (size_t right = 0; right < input_count; right++) {
5581 const Expected& expected = expected_adcs_w[left][right];
5582 AdcsSbcsHelper(&MacroAssembler::Adcs,
5583 inputs[left],
5584 inputs[right],
5585 0,
5586 expected.carry0_result,
5587 expected.carry0_flags);
5588 AdcsSbcsHelper(&MacroAssembler::Adcs,
5589 inputs[left],
5590 inputs[right],
5591 1,
5592 expected.carry1_result,
5593 expected.carry1_flags);
5594 }
5595 }
5596
5597 for (size_t left = 0; left < input_count; left++) {
5598 for (size_t right = 0; right < input_count; right++) {
5599 const Expected& expected = expected_sbcs_w[left][right];
5600 AdcsSbcsHelper(&MacroAssembler::Sbcs,
5601 inputs[left],
5602 inputs[right],
5603 0,
5604 expected.carry0_result,
5605 expected.carry0_flags);
5606 AdcsSbcsHelper(&MacroAssembler::Sbcs,
5607 inputs[left],
5608 inputs[right],
5609 1,
5610 expected.carry1_result,
5611 expected.carry1_flags);
5612 }
5613 }
5614 }
5615
5616
5617 TEST(adc_sbc_shift) {
5618 SETUP();
5619
5620 START();
5621 __ Mov(x0, 0);
5622 __ Mov(x1, 1);
5623 __ Mov(x2, 0x0123456789abcdef);
5624 __ Mov(x3, 0xfedcba9876543210);
5625 __ Mov(x4, 0xffffffffffffffff);
5626
5627 // Clear the C flag.
5628 __ Adds(x0, x0, Operand(0));
5629
5630 __ Adc(x5, x2, Operand(x3));
5631 __ Adc(x6, x0, Operand(x1, LSL, 60));
5632 __ Sbc(x7, x4, Operand(x3, LSR, 4));
5633 __ Adc(x8, x2, Operand(x3, ASR, 4));
5634 __ Adc(x9, x2, Operand(x3, ROR, 8));
5635
5636 __ Adc(w10, w2, Operand(w3));
5637 __ Adc(w11, w0, Operand(w1, LSL, 30));
5638 __ Sbc(w12, w4, Operand(w3, LSR, 4));
5639 __ Adc(w13, w2, Operand(w3, ASR, 4));
5640 __ Adc(w14, w2, Operand(w3, ROR, 8));
5641
5642 // Set the C flag.
5643 __ Cmp(w0, Operand(w0));
5644
5645 __ Adc(x18, x2, Operand(x3));
5646 __ Adc(x19, x0, Operand(x1, LSL, 60));
5647 __ Sbc(x20, x4, Operand(x3, LSR, 4));
5648 __ Adc(x21, x2, Operand(x3, ASR, 4));
5649 __ Adc(x22, x2, Operand(x3, ROR, 8));
5650
5651 __ Adc(w23, w2, Operand(w3));
5652 __ Adc(w24, w0, Operand(w1, LSL, 30));
5653 __ Sbc(w25, w4, Operand(w3, LSR, 4));
5654 __ Adc(w26, w2, Operand(w3, ASR, 4));
5655 __ Adc(w27, w2, Operand(w3, ROR, 8));
5656 END();
5657
5658 if (CAN_RUN()) {
5659 RUN();
5660
5661 ASSERT_EQUAL_64(0xffffffffffffffff, x5);
5662 ASSERT_EQUAL_64(INT64_C(1) << 60, x6);
5663 ASSERT_EQUAL_64(0xf0123456789abcdd, x7);
5664 ASSERT_EQUAL_64(0x0111111111111110, x8);
5665 ASSERT_EQUAL_64(0x1222222222222221, x9);
5666
5667 ASSERT_EQUAL_32(0xffffffff, w10);
5668 ASSERT_EQUAL_32(INT32_C(1) << 30, w11);
5669 ASSERT_EQUAL_32(0xf89abcdd, w12);
5670 ASSERT_EQUAL_32(0x91111110, w13);
5671 ASSERT_EQUAL_32(0x9a222221, w14);
5672
5673 ASSERT_EQUAL_64(0xffffffffffffffff + 1, x18);
5674 ASSERT_EQUAL_64((INT64_C(1) << 60) + 1, x19);
5675 ASSERT_EQUAL_64(0xf0123456789abcdd + 1, x20);
5676 ASSERT_EQUAL_64(0x0111111111111110 + 1, x21);
5677 ASSERT_EQUAL_64(0x1222222222222221 + 1, x22);
5678
5679 ASSERT_EQUAL_32(0xffffffff + 1, w23);
5680 ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, w24);
5681 ASSERT_EQUAL_32(0xf89abcdd + 1, w25);
5682 ASSERT_EQUAL_32(0x91111110 + 1, w26);
5683 ASSERT_EQUAL_32(0x9a222221 + 1, w27);
5684 }
5685 }
5686
5687
5688 TEST(adc_sbc_extend) {
5689 SETUP();
5690
5691 START();
5692 // Clear the C flag.
5693 __ Adds(x0, x0, Operand(0));
5694
5695 __ Mov(x0, 0);
5696 __ Mov(x1, 1);
5697 __ Mov(x2, 0x0123456789abcdef);
5698
5699 __ Adc(x10, x1, Operand(w2, UXTB, 1));
5700 __ Adc(x11, x1, Operand(x2, SXTH, 2));
5701 __ Sbc(x12, x1, Operand(w2, UXTW, 4));
5702 __ Adc(x13, x1, Operand(x2, UXTX, 4));
5703
5704 __ Adc(w14, w1, Operand(w2, UXTB, 1));
5705 __ Adc(w15, w1, Operand(w2, SXTH, 2));
5706 __ Adc(w9, w1, Operand(w2, UXTW, 4));
5707
5708 // Set the C flag.
5709 __ Cmp(w0, Operand(w0));
5710
5711 __ Adc(x20, x1, Operand(w2, UXTB, 1));
5712 __ Adc(x21, x1, Operand(x2, SXTH, 2));
5713 __ Sbc(x22, x1, Operand(w2, UXTW, 4));
5714 __ Adc(x23, x1, Operand(x2, UXTX, 4));
5715
5716 __ Adc(w24, w1, Operand(w2, UXTB, 1));
5717 __ Adc(w25, w1, Operand(w2, SXTH, 2));
5718 __ Adc(w26, w1, Operand(w2, UXTW, 4));
5719 END();
5720
5721 if (CAN_RUN()) {
5722 RUN();
5723
5724 ASSERT_EQUAL_64(0x1df, x10);
5725 ASSERT_EQUAL_64(0xffffffffffff37bd, x11);
5726 ASSERT_EQUAL_64(0xfffffff765432110, x12);
5727 ASSERT_EQUAL_64(0x123456789abcdef1, x13);
5728
5729 ASSERT_EQUAL_32(0x1df, w14);
5730 ASSERT_EQUAL_32(0xffff37bd, w15);
5731 ASSERT_EQUAL_32(0x9abcdef1, w9);
5732
5733 ASSERT_EQUAL_64(0x1df + 1, x20);
5734 ASSERT_EQUAL_64(0xffffffffffff37bd + 1, x21);
5735 ASSERT_EQUAL_64(0xfffffff765432110 + 1, x22);
5736 ASSERT_EQUAL_64(0x123456789abcdef1 + 1, x23);
5737
5738 ASSERT_EQUAL_32(0x1df + 1, w24);
5739 ASSERT_EQUAL_32(0xffff37bd + 1, w25);
5740 ASSERT_EQUAL_32(0x9abcdef1 + 1, w26);
5741 }
5742
5743 // Check that adc correctly sets the condition flags.
5744 START();
5745 __ Mov(x0, 0xff);
5746 __ Mov(x1, 0xffffffffffffffff);
5747 // Clear the C flag.
5748 __ Adds(x0, x0, Operand(0));
5749 __ Adcs(x10, x0, Operand(x1, SXTX, 1));
5750 END();
5751
5752 if (CAN_RUN()) {
5753 RUN();
5754
5755 ASSERT_EQUAL_NZCV(CFlag);
5756 }
5757
5758 START();
5759 __ Mov(x0, 0x7fffffffffffffff);
5760 __ Mov(x1, 1);
5761 // Clear the C flag.
5762 __ Adds(x0, x0, Operand(0));
5763 __ Adcs(x10, x0, Operand(x1, UXTB, 2));
5764 END();
5765
5766 if (CAN_RUN()) {
5767 RUN();
5768
5769 ASSERT_EQUAL_NZCV(NVFlag);
5770 }
5771
5772 START();
5773 __ Mov(x0, 0x7fffffffffffffff);
5774 // Clear the C flag.
5775 __ Adds(x0, x0, Operand(0));
5776 __ Adcs(x10, x0, Operand(1));
5777 END();
5778
5779 if (CAN_RUN()) {
5780 RUN();
5781
5782 ASSERT_EQUAL_NZCV(NVFlag);
5783 }
5784 }
5785
5786
5787 TEST(adc_sbc_wide_imm) {
5788 SETUP();
5789
5790 START();
5791 __ Mov(x0, 0);
5792
5793 // Clear the C flag.
5794 __ Adds(x0, x0, Operand(0));
5795
5796 __ Adc(x7, x0, Operand(0x1234567890abcdef));
5797 __ Adc(w8, w0, Operand(0xffffffff));
5798 __ Sbc(x9, x0, Operand(0x1234567890abcdef));
5799 __ Sbc(w10, w0, Operand(0xffffffff));
5800 __ Ngc(x11, Operand(0xffffffff00000000));
5801 __ Ngc(w12, Operand(0xffff0000));
5802
5803 // Set the C flag.
5804 __ Cmp(w0, Operand(w0));
5805
5806 __ Adc(x18, x0, Operand(0x1234567890abcdef));
5807 __ Adc(w19, w0, Operand(0xffffffff));
5808 __ Sbc(x20, x0, Operand(0x1234567890abcdef));
5809 __ Sbc(w21, w0, Operand(0xffffffff));
5810 __ Ngc(x22, Operand(0xffffffff00000000));
5811 __ Ngc(w23, Operand(0xffff0000));
5812 END();
5813
5814 if (CAN_RUN()) {
5815 RUN();
5816
5817 ASSERT_EQUAL_64(0x1234567890abcdef, x7);
5818 ASSERT_EQUAL_64(0xffffffff, x8);
5819 ASSERT_EQUAL_64(0xedcba9876f543210, x9);
5820 ASSERT_EQUAL_64(0, x10);
5821 ASSERT_EQUAL_64(0xffffffff, x11);
5822 ASSERT_EQUAL_64(0xffff, x12);
5823
5824 ASSERT_EQUAL_64(0x1234567890abcdef + 1, x18);
5825 ASSERT_EQUAL_64(0, x19);
5826 ASSERT_EQUAL_64(0xedcba9876f543211, x20);
5827 ASSERT_EQUAL_64(1, x21);
5828 ASSERT_EQUAL_64(0x0000000100000000, x22);
5829 ASSERT_EQUAL_64(0x0000000000010000, x23);
5830 }
5831 }
5832
5833
5834 TEST(rmif) {
5835 SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
5836
5837 START();
5838 __ Mov(x0, 0x0123456789abcdef);
5839
5840 // Set NZCV to 0b1011 (0xb)
5841 __ Rmif(x0, 0, NCVFlag);
5842 __ Mrs(x1, NZCV);
5843
5844 // Set NZCV to 0b0111 (0x7)
5845 __ Rmif(x0, 6, NZCVFlag);
5846 __ Mrs(x2, NZCV);
5847
5848 // Set Z to 0, NZCV = 0b0011 (0x3)
5849 __ Rmif(x0, 60, ZFlag);
5850 __ Mrs(x3, NZCV);
5851
5852 // Set N to 1 and C to 0, NZCV = 0b1001 (0x9)
5853 __ Rmif(x0, 62, NCFlag);
5854 __ Mrs(x4, NZCV);
5855
5856 // No change to NZCV
5857 __ Rmif(x0, 0, NoFlag);
5858 __ Mrs(x5, NZCV);
5859 END();
5860
5861 if (CAN_RUN()) {
5862 RUN();
5863 ASSERT_EQUAL_32(NCVFlag, w1);
5864 ASSERT_EQUAL_32(ZCVFlag, w2);
5865 ASSERT_EQUAL_32(CVFlag, w3);
5866 ASSERT_EQUAL_32(NVFlag, w4);
5867 ASSERT_EQUAL_32(NVFlag, w5);
5868 }
5869 }
5870
5871
5872 TEST(setf8_setf16) {
5873 SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
5874
5875 START();
5876 __ Mov(x0, 0x0);
5877 __ Mov(x1, 0x1);
5878 __ Mov(x2, 0xff);
5879 __ Mov(x3, 0x100);
5880 __ Mov(x4, 0x101);
5881 __ Mov(x5, 0xffff);
5882 __ Mov(x6, 0x10000);
5883 __ Mov(x7, 0x10001);
5884 __ Mov(x8, 0xfffffffff);
5885
5886 __ Setf8(w0);
5887 __ Mrs(x9, NZCV);
5888 __ Setf8(w1);
5889 __ Mrs(x10, NZCV);
5890 __ Setf8(w2);
5891 __ Mrs(x11, NZCV);
5892 __ Setf8(w3);
5893 __ Mrs(x12, NZCV);
5894 __ Setf8(w4);
5895 __ Mrs(x13, NZCV);
5896 __ Setf8(w8);
5897 __ Mrs(x14, NZCV);
5898
5899 __ Setf16(w0);
5900 __ Mrs(x15, NZCV);
5901 __ Setf16(w1);
5902 __ Mrs(x16, NZCV);
5903 __ Setf16(w5);
5904 __ Mrs(x17, NZCV);
5905 __ Setf16(w6);
5906 __ Mrs(x18, NZCV);
5907 __ Setf16(w7);
5908 __ Mrs(x19, NZCV);
5909 __ Setf16(w8);
5910 __ Mrs(x20, NZCV);
5911 END();
5912
5913 if (CAN_RUN()) {
5914 RUN();
5915
5916 ASSERT_EQUAL_32(ZFlag, w9); // Zero
5917 ASSERT_EQUAL_32(NoFlag, w10); // Regular int8
5918 ASSERT_EQUAL_32(NVFlag, w11); // Negative but not sign-extended (overflow)
5919 ASSERT_EQUAL_32(ZVFlag, w12); // Overflow with zero remainder
5920 ASSERT_EQUAL_32(VFlag, w13); // Overflow with non-zero remainder
5921 ASSERT_EQUAL_32(NFlag, w14); // Negative and sign-extended
5922
5923 ASSERT_EQUAL_32(ZFlag, w15); // Zero
5924 ASSERT_EQUAL_32(NoFlag, w16); // Regular int16
5925 ASSERT_EQUAL_32(NVFlag, w17); // Negative but not sign-extended (overflow)
5926 ASSERT_EQUAL_32(ZVFlag, w18); // Overflow with zero remainder
5927 ASSERT_EQUAL_32(VFlag, w19); // Overflow with non-zero remainder
5928 ASSERT_EQUAL_32(NFlag, w20); // Negative and sign-extended
5929 }
5930 }
5931
5932
5933 TEST(flags) {
5934 SETUP();
5935
5936 START();
5937 __ Mov(x0, 0);
5938 __ Mov(x1, 0x1111111111111111);
5939 __ Neg(x10, Operand(x0));
5940 __ Neg(x11, Operand(x1));
5941 __ Neg(w12, Operand(w1));
5942 // Clear the C flag.
5943 __ Adds(x0, x0, Operand(0));
5944 __ Ngc(x13, Operand(x0));
5945 // Set the C flag.
5946 __ Cmp(x0, Operand(x0));
5947 __ Ngc(w14, Operand(w0));
5948 END();
5949
5950 if (CAN_RUN()) {
5951 RUN();
5952
5953 ASSERT_EQUAL_64(0, x10);
5954 ASSERT_EQUAL_64(-0x1111111111111111, x11);
5955 ASSERT_EQUAL_32(-0x11111111, w12);
5956 ASSERT_EQUAL_64(-1, x13);
5957 ASSERT_EQUAL_32(0, w14);
5958 }
5959
5960 START();
5961 __ Mov(x0, 0);
5962 __ Cmp(x0, Operand(x0));
5963 END();
5964
5965 if (CAN_RUN()) {
5966 RUN();
5967
5968 ASSERT_EQUAL_NZCV(ZCFlag);
5969 }
5970
5971 START();
5972 __ Mov(w0, 0);
5973 __ Cmp(w0, Operand(w0));
5974 END();
5975
5976 if (CAN_RUN()) {
5977 RUN();
5978
5979 ASSERT_EQUAL_NZCV(ZCFlag);
5980 }
5981
5982 START();
5983 __ Mov(x0, 0);
5984 __ Mov(x1, 0x1111111111111111);
5985 __ Cmp(x0, Operand(x1));
5986 END();
5987
5988 if (CAN_RUN()) {
5989 RUN();
5990
5991 ASSERT_EQUAL_NZCV(NFlag);
5992 }
5993
5994 START();
5995 __ Mov(w0, 0);
5996 __ Mov(w1, 0x11111111);
5997 __ Cmp(w0, Operand(w1));
5998 END();
5999
6000 if (CAN_RUN()) {
6001 RUN();
6002
6003 ASSERT_EQUAL_NZCV(NFlag);
6004 }
6005
6006 START();
6007 __ Mov(x1, 0x1111111111111111);
6008 __ Cmp(x1, Operand(0));
6009 END();
6010
6011 if (CAN_RUN()) {
6012 RUN();
6013
6014 ASSERT_EQUAL_NZCV(CFlag);
6015 }
6016
6017 START();
6018 __ Mov(w1, 0x11111111);
6019 __ Cmp(w1, Operand(0));
6020 END();
6021
6022 if (CAN_RUN()) {
6023 RUN();
6024
6025 ASSERT_EQUAL_NZCV(CFlag);
6026 }
6027
6028 START();
6029 __ Mov(x0, 1);
6030 __ Mov(x1, 0x7fffffffffffffff);
6031 __ Cmn(x1, Operand(x0));
6032 END();
6033
6034 if (CAN_RUN()) {
6035 RUN();
6036
6037 ASSERT_EQUAL_NZCV(NVFlag);
6038 }
6039
6040 START();
6041 __ Mov(w0, 1);
6042 __ Mov(w1, 0x7fffffff);
6043 __ Cmn(w1, Operand(w0));
6044 END();
6045
6046 if (CAN_RUN()) {
6047 RUN();
6048
6049 ASSERT_EQUAL_NZCV(NVFlag);
6050 }
6051
6052 START();
6053 __ Mov(x0, 1);
6054 __ Mov(x1, 0xffffffffffffffff);
6055 __ Cmn(x1, Operand(x0));
6056 END();
6057
6058 if (CAN_RUN()) {
6059 RUN();
6060
6061 ASSERT_EQUAL_NZCV(ZCFlag);
6062 }
6063
6064 START();
6065 __ Mov(w0, 1);
6066 __ Mov(w1, 0xffffffff);
6067 __ Cmn(w1, Operand(w0));
6068 END();
6069
6070 if (CAN_RUN()) {
6071 RUN();
6072
6073 ASSERT_EQUAL_NZCV(ZCFlag);
6074 }
6075
6076 START();
6077 __ Mov(w0, 0);
6078 __ Mov(w1, 1);
6079 // Clear the C flag.
6080 __ Adds(w0, w0, Operand(0));
6081 __ Ngcs(w0, Operand(w1));
6082 END();
6083
6084 if (CAN_RUN()) {
6085 RUN();
6086
6087 ASSERT_EQUAL_NZCV(NFlag);
6088 }
6089
6090 START();
6091 __ Mov(w0, 0);
6092 __ Mov(w1, 0);
6093 // Set the C flag.
6094 __ Cmp(w0, Operand(w0));
6095 __ Ngcs(w0, Operand(w1));
6096 END();
6097
6098 if (CAN_RUN()) {
6099 RUN();
6100
6101 ASSERT_EQUAL_NZCV(ZCFlag);
6102 }
6103 }
6104
6105
6106 TEST(cmp_shift) {
6107 SETUP();
6108
6109 START();
6110 __ Mov(x18, 0xf0000000);
6111 __ Mov(x19, 0xf000000010000000);
6112 __ Mov(x20, 0xf0000000f0000000);
6113 __ Mov(x21, 0x7800000078000000);
6114 __ Mov(x22, 0x3c0000003c000000);
6115 __ Mov(x23, 0x8000000780000000);
6116 __ Mov(x24, 0x0000000f00000000);
6117 __ Mov(x25, 0x00000003c0000000);
6118 __ Mov(x26, 0x8000000780000000);
6119 __ Mov(x27, 0xc0000003);
6120
6121 __ Cmp(w20, Operand(w21, LSL, 1));
6122 __ Mrs(x0, NZCV);
6123
6124 __ Cmp(x20, Operand(x22, LSL, 2));
6125 __ Mrs(x1, NZCV);
6126
6127 __ Cmp(w19, Operand(w23, LSR, 3));
6128 __ Mrs(x2, NZCV);
6129
6130 __ Cmp(x18, Operand(x24, LSR, 4));
6131 __ Mrs(x3, NZCV);
6132
6133 __ Cmp(w20, Operand(w25, ASR, 2));
6134 __ Mrs(x4, NZCV);
6135
6136 __ Cmp(x20, Operand(x26, ASR, 3));
6137 __ Mrs(x5, NZCV);
6138
6139 __ Cmp(w27, Operand(w22, ROR, 28));
6140 __ Mrs(x6, NZCV);
6141
6142 __ Cmp(x20, Operand(x21, ROR, 31));
6143 __ Mrs(x7, NZCV);
6144 END();
6145
6146 if (CAN_RUN()) {
6147 RUN();
6148
6149 ASSERT_EQUAL_32(ZCFlag, w0);
6150 ASSERT_EQUAL_32(ZCFlag, w1);
6151 ASSERT_EQUAL_32(ZCFlag, w2);
6152 ASSERT_EQUAL_32(ZCFlag, w3);
6153 ASSERT_EQUAL_32(ZCFlag, w4);
6154 ASSERT_EQUAL_32(ZCFlag, w5);
6155 ASSERT_EQUAL_32(ZCFlag, w6);
6156 ASSERT_EQUAL_32(ZCFlag, w7);
6157 }
6158 }
6159
6160
6161 TEST(cmp_extend) {
6162 SETUP();
6163
6164 START();
6165 __ Mov(w20, 0x2);
6166 __ Mov(w21, 0x1);
6167 __ Mov(x22, 0xffffffffffffffff);
6168 __ Mov(x23, 0xff);
6169 __ Mov(x24, 0xfffffffffffffffe);
6170 __ Mov(x25, 0xffff);
6171 __ Mov(x26, 0xffffffff);
6172
6173 __ Cmp(w20, Operand(w21, LSL, 1));
6174 __ Mrs(x0, NZCV);
6175
6176 __ Cmp(x22, Operand(x23, SXTB, 0));
6177 __ Mrs(x1, NZCV);
6178
6179 __ Cmp(x24, Operand(x23, SXTB, 1));
6180 __ Mrs(x2, NZCV);
6181
6182 __ Cmp(x24, Operand(x23, UXTB, 1));
6183 __ Mrs(x3, NZCV);
6184
6185 __ Cmp(w22, Operand(w25, UXTH));
6186 __ Mrs(x4, NZCV);
6187
6188 __ Cmp(x22, Operand(x25, SXTH));
6189 __ Mrs(x5, NZCV);
6190
6191 __ Cmp(x22, Operand(x26, UXTW));
6192 __ Mrs(x6, NZCV);
6193
6194 __ Cmp(x24, Operand(x26, SXTW, 1));
6195 __ Mrs(x7, NZCV);
6196 END();
6197
6198 if (CAN_RUN()) {
6199 RUN();
6200
6201 ASSERT_EQUAL_32(ZCFlag, w0);
6202 ASSERT_EQUAL_32(ZCFlag, w1);
6203 ASSERT_EQUAL_32(ZCFlag, w2);
6204 ASSERT_EQUAL_32(NCFlag, w3);
6205 ASSERT_EQUAL_32(NCFlag, w4);
6206 ASSERT_EQUAL_32(ZCFlag, w5);
6207 ASSERT_EQUAL_32(NCFlag, w6);
6208 ASSERT_EQUAL_32(ZCFlag, w7);
6209 }
6210 }
6211
6212
6213 TEST(ccmp) {
6214 SETUP();
6215
6216 START();
6217 __ Mov(w16, 0);
6218 __ Mov(w17, 1);
6219 __ Cmp(w16, w16);
6220 __ Ccmp(w16, w17, NCFlag, eq);
6221 __ Mrs(x0, NZCV);
6222
6223 __ Cmp(w16, w16);
6224 __ Ccmp(w16, w17, NCFlag, ne);
6225 __ Mrs(x1, NZCV);
6226
6227 __ Cmp(x16, x16);
6228 __ Ccmn(x16, 2, NZCVFlag, eq);
6229 __ Mrs(x2, NZCV);
6230
6231 __ Cmp(x16, x16);
6232 __ Ccmn(x16, 2, NZCVFlag, ne);
6233 __ Mrs(x3, NZCV);
6234
6235 // The MacroAssembler does not allow al as a condition.
6236 {
6237 ExactAssemblyScope scope(&masm, kInstructionSize);
6238 __ ccmp(x16, x16, NZCVFlag, al);
6239 }
6240 __ Mrs(x4, NZCV);
6241
6242 // The MacroAssembler does not allow nv as a condition.
6243 {
6244 ExactAssemblyScope scope(&masm, kInstructionSize);
6245 __ ccmp(x16, x16, NZCVFlag, nv);
6246 }
6247 __ Mrs(x5, NZCV);
6248
6249 END();
6250
6251 if (CAN_RUN()) {
6252 RUN();
6253
6254 ASSERT_EQUAL_32(NFlag, w0);
6255 ASSERT_EQUAL_32(NCFlag, w1);
6256 ASSERT_EQUAL_32(NoFlag, w2);
6257 ASSERT_EQUAL_32(NZCVFlag, w3);
6258 ASSERT_EQUAL_32(ZCFlag, w4);
6259 ASSERT_EQUAL_32(ZCFlag, w5);
6260 }
6261 }
6262
6263
6264 TEST(ccmp_wide_imm) {
6265 SETUP();
6266
6267 START();
6268 __ Mov(w20, 0);
6269
6270 __ Cmp(w20, Operand(w20));
6271 __ Ccmp(w20, Operand(0x12345678), NZCVFlag, eq);
6272 __ Mrs(x0, NZCV);
6273
6274 __ Cmp(w20, Operand(w20));
6275 __ Ccmp(x20, Operand(0xffffffffffffffff), NZCVFlag, eq);
6276 __ Mrs(x1, NZCV);
6277 END();
6278
6279 if (CAN_RUN()) {
6280 RUN();
6281
6282 ASSERT_EQUAL_32(NFlag, w0);
6283 ASSERT_EQUAL_32(NoFlag, w1);
6284 }
6285 }
6286
6287
6288 TEST(ccmp_shift_extend) {
6289 SETUP();
6290
6291 START();
6292 __ Mov(w20, 0x2);
6293 __ Mov(w21, 0x1);
6294 __ Mov(x22, 0xffffffffffffffff);
6295 __ Mov(x23, 0xff);
6296 __ Mov(x24, 0xfffffffffffffffe);
6297
6298 __ Cmp(w20, Operand(w20));
6299 __ Ccmp(w20, Operand(w21, LSL, 1), NZCVFlag, eq);
6300 __ Mrs(x0, NZCV);
6301
6302 __ Cmp(w20, Operand(w20));
6303 __ Ccmp(x22, Operand(x23, SXTB, 0), NZCVFlag, eq);
6304 __ Mrs(x1, NZCV);
6305
6306 __ Cmp(w20, Operand(w20));
6307 __ Ccmp(x24, Operand(x23, SXTB, 1), NZCVFlag, eq);
6308 __ Mrs(x2, NZCV);
6309
6310 __ Cmp(w20, Operand(w20));
6311 __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, eq);
6312 __ Mrs(x3, NZCV);
6313
6314 __ Cmp(w20, Operand(w20));
6315 __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, ne);
6316 __ Mrs(x4, NZCV);
6317 END();
6318
6319 if (CAN_RUN()) {
6320 RUN();
6321
6322 ASSERT_EQUAL_32(ZCFlag, w0);
6323 ASSERT_EQUAL_32(ZCFlag, w1);
6324 ASSERT_EQUAL_32(ZCFlag, w2);
6325 ASSERT_EQUAL_32(NCFlag, w3);
6326 ASSERT_EQUAL_32(NZCVFlag, w4);
6327 }
6328 }
6329
6330
6331 TEST(csel_reg) {
6332 SETUP();
6333
6334 START();
6335 __ Mov(x16, 0);
6336 __ Mov(x24, 0x0000000f0000000f);
6337 __ Mov(x25, 0x0000001f0000001f);
6338
6339 __ Cmp(w16, Operand(0));
6340 __ Csel(w0, w24, w25, eq);
6341 __ Csel(w1, w24, w25, ne);
6342 __ Csinc(w2, w24, w25, mi);
6343 __ Csinc(w3, w24, w25, pl);
6344
6345 // The MacroAssembler does not allow al or nv as a condition.
6346 {
6347 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
6348 __ csel(w13, w24, w25, al);
6349 __ csel(x14, x24, x25, nv);
6350 }
6351
6352 __ Cmp(x16, Operand(1));
6353 __ Csinv(x4, x24, x25, gt);
6354 __ Csinv(x5, x24, x25, le);
6355 __ Csneg(x6, x24, x25, hs);
6356 __ Csneg(x7, x24, x25, lo);
6357
6358 __ Cset(w8, ne);
6359 __ Csetm(w9, ne);
6360 __ Cinc(x10, x25, ne);
6361 __ Cinv(x11, x24, ne);
6362 __ Cneg(x12, x24, ne);
6363
6364 // The MacroAssembler does not allow al or nv as a condition.
6365 {
6366 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
6367 __ csel(w15, w24, w25, al);
6368 __ csel(x17, x24, x25, nv);
6369 }
6370
6371 END();
6372
6373 if (CAN_RUN()) {
6374 RUN();
6375
6376 ASSERT_EQUAL_64(0x0000000f, x0);
6377 ASSERT_EQUAL_64(0x0000001f, x1);
6378 ASSERT_EQUAL_64(0x00000020, x2);
6379 ASSERT_EQUAL_64(0x0000000f, x3);
6380 ASSERT_EQUAL_64(0xffffffe0ffffffe0, x4);
6381 ASSERT_EQUAL_64(0x0000000f0000000f, x5);
6382 ASSERT_EQUAL_64(0xffffffe0ffffffe1, x6);
6383 ASSERT_EQUAL_64(0x0000000f0000000f, x7);
6384 ASSERT_EQUAL_64(0x00000001, x8);
6385 ASSERT_EQUAL_64(0xffffffff, x9);
6386 ASSERT_EQUAL_64(0x0000001f00000020, x10);
6387 ASSERT_EQUAL_64(0xfffffff0fffffff0, x11);
6388 ASSERT_EQUAL_64(0xfffffff0fffffff1, x12);
6389 ASSERT_EQUAL_64(0x0000000f, x13);
6390 ASSERT_EQUAL_64(0x0000000f0000000f, x14);
6391 ASSERT_EQUAL_64(0x0000000f, x15);
6392 ASSERT_EQUAL_64(0x0000000f0000000f, x17);
6393 }
6394 }
6395
6396 TEST(csel_zero) {
6397 SETUP();
6398
6399 START();
6400
6401 __ Mov(x15, 0x0);
6402 __ Mov(x16, 0x0000001f0000002f);
6403
6404 // Check results when zero registers are used as inputs
6405 // for Csinc, Csinv and Csneg for both true and false conditions.
6406 __ Cmp(x15, 0);
6407 __ Csinc(x0, x16, xzr, eq);
6408 __ Csinc(x1, xzr, x16, eq);
6409 __ Cmp(x15, 1);
6410 __ Csinc(w2, w16, wzr, eq);
6411 __ Csinc(w3, wzr, w16, eq);
6412
6413 __ Csinc(x4, xzr, xzr, eq);
6414
6415 __ Cmp(x15, 0);
6416 __ Csinv(x5, x16, xzr, eq);
6417 __ Csinv(x6, xzr, x16, eq);
6418 __ Cmp(x15, 1);
6419 __ Csinv(w7, w16, wzr, eq);
6420 __ Csinv(w8, wzr, w16, eq);
6421
6422 __ Csinv(x9, xzr, xzr, eq);
6423
6424 __ Cmp(x15, 0);
6425 __ Csneg(x10, x16, xzr, eq);
6426 __ Csneg(x11, xzr, x16, eq);
6427 __ Cmp(x15, 1);
6428 __ Csneg(w12, w16, wzr, eq);
6429 __ Csneg(w13, wzr, w16, eq);
6430
6431 __ Csneg(x14, xzr, xzr, eq);
6432
6433 END();
6434
6435 if (CAN_RUN()) {
6436 RUN();
6437
6438 ASSERT_EQUAL_64(0x0000001f0000002f, x0);
6439 ASSERT_EQUAL_64(0x0, x1);
6440 ASSERT_EQUAL_32(0x1, w2);
6441 ASSERT_EQUAL_32(0x30, w3);
6442 ASSERT_EQUAL_64(0x1, x4);
6443 ASSERT_EQUAL_64(0x0000001f0000002f, x5);
6444 ASSERT_EQUAL_64(0x0, x6);
6445 ASSERT_EQUAL_32(0xffffffff, w7);
6446 ASSERT_EQUAL_32(0xffffffd0, w8);
6447 ASSERT_EQUAL_64(0xffffffffffffffff, x9);
6448 ASSERT_EQUAL_64(0x0000001f0000002f, x10);
6449 ASSERT_EQUAL_64(0x0, x11);
6450 ASSERT_EQUAL_32(0x0, w12);
6451 ASSERT_EQUAL_32(0xffffffd1, w13);
6452 ASSERT_EQUAL_64(0x0, x14);
6453 }
6454 }
6455
6456
6457 TEST(csel_imm) {
6458 SETUP();
6459
6460 int values[] = {-123, -2, -1, 0, 1, 2, 123};
6461 int n_values = sizeof(values) / sizeof(values[0]);
6462
6463 for (int i = 0; i < n_values; i++) {
6464 for (int j = 0; j < n_values; j++) {
6465 int left = values[i];
6466 int right = values[j];
6467
6468 START();
6469 __ Mov(x10, 0);
6470 __ Cmp(x10, 0);
6471 __ Csel(w0, left, right, eq);
6472 __ Csel(w1, left, right, ne);
6473 __ Csel(x2, left, right, eq);
6474 __ Csel(x3, left, right, ne);
6475
6476 END();
6477
6478 if (CAN_RUN()) {
6479 RUN();
6480
6481 ASSERT_EQUAL_32(left, w0);
6482 ASSERT_EQUAL_32(right, w1);
6483 ASSERT_EQUAL_64(left, x2);
6484 ASSERT_EQUAL_64(right, x3);
6485 }
6486 }
6487 }
6488 }
6489
6490
6491 TEST(csel_mixed) {
6492 SETUP();
6493
6494 START();
6495 __ Mov(x18, 0);
6496 __ Mov(x19, 0x80000000);
6497 __ Mov(x20, 0x8000000000000000);
6498
6499 __ Cmp(x18, Operand(0));
6500 __ Csel(w0, w19, -2, ne);
6501 __ Csel(w1, w19, -1, ne);
6502 __ Csel(w2, w19, 0, ne);
6503 __ Csel(w3, w19, 1, ne);
6504 __ Csel(w4, w19, 2, ne);
6505 __ Csel(w5, w19, Operand(w19, ASR, 31), ne);
6506 __ Csel(w6, w19, Operand(w19, ROR, 1), ne);
6507 __ Csel(w7, w19, 3, eq);
6508
6509 __ Csel(x8, x20, -2, ne);
6510 __ Csel(x9, x20, -1, ne);
6511 __ Csel(x10, x20, 0, ne);
6512 __ Csel(x11, x20, 1, ne);
6513 __ Csel(x12, x20, 2, ne);
6514 __ Csel(x13, x20, Operand(x20, ASR, 63), ne);
6515 __ Csel(x14, x20, Operand(x20, ROR, 1), ne);
6516 __ Csel(x15, x20, 3, eq);
6517
6518 END();
6519
6520 if (CAN_RUN()) {
6521 RUN();
6522
6523 ASSERT_EQUAL_32(-2, w0);
6524 ASSERT_EQUAL_32(-1, w1);
6525 ASSERT_EQUAL_32(0, w2);
6526 ASSERT_EQUAL_32(1, w3);
6527 ASSERT_EQUAL_32(2, w4);
6528 ASSERT_EQUAL_32(-1, w5);
6529 ASSERT_EQUAL_32(0x40000000, w6);
6530 ASSERT_EQUAL_32(0x80000000, w7);
6531
6532 ASSERT_EQUAL_64(-2, x8);
6533 ASSERT_EQUAL_64(-1, x9);
6534 ASSERT_EQUAL_64(0, x10);
6535 ASSERT_EQUAL_64(1, x11);
6536 ASSERT_EQUAL_64(2, x12);
6537 ASSERT_EQUAL_64(-1, x13);
6538 ASSERT_EQUAL_64(0x4000000000000000, x14);
6539 ASSERT_EQUAL_64(0x8000000000000000, x15);
6540 }
6541 }
6542
6543
6544 TEST(lslv) {
6545 SETUP();
6546
6547 uint64_t value = 0x0123456789abcdef;
6548 int shift[] = {1, 3, 5, 9, 17, 33};
6549
6550 START();
6551 __ Mov(x0, value);
6552 __ Mov(w1, shift[0]);
6553 __ Mov(w2, shift[1]);
6554 __ Mov(w3, shift[2]);
6555 __ Mov(w4, shift[3]);
6556 __ Mov(w5, shift[4]);
6557 __ Mov(w6, shift[5]);
6558
6559 // The MacroAssembler does not allow zr as an argument.
6560 {
6561 ExactAssemblyScope scope(&masm, kInstructionSize);
6562 __ lslv(x0, x0, xzr);
6563 }
6564
6565 __ Lsl(x16, x0, x1);
6566 __ Lsl(x17, x0, x2);
6567 __ Lsl(x18, x0, x3);
6568 __ Lsl(x19, x0, x4);
6569 __ Lsl(x20, x0, x5);
6570 __ Lsl(x21, x0, x6);
6571
6572 __ Lsl(w22, w0, w1);
6573 __ Lsl(w23, w0, w2);
6574 __ Lsl(w24, w0, w3);
6575 __ Lsl(w25, w0, w4);
6576 __ Lsl(w26, w0, w5);
6577 __ Lsl(w27, w0, w6);
6578 END();
6579
6580 if (CAN_RUN()) {
6581 RUN();
6582
6583 ASSERT_EQUAL_64(value, x0);
6584 ASSERT_EQUAL_64(value << (shift[0] & 63), x16);
6585 ASSERT_EQUAL_64(value << (shift[1] & 63), x17);
6586 ASSERT_EQUAL_64(value << (shift[2] & 63), x18);
6587 ASSERT_EQUAL_64(value << (shift[3] & 63), x19);
6588 ASSERT_EQUAL_64(value << (shift[4] & 63), x20);
6589 ASSERT_EQUAL_64(value << (shift[5] & 63), x21);
6590 ASSERT_EQUAL_32(value << (shift[0] & 31), w22);
6591 ASSERT_EQUAL_32(value << (shift[1] & 31), w23);
6592 ASSERT_EQUAL_32(value << (shift[2] & 31), w24);
6593 ASSERT_EQUAL_32(value << (shift[3] & 31), w25);
6594 ASSERT_EQUAL_32(value << (shift[4] & 31), w26);
6595 ASSERT_EQUAL_32(value << (shift[5] & 31), w27);
6596 }
6597 }
6598
6599
6600 TEST(lsrv) {
6601 SETUP();
6602
6603 uint64_t value = 0x0123456789abcdef;
6604 int shift[] = {1, 3, 5, 9, 17, 33};
6605
6606 START();
6607 __ Mov(x0, value);
6608 __ Mov(w1, shift[0]);
6609 __ Mov(w2, shift[1]);
6610 __ Mov(w3, shift[2]);
6611 __ Mov(w4, shift[3]);
6612 __ Mov(w5, shift[4]);
6613 __ Mov(w6, shift[5]);
6614
6615 // The MacroAssembler does not allow zr as an argument.
6616 {
6617 ExactAssemblyScope scope(&masm, kInstructionSize);
6618 __ lsrv(x0, x0, xzr);
6619 }
6620
6621 __ Lsr(x16, x0, x1);
6622 __ Lsr(x17, x0, x2);
6623 __ Lsr(x18, x0, x3);
6624 __ Lsr(x19, x0, x4);
6625 __ Lsr(x20, x0, x5);
6626 __ Lsr(x21, x0, x6);
6627
6628 __ Lsr(w22, w0, w1);
6629 __ Lsr(w23, w0, w2);
6630 __ Lsr(w24, w0, w3);
6631 __ Lsr(w25, w0, w4);
6632 __ Lsr(w26, w0, w5);
6633 __ Lsr(w27, w0, w6);
6634 END();
6635
6636 if (CAN_RUN()) {
6637 RUN();
6638
6639 ASSERT_EQUAL_64(value, x0);
6640 ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
6641 ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
6642 ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
6643 ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
6644 ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
6645 ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
6646
6647 value &= 0xffffffff;
6648 ASSERT_EQUAL_32(value >> (shift[0] & 31), w22);
6649 ASSERT_EQUAL_32(value >> (shift[1] & 31), w23);
6650 ASSERT_EQUAL_32(value >> (shift[2] & 31), w24);
6651 ASSERT_EQUAL_32(value >> (shift[3] & 31), w25);
6652 ASSERT_EQUAL_32(value >> (shift[4] & 31), w26);
6653 ASSERT_EQUAL_32(value >> (shift[5] & 31), w27);
6654 }
6655 }
6656
6657
6658 TEST(asrv) {
6659 SETUP();
6660
6661 int64_t value = 0xfedcba98fedcba98;
6662 int shift[] = {1, 3, 5, 9, 17, 33};
6663
6664 START();
6665 __ Mov(x0, value);
6666 __ Mov(w1, shift[0]);
6667 __ Mov(w2, shift[1]);
6668 __ Mov(w3, shift[2]);
6669 __ Mov(w4, shift[3]);
6670 __ Mov(w5, shift[4]);
6671 __ Mov(w6, shift[5]);
6672
6673 // The MacroAssembler does not allow zr as an argument.
6674 {
6675 ExactAssemblyScope scope(&masm, kInstructionSize);
6676 __ asrv(x0, x0, xzr);
6677 }
6678
6679 __ Asr(x16, x0, x1);
6680 __ Asr(x17, x0, x2);
6681 __ Asr(x18, x0, x3);
6682 __ Asr(x19, x0, x4);
6683 __ Asr(x20, x0, x5);
6684 __ Asr(x21, x0, x6);
6685
6686 __ Asr(w22, w0, w1);
6687 __ Asr(w23, w0, w2);
6688 __ Asr(w24, w0, w3);
6689 __ Asr(w25, w0, w4);
6690 __ Asr(w26, w0, w5);
6691 __ Asr(w27, w0, w6);
6692 END();
6693
6694 if (CAN_RUN()) {
6695 RUN();
6696
6697 ASSERT_EQUAL_64(value, x0);
6698 ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
6699 ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
6700 ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
6701 ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
6702 ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
6703 ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
6704
6705 int32_t value32 = static_cast<int32_t>(value & 0xffffffff);
6706 ASSERT_EQUAL_32(value32 >> (shift[0] & 31), w22);
6707 ASSERT_EQUAL_32(value32 >> (shift[1] & 31), w23);
6708 ASSERT_EQUAL_32(value32 >> (shift[2] & 31), w24);
6709 ASSERT_EQUAL_32(value32 >> (shift[3] & 31), w25);
6710 ASSERT_EQUAL_32(value32 >> (shift[4] & 31), w26);
6711 ASSERT_EQUAL_32(value32 >> (shift[5] & 31), w27);
6712 }
6713 }
6714
6715
6716 TEST(rorv) {
6717 SETUP();
6718
6719 uint64_t value = 0x0123456789abcdef;
6720 int shift[] = {4, 8, 12, 16, 24, 36};
6721
6722 START();
6723 __ Mov(x0, value);
6724 __ Mov(w1, shift[0]);
6725 __ Mov(w2, shift[1]);
6726 __ Mov(w3, shift[2]);
6727 __ Mov(w4, shift[3]);
6728 __ Mov(w5, shift[4]);
6729 __ Mov(w6, shift[5]);
6730
6731 // The MacroAssembler does not allow zr as an argument.
6732 {
6733 ExactAssemblyScope scope(&masm, kInstructionSize);
6734 __ rorv(x0, x0, xzr);
6735 }
6736
6737 __ Ror(x16, x0, x1);
6738 __ Ror(x17, x0, x2);
6739 __ Ror(x18, x0, x3);
6740 __ Ror(x19, x0, x4);
6741 __ Ror(x20, x0, x5);
6742 __ Ror(x21, x0, x6);
6743
6744 __ Ror(w22, w0, w1);
6745 __ Ror(w23, w0, w2);
6746 __ Ror(w24, w0, w3);
6747 __ Ror(w25, w0, w4);
6748 __ Ror(w26, w0, w5);
6749 __ Ror(w27, w0, w6);
6750 END();
6751
6752 if (CAN_RUN()) {
6753 RUN();
6754
6755 ASSERT_EQUAL_64(value, x0);
6756 ASSERT_EQUAL_64(0xf0123456789abcde, x16);
6757 ASSERT_EQUAL_64(0xef0123456789abcd, x17);
6758 ASSERT_EQUAL_64(0xdef0123456789abc, x18);
6759 ASSERT_EQUAL_64(0xcdef0123456789ab, x19);
6760 ASSERT_EQUAL_64(0xabcdef0123456789, x20);
6761 ASSERT_EQUAL_64(0x789abcdef0123456, x21);
6762 ASSERT_EQUAL_32(0xf89abcde, w22);
6763 ASSERT_EQUAL_32(0xef89abcd, w23);
6764 ASSERT_EQUAL_32(0xdef89abc, w24);
6765 ASSERT_EQUAL_32(0xcdef89ab, w25);
6766 ASSERT_EQUAL_32(0xabcdef89, w26);
6767 ASSERT_EQUAL_32(0xf89abcde, w27);
6768 }
6769 }
6770
6771
6772 TEST(bfm) {
6773 SETUP();
6774
6775 START();
6776 __ Mov(x1, 0x0123456789abcdef);
6777
6778 __ Mov(x10, 0x8888888888888888);
6779 __ Mov(x11, 0x8888888888888888);
6780 __ Mov(x12, 0x8888888888888888);
6781 __ Mov(x13, 0x8888888888888888);
6782 __ Mov(x14, 0xffffffffffffffff);
6783 __ Mov(w20, 0x88888888);
6784 __ Mov(w21, 0x88888888);
6785
6786 __ Bfm(x10, x1, 16, 31);
6787 __ Bfm(x11, x1, 32, 15);
6788
6789 __ Bfm(w20, w1, 16, 23);
6790 __ Bfm(w21, w1, 24, 15);
6791
6792 // Aliases.
6793 __ Bfi(x12, x1, 16, 8);
6794 __ Bfxil(x13, x1, 16, 8);
6795 __ Bfc(x14, 16, 8);
6796 END();
6797
6798 if (CAN_RUN()) {
6799 RUN();
6800
6801
6802 ASSERT_EQUAL_64(0x88888888888889ab, x10);
6803 ASSERT_EQUAL_64(0x8888cdef88888888, x11);
6804
6805 ASSERT_EQUAL_32(0x888888ab, w20);
6806 ASSERT_EQUAL_32(0x88cdef88, w21);
6807
6808 ASSERT_EQUAL_64(0x8888888888ef8888, x12);
6809 ASSERT_EQUAL_64(0x88888888888888ab, x13);
6810 ASSERT_EQUAL_64(0xffffffffff00ffff, x14);
6811 }
6812 }
6813
6814
6815 TEST(sbfm) {
6816 SETUP();
6817
6818 START();
6819 __ Mov(x1, 0x0123456789abcdef);
6820 __ Mov(x2, 0xfedcba9876543210);
6821
6822 __ Sbfm(x10, x1, 16, 31);
6823 __ Sbfm(x11, x1, 32, 15);
6824 __ Sbfm(x12, x1, 32, 47);
6825 __ Sbfm(x13, x1, 48, 35);
6826
6827 __ Sbfm(w14, w1, 16, 23);
6828 __ Sbfm(w15, w1, 24, 15);
6829 __ Sbfm(w16, w2, 16, 23);
6830 __ Sbfm(w17, w2, 24, 15);
6831
6832 // Aliases.
6833 __ Asr(x18, x1, 32);
6834 __ Asr(x19, x2, 32);
6835 __ Sbfiz(x20, x1, 8, 16);
6836 __ Sbfiz(x21, x2, 8, 16);
6837 __ Sbfx(x22, x1, 8, 16);
6838 __ Sbfx(x23, x2, 8, 16);
6839 __ Sxtb(x24, w1);
6840 __ Sxtb(x25, x2);
6841 __ Sxth(x26, w1);
6842 __ Sxth(x27, x2);
6843 __ Sxtw(x28, w1);
6844 __ Sxtw(x29, x2);
6845 END();
6846
6847 if (CAN_RUN()) {
6848 RUN();
6849
6850
6851 ASSERT_EQUAL_64(0xffffffffffff89ab, x10);
6852 ASSERT_EQUAL_64(0xffffcdef00000000, x11);
6853 ASSERT_EQUAL_64(0x0000000000004567, x12);
6854 ASSERT_EQUAL_64(0x000789abcdef0000, x13);
6855
6856 ASSERT_EQUAL_32(0xffffffab, w14);
6857 ASSERT_EQUAL_32(0xffcdef00, w15);
6858 ASSERT_EQUAL_32(0x00000054, w16);
6859 ASSERT_EQUAL_32(0x00321000, w17);
6860
6861 ASSERT_EQUAL_64(0x0000000001234567, x18);
6862 ASSERT_EQUAL_64(0xfffffffffedcba98, x19);
6863 ASSERT_EQUAL_64(0xffffffffffcdef00, x20);
6864 ASSERT_EQUAL_64(0x0000000000321000, x21);
6865 ASSERT_EQUAL_64(0xffffffffffffabcd, x22);
6866 ASSERT_EQUAL_64(0x0000000000005432, x23);
6867 ASSERT_EQUAL_64(0xffffffffffffffef, x24);
6868 ASSERT_EQUAL_64(0x0000000000000010, x25);
6869 ASSERT_EQUAL_64(0xffffffffffffcdef, x26);
6870 ASSERT_EQUAL_64(0x0000000000003210, x27);
6871 ASSERT_EQUAL_64(0xffffffff89abcdef, x28);
6872 ASSERT_EQUAL_64(0x0000000076543210, x29);
6873 }
6874 }
6875
6876
6877 TEST(ubfm) {
6878 SETUP();
6879
6880 START();
6881 __ Mov(x1, 0x0123456789abcdef);
6882 __ Mov(x2, 0xfedcba9876543210);
6883
6884 __ Mov(x10, 0x8888888888888888);
6885 __ Mov(x11, 0x8888888888888888);
6886
6887 __ Ubfm(x10, x1, 16, 31);
6888 __ Ubfm(x11, x1, 32, 15);
6889 __ Ubfm(x12, x1, 32, 47);
6890 __ Ubfm(x13, x1, 48, 35);
6891
6892 __ Ubfm(w25, w1, 16, 23);
6893 __ Ubfm(w26, w1, 24, 15);
6894 __ Ubfm(w27, w2, 16, 23);
6895 __ Ubfm(w28, w2, 24, 15);
6896
6897 // Aliases
6898 __ Lsl(x15, x1, 63);
6899 __ Lsl(x16, x1, 0);
6900 __ Lsr(x17, x1, 32);
6901 __ Ubfiz(x18, x1, 8, 16);
6902 __ Ubfx(x19, x1, 8, 16);
6903 __ Uxtb(x20, x1);
6904 __ Uxth(x21, x1);
6905 __ Uxtw(x22, x1);
6906 END();
6907
6908 if (CAN_RUN()) {
6909 RUN();
6910
6911 ASSERT_EQUAL_64(0x00000000000089ab, x10);
6912 ASSERT_EQUAL_64(0x0000cdef00000000, x11);
6913 ASSERT_EQUAL_64(0x0000000000004567, x12);
6914 ASSERT_EQUAL_64(0x000789abcdef0000, x13);
6915
6916 ASSERT_EQUAL_32(0x000000ab, w25);
6917 ASSERT_EQUAL_32(0x00cdef00, w26);
6918 ASSERT_EQUAL_32(0x00000054, w27);
6919 ASSERT_EQUAL_32(0x00321000, w28);
6920
6921 ASSERT_EQUAL_64(0x8000000000000000, x15);
6922 ASSERT_EQUAL_64(0x0123456789abcdef, x16);
6923 ASSERT_EQUAL_64(0x0000000001234567, x17);
6924 ASSERT_EQUAL_64(0x0000000000cdef00, x18);
6925 ASSERT_EQUAL_64(0x000000000000abcd, x19);
6926 ASSERT_EQUAL_64(0x00000000000000ef, x20);
6927 ASSERT_EQUAL_64(0x000000000000cdef, x21);
6928 ASSERT_EQUAL_64(0x0000000089abcdef, x22);
6929 }
6930 }
6931
6932
6933 TEST(extr) {
6934 SETUP();
6935
6936 START();
6937 __ Mov(x1, 0x0123456789abcdef);
6938 __ Mov(x2, 0xfedcba9876543210);
6939
6940 __ Extr(w10, w1, w2, 0);
6941 __ Extr(w11, w1, w2, 1);
6942 __ Extr(x12, x2, x1, 2);
6943
6944 __ Ror(w13, w1, 0);
6945 __ Ror(w14, w2, 17);
6946 __ Ror(w15, w1, 31);
6947 __ Ror(x18, x2, 0);
6948 __ Ror(x19, x2, 1);
6949 __ Ror(x20, x1, 63);
6950 END();
6951
6952 if (CAN_RUN()) {
6953 RUN();
6954
6955 ASSERT_EQUAL_64(0x76543210, x10);
6956 ASSERT_EQUAL_64(0xbb2a1908, x11);
6957 ASSERT_EQUAL_64(0x0048d159e26af37b, x12);
6958 ASSERT_EQUAL_64(0x89abcdef, x13);
6959 ASSERT_EQUAL_64(0x19083b2a, x14);
6960 ASSERT_EQUAL_64(0x13579bdf, x15);
6961 ASSERT_EQUAL_64(0xfedcba9876543210, x18);
6962 ASSERT_EQUAL_64(0x7f6e5d4c3b2a1908, x19);
6963 ASSERT_EQUAL_64(0x02468acf13579bde, x20);
6964 }
6965 }
6966
6967
6968 TEST(system_mrs) {
6969 SETUP();
6970
6971 START();
6972 __ Mov(w0, 0);
6973 __ Mov(w1, 1);
6974 __ Mov(w2, 0x80000000);
6975
6976 // Set the Z and C flags.
6977 __ Cmp(w0, w0);
6978 __ Mrs(x3, NZCV);
6979
6980 // Set the N flag.
6981 __ Cmp(w0, w1);
6982 __ Mrs(x4, NZCV);
6983
6984 // Set the Z, C and V flags.
6985 __ Adds(w0, w2, w2);
6986 __ Mrs(x5, NZCV);
6987
6988 // Read the default FPCR.
6989 __ Mrs(x6, FPCR);
6990 END();
6991
6992 if (CAN_RUN()) {
6993 RUN();
6994
6995 // NZCV
6996 ASSERT_EQUAL_32(ZCFlag, w3);
6997 ASSERT_EQUAL_32(NFlag, w4);
6998 ASSERT_EQUAL_32(ZCVFlag, w5);
6999
7000 // FPCR
7001 // The default FPCR on Linux-based platforms is 0.
7002 ASSERT_EQUAL_32(0, w6);
7003 }
7004 }
7005
7006 TEST(system_rng) {
7007 SETUP_WITH_FEATURES(CPUFeatures::kRNG);
7008
7009 START();
7010 // Random number.
7011 __ Mrs(x1, RNDR);
7012 // Assume that each generation is successful now.
7013 // TODO: Return failure occasionally.
7014 __ Mrs(x2, NZCV);
7015 __ Mrs(x3, RNDR);
7016 __ Mrs(x4, NZCV);
7017
7018 // Reseeded random number.
7019 __ Mrs(x5, RNDRRS);
7020 // Assume that each generation is successful now.
7021 // TODO: Return failure occasionally.
7022 __ Mrs(x6, NZCV);
7023 __ Mrs(x7, RNDRRS);
7024 __ Mrs(x8, NZCV);
7025 END();
7026
7027 if (CAN_RUN()) {
7028 RUN();
7029 // Random number generation series.
7030 // Check random numbers have been generated and aren't equal when reseed has
7031 // happened.
7032 // NOTE: With a different architectural implementation, there may be a
7033 // collison.
7034 // TODO: Return failure occasionally. Set ZFlag and return UNKNOWN value.
7035 ASSERT_NOT_EQUAL_64(x1, x3);
7036 ASSERT_EQUAL_64(NoFlag, x2);
7037 ASSERT_EQUAL_64(NoFlag, x4);
7038 ASSERT_NOT_EQUAL_64(x5, x7);
7039 ASSERT_EQUAL_64(NoFlag, x6);
7040 ASSERT_EQUAL_64(NoFlag, x8);
7041 }
7042 }
7043
7044 TEST(cfinv) {
7045 SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
7046
7047 START();
7048 __ Mov(w0, 1);
7049
7050 // Set the C flag.
7051 __ Cmp(w0, 0);
7052 __ Mrs(x1, NZCV);
7053
7054 // Invert the C flag.
7055 __ Cfinv();
7056 __ Mrs(x2, NZCV);
7057
7058 // Invert the C flag again.
7059 __ Cfinv();
7060 __ Mrs(x3, NZCV);
7061 END();
7062
7063 if (CAN_RUN()) {
7064 RUN();
7065
7066 ASSERT_EQUAL_32(CFlag, w1);
7067 ASSERT_EQUAL_32(NoFlag, w2);
7068 ASSERT_EQUAL_32(CFlag, w3);
7069 }
7070 }
7071
7072
7073 TEST(axflag_xaflag) {
7074 // The AXFLAG and XAFLAG instructions are designed for converting the FP
7075 // conditional flags from Arm format to an alternate format efficiently.
7076 // There are only 4 cases which are relevant for this conversion but we test
7077 // the behaviour for all 16 cases anyway. The 4 important cases are labelled
7078 // below.
7079 StatusFlags expected_x[16] = {NoFlag,
7080 ZFlag,
7081 CFlag, // Greater than
7082 ZFlag, // Unordered
7083 ZFlag,
7084 ZFlag,
7085 ZCFlag, // Equal to
7086 ZFlag,
7087 NoFlag, // Less than
7088 ZFlag,
7089 CFlag,
7090 ZFlag,
7091 ZFlag,
7092 ZFlag,
7093 ZCFlag,
7094 ZFlag};
7095 StatusFlags expected_a[16] = {NFlag, // Less than
7096 NFlag,
7097 CFlag, // Greater than
7098 CFlag,
7099 CVFlag, // Unordered
7100 CVFlag,
7101 ZCFlag, // Equal to
7102 ZCFlag,
7103 NFlag,
7104 NFlag,
7105 CFlag,
7106 CFlag,
7107 CVFlag,
7108 CVFlag,
7109 ZCFlag,
7110 ZCFlag};
7111
7112 for (unsigned i = 0; i < 16; i++) {
7113 SETUP_WITH_FEATURES(CPUFeatures::kAXFlag);
7114
7115 START();
7116 __ Mov(x0, i << Flags_offset);
7117 __ Msr(NZCV, x0);
7118 __ Axflag();
7119 __ Mrs(x1, NZCV);
7120 __ Msr(NZCV, x0);
7121 __ Xaflag();
7122 __ Mrs(x2, NZCV);
7123 END();
7124
7125 if (CAN_RUN()) {
7126 RUN();
7127 ASSERT_EQUAL_32(expected_x[i], w1);
7128 ASSERT_EQUAL_32(expected_a[i], w2);
7129 }
7130 }
7131 }
7132
7133
7134 TEST(system_msr) {
7135 // All FPCR fields that must be implemented: AHP, DN, FZ, RMode
7136 const uint64_t fpcr_core = (0b1 << 26) | // AHP
7137 (0b1 << 25) | // DN
7138 (0b1 << 24) | // FZ
7139 (0b11 << 22); // RMode
7140
7141 SETUP();
7142
7143 START();
7144 __ Mov(w0, 0);
7145 __ Mov(w1, 0x7fffffff);
7146
7147 __ Mov(x7, 0);
7148
7149 __ Mov(x10, NVFlag);
7150 __ Cmp(w0, w0); // Set Z and C.
7151 __ Msr(NZCV, x10); // Set N and V.
7152 // The Msr should have overwritten every flag set by the Cmp.
7153 __ Cinc(x7, x7, mi); // N
7154 __ Cinc(x7, x7, ne); // !Z
7155 __ Cinc(x7, x7, lo); // !C
7156 __ Cinc(x7, x7, vs); // V
7157
7158 __ Mov(x10, ZCFlag);
7159 __ Cmn(w1, w1); // Set N and V.
7160 __ Msr(NZCV, x10); // Set Z and C.
7161 // The Msr should have overwritten every flag set by the Cmn.
7162 __ Cinc(x7, x7, pl); // !N
7163 __ Cinc(x7, x7, eq); // Z
7164 __ Cinc(x7, x7, hs); // C
7165 __ Cinc(x7, x7, vc); // !V
7166
7167 Register old_fpcr = x15;
7168 __ Mrs(old_fpcr, FPCR);
7169
7170 // All core FPCR fields must be writable.
7171 __ Mov(x8, fpcr_core);
7172 __ Msr(FPCR, x8);
7173 __ Mrs(x8, FPCR);
7174
7175 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7176 // All FPCR fields that aren't `RES0`:
7177 const uint64_t fpcr_all = fpcr_core | (0b11 << 20) | // Stride
7178 (0b1 << 19) | // FZ16
7179 (0b111 << 16) | // Len
7180 (0b1 << 15) | // IDE
7181 (0b1 << 12) | // IXE
7182 (0b1 << 11) | // UFE
7183 (0b1 << 10) | // OFE
7184 (0b1 << 9) | // DZE
7185 (0b1 << 8); // IOE
7186
7187 // All FPCR fields, including optional ones. This part of the test doesn't
7188 // achieve much other than ensuring that supported fields can be cleared by
7189 // the next test.
7190 __ Mov(x9, fpcr_all);
7191 __ Msr(FPCR, x9);
7192 __ Mrs(x9, FPCR);
7193 __ And(x9, x9, fpcr_core);
7194
7195 // The undefined bits must ignore writes.
7196 // It's conceivable that a future version of the architecture could use these
7197 // fields (making this test fail), but in the meantime this is a useful test
7198 // for the simulator.
7199 __ Mov(x10, ~fpcr_all);
7200 __ Msr(FPCR, x10);
7201 __ Mrs(x10, FPCR);
7202 #endif
7203
7204 __ Msr(FPCR, old_fpcr);
7205
7206 END();
7207
7208 if (CAN_RUN()) {
7209 RUN();
7210
7211 // We should have incremented x7 (from 0) exactly 8 times.
7212 ASSERT_EQUAL_64(8, x7);
7213
7214 ASSERT_EQUAL_64(fpcr_core, x8);
7215
7216 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7217 ASSERT_EQUAL_64(fpcr_core, x9);
7218 ASSERT_EQUAL_64(0, x10);
7219 #endif
7220 }
7221 }
7222
7223
7224 TEST(system_pauth_a) {
7225 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7226 START();
7227
7228 // Exclude x16 and x17 from the scratch register list so we can use
7229 // Pac/Autia1716 safely.
7230 UseScratchRegisterScope temps(&masm);
7231 temps.Exclude(x16, x17);
7232 temps.Include(x10, x11);
7233
7234 // Backup stack pointer.
7235 __ Mov(x20, sp);
7236
7237 // Modifiers
7238 __ Mov(x16, 0x477d469dec0b8760);
7239 __ Mov(sp, 0x477d469dec0b8760);
7240
7241 // Generate PACs using the 3 system instructions.
7242 __ Mov(x17, 0x0000000012345678);
7243 __ Pacia1716();
7244 __ Mov(x0, x17);
7245
7246 __ Mov(lr, 0x0000000012345678);
7247 __ Paciaz();
7248 __ Mov(x1, lr);
7249
7250 __ Mov(lr, 0x0000000012345678);
7251 __ Paciasp();
7252 __ Mov(x2, lr);
7253
7254 // Authenticate the pointers above.
7255 __ Mov(x17, x0);
7256 __ Autia1716();
7257 __ Mov(x3, x17);
7258
7259 __ Mov(lr, x1);
7260 __ Autiaz();
7261 __ Mov(x4, lr);
7262
7263 __ Mov(lr, x2);
7264 __ Autiasp();
7265 __ Mov(x5, lr);
7266
7267 // Attempt to authenticate incorrect pointers.
7268 __ Mov(x17, x1);
7269 __ Autia1716();
7270 __ Mov(x6, x17);
7271
7272 __ Mov(lr, x0);
7273 __ Autiaz();
7274 __ Mov(x7, lr);
7275
7276 __ Mov(lr, x1);
7277 __ Autiasp();
7278 __ Mov(x8, lr);
7279
7280 // Strip the pac code from the pointer in x0.
7281 __ Mov(lr, x0);
7282 __ Xpaclri();
7283 __ Mov(x9, lr);
7284
7285 // Restore stack pointer.
7286 __ Mov(sp, x20);
7287
7288 // Mask out just the PAC code bits.
7289 // TODO: use Simulator::CalculatePACMask in a nice way.
7290 __ And(x0, x0, 0x007f000000000000);
7291 __ And(x1, x1, 0x007f000000000000);
7292 __ And(x2, x2, 0x007f000000000000);
7293
7294 END();
7295
7296 if (CAN_RUN()) {
7297 RUN();
7298
7299 // Check PAC codes have been generated and aren't equal.
7300 // NOTE: with a different ComputePAC implementation, there may be a
7301 // collision.
7302 ASSERT_NOT_EQUAL_64(0, x0);
7303 ASSERT_NOT_EQUAL_64(0, x1);
7304 ASSERT_NOT_EQUAL_64(0, x2);
7305 ASSERT_NOT_EQUAL_64(x0, x1);
7306 ASSERT_EQUAL_64(x0, x2);
7307
7308 // Pointers correctly authenticated.
7309 ASSERT_EQUAL_64(0x0000000012345678, x3);
7310 ASSERT_EQUAL_64(0x0000000012345678, x4);
7311 ASSERT_EQUAL_64(0x0000000012345678, x5);
7312
7313 // Pointers corrupted after failing to authenticate.
7314 ASSERT_EQUAL_64(0x0020000012345678, x6);
7315 ASSERT_EQUAL_64(0x0020000012345678, x7);
7316 ASSERT_EQUAL_64(0x0020000012345678, x8);
7317
7318 // Pointer with code stripped.
7319 ASSERT_EQUAL_64(0x0000000012345678, x9);
7320 }
7321 }
7322
7323
7324 TEST(system_pauth_b) {
7325 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7326 START();
7327
7328 // Exclude x16 and x17 from the scratch register list so we can use
7329 // Pac/Autia1716 safely.
7330 UseScratchRegisterScope temps(&masm);
7331 temps.Exclude(x16, x17);
7332 temps.Include(x10, x11);
7333
7334 // Backup stack pointer.
7335 __ Mov(x20, sp);
7336
7337 // Modifiers
7338 __ Mov(x16, 0x477d469dec0b8760);
7339 __ Mov(sp, 0x477d469dec0b8760);
7340
7341 // Generate PACs using the 3 system instructions.
7342 __ Mov(x17, 0x0000000012345678);
7343 __ Pacib1716();
7344 __ Mov(x0, x17);
7345
7346 __ Mov(lr, 0x0000000012345678);
7347 __ Pacibz();
7348 __ Mov(x1, lr);
7349
7350 __ Mov(lr, 0x0000000012345678);
7351 __ Pacibsp();
7352 __ Mov(x2, lr);
7353
7354 // Authenticate the pointers above.
7355 __ Mov(x17, x0);
7356 __ Autib1716();
7357 __ Mov(x3, x17);
7358
7359 __ Mov(lr, x1);
7360 __ Autibz();
7361 __ Mov(x4, lr);
7362
7363 __ Mov(lr, x2);
7364 __ Autibsp();
7365 __ Mov(x5, lr);
7366
7367 // Attempt to authenticate incorrect pointers.
7368 __ Mov(x17, x1);
7369 __ Autib1716();
7370 __ Mov(x6, x17);
7371
7372 __ Mov(lr, x0);
7373 __ Autibz();
7374 __ Mov(x7, lr);
7375
7376 __ Mov(lr, x1);
7377 __ Autibsp();
7378 __ Mov(x8, lr);
7379
7380 // Strip the pac code from the pointer in x0.
7381 __ Mov(lr, x0);
7382 __ Xpaclri();
7383 __ Mov(x9, lr);
7384
7385 // Restore stack pointer.
7386 __ Mov(sp, x20);
7387
7388 // Mask out just the PAC code bits.
7389 // TODO: use Simulator::CalculatePACMask in a nice way.
7390 __ And(x0, x0, 0x007f000000000000);
7391 __ And(x1, x1, 0x007f000000000000);
7392 __ And(x2, x2, 0x007f000000000000);
7393
7394 END();
7395
7396 if (CAN_RUN()) {
7397 RUN();
7398
7399 // Check PAC codes have been generated and aren't equal.
7400 // NOTE: with a different ComputePAC implementation, there may be a
7401 // collision.
7402 ASSERT_NOT_EQUAL_64(0, x0);
7403 ASSERT_NOT_EQUAL_64(0, x1);
7404 ASSERT_NOT_EQUAL_64(0, x2);
7405 ASSERT_NOT_EQUAL_64(x0, x1);
7406 ASSERT_EQUAL_64(x0, x2);
7407
7408 // Pointers correctly authenticated.
7409 ASSERT_EQUAL_64(0x0000000012345678, x3);
7410 ASSERT_EQUAL_64(0x0000000012345678, x4);
7411 ASSERT_EQUAL_64(0x0000000012345678, x5);
7412
7413 // Pointers corrupted after failing to authenticate.
7414 ASSERT_EQUAL_64(0x0040000012345678, x6);
7415 ASSERT_EQUAL_64(0x0040000012345678, x7);
7416 ASSERT_EQUAL_64(0x0040000012345678, x8);
7417
7418 // Pointer with code stripped.
7419 ASSERT_EQUAL_64(0x0000000012345678, x9);
7420 }
7421 }
7422
7423 #ifdef VIXL_NEGATIVE_TESTING
7424 TEST(system_pauth_negative_test) {
7425 SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7426 START();
7427
7428 // Test for an assert (independent of order).
7429 MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7430 "Assertion failed "
7431 "(!GetScratchRegisterList()->IncludesAliasOf(");
7432
7433 // Test for x16 assert.
7434 {
7435 UseScratchRegisterScope temps(&masm);
7436 temps.Exclude(x17);
7437 temps.Include(x16);
7438 MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7439 "Assertion failed "
7440 "(!GetScratchRegisterList()->IncludesAliasOf(x16))");
7441 }
7442
7443 // Test for x17 assert.
7444 {
7445 UseScratchRegisterScope temps(&masm);
7446 temps.Exclude(x16);
7447 temps.Include(x17);
7448 MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7449 "Assertion failed "
7450 "(!GetScratchRegisterList()->IncludesAliasOf(x17))");
7451 }
7452
7453 // Repeat first test for other 1716 instructions.
7454 MUST_FAIL_WITH_MESSAGE(__ Pacib1716(),
7455 "Assertion failed "
7456 "(!GetScratchRegisterList()->IncludesAliasOf(");
7457 MUST_FAIL_WITH_MESSAGE(__ Autia1716(),
7458 "Assertion failed "
7459 "(!GetScratchRegisterList()->IncludesAliasOf(");
7460 MUST_FAIL_WITH_MESSAGE(__ Autib1716(),
7461 "Assertion failed "
7462 "(!GetScratchRegisterList()->IncludesAliasOf(");
7463
7464 END();
7465 }
7466 #endif // VIXL_NEGATIVE_TESTING
7467
7468
7469 TEST(system) {
7470 // RegisterDump::Dump uses NEON.
7471 SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRAS);
7472 RegisterDump before;
7473
7474 START();
7475 before.Dump(&masm);
7476 __ Nop();
7477 __ Esb();
7478 __ Csdb();
7479 END();
7480
7481 if (CAN_RUN()) {
7482 RUN();
7483
7484 ASSERT_EQUAL_REGISTERS(before);
7485 ASSERT_EQUAL_NZCV(before.flags_nzcv());
7486 }
7487 }
7488
7489 static void BtiHelper(Register ipreg) {
7490 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7491
7492 Label jump_target, jump_call_target, call_target, done;
7493 START();
7494 UseScratchRegisterScope temps(&masm);
7495 temps.Exclude(ipreg);
7496 __ Adr(x0, &jump_target);
7497 __ Br(x0);
7498 __ Nop();
7499 __ Bind(&jump_target, EmitBTI_j);
7500 __ Adr(x0, &call_target);
7501 __ Blr(x0);
7502 __ Adr(ipreg, &jump_call_target);
7503 __ Blr(ipreg);
7504 __ Adr(lr, &done); // Make Ret return to done label.
7505 __ Br(ipreg);
7506 __ Bind(&call_target, EmitBTI_c);
7507 __ Ret();
7508 __ Bind(&jump_call_target, EmitBTI_jc);
7509 __ Ret();
7510 __ Bind(&done);
7511 END();
7512
7513 if (CAN_RUN()) {
7514 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7515 simulator.SetGuardedPages(true);
7516 #else
7517 VIXL_UNIMPLEMENTED();
7518 #endif
7519 RUN();
7520 }
7521 }
7522
7523 TEST(bti) {
7524 BtiHelper(x16);
7525 BtiHelper(x17);
7526 }
7527
7528 TEST(unguarded_bti_is_nop) {
7529 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7530
7531 Label start, none, c, j, jc;
7532 START();
7533 __ B(&start);
7534 __ Bind(&none, EmitBTI);
7535 __ Bind(&c, EmitBTI_c);
7536 __ Bind(&j, EmitBTI_j);
7537 __ Bind(&jc, EmitBTI_jc);
7538 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&none) == 4 * kInstructionSize);
7539 __ Ret();
7540
7541 Label jump_to_c, call_to_j;
7542 __ Bind(&start);
7543 __ Adr(x0, &none);
7544 __ Adr(lr, &jump_to_c);
7545 __ Br(x0);
7546
7547 __ Bind(&jump_to_c);
7548 __ Adr(x0, &c);
7549 __ Adr(lr, &call_to_j);
7550 __ Br(x0);
7551
7552 __ Bind(&call_to_j);
7553 __ Adr(x0, &j);
7554 __ Blr(x0);
7555 END();
7556
7557 if (CAN_RUN()) {
7558 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7559 simulator.SetGuardedPages(false);
7560 #else
7561 VIXL_UNIMPLEMENTED();
7562 #endif
7563 RUN();
7564 }
7565 }
7566
7567 #ifdef VIXL_NEGATIVE_TESTING
7568 TEST(bti_jump_to_ip_unidentified) {
7569 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7570
7571 START();
7572 UseScratchRegisterScope temps(&masm);
7573 temps.Exclude(x17);
7574 Label l;
7575 __ Adr(x17, &l);
7576 __ Br(x17);
7577 __ Nop();
7578 __ Bind(&l);
7579 __ Nop();
7580 END();
7581
7582 if (CAN_RUN()) {
7583 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7584 simulator.SetGuardedPages(true);
7585 #else
7586 VIXL_UNIMPLEMENTED();
7587 #endif
7588 MUST_FAIL_WITH_MESSAGE(RUN(),
7589 "Executing non-BTI instruction with wrong "
7590 "BType.");
7591 }
7592 }
7593
7594 TEST(bti_jump_to_unidentified) {
7595 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7596
7597 START();
7598 Label l;
7599 __ Adr(x0, &l);
7600 __ Br(x0);
7601 __ Nop();
7602 __ Bind(&l);
7603 __ Nop();
7604 END();
7605
7606 if (CAN_RUN()) {
7607 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7608 simulator.SetGuardedPages(true);
7609 #else
7610 VIXL_UNIMPLEMENTED();
7611 #endif
7612 MUST_FAIL_WITH_MESSAGE(RUN(),
7613 "Executing non-BTI instruction with wrong "
7614 "BType.");
7615 }
7616 }
7617
7618 TEST(bti_call_to_unidentified) {
7619 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7620
7621 START();
7622 Label l;
7623 __ Adr(x0, &l);
7624 __ Blr(x0);
7625 __ Nop();
7626 __ Bind(&l);
7627 __ Nop();
7628 END();
7629
7630 if (CAN_RUN()) {
7631 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7632 simulator.SetGuardedPages(true);
7633 #else
7634 VIXL_UNIMPLEMENTED();
7635 #endif
7636 MUST_FAIL_WITH_MESSAGE(RUN(),
7637 "Executing non-BTI instruction with wrong "
7638 "BType.");
7639 }
7640 }
7641
7642 TEST(bti_jump_to_c) {
7643 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7644
7645 START();
7646 // Jumping to a "BTI c" target must fail.
7647 Label jump_target;
7648 __ Adr(x0, &jump_target);
7649 __ Br(x0);
7650 __ Nop();
7651 __ Bind(&jump_target, EmitBTI_c);
7652 __ Nop();
7653 END();
7654
7655 if (CAN_RUN()) {
7656 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7657 simulator.SetGuardedPages(true);
7658 #else
7659 VIXL_UNIMPLEMENTED();
7660 #endif
7661 MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI c with wrong BType.");
7662 }
7663 }
7664
7665 TEST(bti_call_to_j) {
7666 SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7667
7668 START();
7669 // Calling a "BTI j" target must fail.
7670 Label call_target;
7671 __ Adr(x0, &call_target);
7672 __ Blr(x0);
7673 __ Nop();
7674 __ Bind(&call_target, EmitBTI_j);
7675 __ Nop();
7676 END();
7677
7678 if (CAN_RUN()) {
7679 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7680 simulator.SetGuardedPages(true);
7681 #else
7682 VIXL_UNIMPLEMENTED();
7683 #endif
7684 MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI j with wrong BType.");
7685 }
7686 }
7687 #endif // VIXL_NEGATIVE_TESTING
7688
7689 TEST(fall_through_bti) {
7690 SETUP_WITH_FEATURES(CPUFeatures::kBTI, CPUFeatures::kPAuth);
7691
7692 START();
7693 Label target, target_j, target_c, target_jc;
7694 __ Mov(x0, 0); // 'Normal' instruction sets BTYPE to zero.
7695 __ Bind(&target, EmitBTI);
7696 __ Add(x0, x0, 1);
7697 __ Bind(&target_j, EmitBTI_j);
7698 __ Add(x0, x0, 1);
7699 __ Bind(&target_c, EmitBTI_c);
7700 __ Add(x0, x0, 1);
7701 __ Bind(&target_jc, EmitBTI_jc);
7702 __ Add(x0, x0, 1);
7703 __ Paciasp();
7704 END();
7705
7706 if (CAN_RUN()) {
7707 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7708 simulator.SetGuardedPages(true);
7709 #else
7710 VIXL_UNIMPLEMENTED();
7711 #endif
7712 RUN();
7713
7714 ASSERT_EQUAL_64(4, x0);
7715 }
7716 }
7717
7718 TEST(zero_dest) {
7719 // RegisterDump::Dump uses NEON.
7720 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
7721 RegisterDump before;
7722
7723 START();
7724 // Preserve the stack pointer, in case we clobber it.
7725 __ Mov(x30, sp);
7726 // Initialize the other registers used in this test.
7727 uint64_t literal_base = 0x0100001000100101;
7728 __ Mov(x0, 0);
7729 __ Mov(x1, literal_base);
7730 for (unsigned i = 2; i < x30.GetCode(); i++) {
7731 __ Add(XRegister(i), XRegister(i - 1), x1);
7732 }
7733 before.Dump(&masm);
7734
7735 // All of these instructions should be NOPs in these forms, but have
7736 // alternate forms which can write into the stack pointer.
7737 {
7738 ExactAssemblyScope scope(&masm, 3 * 7 * kInstructionSize);
7739 __ add(xzr, x0, x1);
7740 __ add(xzr, x1, xzr);
7741 __ add(xzr, xzr, x1);
7742
7743 __ and_(xzr, x0, x2);
7744 __ and_(xzr, x2, xzr);
7745 __ and_(xzr, xzr, x2);
7746
7747 __ bic(xzr, x0, x3);
7748 __ bic(xzr, x3, xzr);
7749 __ bic(xzr, xzr, x3);
7750
7751 __ eon(xzr, x0, x4);
7752 __ eon(xzr, x4, xzr);
7753 __ eon(xzr, xzr, x4);
7754
7755 __ eor(xzr, x0, x5);
7756 __ eor(xzr, x5, xzr);
7757 __ eor(xzr, xzr, x5);
7758
7759 __ orr(xzr, x0, x6);
7760 __ orr(xzr, x6, xzr);
7761 __ orr(xzr, xzr, x6);
7762
7763 __ sub(xzr, x0, x7);
7764 __ sub(xzr, x7, xzr);
7765 __ sub(xzr, xzr, x7);
7766 }
7767
7768 // Swap the saved stack pointer with the real one. If sp was written
7769 // during the test, it will show up in x30. This is done because the test
7770 // framework assumes that sp will be valid at the end of the test.
7771 __ Mov(x29, x30);
7772 __ Mov(x30, sp);
7773 __ Mov(sp, x29);
7774 // We used x29 as a scratch register, so reset it to make sure it doesn't
7775 // trigger a test failure.
7776 __ Add(x29, x28, x1);
7777 END();
7778
7779 if (CAN_RUN()) {
7780 RUN();
7781
7782 ASSERT_EQUAL_REGISTERS(before);
7783 ASSERT_EQUAL_NZCV(before.flags_nzcv());
7784 }
7785 }
7786
7787
7788 TEST(zero_dest_setflags) {
7789 // RegisterDump::Dump uses NEON.
7790 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
7791 RegisterDump before;
7792
7793 START();
7794 // Preserve the stack pointer, in case we clobber it.
7795 __ Mov(x30, sp);
7796 // Initialize the other registers used in this test.
7797 uint64_t literal_base = 0x0100001000100101;
7798 __ Mov(x0, 0);
7799 __ Mov(x1, literal_base);
7800 for (int i = 2; i < 30; i++) {
7801 __ Add(XRegister(i), XRegister(i - 1), x1);
7802 }
7803 before.Dump(&masm);
7804
7805 // All of these instructions should only write to the flags in these forms,
7806 // but have alternate forms which can write into the stack pointer.
7807 {
7808 ExactAssemblyScope scope(&masm, 6 * kInstructionSize);
7809 __ adds(xzr, x0, Operand(x1, UXTX));
7810 __ adds(xzr, x1, Operand(xzr, UXTX));
7811 __ adds(xzr, x1, 1234);
7812 __ adds(xzr, x0, x1);
7813 __ adds(xzr, x1, xzr);
7814 __ adds(xzr, xzr, x1);
7815 }
7816
7817 {
7818 ExactAssemblyScope scope(&masm, 5 * kInstructionSize);
7819 __ ands(xzr, x2, ~0xf);
7820 __ ands(xzr, xzr, ~0xf);
7821 __ ands(xzr, x0, x2);
7822 __ ands(xzr, x2, xzr);
7823 __ ands(xzr, xzr, x2);
7824 }
7825
7826 {
7827 ExactAssemblyScope scope(&masm, 5 * kInstructionSize);
7828 __ bics(xzr, x3, ~0xf);
7829 __ bics(xzr, xzr, ~0xf);
7830 __ bics(xzr, x0, x3);
7831 __ bics(xzr, x3, xzr);
7832 __ bics(xzr, xzr, x3);
7833 }
7834
7835 {
7836 ExactAssemblyScope scope(&masm, 6 * kInstructionSize);
7837 __ subs(xzr, x0, Operand(x3, UXTX));
7838 __ subs(xzr, x3, Operand(xzr, UXTX));
7839 __ subs(xzr, x3, 1234);
7840 __ subs(xzr, x0, x3);
7841 __ subs(xzr, x3, xzr);
7842 __ subs(xzr, xzr, x3);
7843 }
7844
7845 // Swap the saved stack pointer with the real one. If sp was written
7846 // during the test, it will show up in x30. This is done because the test
7847 // framework assumes that sp will be valid at the end of the test.
7848 __ Mov(x29, x30);
7849 __ Mov(x30, sp);
7850 __ Mov(sp, x29);
7851 // We used x29 as a scratch register, so reset it to make sure it doesn't
7852 // trigger a test failure.
7853 __ Add(x29, x28, x1);
7854 END();
7855
7856 if (CAN_RUN()) {
7857 RUN();
7858
7859 ASSERT_EQUAL_REGISTERS(before);
7860 }
7861 }
7862
7863
7864 TEST(stack_pointer_override) {
7865 // This test generates some stack maintenance code, but the test only checks
7866 // the reported state.
7867 SETUP();
7868 START();
7869
7870 // The default stack pointer in VIXL is sp.
7871 VIXL_CHECK(sp.Is(__ StackPointer()));
7872 __ SetStackPointer(x0);
7873 VIXL_CHECK(x0.Is(__ StackPointer()));
7874 __ SetStackPointer(x28);
7875 VIXL_CHECK(x28.Is(__ StackPointer()));
7876 __ SetStackPointer(sp);
7877 VIXL_CHECK(sp.Is(__ StackPointer()));
7878
7879 END();
7880 if (CAN_RUN()) {
7881 RUN();
7882 }
7883 }
7884
7885
7886 TEST(peek_poke_simple) {
7887 SETUP();
7888 START();
7889
7890 static const RegList x0_to_x3 =
7891 x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit();
7892 static const RegList x10_to_x13 =
7893 x10.GetBit() | x11.GetBit() | x12.GetBit() | x13.GetBit();
7894
7895 // The literal base is chosen to have two useful properties:
7896 // * When multiplied by small values (such as a register index), this value
7897 // is clearly readable in the result.
7898 // * The value is not formed from repeating fixed-size smaller values, so it
7899 // can be used to detect endianness-related errors.
7900 uint64_t literal_base = 0x0100001000100101;
7901
7902 // Initialize the registers.
7903 __ Mov(x0, literal_base);
7904 __ Add(x1, x0, x0);
7905 __ Add(x2, x1, x0);
7906 __ Add(x3, x2, x0);
7907
7908 __ Claim(32);
7909
7910 // Simple exchange.
7911 // After this test:
7912 // x0-x3 should be unchanged.
7913 // w10-w13 should contain the lower words of x0-x3.
7914 __ Poke(x0, 0);
7915 __ Poke(x1, 8);
7916 __ Poke(x2, 16);
7917 __ Poke(x3, 24);
7918 Clobber(&masm, x0_to_x3);
7919 __ Peek(x0, 0);
7920 __ Peek(x1, 8);
7921 __ Peek(x2, 16);
7922 __ Peek(x3, 24);
7923
7924 __ Poke(w0, 0);
7925 __ Poke(w1, 4);
7926 __ Poke(w2, 8);
7927 __ Poke(w3, 12);
7928 Clobber(&masm, x10_to_x13);
7929 __ Peek(w10, 0);
7930 __ Peek(w11, 4);
7931 __ Peek(w12, 8);
7932 __ Peek(w13, 12);
7933
7934 __ Drop(32);
7935
7936 END();
7937 if (CAN_RUN()) {
7938 RUN();
7939
7940 ASSERT_EQUAL_64(literal_base * 1, x0);
7941 ASSERT_EQUAL_64(literal_base * 2, x1);
7942 ASSERT_EQUAL_64(literal_base * 3, x2);
7943 ASSERT_EQUAL_64(literal_base * 4, x3);
7944
7945 ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
7946 ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
7947 ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
7948 ASSERT_EQUAL_64((literal_base * 4) & 0xffffffff, x13);
7949 }
7950 }
7951
7952
7953 TEST(peek_poke_unaligned) {
7954 SETUP();
7955 START();
7956
7957 // The literal base is chosen to have two useful properties:
7958 // * When multiplied by small values (such as a register index), this value
7959 // is clearly readable in the result.
7960 // * The value is not formed from repeating fixed-size smaller values, so it
7961 // can be used to detect endianness-related errors.
7962 uint64_t literal_base = 0x0100001000100101;
7963
7964 // Initialize the registers.
7965 __ Mov(x0, literal_base);
7966 __ Add(x1, x0, x0);
7967 __ Add(x2, x1, x0);
7968 __ Add(x3, x2, x0);
7969 __ Add(x4, x3, x0);
7970 __ Add(x5, x4, x0);
7971 __ Add(x6, x5, x0);
7972
7973 __ Claim(32);
7974
7975 // Unaligned exchanges.
7976 // After this test:
7977 // x0-x6 should be unchanged.
7978 // w10-w12 should contain the lower words of x0-x2.
7979 __ Poke(x0, 1);
7980 Clobber(&masm, x0.GetBit());
7981 __ Peek(x0, 1);
7982 __ Poke(x1, 2);
7983 Clobber(&masm, x1.GetBit());
7984 __ Peek(x1, 2);
7985 __ Poke(x2, 3);
7986 Clobber(&masm, x2.GetBit());
7987 __ Peek(x2, 3);
7988 __ Poke(x3, 4);
7989 Clobber(&masm, x3.GetBit());
7990 __ Peek(x3, 4);
7991 __ Poke(x4, 5);
7992 Clobber(&masm, x4.GetBit());
7993 __ Peek(x4, 5);
7994 __ Poke(x5, 6);
7995 Clobber(&masm, x5.GetBit());
7996 __ Peek(x5, 6);
7997 __ Poke(x6, 7);
7998 Clobber(&masm, x6.GetBit());
7999 __ Peek(x6, 7);
8000
8001 __ Poke(w0, 1);
8002 Clobber(&masm, w10.GetBit());
8003 __ Peek(w10, 1);
8004 __ Poke(w1, 2);
8005 Clobber(&masm, w11.GetBit());
8006 __ Peek(w11, 2);
8007 __ Poke(w2, 3);
8008 Clobber(&masm, w12.GetBit());
8009 __ Peek(w12, 3);
8010
8011 __ Drop(32);
8012
8013 END();
8014 if (CAN_RUN()) {
8015 RUN();
8016
8017 ASSERT_EQUAL_64(literal_base * 1, x0);
8018 ASSERT_EQUAL_64(literal_base * 2, x1);
8019 ASSERT_EQUAL_64(literal_base * 3, x2);
8020 ASSERT_EQUAL_64(literal_base * 4, x3);
8021 ASSERT_EQUAL_64(literal_base * 5, x4);
8022 ASSERT_EQUAL_64(literal_base * 6, x5);
8023 ASSERT_EQUAL_64(literal_base * 7, x6);
8024
8025 ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
8026 ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
8027 ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
8028 }
8029 }
8030
8031
8032 TEST(peek_poke_endianness) {
8033 SETUP();
8034 START();
8035
8036 // The literal base is chosen to have two useful properties:
8037 // * When multiplied by small values (such as a register index), this value
8038 // is clearly readable in the result.
8039 // * The value is not formed from repeating fixed-size smaller values, so it
8040 // can be used to detect endianness-related errors.
8041 uint64_t literal_base = 0x0100001000100101;
8042
8043 // Initialize the registers.
8044 __ Mov(x0, literal_base);
8045 __ Add(x1, x0, x0);
8046
8047 __ Claim(32);
8048
8049 // Endianness tests.
8050 // After this section:
8051 // x4 should match x0[31:0]:x0[63:32]
8052 // w5 should match w1[15:0]:w1[31:16]
8053 __ Poke(x0, 0);
8054 __ Poke(x0, 8);
8055 __ Peek(x4, 4);
8056
8057 __ Poke(w1, 0);
8058 __ Poke(w1, 4);
8059 __ Peek(w5, 2);
8060
8061 __ Drop(32);
8062
8063 END();
8064 if (CAN_RUN()) {
8065 RUN();
8066
8067 uint64_t x0_expected = literal_base * 1;
8068 uint64_t x1_expected = literal_base * 2;
8069 uint64_t x4_expected = (x0_expected << 32) | (x0_expected >> 32);
8070 uint64_t x5_expected =
8071 ((x1_expected << 16) & 0xffff0000) | ((x1_expected >> 16) & 0x0000ffff);
8072
8073 ASSERT_EQUAL_64(x0_expected, x0);
8074 ASSERT_EQUAL_64(x1_expected, x1);
8075 ASSERT_EQUAL_64(x4_expected, x4);
8076 ASSERT_EQUAL_64(x5_expected, x5);
8077 }
8078 }
8079
8080
8081 TEST(peek_poke_mixed) {
8082 SETUP();
8083 START();
8084
8085 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8086 UseScratchRegisterScope temps(&masm);
8087 temps.ExcludeAll();
8088
8089 // The literal base is chosen to have two useful properties:
8090 // * When multiplied by small values (such as a register index), this value
8091 // is clearly readable in the result.
8092 // * The value is not formed from repeating fixed-size smaller values, so it
8093 // can be used to detect endianness-related errors.
8094 uint64_t literal_base = 0x0100001000100101;
8095
8096 // Initialize the registers.
8097 __ Mov(x0, literal_base);
8098 __ Add(x1, x0, x0);
8099 __ Add(x2, x1, x0);
8100 __ Add(x3, x2, x0);
8101
8102 __ Claim(32);
8103
8104 // Mix with other stack operations.
8105 // After this section:
8106 // x0-x3 should be unchanged.
8107 // x6 should match x1[31:0]:x0[63:32]
8108 // w7 should match x1[15:0]:x0[63:48]
8109 __ Poke(x1, 8);
8110 __ Poke(x0, 0);
8111 {
8112 VIXL_ASSERT(__ StackPointer().Is(sp));
8113 __ Mov(x4, __ StackPointer());
8114 __ SetStackPointer(x4);
8115
8116 __ Poke(wzr, 0); // Clobber the space we're about to drop.
8117 __ Drop(4);
8118 __ Peek(x6, 0);
8119 __ Claim(8);
8120 __ Peek(w7, 10);
8121 __ Poke(x3, 28);
8122 __ Poke(xzr, 0); // Clobber the space we're about to drop.
8123 __ Drop(8);
8124 __ Poke(x2, 12);
8125 __ Push(w0);
8126
8127 __ Mov(sp, __ StackPointer());
8128 __ SetStackPointer(sp);
8129 }
8130
8131 __ Pop(x0, x1, x2, x3);
8132
8133 END();
8134 if (CAN_RUN()) {
8135 RUN();
8136
8137 uint64_t x0_expected = literal_base * 1;
8138 uint64_t x1_expected = literal_base * 2;
8139 uint64_t x2_expected = literal_base * 3;
8140 uint64_t x3_expected = literal_base * 4;
8141 uint64_t x6_expected = (x1_expected << 32) | (x0_expected >> 32);
8142 uint64_t x7_expected =
8143 ((x1_expected << 16) & 0xffff0000) | ((x0_expected >> 48) & 0x0000ffff);
8144
8145 ASSERT_EQUAL_64(x0_expected, x0);
8146 ASSERT_EQUAL_64(x1_expected, x1);
8147 ASSERT_EQUAL_64(x2_expected, x2);
8148 ASSERT_EQUAL_64(x3_expected, x3);
8149 ASSERT_EQUAL_64(x6_expected, x6);
8150 ASSERT_EQUAL_64(x7_expected, x7);
8151 }
8152 }
8153
8154
8155 TEST(peek_poke_reglist) {
8156 SETUP_WITH_FEATURES(CPUFeatures::kFP);
8157
8158 START();
8159
8160 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8161 UseScratchRegisterScope temps(&masm);
8162 temps.ExcludeAll();
8163
8164 // The literal base is chosen to have two useful properties:
8165 // * When multiplied by small values (such as a register index), this value
8166 // is clearly readable in the result.
8167 // * The value is not formed from repeating fixed-size smaller values, so it
8168 // can be used to detect endianness-related errors.
8169 uint64_t base = 0x0100001000100101;
8170
8171 // Initialize the registers.
8172 __ Mov(x1, base);
8173 __ Add(x2, x1, x1);
8174 __ Add(x3, x2, x1);
8175 __ Add(x4, x3, x1);
8176
8177 CPURegList list_1(x1, x2, x3, x4);
8178 CPURegList list_2(x11, x12, x13, x14);
8179 int list_1_size = list_1.GetTotalSizeInBytes();
8180
8181 __ Claim(2 * list_1_size);
8182
8183 __ PokeCPURegList(list_1, 0);
8184 __ PokeXRegList(list_1.GetList(), list_1_size);
8185 __ PeekCPURegList(list_2, 2 * kXRegSizeInBytes);
8186 __ PeekXRegList(x15.GetBit(), kWRegSizeInBytes);
8187 __ PeekWRegList(w16.GetBit() | w17.GetBit(), 3 * kXRegSizeInBytes);
8188
8189 __ Drop(2 * list_1_size);
8190
8191
8192 uint64_t base_d = 0x1010010001000010;
8193
8194 // Initialize the registers.
8195 __ Mov(x1, base_d);
8196 __ Add(x2, x1, x1);
8197 __ Add(x3, x2, x1);
8198 __ Add(x4, x3, x1);
8199 __ Fmov(d1, x1);
8200 __ Fmov(d2, x2);
8201 __ Fmov(d3, x3);
8202 __ Fmov(d4, x4);
8203
8204 CPURegList list_d_1(d1, d2, d3, d4);
8205 CPURegList list_d_2(d11, d12, d13, d14);
8206 int list_d_1_size = list_d_1.GetTotalSizeInBytes();
8207
8208 __ Claim(2 * list_d_1_size);
8209
8210 __ PokeCPURegList(list_d_1, 0);
8211 __ PokeDRegList(list_d_1.GetList(), list_d_1_size);
8212 __ PeekCPURegList(list_d_2, 2 * kDRegSizeInBytes);
8213 __ PeekDRegList(d15.GetBit(), kSRegSizeInBytes);
8214 __ PeekSRegList(s16.GetBit() | s17.GetBit(), 3 * kDRegSizeInBytes);
8215
8216 __ Drop(2 * list_d_1_size);
8217
8218
8219 END();
8220 if (CAN_RUN()) {
8221 RUN();
8222
8223 ASSERT_EQUAL_64(3 * base, x11);
8224 ASSERT_EQUAL_64(4 * base, x12);
8225 ASSERT_EQUAL_64(1 * base, x13);
8226 ASSERT_EQUAL_64(2 * base, x14);
8227 ASSERT_EQUAL_64(((1 * base) >> kWRegSize) | ((2 * base) << kWRegSize), x15);
8228 ASSERT_EQUAL_64(2 * base, x14);
8229 ASSERT_EQUAL_32((4 * base) & kWRegMask, w16);
8230 ASSERT_EQUAL_32((4 * base) >> kWRegSize, w17);
8231
8232 ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base_d), d11);
8233 ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base_d), d12);
8234 ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base_d), d13);
8235 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14);
8236 ASSERT_EQUAL_FP64(RawbitsToDouble((base_d >> kSRegSize) |
8237 ((2 * base_d) << kSRegSize)),
8238 d15);
8239 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14);
8240 ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) & kSRegMask), s16);
8241 ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) >> kSRegSize), s17);
8242 }
8243 }
8244
8245
8246 TEST(load_store_reglist) {
8247 SETUP_WITH_FEATURES(CPUFeatures::kFP);
8248
8249 START();
8250
8251 // The literal base is chosen to have two useful properties:
8252 // * When multiplied by small values (such as a register index), this value
8253 // is clearly readable in the result.
8254 // * The value is not formed from repeating fixed-size smaller values, so it
8255 // can be used to detect endianness-related errors.
8256 uint64_t high_base = UINT32_C(0x01000010);
8257 uint64_t low_base = UINT32_C(0x00100101);
8258 uint64_t base = (high_base << 32) | low_base;
8259 uint64_t array[21];
8260 memset(array, 0, sizeof(array));
8261
8262 // Initialize the registers.
8263 __ Mov(x1, base);
8264 __ Add(x2, x1, x1);
8265 __ Add(x3, x2, x1);
8266 __ Add(x4, x3, x1);
8267 __ Fmov(d1, x1);
8268 __ Fmov(d2, x2);
8269 __ Fmov(d3, x3);
8270 __ Fmov(d4, x4);
8271 __ Fmov(d5, x1);
8272 __ Fmov(d6, x2);
8273 __ Fmov(d7, x3);
8274 __ Fmov(d8, x4);
8275
8276 Register reg_base = x20;
8277 Register reg_index = x21;
8278 int size_stored = 0;
8279
8280 __ Mov(reg_base, reinterpret_cast<uintptr_t>(&array));
8281
8282 // Test aligned accesses.
8283 CPURegList list_src(w1, w2, w3, w4);
8284 CPURegList list_dst(w11, w12, w13, w14);
8285 CPURegList list_fp_src_1(d1, d2, d3, d4);
8286 CPURegList list_fp_dst_1(d11, d12, d13, d14);
8287
8288 __ StoreCPURegList(list_src, MemOperand(reg_base, 0 * sizeof(uint64_t)));
8289 __ LoadCPURegList(list_dst, MemOperand(reg_base, 0 * sizeof(uint64_t)));
8290 size_stored += 4 * kWRegSizeInBytes;
8291
8292 __ Mov(reg_index, size_stored);
8293 __ StoreCPURegList(list_src, MemOperand(reg_base, reg_index));
8294 __ LoadCPURegList(list_dst, MemOperand(reg_base, reg_index));
8295 size_stored += 4 * kWRegSizeInBytes;
8296
8297 __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, size_stored));
8298 __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, size_stored));
8299 size_stored += 4 * kDRegSizeInBytes;
8300
8301 __ Mov(reg_index, size_stored);
8302 __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, reg_index));
8303 __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, reg_index));
8304 size_stored += 4 * kDRegSizeInBytes;
8305
8306 // Test unaligned accesses.
8307 CPURegList list_fp_src_2(d5, d6, d7, d8);
8308 CPURegList list_fp_dst_2(d15, d16, d17, d18);
8309
8310 __ Str(wzr, MemOperand(reg_base, size_stored));
8311 size_stored += 1 * kWRegSizeInBytes;
8312 __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, size_stored));
8313 __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, size_stored));
8314 size_stored += 4 * kDRegSizeInBytes;
8315
8316 __ Mov(reg_index, size_stored);
8317 __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, reg_index));
8318 __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, reg_index));
8319
8320 END();
8321 if (CAN_RUN()) {
8322 RUN();
8323
8324 VIXL_CHECK(array[0] == (1 * low_base) + (2 * low_base << kWRegSize));
8325 VIXL_CHECK(array[1] == (3 * low_base) + (4 * low_base << kWRegSize));
8326 VIXL_CHECK(array[2] == (1 * low_base) + (2 * low_base << kWRegSize));
8327 VIXL_CHECK(array[3] == (3 * low_base) + (4 * low_base << kWRegSize));
8328 VIXL_CHECK(array[4] == 1 * base);
8329 VIXL_CHECK(array[5] == 2 * base);
8330 VIXL_CHECK(array[6] == 3 * base);
8331 VIXL_CHECK(array[7] == 4 * base);
8332 VIXL_CHECK(array[8] == 1 * base);
8333 VIXL_CHECK(array[9] == 2 * base);
8334 VIXL_CHECK(array[10] == 3 * base);
8335 VIXL_CHECK(array[11] == 4 * base);
8336 VIXL_CHECK(array[12] == ((1 * low_base) << kSRegSize));
8337 VIXL_CHECK(array[13] == (((2 * low_base) << kSRegSize) | (1 * high_base)));
8338 VIXL_CHECK(array[14] == (((3 * low_base) << kSRegSize) | (2 * high_base)));
8339 VIXL_CHECK(array[15] == (((4 * low_base) << kSRegSize) | (3 * high_base)));
8340 VIXL_CHECK(array[16] == (((1 * low_base) << kSRegSize) | (4 * high_base)));
8341 VIXL_CHECK(array[17] == (((2 * low_base) << kSRegSize) | (1 * high_base)));
8342 VIXL_CHECK(array[18] == (((3 * low_base) << kSRegSize) | (2 * high_base)));
8343 VIXL_CHECK(array[19] == (((4 * low_base) << kSRegSize) | (3 * high_base)));
8344 VIXL_CHECK(array[20] == (4 * high_base));
8345
8346 ASSERT_EQUAL_64(1 * low_base, x11);
8347 ASSERT_EQUAL_64(2 * low_base, x12);
8348 ASSERT_EQUAL_64(3 * low_base, x13);
8349 ASSERT_EQUAL_64(4 * low_base, x14);
8350 ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d11);
8351 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d12);
8352 ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d13);
8353 ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d14);
8354 ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d15);
8355 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d16);
8356 ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d17);
8357 ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d18);
8358 }
8359 }
8360
8361
8362 // This enum is used only as an argument to the push-pop test helpers.
8363 enum PushPopMethod {
8364 // Push or Pop using the Push and Pop methods, with blocks of up to four
8365 // registers. (Smaller blocks will be used if necessary.)
8366 PushPopByFour,
8367
8368 // Use Push<Size>RegList and Pop<Size>RegList to transfer the registers.
8369 PushPopRegList
8370 };
8371
8372
8373 // For the PushPop* tests, use the maximum number of registers that the test
8374 // supports (where a reg_count argument would otherwise be provided).
8375 static int const kPushPopUseMaxRegCount = -1;
8376
8377 // Test a simple push-pop pattern:
8378 // * Claim <claim> bytes to set the stack alignment.
8379 // * Push <reg_count> registers with size <reg_size>.
8380 // * Clobber the register contents.
8381 // * Pop <reg_count> registers to restore the original contents.
8382 // * Drop <claim> bytes to restore the original stack pointer.
8383 //
8384 // Different push and pop methods can be specified independently to test for
8385 // proper word-endian behaviour.
8386 static void PushPopSimpleHelper(int reg_count,
8387 int claim,
8388 int reg_size,
8389 PushPopMethod push_method,
8390 PushPopMethod pop_method) {
8391 SETUP();
8392
8393 START();
8394
8395 // Arbitrarily pick a register to use as a stack pointer.
8396 const Register& stack_pointer = x20;
8397 const RegList allowed = ~stack_pointer.GetBit();
8398 if (reg_count == kPushPopUseMaxRegCount) {
8399 reg_count = CountSetBits(allowed, kNumberOfRegisters);
8400 }
8401 // Work out which registers to use, based on reg_size.
8402 Register r[kNumberOfRegisters];
8403 Register x[kNumberOfRegisters];
8404 RegList list =
8405 PopulateRegisterArray(NULL, x, r, reg_size, reg_count, allowed);
8406
8407 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8408 UseScratchRegisterScope temps(&masm);
8409 temps.ExcludeAll();
8410
8411 // The literal base is chosen to have two useful properties:
8412 // * When multiplied by small values (such as a register index), this value
8413 // is clearly readable in the result.
8414 // * The value is not formed from repeating fixed-size smaller values, so it
8415 // can be used to detect endianness-related errors.
8416 uint64_t literal_base = 0x0100001000100101;
8417
8418 {
8419 VIXL_ASSERT(__ StackPointer().Is(sp));
8420 __ Mov(stack_pointer, __ StackPointer());
8421 __ SetStackPointer(stack_pointer);
8422
8423 int i;
8424
8425 // Initialize the registers.
8426 for (i = 0; i < reg_count; i++) {
8427 // Always write into the X register, to ensure that the upper word is
8428 // properly ignored by Push when testing W registers.
8429 __ Mov(x[i], literal_base * i);
8430 }
8431
8432 // Claim memory first, as requested.
8433 __ Claim(claim);
8434
8435 switch (push_method) {
8436 case PushPopByFour:
8437 // Push high-numbered registers first (to the highest addresses).
8438 for (i = reg_count; i >= 4; i -= 4) {
8439 __ Push(r[i - 1], r[i - 2], r[i - 3], r[i - 4]);
8440 }
8441 // Finish off the leftovers.
8442 switch (i) {
8443 case 3:
8444 __ Push(r[2], r[1], r[0]);
8445 break;
8446 case 2:
8447 __ Push(r[1], r[0]);
8448 break;
8449 case 1:
8450 __ Push(r[0]);
8451 break;
8452 default:
8453 VIXL_ASSERT(i == 0);
8454 break;
8455 }
8456 break;
8457 case PushPopRegList:
8458 __ PushSizeRegList(list, reg_size);
8459 break;
8460 }
8461
8462 // Clobber all the registers, to ensure that they get repopulated by Pop.
8463 Clobber(&masm, list);
8464
8465 switch (pop_method) {
8466 case PushPopByFour:
8467 // Pop low-numbered registers first (from the lowest addresses).
8468 for (i = 0; i <= (reg_count - 4); i += 4) {
8469 __ Pop(r[i], r[i + 1], r[i + 2], r[i + 3]);
8470 }
8471 // Finish off the leftovers.
8472 switch (reg_count - i) {
8473 case 3:
8474 __ Pop(r[i], r[i + 1], r[i + 2]);
8475 break;
8476 case 2:
8477 __ Pop(r[i], r[i + 1]);
8478 break;
8479 case 1:
8480 __ Pop(r[i]);
8481 break;
8482 default:
8483 VIXL_ASSERT(i == reg_count);
8484 break;
8485 }
8486 break;
8487 case PushPopRegList:
8488 __ PopSizeRegList(list, reg_size);
8489 break;
8490 }
8491
8492 // Drop memory to restore stack_pointer.
8493 __ Drop(claim);
8494
8495 __ Mov(sp, __ StackPointer());
8496 __ SetStackPointer(sp);
8497 }
8498
8499 END();
8500
8501 if (CAN_RUN()) {
8502 RUN();
8503
8504 // Check that the register contents were preserved.
8505 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
8506 // that the upper word was properly cleared by Pop.
8507 literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8508 for (int i = 0; i < reg_count; i++) {
8509 if (x[i].Is(xzr)) {
8510 ASSERT_EQUAL_64(0, x[i]);
8511 } else {
8512 ASSERT_EQUAL_64(literal_base * i, x[i]);
8513 }
8514 }
8515 }
8516 }
8517
8518
8519 TEST(push_pop_xreg_simple_32) {
8520 for (int claim = 0; claim <= 8; claim++) {
8521 for (int count = 0; count <= 8; count++) {
8522 PushPopSimpleHelper(count,
8523 claim,
8524 kWRegSize,
8525 PushPopByFour,
8526 PushPopByFour);
8527 PushPopSimpleHelper(count,
8528 claim,
8529 kWRegSize,
8530 PushPopByFour,
8531 PushPopRegList);
8532 PushPopSimpleHelper(count,
8533 claim,
8534 kWRegSize,
8535 PushPopRegList,
8536 PushPopByFour);
8537 PushPopSimpleHelper(count,
8538 claim,
8539 kWRegSize,
8540 PushPopRegList,
8541 PushPopRegList);
8542 }
8543 // Test with the maximum number of registers.
8544 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8545 claim,
8546 kWRegSize,
8547 PushPopByFour,
8548 PushPopByFour);
8549 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8550 claim,
8551 kWRegSize,
8552 PushPopByFour,
8553 PushPopRegList);
8554 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8555 claim,
8556 kWRegSize,
8557 PushPopRegList,
8558 PushPopByFour);
8559 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8560 claim,
8561 kWRegSize,
8562 PushPopRegList,
8563 PushPopRegList);
8564 }
8565 }
8566
8567
8568 TEST(push_pop_xreg_simple_64) {
8569 for (int claim = 0; claim <= 8; claim++) {
8570 for (int count = 0; count <= 8; count++) {
8571 PushPopSimpleHelper(count,
8572 claim,
8573 kXRegSize,
8574 PushPopByFour,
8575 PushPopByFour);
8576 PushPopSimpleHelper(count,
8577 claim,
8578 kXRegSize,
8579 PushPopByFour,
8580 PushPopRegList);
8581 PushPopSimpleHelper(count,
8582 claim,
8583 kXRegSize,
8584 PushPopRegList,
8585 PushPopByFour);
8586 PushPopSimpleHelper(count,
8587 claim,
8588 kXRegSize,
8589 PushPopRegList,
8590 PushPopRegList);
8591 }
8592 // Test with the maximum number of registers.
8593 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8594 claim,
8595 kXRegSize,
8596 PushPopByFour,
8597 PushPopByFour);
8598 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8599 claim,
8600 kXRegSize,
8601 PushPopByFour,
8602 PushPopRegList);
8603 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8604 claim,
8605 kXRegSize,
8606 PushPopRegList,
8607 PushPopByFour);
8608 PushPopSimpleHelper(kPushPopUseMaxRegCount,
8609 claim,
8610 kXRegSize,
8611 PushPopRegList,
8612 PushPopRegList);
8613 }
8614 }
8615
8616 // For the PushPopFP* tests, use the maximum number of registers that the test
8617 // supports (where a reg_count argument would otherwise be provided).
8618 static int const kPushPopFPUseMaxRegCount = -1;
8619
8620 // Test a simple push-pop pattern:
8621 // * Claim <claim> bytes to set the stack alignment.
8622 // * Push <reg_count> FP registers with size <reg_size>.
8623 // * Clobber the register contents.
8624 // * Pop <reg_count> FP registers to restore the original contents.
8625 // * Drop <claim> bytes to restore the original stack pointer.
8626 //
8627 // Different push and pop methods can be specified independently to test for
8628 // proper word-endian behaviour.
8629 static void PushPopFPSimpleHelper(int reg_count,
8630 int claim,
8631 int reg_size,
8632 PushPopMethod push_method,
8633 PushPopMethod pop_method) {
8634 SETUP_WITH_FEATURES((reg_count == 0) ? CPUFeatures::kNone : CPUFeatures::kFP);
8635
8636 START();
8637
8638 // We can use any floating-point register. None of them are reserved for
8639 // debug code, for example.
8640 static RegList const allowed = ~0;
8641 if (reg_count == kPushPopFPUseMaxRegCount) {
8642 reg_count = CountSetBits(allowed, kNumberOfVRegisters);
8643 }
8644 // Work out which registers to use, based on reg_size.
8645 VRegister v[kNumberOfRegisters];
8646 VRegister d[kNumberOfRegisters];
8647 RegList list =
8648 PopulateVRegisterArray(NULL, d, v, reg_size, reg_count, allowed);
8649
8650 // Arbitrarily pick a register to use as a stack pointer.
8651 const Register& stack_pointer = x10;
8652
8653 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8654 UseScratchRegisterScope temps(&masm);
8655 temps.ExcludeAll();
8656
8657 // The literal base is chosen to have two useful properties:
8658 // * When multiplied (using an integer) by small values (such as a register
8659 // index), this value is clearly readable in the result.
8660 // * The value is not formed from repeating fixed-size smaller values, so it
8661 // can be used to detect endianness-related errors.
8662 // * It is never a floating-point NaN, and will therefore always compare
8663 // equal to itself.
8664 uint64_t literal_base = 0x0100001000100101;
8665
8666 {
8667 VIXL_ASSERT(__ StackPointer().Is(sp));
8668 __ Mov(stack_pointer, __ StackPointer());
8669 __ SetStackPointer(stack_pointer);
8670
8671 int i;
8672
8673 // Initialize the registers, using X registers to load the literal.
8674 __ Mov(x0, 0);
8675 __ Mov(x1, literal_base);
8676 for (i = 0; i < reg_count; i++) {
8677 // Always write into the D register, to ensure that the upper word is
8678 // properly ignored by Push when testing S registers.
8679 __ Fmov(d[i], x0);
8680 // Calculate the next literal.
8681 __ Add(x0, x0, x1);
8682 }
8683
8684 // Claim memory first, as requested.
8685 __ Claim(claim);
8686
8687 switch (push_method) {
8688 case PushPopByFour:
8689 // Push high-numbered registers first (to the highest addresses).
8690 for (i = reg_count; i >= 4; i -= 4) {
8691 __ Push(v[i - 1], v[i - 2], v[i - 3], v[i - 4]);
8692 }
8693 // Finish off the leftovers.
8694 switch (i) {
8695 case 3:
8696 __ Push(v[2], v[1], v[0]);
8697 break;
8698 case 2:
8699 __ Push(v[1], v[0]);
8700 break;
8701 case 1:
8702 __ Push(v[0]);
8703 break;
8704 default:
8705 VIXL_ASSERT(i == 0);
8706 break;
8707 }
8708 break;
8709 case PushPopRegList:
8710 __ PushSizeRegList(list, reg_size, CPURegister::kVRegister);
8711 break;
8712 }
8713
8714 // Clobber all the registers, to ensure that they get repopulated by Pop.
8715 ClobberFP(&masm, list);
8716
8717 switch (pop_method) {
8718 case PushPopByFour:
8719 // Pop low-numbered registers first (from the lowest addresses).
8720 for (i = 0; i <= (reg_count - 4); i += 4) {
8721 __ Pop(v[i], v[i + 1], v[i + 2], v[i + 3]);
8722 }
8723 // Finish off the leftovers.
8724 switch (reg_count - i) {
8725 case 3:
8726 __ Pop(v[i], v[i + 1], v[i + 2]);
8727 break;
8728 case 2:
8729 __ Pop(v[i], v[i + 1]);
8730 break;
8731 case 1:
8732 __ Pop(v[i]);
8733 break;
8734 default:
8735 VIXL_ASSERT(i == reg_count);
8736 break;
8737 }
8738 break;
8739 case PushPopRegList:
8740 __ PopSizeRegList(list, reg_size, CPURegister::kVRegister);
8741 break;
8742 }
8743
8744 // Drop memory to restore the stack pointer.
8745 __ Drop(claim);
8746
8747 __ Mov(sp, __ StackPointer());
8748 __ SetStackPointer(sp);
8749 }
8750
8751 END();
8752
8753 if (CAN_RUN()) {
8754 RUN();
8755
8756 // Check that the register contents were preserved.
8757 // Always use ASSERT_EQUAL_FP64, even when testing S registers, so we can
8758 // test that the upper word was properly cleared by Pop.
8759 literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8760 for (int i = 0; i < reg_count; i++) {
8761 uint64_t literal = literal_base * i;
8762 double expected;
8763 memcpy(&expected, &literal, sizeof(expected));
8764 ASSERT_EQUAL_FP64(expected, d[i]);
8765 }
8766 }
8767 }
8768
8769
8770 TEST(push_pop_fp_xreg_simple_32) {
8771 for (int claim = 0; claim <= 8; claim++) {
8772 for (int count = 0; count <= 8; count++) {
8773 PushPopFPSimpleHelper(count,
8774 claim,
8775 kSRegSize,
8776 PushPopByFour,
8777 PushPopByFour);
8778 PushPopFPSimpleHelper(count,
8779 claim,
8780 kSRegSize,
8781 PushPopByFour,
8782 PushPopRegList);
8783 PushPopFPSimpleHelper(count,
8784 claim,
8785 kSRegSize,
8786 PushPopRegList,
8787 PushPopByFour);
8788 PushPopFPSimpleHelper(count,
8789 claim,
8790 kSRegSize,
8791 PushPopRegList,
8792 PushPopRegList);
8793 }
8794 // Test with the maximum number of registers.
8795 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8796 claim,
8797 kSRegSize,
8798 PushPopByFour,
8799 PushPopByFour);
8800 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8801 claim,
8802 kSRegSize,
8803 PushPopByFour,
8804 PushPopRegList);
8805 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8806 claim,
8807 kSRegSize,
8808 PushPopRegList,
8809 PushPopByFour);
8810 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8811 claim,
8812 kSRegSize,
8813 PushPopRegList,
8814 PushPopRegList);
8815 }
8816 }
8817
8818
8819 TEST(push_pop_fp_xreg_simple_64) {
8820 for (int claim = 0; claim <= 8; claim++) {
8821 for (int count = 0; count <= 8; count++) {
8822 PushPopFPSimpleHelper(count,
8823 claim,
8824 kDRegSize,
8825 PushPopByFour,
8826 PushPopByFour);
8827 PushPopFPSimpleHelper(count,
8828 claim,
8829 kDRegSize,
8830 PushPopByFour,
8831 PushPopRegList);
8832 PushPopFPSimpleHelper(count,
8833 claim,
8834 kDRegSize,
8835 PushPopRegList,
8836 PushPopByFour);
8837 PushPopFPSimpleHelper(count,
8838 claim,
8839 kDRegSize,
8840 PushPopRegList,
8841 PushPopRegList);
8842 }
8843 // Test with the maximum number of registers.
8844 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8845 claim,
8846 kDRegSize,
8847 PushPopByFour,
8848 PushPopByFour);
8849 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8850 claim,
8851 kDRegSize,
8852 PushPopByFour,
8853 PushPopRegList);
8854 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8855 claim,
8856 kDRegSize,
8857 PushPopRegList,
8858 PushPopByFour);
8859 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8860 claim,
8861 kDRegSize,
8862 PushPopRegList,
8863 PushPopRegList);
8864 }
8865 }
8866
8867
8868 // Push and pop data using an overlapping combination of Push/Pop and
8869 // RegList-based methods.
8870 static void PushPopMixedMethodsHelper(int claim, int reg_size) {
8871 SETUP();
8872
8873 // Arbitrarily pick a register to use as a stack pointer.
8874 const Register& stack_pointer = x5;
8875 const RegList allowed = ~stack_pointer.GetBit();
8876 // Work out which registers to use, based on reg_size.
8877 Register r[10];
8878 Register x[10];
8879 PopulateRegisterArray(NULL, x, r, reg_size, 10, allowed);
8880
8881 // Calculate some handy register lists.
8882 RegList r0_to_r3 = 0;
8883 for (int i = 0; i <= 3; i++) {
8884 r0_to_r3 |= x[i].GetBit();
8885 }
8886 RegList r4_to_r5 = 0;
8887 for (int i = 4; i <= 5; i++) {
8888 r4_to_r5 |= x[i].GetBit();
8889 }
8890 RegList r6_to_r9 = 0;
8891 for (int i = 6; i <= 9; i++) {
8892 r6_to_r9 |= x[i].GetBit();
8893 }
8894
8895 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8896 UseScratchRegisterScope temps(&masm);
8897 temps.ExcludeAll();
8898
8899 // The literal base is chosen to have two useful properties:
8900 // * When multiplied by small values (such as a register index), this value
8901 // is clearly readable in the result.
8902 // * The value is not formed from repeating fixed-size smaller values, so it
8903 // can be used to detect endianness-related errors.
8904 uint64_t literal_base = 0x0100001000100101;
8905
8906 START();
8907 {
8908 VIXL_ASSERT(__ StackPointer().Is(sp));
8909 __ Mov(stack_pointer, __ StackPointer());
8910 __ SetStackPointer(stack_pointer);
8911
8912 // Claim memory first, as requested.
8913 __ Claim(claim);
8914
8915 __ Mov(x[3], literal_base * 3);
8916 __ Mov(x[2], literal_base * 2);
8917 __ Mov(x[1], literal_base * 1);
8918 __ Mov(x[0], literal_base * 0);
8919
8920 __ PushSizeRegList(r0_to_r3, reg_size);
8921 __ Push(r[3], r[2]);
8922
8923 Clobber(&masm, r0_to_r3);
8924 __ PopSizeRegList(r0_to_r3, reg_size);
8925
8926 __ Push(r[2], r[1], r[3], r[0]);
8927
8928 Clobber(&masm, r4_to_r5);
8929 __ Pop(r[4], r[5]);
8930 Clobber(&masm, r6_to_r9);
8931 __ Pop(r[6], r[7], r[8], r[9]);
8932
8933 // Drop memory to restore stack_pointer.
8934 __ Drop(claim);
8935
8936 __ Mov(sp, __ StackPointer());
8937 __ SetStackPointer(sp);
8938 }
8939
8940 END();
8941
8942 if (CAN_RUN()) {
8943 RUN();
8944
8945 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
8946 // that the upper word was properly cleared by Pop.
8947 literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8948
8949 ASSERT_EQUAL_64(literal_base * 3, x[9]);
8950 ASSERT_EQUAL_64(literal_base * 2, x[8]);
8951 ASSERT_EQUAL_64(literal_base * 0, x[7]);
8952 ASSERT_EQUAL_64(literal_base * 3, x[6]);
8953 ASSERT_EQUAL_64(literal_base * 1, x[5]);
8954 ASSERT_EQUAL_64(literal_base * 2, x[4]);
8955 }
8956 }
8957
8958
8959 TEST(push_pop_xreg_mixed_methods_64) {
8960 for (int claim = 0; claim <= 8; claim++) {
8961 PushPopMixedMethodsHelper(claim, kXRegSize);
8962 }
8963 }
8964
8965
8966 TEST(push_pop_xreg_mixed_methods_32) {
8967 for (int claim = 0; claim <= 8; claim++) {
8968 PushPopMixedMethodsHelper(claim, kWRegSize);
8969 }
8970 }
8971
8972
8973 // Push and pop data using overlapping X- and W-sized quantities.
8974 static void PushPopWXOverlapHelper(int reg_count, int claim) {
8975 SETUP();
8976
8977 // Arbitrarily pick a register to use as a stack pointer.
8978 const Register& stack_pointer = x10;
8979 const RegList allowed = ~stack_pointer.GetBit();
8980 if (reg_count == kPushPopUseMaxRegCount) {
8981 reg_count = CountSetBits(allowed, kNumberOfRegisters);
8982 }
8983 // Work out which registers to use, based on reg_size.
8984 Register w[kNumberOfRegisters];
8985 Register x[kNumberOfRegisters];
8986 RegList list = PopulateRegisterArray(w, x, NULL, 0, reg_count, allowed);
8987
8988 // The number of W-sized slots we expect to pop. When we pop, we alternate
8989 // between W and X registers, so we need reg_count*1.5 W-sized slots.
8990 int const requested_w_slots = reg_count + reg_count / 2;
8991
8992 // Track what _should_ be on the stack, using W-sized slots.
8993 static int const kMaxWSlots = kNumberOfRegisters + kNumberOfRegisters / 2;
8994 uint32_t stack[kMaxWSlots];
8995 for (int i = 0; i < kMaxWSlots; i++) {
8996 stack[i] = 0xdeadbeef;
8997 }
8998
8999 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
9000 UseScratchRegisterScope temps(&masm);
9001 temps.ExcludeAll();
9002
9003 // The literal base is chosen to have two useful properties:
9004 // * When multiplied by small values (such as a register index), this value
9005 // is clearly readable in the result.
9006 // * The value is not formed from repeating fixed-size smaller values, so it
9007 // can be used to detect endianness-related errors.
9008 static uint64_t const literal_base = 0x0100001000100101;
9009 static uint64_t const literal_base_hi = literal_base >> 32;
9010 static uint64_t const literal_base_lo = literal_base & 0xffffffff;
9011 static uint64_t const literal_base_w = literal_base & 0xffffffff;
9012
9013 START();
9014 {
9015 VIXL_ASSERT(__ StackPointer().Is(sp));
9016 __ Mov(stack_pointer, __ StackPointer());
9017 __ SetStackPointer(stack_pointer);
9018
9019 // Initialize the registers.
9020 for (int i = 0; i < reg_count; i++) {
9021 // Always write into the X register, to ensure that the upper word is
9022 // properly ignored by Push when testing W registers.
9023 __ Mov(x[i], literal_base * i);
9024 }
9025
9026 // Claim memory first, as requested.
9027 __ Claim(claim);
9028
9029 // The push-pop pattern is as follows:
9030 // Push: Pop:
9031 // x[0](hi) -> w[0]
9032 // x[0](lo) -> x[1](hi)
9033 // w[1] -> x[1](lo)
9034 // w[1] -> w[2]
9035 // x[2](hi) -> x[2](hi)
9036 // x[2](lo) -> x[2](lo)
9037 // x[2](hi) -> w[3]
9038 // x[2](lo) -> x[4](hi)
9039 // x[2](hi) -> x[4](lo)
9040 // x[2](lo) -> w[5]
9041 // w[3] -> x[5](hi)
9042 // w[3] -> x[6](lo)
9043 // w[3] -> w[7]
9044 // w[3] -> x[8](hi)
9045 // x[4](hi) -> x[8](lo)
9046 // x[4](lo) -> w[9]
9047 // ... pattern continues ...
9048 //
9049 // That is, registers are pushed starting with the lower numbers,
9050 // alternating between x and w registers, and pushing i%4+1 copies of each,
9051 // where i is the register number.
9052 // Registers are popped starting with the higher numbers one-by-one,
9053 // alternating between x and w registers, but only popping one at a time.
9054 //
9055 // This pattern provides a wide variety of alignment effects and overlaps.
9056
9057 // ---- Push ----
9058
9059 int active_w_slots = 0;
9060 for (int i = 0; active_w_slots < requested_w_slots; i++) {
9061 VIXL_ASSERT(i < reg_count);
9062 // In order to test various arguments to PushMultipleTimes, and to try to
9063 // exercise different alignment and overlap effects, we push each
9064 // register a different number of times.
9065 int times = i % 4 + 1;
9066 if (i & 1) {
9067 // Push odd-numbered registers as W registers.
9068 __ PushMultipleTimes(times, w[i]);
9069 // Fill in the expected stack slots.
9070 for (int j = 0; j < times; j++) {
9071 if (w[i].Is(wzr)) {
9072 // The zero register always writes zeroes.
9073 stack[active_w_slots++] = 0;
9074 } else {
9075 stack[active_w_slots++] = literal_base_w * i;
9076 }
9077 }
9078 } else {
9079 // Push even-numbered registers as X registers.
9080 __ PushMultipleTimes(times, x[i]);
9081 // Fill in the expected stack slots.
9082 for (int j = 0; j < times; j++) {
9083 if (x[i].Is(xzr)) {
9084 // The zero register always writes zeroes.
9085 stack[active_w_slots++] = 0;
9086 stack[active_w_slots++] = 0;
9087 } else {
9088 stack[active_w_slots++] = literal_base_hi * i;
9089 stack[active_w_slots++] = literal_base_lo * i;
9090 }
9091 }
9092 }
9093 }
9094 // Because we were pushing several registers at a time, we probably pushed
9095 // more than we needed to.
9096 if (active_w_slots > requested_w_slots) {
9097 __ Drop((active_w_slots - requested_w_slots) * kWRegSizeInBytes);
9098 // Bump the number of active W-sized slots back to where it should be,
9099 // and fill the empty space with a placeholder value.
9100 do {
9101 stack[active_w_slots--] = 0xdeadbeef;
9102 } while (active_w_slots > requested_w_slots);
9103 }
9104
9105 // ---- Pop ----
9106
9107 Clobber(&masm, list);
9108
9109 // If popping an even number of registers, the first one will be X-sized.
9110 // Otherwise, the first one will be W-sized.
9111 bool next_is_64 = !(reg_count & 1);
9112 for (int i = reg_count - 1; i >= 0; i--) {
9113 if (next_is_64) {
9114 __ Pop(x[i]);
9115 active_w_slots -= 2;
9116 } else {
9117 __ Pop(w[i]);
9118 active_w_slots -= 1;
9119 }
9120 next_is_64 = !next_is_64;
9121 }
9122 VIXL_ASSERT(active_w_slots == 0);
9123
9124 // Drop memory to restore stack_pointer.
9125 __ Drop(claim);
9126
9127 __ Mov(sp, __ StackPointer());
9128 __ SetStackPointer(sp);
9129 }
9130
9131 END();
9132
9133 if (CAN_RUN()) {
9134 RUN();
9135
9136 int slot = 0;
9137 for (int i = 0; i < reg_count; i++) {
9138 // Even-numbered registers were written as W registers.
9139 // Odd-numbered registers were written as X registers.
9140 bool expect_64 = (i & 1);
9141 uint64_t expected;
9142
9143 if (expect_64) {
9144 uint64_t hi = stack[slot++];
9145 uint64_t lo = stack[slot++];
9146 expected = (hi << 32) | lo;
9147 } else {
9148 expected = stack[slot++];
9149 }
9150
9151 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can
9152 // test that the upper word was properly cleared by Pop.
9153 if (x[i].Is(xzr)) {
9154 ASSERT_EQUAL_64(0, x[i]);
9155 } else {
9156 ASSERT_EQUAL_64(expected, x[i]);
9157 }
9158 }
9159 VIXL_ASSERT(slot == requested_w_slots);
9160 }
9161 }
9162
9163
9164 TEST(push_pop_xreg_wx_overlap) {
9165 for (int claim = 0; claim <= 8; claim++) {
9166 for (int count = 1; count <= 8; count++) {
9167 PushPopWXOverlapHelper(count, claim);
9168 }
9169 // Test with the maximum number of registers.
9170 PushPopWXOverlapHelper(kPushPopUseMaxRegCount, claim);
9171 }
9172 }
9173
9174
9175 TEST(push_pop_sp) {
9176 SETUP();
9177
9178 START();
9179
9180 VIXL_ASSERT(sp.Is(__ StackPointer()));
9181
9182 // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
9183 UseScratchRegisterScope temps(&masm);
9184 temps.ExcludeAll();
9185
9186 __ Mov(x3, 0x3333333333333333);
9187 __ Mov(x2, 0x2222222222222222);
9188 __ Mov(x1, 0x1111111111111111);
9189 __ Mov(x0, 0x0000000000000000);
9190 __ Claim(2 * kXRegSizeInBytes);
9191 __ PushXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit());
9192 __ Push(x3, x2);
9193 __ PopXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit());
9194 __ Push(x2, x1, x3, x0);
9195 __ Pop(x4, x5);
9196 __ Pop(x6, x7, x8, x9);
9197
9198 __ Claim(2 * kXRegSizeInBytes);
9199 __ PushWRegList(w0.GetBit() | w1.GetBit() | w2.GetBit() | w3.GetBit());
9200 __ Push(w3, w1, w2, w0);
9201 __ PopWRegList(w10.GetBit() | w11.GetBit() | w12.GetBit() | w13.GetBit());
9202 __ Pop(w14, w15, w16, w17);
9203
9204 __ Claim(2 * kXRegSizeInBytes);
9205 __ Push(w2, w2, w1, w1);
9206 __ Push(x3, x3);
9207 __ Pop(w18, w19, w20, w21);
9208 __ Pop(x22, x23);
9209
9210 __ Claim(2 * kXRegSizeInBytes);
9211 __ PushXRegList(x1.GetBit() | x22.GetBit());
9212 __ PopXRegList(x24.GetBit() | x26.GetBit());
9213
9214 __ Claim(2 * kXRegSizeInBytes);
9215 __ PushWRegList(w1.GetBit() | w2.GetBit() | w4.GetBit() | w22.GetBit());
9216 __ PopWRegList(w25.GetBit() | w27.GetBit() | w28.GetBit() | w29.GetBit());
9217
9218 __ Claim(2 * kXRegSizeInBytes);
9219 __ PushXRegList(0);
9220 __ PopXRegList(0);
9221 __ PushXRegList(0xffffffff);
9222 __ PopXRegList(0xffffffff);
9223 __ Drop(12 * kXRegSizeInBytes);
9224 END();
9225
9226 if (CAN_RUN()) {
9227 RUN();
9228
9229 ASSERT_EQUAL_64(0x1111111111111111, x3);
9230 ASSERT_EQUAL_64(0x0000000000000000, x2);
9231 ASSERT_EQUAL_64(0x3333333333333333, x1);
9232 ASSERT_EQUAL_64(0x2222222222222222, x0);
9233 ASSERT_EQUAL_64(0x3333333333333333, x9);
9234 ASSERT_EQUAL_64(0x2222222222222222, x8);
9235 ASSERT_EQUAL_64(0x0000000000000000, x7);
9236 ASSERT_EQUAL_64(0x3333333333333333, x6);
9237 ASSERT_EQUAL_64(0x1111111111111111, x5);
9238 ASSERT_EQUAL_64(0x2222222222222222, x4);
9239
9240 ASSERT_EQUAL_32(0x11111111U, w13);
9241 ASSERT_EQUAL_32(0x33333333U, w12);
9242 ASSERT_EQUAL_32(0x00000000U, w11);
9243 ASSERT_EQUAL_32(0x22222222U, w10);
9244 ASSERT_EQUAL_32(0x11111111U, w17);
9245 ASSERT_EQUAL_32(0x00000000U, w16);
9246 ASSERT_EQUAL_32(0x33333333U, w15);
9247 ASSERT_EQUAL_32(0x22222222U, w14);
9248
9249 ASSERT_EQUAL_32(0x11111111U, w18);
9250 ASSERT_EQUAL_32(0x11111111U, w19);
9251 ASSERT_EQUAL_32(0x11111111U, w20);
9252 ASSERT_EQUAL_32(0x11111111U, w21);
9253 ASSERT_EQUAL_64(0x3333333333333333, x22);
9254 ASSERT_EQUAL_64(0x0000000000000000, x23);
9255
9256 ASSERT_EQUAL_64(0x3333333333333333, x24);
9257 ASSERT_EQUAL_64(0x3333333333333333, x26);
9258
9259 ASSERT_EQUAL_32(0x33333333U, w25);
9260 ASSERT_EQUAL_32(0x00000000U, w27);
9261 ASSERT_EQUAL_32(0x22222222U, w28);
9262 ASSERT_EQUAL_32(0x33333333U, w29);
9263 }
9264 }
9265
9266
9267 TEST(printf) {
9268 // RegisterDump::Dump uses NEON.
9269 // Printf uses FP to cast FP arguments to doubles.
9270 SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
9271
9272 START();
9273
9274 char const* test_plain_string = "Printf with no arguments.\n";
9275 char const* test_substring = "'This is a substring.'";
9276 RegisterDump before;
9277
9278 // Initialize x29 to the value of the stack pointer. We will use x29 as a
9279 // temporary stack pointer later, and initializing it in this way allows the
9280 // RegisterDump check to pass.
9281 __ Mov(x29, __ StackPointer());
9282
9283 // Test simple integer arguments.
9284 __ Mov(x0, 1234);
9285 __ Mov(x1, 0x1234);
9286
9287 // Test simple floating-point arguments.
9288 __ Fmov(d0, 1.234);
9289
9290 // Test pointer (string) arguments.
9291 __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9292
9293 // Test the maximum number of arguments, and sign extension.
9294 __ Mov(w3, 0xffffffff);
9295 __ Mov(w4, 0xffffffff);
9296 __ Mov(x5, 0xffffffffffffffff);
9297 __ Mov(x6, 0xffffffffffffffff);
9298 __ Fmov(s1, 1.234);
9299 __ Fmov(s2, 2.345);
9300 __ Fmov(d3, 3.456);
9301 __ Fmov(d4, 4.567);
9302
9303 // Test printing callee-saved registers.
9304 __ Mov(x28, 0x123456789abcdef);
9305 __ Fmov(d10, 42.0);
9306
9307 // Test with three arguments.
9308 __ Mov(x10, 3);
9309 __ Mov(x11, 40);
9310 __ Mov(x12, 500);
9311
9312 // A single character.
9313 __ Mov(w13, 'x');
9314
9315 // Check that we don't clobber any registers.
9316 before.Dump(&masm);
9317
9318 __ Printf(test_plain_string); // NOLINT(runtime/printf)
9319 __ Printf("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
9320 __ Printf("w5: %" PRId32 ", x5: %" PRId64 "\n", w5, x5);
9321 __ Printf("d0: %f\n", d0);
9322 __ Printf("Test %%s: %s\n", x2);
9323 __ Printf("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32
9324 "\n"
9325 "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9326 w3,
9327 w4,
9328 x5,
9329 x6);
9330 __ Printf("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
9331 __ Printf("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
9332 __ Printf("%g\n", d10);
9333 __ Printf("%%%%%s%%%c%%\n", x2, w13);
9334
9335 // Print the stack pointer (sp).
9336 __ Printf("StackPointer(sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
9337 __ StackPointer(),
9338 __ StackPointer().W());
9339
9340 // Test with a different stack pointer.
9341 const Register old_stack_pointer = __ StackPointer();
9342 __ Mov(x29, old_stack_pointer);
9343 __ SetStackPointer(x29);
9344 // Print the stack pointer (not sp).
9345 __ Printf("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
9346 __ StackPointer(),
9347 __ StackPointer().W());
9348 __ Mov(old_stack_pointer, __ StackPointer());
9349 __ SetStackPointer(old_stack_pointer);
9350
9351 // Test with three arguments.
9352 __ Printf("3=%u, 4=%u, 5=%u\n", x10, x11, x12);
9353
9354 // Mixed argument types.
9355 __ Printf("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
9356 w3,
9357 s1,
9358 x5,
9359 d3);
9360 __ Printf("s1: %f, d3: %f, w3: %" PRId32 ", x5: %" PRId64 "\n",
9361 s1,
9362 d3,
9363 w3,
9364 x5);
9365
9366 END();
9367 if (CAN_RUN()) {
9368 RUN();
9369
9370 // We cannot easily test the output of the Printf sequences, and because
9371 // Printf preserves all registers by default, we can't look at the number of
9372 // bytes that were printed. However, the printf_no_preserve test should
9373 // check
9374 // that, and here we just test that we didn't clobber any registers.
9375 ASSERT_EQUAL_REGISTERS(before);
9376 }
9377 }
9378
9379
9380 TEST(printf_no_preserve) {
9381 // PrintfNoPreserve uses FP to cast FP arguments to doubles.
9382 SETUP_WITH_FEATURES(CPUFeatures::kFP);
9383
9384 START();
9385
9386 char const* test_plain_string = "Printf with no arguments.\n";
9387 char const* test_substring = "'This is a substring.'";
9388
9389 __ PrintfNoPreserve(test_plain_string);
9390 __ Mov(x19, x0);
9391
9392 // Test simple integer arguments.
9393 __ Mov(x0, 1234);
9394 __ Mov(x1, 0x1234);
9395 __ PrintfNoPreserve("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
9396 __ Mov(x20, x0);
9397
9398 // Test simple floating-point arguments.
9399 __ Fmov(d0, 1.234);
9400 __ PrintfNoPreserve("d0: %f\n", d0);
9401 __ Mov(x21, x0);
9402
9403 // Test pointer (string) arguments.
9404 __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9405 __ PrintfNoPreserve("Test %%s: %s\n", x2);
9406 __ Mov(x22, x0);
9407
9408 // Test the maximum number of arguments, and sign extension.
9409 __ Mov(w3, 0xffffffff);
9410 __ Mov(w4, 0xffffffff);
9411 __ Mov(x5, 0xffffffffffffffff);
9412 __ Mov(x6, 0xffffffffffffffff);
9413 __ PrintfNoPreserve("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32
9414 "\n"
9415 "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9416 w3,
9417 w4,
9418 x5,
9419 x6);
9420 __ Mov(x23, x0);
9421
9422 __ Fmov(s1, 1.234);
9423 __ Fmov(s2, 2.345);
9424 __ Fmov(d3, 3.456);
9425 __ Fmov(d4, 4.567);
9426 __ PrintfNoPreserve("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
9427 __ Mov(x24, x0);
9428
9429 // Test printing callee-saved registers.
9430 __ Mov(x28, 0x123456789abcdef);
9431 __ PrintfNoPreserve("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
9432 __ Mov(x25, x0);
9433
9434 __ Fmov(d10, 42.0);
9435 __ PrintfNoPreserve("%g\n", d10);
9436 __ Mov(x26, x0);
9437
9438 // Test with a different stack pointer.
9439 const Register old_stack_pointer = __ StackPointer();
9440 __ Mov(x29, old_stack_pointer);
9441 __ SetStackPointer(x29);
9442 // Print the stack pointer (not sp).
9443 __ PrintfNoPreserve("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32
9444 "\n",
9445 __ StackPointer(),
9446 __ StackPointer().W());
9447 __ Mov(x27, x0);
9448 __ Mov(old_stack_pointer, __ StackPointer());
9449 __ SetStackPointer(old_stack_pointer);
9450
9451 // Test with three arguments.
9452 __ Mov(x3, 3);
9453 __ Mov(x4, 40);
9454 __ Mov(x5, 500);
9455 __ PrintfNoPreserve("3=%u, 4=%u, 5=%u\n", x3, x4, x5);
9456 __ Mov(x28, x0);
9457
9458 // Mixed argument types.
9459 __ Mov(w3, 0xffffffff);
9460 __ Fmov(s1, 1.234);
9461 __ Mov(x5, 0xffffffffffffffff);
9462 __ Fmov(d3, 3.456);
9463 __ PrintfNoPreserve("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
9464 w3,
9465 s1,
9466 x5,
9467 d3);
9468 __ Mov(x29, x0);
9469
9470 END();
9471 if (CAN_RUN()) {
9472 RUN();
9473
9474 // We cannot easily test the exact output of the Printf sequences, but we
9475 // can
9476 // use the return code to check that the string length was correct.
9477
9478 // Printf with no arguments.
9479 ASSERT_EQUAL_64(strlen(test_plain_string), x19);
9480 // x0: 1234, x1: 0x00001234
9481 ASSERT_EQUAL_64(25, x20);
9482 // d0: 1.234000
9483 ASSERT_EQUAL_64(13, x21);
9484 // Test %s: 'This is a substring.'
9485 ASSERT_EQUAL_64(32, x22);
9486 // w3(uint32): 4294967295
9487 // w4(int32): -1
9488 // x5(uint64): 18446744073709551615
9489 // x6(int64): -1
9490 ASSERT_EQUAL_64(23 + 14 + 33 + 14, x23);
9491 // %f: 1.234000
9492 // %g: 2.345
9493 // %e: 3.456000e+00
9494 // %E: 4.567000E+00
9495 ASSERT_EQUAL_64(13 + 10 + 17 + 17, x24);
9496 // 0x89abcdef, 0x123456789abcdef
9497 ASSERT_EQUAL_64(30, x25);
9498 // 42
9499 ASSERT_EQUAL_64(3, x26);
9500 // StackPointer(not sp): 0x00007fb037ae2370, 0x37ae2370
9501 // Note: This is an example value, but the field width is fixed here so the
9502 // string length is still predictable.
9503 ASSERT_EQUAL_64(53, x27);
9504 // 3=3, 4=40, 5=500
9505 ASSERT_EQUAL_64(17, x28);
9506 // w3: 4294967295, s1: 1.234000, x5: 18446744073709551615, d3: 3.456000
9507 ASSERT_EQUAL_64(69, x29);
9508 }
9509 }
9510
9511
9512 TEST(trace) {
9513 // The Trace helper should not generate any code unless the simulator is being
9514 // used.
9515 SETUP();
9516 START();
9517
9518 Label start;
9519 __ Bind(&start);
9520 __ Trace(LOG_ALL, TRACE_ENABLE);
9521 __ Trace(LOG_ALL, TRACE_DISABLE);
9522 if (masm.GenerateSimulatorCode()) {
9523 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0);
9524 } else {
9525 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
9526 }
9527
9528 END();
9529 }
9530
9531
9532 TEST(log) {
9533 // The Log helper should not generate any code unless the simulator is being
9534 // used.
9535 SETUP();
9536 START();
9537
9538 Label start;
9539 __ Bind(&start);
9540 __ Log(LOG_ALL);
9541 if (masm.GenerateSimulatorCode()) {
9542 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0);
9543 } else {
9544 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
9545 }
9546
9547 END();
9548 }
9549
9550
9551 TEST(blr_lr) {
9552 // A simple test to check that the simulator correctly handle "blr lr".
9553 SETUP();
9554
9555 START();
9556 Label target;
9557 Label end;
9558
9559 __ Mov(x0, 0x0);
9560 __ Adr(lr, &target);
9561
9562 __ Blr(lr);
9563 __ Mov(x0, 0xdeadbeef);
9564 __ B(&end);
9565
9566 __ Bind(&target);
9567 __ Mov(x0, 0xc001c0de);
9568
9569 __ Bind(&end);
9570 END();
9571
9572 if (CAN_RUN()) {
9573 RUN();
9574
9575 ASSERT_EQUAL_64(0xc001c0de, x0);
9576 }
9577 }
9578
9579
9580 TEST(barriers) {
9581 // Generate all supported barriers, this is just a smoke test
9582 SETUP();
9583
9584 START();
9585
9586 // DMB
9587 __ Dmb(FullSystem, BarrierAll);
9588 __ Dmb(FullSystem, BarrierReads);
9589 __ Dmb(FullSystem, BarrierWrites);
9590 __ Dmb(FullSystem, BarrierOther);
9591
9592 __ Dmb(InnerShareable, BarrierAll);
9593 __ Dmb(InnerShareable, BarrierReads);
9594 __ Dmb(InnerShareable, BarrierWrites);
9595 __ Dmb(InnerShareable, BarrierOther);
9596
9597 __ Dmb(NonShareable, BarrierAll);
9598 __ Dmb(NonShareable, BarrierReads);
9599 __ Dmb(NonShareable, BarrierWrites);
9600 __ Dmb(NonShareable, BarrierOther);
9601
9602 __ Dmb(OuterShareable, BarrierAll);
9603 __ Dmb(OuterShareable, BarrierReads);
9604 __ Dmb(OuterShareable, BarrierWrites);
9605 __ Dmb(OuterShareable, BarrierOther);
9606
9607 // DSB
9608 __ Dsb(FullSystem, BarrierAll);
9609 __ Dsb(FullSystem, BarrierReads);
9610 __ Dsb(FullSystem, BarrierWrites);
9611 __ Dsb(FullSystem, BarrierOther);
9612
9613 __ Dsb(InnerShareable, BarrierAll);
9614 __ Dsb(InnerShareable, BarrierReads);
9615 __ Dsb(InnerShareable, BarrierWrites);
9616 __ Dsb(InnerShareable, BarrierOther);
9617
9618 __ Dsb(NonShareable, BarrierAll);
9619 __ Dsb(NonShareable, BarrierReads);
9620 __ Dsb(NonShareable, BarrierWrites);
9621 __ Dsb(NonShareable, BarrierOther);
9622
9623 __ Dsb(OuterShareable, BarrierAll);
9624 __ Dsb(OuterShareable, BarrierReads);
9625 __ Dsb(OuterShareable, BarrierWrites);
9626 __ Dsb(OuterShareable, BarrierOther);
9627
9628 // ISB
9629 __ Isb();
9630
9631 END();
9632
9633 if (CAN_RUN()) {
9634 RUN();
9635 }
9636 }
9637
9638
9639 TEST(ldar_stlr) {
9640 // The middle value is read, modified, and written. The padding exists only to
9641 // check for over-write.
9642 uint8_t b[] = {0, 0x12, 0};
9643 uint16_t h[] = {0, 0x1234, 0};
9644 uint32_t w[] = {0, 0x12345678, 0};
9645 uint64_t x[] = {0, 0x123456789abcdef0, 0};
9646
9647 SETUP();
9648 START();
9649
9650 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9651 __ Ldarb(w0, MemOperand(x10));
9652 __ Add(w0, w0, 1);
9653 __ Stlrb(w0, MemOperand(x10));
9654
9655 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9656 __ Ldarh(w0, MemOperand(x10));
9657 __ Add(w0, w0, 1);
9658 __ Stlrh(w0, MemOperand(x10));
9659
9660 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9661 __ Ldar(w0, MemOperand(x10));
9662 __ Add(w0, w0, 1);
9663 __ Stlr(w0, MemOperand(x10));
9664
9665 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9666 __ Ldar(x0, MemOperand(x10));
9667 __ Add(x0, x0, 1);
9668 __ Stlr(x0, MemOperand(x10));
9669
9670 END();
9671 if (CAN_RUN()) {
9672 RUN();
9673
9674 ASSERT_EQUAL_32(0x13, b[1]);
9675 ASSERT_EQUAL_32(0x1235, h[1]);
9676 ASSERT_EQUAL_32(0x12345679, w[1]);
9677 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9678
9679 // Check for over-write.
9680 ASSERT_EQUAL_32(0, b[0]);
9681 ASSERT_EQUAL_32(0, b[2]);
9682 ASSERT_EQUAL_32(0, h[0]);
9683 ASSERT_EQUAL_32(0, h[2]);
9684 ASSERT_EQUAL_32(0, w[0]);
9685 ASSERT_EQUAL_32(0, w[2]);
9686 ASSERT_EQUAL_64(0, x[0]);
9687 ASSERT_EQUAL_64(0, x[2]);
9688 }
9689 }
9690
9691
9692 TEST(ldlar_stllr) {
9693 // The middle value is read, modified, and written. The padding exists only to
9694 // check for over-write.
9695 uint8_t b[] = {0, 0x12, 0};
9696 uint16_t h[] = {0, 0x1234, 0};
9697 uint32_t w[] = {0, 0x12345678, 0};
9698 uint64_t x[] = {0, 0x123456789abcdef0, 0};
9699
9700 SETUP_WITH_FEATURES(CPUFeatures::kLORegions);
9701
9702 START();
9703
9704 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9705 __ Ldlarb(w0, MemOperand(x10));
9706 __ Add(w0, w0, 1);
9707 __ Stllrb(w0, MemOperand(x10));
9708
9709 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9710 __ Ldlarh(w0, MemOperand(x10));
9711 __ Add(w0, w0, 1);
9712 __ Stllrh(w0, MemOperand(x10));
9713
9714 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9715 __ Ldlar(w0, MemOperand(x10));
9716 __ Add(w0, w0, 1);
9717 __ Stllr(w0, MemOperand(x10));
9718
9719 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9720 __ Ldlar(x0, MemOperand(x10));
9721 __ Add(x0, x0, 1);
9722 __ Stllr(x0, MemOperand(x10));
9723
9724 END();
9725
9726 if (CAN_RUN()) {
9727 RUN();
9728
9729 ASSERT_EQUAL_32(0x13, b[1]);
9730 ASSERT_EQUAL_32(0x1235, h[1]);
9731 ASSERT_EQUAL_32(0x12345679, w[1]);
9732 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9733
9734 // Check for over-write.
9735 ASSERT_EQUAL_32(0, b[0]);
9736 ASSERT_EQUAL_32(0, b[2]);
9737 ASSERT_EQUAL_32(0, h[0]);
9738 ASSERT_EQUAL_32(0, h[2]);
9739 ASSERT_EQUAL_32(0, w[0]);
9740 ASSERT_EQUAL_32(0, w[2]);
9741 ASSERT_EQUAL_64(0, x[0]);
9742 ASSERT_EQUAL_64(0, x[2]);
9743 }
9744 }
9745
9746
9747 TEST(ldxr_stxr) {
9748 // The middle value is read, modified, and written. The padding exists only to
9749 // check for over-write.
9750 uint8_t b[] = {0, 0x12, 0};
9751 uint16_t h[] = {0, 0x1234, 0};
9752 uint32_t w[] = {0, 0x12345678, 0};
9753 uint64_t x[] = {0, 0x123456789abcdef0, 0};
9754
9755 // As above, but get suitably-aligned values for ldxp and stxp.
9756 uint32_t wp_data[] = {0, 0, 0, 0, 0};
9757 uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
9758 wp[1] = 0x12345678; // wp[1] is 64-bit-aligned.
9759 wp[2] = 0x87654321;
9760 uint64_t xp_data[] = {0, 0, 0, 0, 0};
9761 uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
9762 xp[1] = 0x123456789abcdef0; // xp[1] is 128-bit-aligned.
9763 xp[2] = 0x0fedcba987654321;
9764
9765 SETUP();
9766 START();
9767
9768 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9769 Label try_b;
9770 __ Bind(&try_b);
9771 __ Ldxrb(w0, MemOperand(x10));
9772 __ Add(w0, w0, 1);
9773 __ Stxrb(w5, w0, MemOperand(x10));
9774 __ Cbnz(w5, &try_b);
9775
9776 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9777 Label try_h;
9778 __ Bind(&try_h);
9779 __ Ldxrh(w0, MemOperand(x10));
9780 __ Add(w0, w0, 1);
9781 __ Stxrh(w5, w0, MemOperand(x10));
9782 __ Cbnz(w5, &try_h);
9783
9784 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9785 Label try_w;
9786 __ Bind(&try_w);
9787 __ Ldxr(w0, MemOperand(x10));
9788 __ Add(w0, w0, 1);
9789 __ Stxr(w5, w0, MemOperand(x10));
9790 __ Cbnz(w5, &try_w);
9791
9792 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9793 Label try_x;
9794 __ Bind(&try_x);
9795 __ Ldxr(x0, MemOperand(x10));
9796 __ Add(x0, x0, 1);
9797 __ Stxr(w5, x0, MemOperand(x10));
9798 __ Cbnz(w5, &try_x);
9799
9800 __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
9801 Label try_wp;
9802 __ Bind(&try_wp);
9803 __ Ldxp(w0, w1, MemOperand(x10));
9804 __ Add(w0, w0, 1);
9805 __ Add(w1, w1, 1);
9806 __ Stxp(w5, w0, w1, MemOperand(x10));
9807 __ Cbnz(w5, &try_wp);
9808
9809 __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
9810 Label try_xp;
9811 __ Bind(&try_xp);
9812 __ Ldxp(x0, x1, MemOperand(x10));
9813 __ Add(x0, x0, 1);
9814 __ Add(x1, x1, 1);
9815 __ Stxp(w5, x0, x1, MemOperand(x10));
9816 __ Cbnz(w5, &try_xp);
9817
9818 END();
9819 if (CAN_RUN()) {
9820 RUN();
9821
9822 ASSERT_EQUAL_32(0x13, b[1]);
9823 ASSERT_EQUAL_32(0x1235, h[1]);
9824 ASSERT_EQUAL_32(0x12345679, w[1]);
9825 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9826 ASSERT_EQUAL_32(0x12345679, wp[1]);
9827 ASSERT_EQUAL_32(0x87654322, wp[2]);
9828 ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
9829 ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
9830
9831 // Check for over-write.
9832 ASSERT_EQUAL_32(0, b[0]);
9833 ASSERT_EQUAL_32(0, b[2]);
9834 ASSERT_EQUAL_32(0, h[0]);
9835 ASSERT_EQUAL_32(0, h[2]);
9836 ASSERT_EQUAL_32(0, w[0]);
9837 ASSERT_EQUAL_32(0, w[2]);
9838 ASSERT_EQUAL_64(0, x[0]);
9839 ASSERT_EQUAL_64(0, x[2]);
9840 ASSERT_EQUAL_32(0, wp[0]);
9841 ASSERT_EQUAL_32(0, wp[3]);
9842 ASSERT_EQUAL_64(0, xp[0]);
9843 ASSERT_EQUAL_64(0, xp[3]);
9844 }
9845 }
9846
9847
9848 TEST(ldaxr_stlxr) {
9849 // The middle value is read, modified, and written. The padding exists only to
9850 // check for over-write.
9851 uint8_t b[] = {0, 0x12, 0};
9852 uint16_t h[] = {0, 0x1234, 0};
9853 uint32_t w[] = {0, 0x12345678, 0};
9854 uint64_t x[] = {0, 0x123456789abcdef0, 0};
9855
9856 // As above, but get suitably-aligned values for ldxp and stxp.
9857 uint32_t wp_data[] = {0, 0, 0, 0, 0};
9858 uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
9859 wp[1] = 0x12345678; // wp[1] is 64-bit-aligned.
9860 wp[2] = 0x87654321;
9861 uint64_t xp_data[] = {0, 0, 0, 0, 0};
9862 uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
9863 xp[1] = 0x123456789abcdef0; // xp[1] is 128-bit-aligned.
9864 xp[2] = 0x0fedcba987654321;
9865
9866 SETUP();
9867 START();
9868
9869 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9870 Label try_b;
9871 __ Bind(&try_b);
9872 __ Ldaxrb(w0, MemOperand(x10));
9873 __ Add(w0, w0, 1);
9874 __ Stlxrb(w5, w0, MemOperand(x10));
9875 __ Cbnz(w5, &try_b);
9876
9877 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9878 Label try_h;
9879 __ Bind(&try_h);
9880 __ Ldaxrh(w0, MemOperand(x10));
9881 __ Add(w0, w0, 1);
9882 __ Stlxrh(w5, w0, MemOperand(x10));
9883 __ Cbnz(w5, &try_h);
9884
9885 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9886 Label try_w;
9887 __ Bind(&try_w);
9888 __ Ldaxr(w0, MemOperand(x10));
9889 __ Add(w0, w0, 1);
9890 __ Stlxr(w5, w0, MemOperand(x10));
9891 __ Cbnz(w5, &try_w);
9892
9893 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9894 Label try_x;
9895 __ Bind(&try_x);
9896 __ Ldaxr(x0, MemOperand(x10));
9897 __ Add(x0, x0, 1);
9898 __ Stlxr(w5, x0, MemOperand(x10));
9899 __ Cbnz(w5, &try_x);
9900
9901 __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
9902 Label try_wp;
9903 __ Bind(&try_wp);
9904 __ Ldaxp(w0, w1, MemOperand(x10));
9905 __ Add(w0, w0, 1);
9906 __ Add(w1, w1, 1);
9907 __ Stlxp(w5, w0, w1, MemOperand(x10));
9908 __ Cbnz(w5, &try_wp);
9909
9910 __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
9911 Label try_xp;
9912 __ Bind(&try_xp);
9913 __ Ldaxp(x0, x1, MemOperand(x10));
9914 __ Add(x0, x0, 1);
9915 __ Add(x1, x1, 1);
9916 __ Stlxp(w5, x0, x1, MemOperand(x10));
9917 __ Cbnz(w5, &try_xp);
9918
9919 END();
9920 if (CAN_RUN()) {
9921 RUN();
9922
9923 ASSERT_EQUAL_32(0x13, b[1]);
9924 ASSERT_EQUAL_32(0x1235, h[1]);
9925 ASSERT_EQUAL_32(0x12345679, w[1]);
9926 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9927 ASSERT_EQUAL_32(0x12345679, wp[1]);
9928 ASSERT_EQUAL_32(0x87654322, wp[2]);
9929 ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
9930 ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
9931
9932 // Check for over-write.
9933 ASSERT_EQUAL_32(0, b[0]);
9934 ASSERT_EQUAL_32(0, b[2]);
9935 ASSERT_EQUAL_32(0, h[0]);
9936 ASSERT_EQUAL_32(0, h[2]);
9937 ASSERT_EQUAL_32(0, w[0]);
9938 ASSERT_EQUAL_32(0, w[2]);
9939 ASSERT_EQUAL_64(0, x[0]);
9940 ASSERT_EQUAL_64(0, x[2]);
9941 ASSERT_EQUAL_32(0, wp[0]);
9942 ASSERT_EQUAL_32(0, wp[3]);
9943 ASSERT_EQUAL_64(0, xp[0]);
9944 ASSERT_EQUAL_64(0, xp[3]);
9945 }
9946 }
9947
9948
9949 TEST(clrex) {
9950 // This data should never be written.
9951 uint64_t data[] = {0, 0, 0};
9952 uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
9953
9954 SETUP();
9955 START();
9956
9957 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
9958 __ Mov(w6, 0);
9959
9960 __ Ldxrb(w0, MemOperand(x10));
9961 __ Clrex();
9962 __ Add(w0, w0, 1);
9963 __ Stxrb(w5, w0, MemOperand(x10));
9964 __ Add(w6, w6, w5);
9965
9966 __ Ldxrh(w0, MemOperand(x10));
9967 __ Clrex();
9968 __ Add(w0, w0, 1);
9969 __ Stxrh(w5, w0, MemOperand(x10));
9970 __ Add(w6, w6, w5);
9971
9972 __ Ldxr(w0, MemOperand(x10));
9973 __ Clrex();
9974 __ Add(w0, w0, 1);
9975 __ Stxr(w5, w0, MemOperand(x10));
9976 __ Add(w6, w6, w5);
9977
9978 __ Ldxr(x0, MemOperand(x10));
9979 __ Clrex();
9980 __ Add(x0, x0, 1);
9981 __ Stxr(w5, x0, MemOperand(x10));
9982 __ Add(w6, w6, w5);
9983
9984 __ Ldxp(w0, w1, MemOperand(x10));
9985 __ Clrex();
9986 __ Add(w0, w0, 1);
9987 __ Add(w1, w1, 1);
9988 __ Stxp(w5, w0, w1, MemOperand(x10));
9989 __ Add(w6, w6, w5);
9990
9991 __ Ldxp(x0, x1, MemOperand(x10));
9992 __ Clrex();
9993 __ Add(x0, x0, 1);
9994 __ Add(x1, x1, 1);
9995 __ Stxp(w5, x0, x1, MemOperand(x10));
9996 __ Add(w6, w6, w5);
9997
9998 // Acquire-release variants.
9999
10000 __ Ldaxrb(w0, MemOperand(x10));
10001 __ Clrex();
10002 __ Add(w0, w0, 1);
10003 __ Stlxrb(w5, w0, MemOperand(x10));
10004 __ Add(w6, w6, w5);
10005
10006 __ Ldaxrh(w0, MemOperand(x10));
10007 __ Clrex();
10008 __ Add(w0, w0, 1);
10009 __ Stlxrh(w5, w0, MemOperand(x10));
10010 __ Add(w6, w6, w5);
10011
10012 __ Ldaxr(w0, MemOperand(x10));
10013 __ Clrex();
10014 __ Add(w0, w0, 1);
10015 __ Stlxr(w5, w0, MemOperand(x10));
10016 __ Add(w6, w6, w5);
10017
10018 __ Ldaxr(x0, MemOperand(x10));
10019 __ Clrex();
10020 __ Add(x0, x0, 1);
10021 __ Stlxr(w5, x0, MemOperand(x10));
10022 __ Add(w6, w6, w5);
10023
10024 __ Ldaxp(w0, w1, MemOperand(x10));
10025 __ Clrex();
10026 __ Add(w0, w0, 1);
10027 __ Add(w1, w1, 1);
10028 __ Stlxp(w5, w0, w1, MemOperand(x10));
10029 __ Add(w6, w6, w5);
10030
10031 __ Ldaxp(x0, x1, MemOperand(x10));
10032 __ Clrex();
10033 __ Add(x0, x0, 1);
10034 __ Add(x1, x1, 1);
10035 __ Stlxp(w5, x0, x1, MemOperand(x10));
10036 __ Add(w6, w6, w5);
10037
10038 END();
10039 if (CAN_RUN()) {
10040 RUN();
10041
10042 // None of the 12 store-exclusives should have succeeded.
10043 ASSERT_EQUAL_32(12, w6);
10044
10045 ASSERT_EQUAL_64(0, data[0]);
10046 ASSERT_EQUAL_64(0, data[1]);
10047 ASSERT_EQUAL_64(0, data[2]);
10048 }
10049 }
10050
10051
10052 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
10053 // Check that the simulator occasionally makes store-exclusive fail.
10054 TEST(ldxr_stxr_fail) {
10055 uint64_t data[] = {0, 0, 0};
10056 uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
10057
10058 // Impose a hard limit on the number of attempts, so the test cannot hang.
10059 static const uint64_t kWatchdog = 10000;
10060 Label done;
10061
10062 SETUP();
10063 START();
10064
10065 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
10066 __ Mov(x11, kWatchdog);
10067
10068 // This loop is the opposite of what we normally do with ldxr and stxr; we
10069 // keep trying until we fail (or the watchdog counter runs out).
10070 Label try_b;
10071 __ Bind(&try_b);
10072 __ Ldxrb(w0, MemOperand(x10));
10073 __ Stxrb(w5, w0, MemOperand(x10));
10074 // Check the watchdog counter.
10075 __ Sub(x11, x11, 1);
10076 __ Cbz(x11, &done);
10077 // Check the exclusive-store result.
10078 __ Cbz(w5, &try_b);
10079
10080 Label try_h;
10081 __ Bind(&try_h);
10082 __ Ldxrh(w0, MemOperand(x10));
10083 __ Stxrh(w5, w0, MemOperand(x10));
10084 __ Sub(x11, x11, 1);
10085 __ Cbz(x11, &done);
10086 __ Cbz(w5, &try_h);
10087
10088 Label try_w;
10089 __ Bind(&try_w);
10090 __ Ldxr(w0, MemOperand(x10));
10091 __ Stxr(w5, w0, MemOperand(x10));
10092 __ Sub(x11, x11, 1);
10093 __ Cbz(x11, &done);
10094 __ Cbz(w5, &try_w);
10095
10096 Label try_x;
10097 __ Bind(&try_x);
10098 __ Ldxr(x0, MemOperand(x10));
10099 __ Stxr(w5, x0, MemOperand(x10));
10100 __ Sub(x11, x11, 1);
10101 __ Cbz(x11, &done);
10102 __ Cbz(w5, &try_x);
10103
10104 Label try_wp;
10105 __ Bind(&try_wp);
10106 __ Ldxp(w0, w1, MemOperand(x10));
10107 __ Stxp(w5, w0, w1, MemOperand(x10));
10108 __ Sub(x11, x11, 1);
10109 __ Cbz(x11, &done);
10110 __ Cbz(w5, &try_wp);
10111
10112 Label try_xp;
10113 __ Bind(&try_xp);
10114 __ Ldxp(x0, x1, MemOperand(x10));
10115 __ Stxp(w5, x0, x1, MemOperand(x10));
10116 __ Sub(x11, x11, 1);
10117 __ Cbz(x11, &done);
10118 __ Cbz(w5, &try_xp);
10119
10120 __ Bind(&done);
10121 // Trigger an error if x11 (watchdog) is zero.
10122 __ Cmp(x11, 0);
10123 __ Cset(x12, eq);
10124
10125 END();
10126 if (CAN_RUN()) {
10127 RUN();
10128
10129 // Check that the watchdog counter didn't run out.
10130 ASSERT_EQUAL_64(0, x12);
10131 }
10132 }
10133 #endif
10134
10135
10136 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
10137 // Check that the simulator occasionally makes store-exclusive fail.
10138 TEST(ldaxr_stlxr_fail) {
10139 uint64_t data[] = {0, 0, 0};
10140 uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
10141
10142 // Impose a hard limit on the number of attempts, so the test cannot hang.
10143 static const uint64_t kWatchdog = 10000;
10144 Label done;
10145
10146 SETUP();
10147 START();
10148
10149 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
10150 __ Mov(x11, kWatchdog);
10151
10152 // This loop is the opposite of what we normally do with ldxr and stxr; we
10153 // keep trying until we fail (or the watchdog counter runs out).
10154 Label try_b;
10155 __ Bind(&try_b);
10156 __ Ldxrb(w0, MemOperand(x10));
10157 __ Stxrb(w5, w0, MemOperand(x10));
10158 // Check the watchdog counter.
10159 __ Sub(x11, x11, 1);
10160 __ Cbz(x11, &done);
10161 // Check the exclusive-store result.
10162 __ Cbz(w5, &try_b);
10163
10164 Label try_h;
10165 __ Bind(&try_h);
10166 __ Ldaxrh(w0, MemOperand(x10));
10167 __ Stlxrh(w5, w0, MemOperand(x10));
10168 __ Sub(x11, x11, 1);
10169 __ Cbz(x11, &done);
10170 __ Cbz(w5, &try_h);
10171
10172 Label try_w;
10173 __ Bind(&try_w);
10174 __ Ldaxr(w0, MemOperand(x10));
10175 __ Stlxr(w5, w0, MemOperand(x10));
10176 __ Sub(x11, x11, 1);
10177 __ Cbz(x11, &done);
10178 __ Cbz(w5, &try_w);
10179
10180 Label try_x;
10181 __ Bind(&try_x);
10182 __ Ldaxr(x0, MemOperand(x10));
10183 __ Stlxr(w5, x0, MemOperand(x10));
10184 __ Sub(x11, x11, 1);
10185 __ Cbz(x11, &done);
10186 __ Cbz(w5, &try_x);
10187
10188 Label try_wp;
10189 __ Bind(&try_wp);
10190 __ Ldaxp(w0, w1, MemOperand(x10));
10191 __ Stlxp(w5, w0, w1, MemOperand(x10));
10192 __ Sub(x11, x11, 1);
10193 __ Cbz(x11, &done);
10194 __ Cbz(w5, &try_wp);
10195
10196 Label try_xp;
10197 __ Bind(&try_xp);
10198 __ Ldaxp(x0, x1, MemOperand(x10));
10199 __ Stlxp(w5, x0, x1, MemOperand(x10));
10200 __ Sub(x11, x11, 1);
10201 __ Cbz(x11, &done);
10202 __ Cbz(w5, &try_xp);
10203
10204 __ Bind(&done);
10205 // Trigger an error if x11 (watchdog) is zero.
10206 __ Cmp(x11, 0);
10207 __ Cset(x12, eq);
10208
10209 END();
10210 if (CAN_RUN()) {
10211 RUN();
10212
10213 // Check that the watchdog counter didn't run out.
10214 ASSERT_EQUAL_64(0, x12);
10215 }
10216 }
10217 #endif
10218
10219 TEST(cas_casa_casl_casal_w) {
10220 uint64_t data1 = 0x0123456789abcdef;
10221 uint64_t data2 = 0x0123456789abcdef;
10222 uint64_t data3 = 0x0123456789abcdef;
10223 uint64_t data4 = 0x0123456789abcdef;
10224 uint64_t data5 = 0x0123456789abcdef;
10225 uint64_t data6 = 0x0123456789abcdef;
10226 uint64_t data7 = 0x0123456789abcdef;
10227 uint64_t data8 = 0x0123456789abcdef;
10228
10229 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10230
10231 START();
10232
10233 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10234 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10235 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 4);
10236 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 4);
10237 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 0);
10238 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 0);
10239 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 4);
10240 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 4);
10241
10242 __ Mov(x0, 0xffffffff);
10243
10244 __ Mov(x1, 0xfedcba9876543210);
10245 __ Mov(x2, 0x0123456789abcdef);
10246 __ Mov(x3, 0xfedcba9876543210);
10247 __ Mov(x4, 0x89abcdef01234567);
10248 __ Mov(x5, 0xfedcba9876543210);
10249 __ Mov(x6, 0x0123456789abcdef);
10250 __ Mov(x7, 0xfedcba9876543210);
10251 __ Mov(x8, 0x89abcdef01234567);
10252
10253 __ Cas(w1, w0, MemOperand(x21));
10254 __ Cas(w2, w0, MemOperand(x22));
10255 __ Casa(w3, w0, MemOperand(x23));
10256 __ Casa(w4, w0, MemOperand(x24));
10257 __ Casl(w5, w0, MemOperand(x25));
10258 __ Casl(w6, w0, MemOperand(x26));
10259 __ Casal(w7, w0, MemOperand(x27));
10260 __ Casal(w8, w0, MemOperand(x28));
10261
10262 END();
10263
10264 if (CAN_RUN()) {
10265 RUN();
10266
10267 ASSERT_EQUAL_64(0x89abcdef, x1);
10268 ASSERT_EQUAL_64(0x89abcdef, x2);
10269 ASSERT_EQUAL_64(0x01234567, x3);
10270 ASSERT_EQUAL_64(0x01234567, x4);
10271 ASSERT_EQUAL_64(0x89abcdef, x5);
10272 ASSERT_EQUAL_64(0x89abcdef, x6);
10273 ASSERT_EQUAL_64(0x01234567, x7);
10274 ASSERT_EQUAL_64(0x01234567, x8);
10275
10276 ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10277 ASSERT_EQUAL_64(0x01234567ffffffff, data2);
10278 ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10279 ASSERT_EQUAL_64(0xffffffff89abcdef, data4);
10280 ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10281 ASSERT_EQUAL_64(0x01234567ffffffff, data6);
10282 ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10283 ASSERT_EQUAL_64(0xffffffff89abcdef, data8);
10284 }
10285 }
10286
10287 TEST(cas_casa_casl_casal_x) {
10288 uint64_t data1 = 0x0123456789abcdef;
10289 uint64_t data2 = 0x0123456789abcdef;
10290 uint64_t data3 = 0x0123456789abcdef;
10291 uint64_t data4 = 0x0123456789abcdef;
10292 uint64_t data5 = 0x0123456789abcdef;
10293 uint64_t data6 = 0x0123456789abcdef;
10294 uint64_t data7 = 0x0123456789abcdef;
10295 uint64_t data8 = 0x0123456789abcdef;
10296
10297 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10298
10299 START();
10300
10301 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1));
10302 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2));
10303 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3));
10304 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4));
10305 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5));
10306 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6));
10307 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7));
10308 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8));
10309
10310 __ Mov(x0, 0xffffffffffffffff);
10311
10312 __ Mov(x1, 0xfedcba9876543210);
10313 __ Mov(x2, 0x0123456789abcdef);
10314 __ Mov(x3, 0xfedcba9876543210);
10315 __ Mov(x4, 0x0123456789abcdef);
10316 __ Mov(x5, 0xfedcba9876543210);
10317 __ Mov(x6, 0x0123456789abcdef);
10318 __ Mov(x7, 0xfedcba9876543210);
10319 __ Mov(x8, 0x0123456789abcdef);
10320
10321 __ Cas(x1, x0, MemOperand(x21));
10322 __ Cas(x2, x0, MemOperand(x22));
10323 __ Casa(x3, x0, MemOperand(x23));
10324 __ Casa(x4, x0, MemOperand(x24));
10325 __ Casl(x5, x0, MemOperand(x25));
10326 __ Casl(x6, x0, MemOperand(x26));
10327 __ Casal(x7, x0, MemOperand(x27));
10328 __ Casal(x8, x0, MemOperand(x28));
10329
10330 END();
10331
10332 if (CAN_RUN()) {
10333 RUN();
10334
10335 ASSERT_EQUAL_64(0x0123456789abcdef, x1);
10336 ASSERT_EQUAL_64(0x0123456789abcdef, x2);
10337 ASSERT_EQUAL_64(0x0123456789abcdef, x3);
10338 ASSERT_EQUAL_64(0x0123456789abcdef, x4);
10339 ASSERT_EQUAL_64(0x0123456789abcdef, x5);
10340 ASSERT_EQUAL_64(0x0123456789abcdef, x6);
10341 ASSERT_EQUAL_64(0x0123456789abcdef, x7);
10342 ASSERT_EQUAL_64(0x0123456789abcdef, x8);
10343
10344 ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10345 ASSERT_EQUAL_64(0xffffffffffffffff, data2);
10346 ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10347 ASSERT_EQUAL_64(0xffffffffffffffff, data4);
10348 ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10349 ASSERT_EQUAL_64(0xffffffffffffffff, data6);
10350 ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10351 ASSERT_EQUAL_64(0xffffffffffffffff, data8);
10352 }
10353 }
10354
10355 TEST(casb_casab_caslb_casalb) {
10356 uint32_t data1 = 0x01234567;
10357 uint32_t data2 = 0x01234567;
10358 uint32_t data3 = 0x01234567;
10359 uint32_t data4 = 0x01234567;
10360 uint32_t data5 = 0x01234567;
10361 uint32_t data6 = 0x01234567;
10362 uint32_t data7 = 0x01234567;
10363 uint32_t data8 = 0x01234567;
10364
10365 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10366
10367 START();
10368
10369 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10370 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10371 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 1);
10372 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 1);
10373 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 2);
10374 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 2);
10375 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 3);
10376 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 3);
10377
10378 __ Mov(x0, 0xff);
10379
10380 __ Mov(x1, 0x76543210);
10381 __ Mov(x2, 0x01234567);
10382 __ Mov(x3, 0x76543210);
10383 __ Mov(x4, 0x67012345);
10384 __ Mov(x5, 0x76543210);
10385 __ Mov(x6, 0x45670123);
10386 __ Mov(x7, 0x76543210);
10387 __ Mov(x8, 0x23456701);
10388
10389 __ Casb(w1, w0, MemOperand(x21));
10390 __ Casb(w2, w0, MemOperand(x22));
10391 __ Casab(w3, w0, MemOperand(x23));
10392 __ Casab(w4, w0, MemOperand(x24));
10393 __ Caslb(w5, w0, MemOperand(x25));
10394 __ Caslb(w6, w0, MemOperand(x26));
10395 __ Casalb(w7, w0, MemOperand(x27));
10396 __ Casalb(w8, w0, MemOperand(x28));
10397
10398 END();
10399
10400 if (CAN_RUN()) {
10401 RUN();
10402
10403 ASSERT_EQUAL_64(0x00000067, x1);
10404 ASSERT_EQUAL_64(0x00000067, x2);
10405 ASSERT_EQUAL_64(0x00000045, x3);
10406 ASSERT_EQUAL_64(0x00000045, x4);
10407 ASSERT_EQUAL_64(0x00000023, x5);
10408 ASSERT_EQUAL_64(0x00000023, x6);
10409 ASSERT_EQUAL_64(0x00000001, x7);
10410 ASSERT_EQUAL_64(0x00000001, x8);
10411
10412 ASSERT_EQUAL_64(0x01234567, data1);
10413 ASSERT_EQUAL_64(0x012345ff, data2);
10414 ASSERT_EQUAL_64(0x01234567, data3);
10415 ASSERT_EQUAL_64(0x0123ff67, data4);
10416 ASSERT_EQUAL_64(0x01234567, data5);
10417 ASSERT_EQUAL_64(0x01ff4567, data6);
10418 ASSERT_EQUAL_64(0x01234567, data7);
10419 ASSERT_EQUAL_64(0xff234567, data8);
10420 }
10421 }
10422
10423 TEST(cash_casah_caslh_casalh) {
10424 uint64_t data1 = 0x0123456789abcdef;
10425 uint64_t data2 = 0x0123456789abcdef;
10426 uint64_t data3 = 0x0123456789abcdef;
10427 uint64_t data4 = 0x0123456789abcdef;
10428 uint64_t data5 = 0x0123456789abcdef;
10429 uint64_t data6 = 0x0123456789abcdef;
10430 uint64_t data7 = 0x0123456789abcdef;
10431 uint64_t data8 = 0x0123456789abcdef;
10432
10433 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10434
10435 START();
10436
10437 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10438 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10439 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 2);
10440 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 2);
10441 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 4);
10442 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 4);
10443 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 6);
10444 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 6);
10445
10446 __ Mov(x0, 0xffff);
10447
10448 __ Mov(x1, 0xfedcba9876543210);
10449 __ Mov(x2, 0x0123456789abcdef);
10450 __ Mov(x3, 0xfedcba9876543210);
10451 __ Mov(x4, 0xcdef0123456789ab);
10452 __ Mov(x5, 0xfedcba9876543210);
10453 __ Mov(x6, 0x89abcdef01234567);
10454 __ Mov(x7, 0xfedcba9876543210);
10455 __ Mov(x8, 0x456789abcdef0123);
10456
10457 __ Cash(w1, w0, MemOperand(x21));
10458 __ Cash(w2, w0, MemOperand(x22));
10459 __ Casah(w3, w0, MemOperand(x23));
10460 __ Casah(w4, w0, MemOperand(x24));
10461 __ Caslh(w5, w0, MemOperand(x25));
10462 __ Caslh(w6, w0, MemOperand(x26));
10463 __ Casalh(w7, w0, MemOperand(x27));
10464 __ Casalh(w8, w0, MemOperand(x28));
10465
10466 END();
10467
10468 if (CAN_RUN()) {
10469 RUN();
10470
10471 ASSERT_EQUAL_64(0x0000cdef, x1);
10472 ASSERT_EQUAL_64(0x0000cdef, x2);
10473 ASSERT_EQUAL_64(0x000089ab, x3);
10474 ASSERT_EQUAL_64(0x000089ab, x4);
10475 ASSERT_EQUAL_64(0x00004567, x5);
10476 ASSERT_EQUAL_64(0x00004567, x6);
10477 ASSERT_EQUAL_64(0x00000123, x7);
10478 ASSERT_EQUAL_64(0x00000123, x8);
10479
10480 ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10481 ASSERT_EQUAL_64(0x0123456789abffff, data2);
10482 ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10483 ASSERT_EQUAL_64(0x01234567ffffcdef, data4);
10484 ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10485 ASSERT_EQUAL_64(0x0123ffff89abcdef, data6);
10486 ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10487 ASSERT_EQUAL_64(0xffff456789abcdef, data8);
10488 }
10489 }
10490
10491 TEST(casp_caspa_caspl_caspal_w) {
10492 uint64_t data1[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10493 uint64_t data2[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10494 uint64_t data3[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10495 uint64_t data4[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10496 uint64_t data5[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10497 uint64_t data6[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10498 uint64_t data7[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10499 uint64_t data8[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10500
10501 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10502
10503 START();
10504
10505 __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0);
10506 __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0);
10507 __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 8);
10508 __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 8);
10509 __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 8);
10510 __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 8);
10511 __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0);
10512 __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0);
10513
10514 __ Mov(x0, 0xfff00fff);
10515 __ Mov(x1, 0xfff11fff);
10516
10517 __ Mov(x2, 0x77665544);
10518 __ Mov(x3, 0x33221100);
10519 __ Mov(x4, 0x33221100);
10520 __ Mov(x5, 0x77665544);
10521
10522 __ Mov(x6, 0xffeeddcc);
10523 __ Mov(x7, 0xbbaa9988);
10524 __ Mov(x8, 0xbbaa9988);
10525 __ Mov(x9, 0xffeeddcc);
10526
10527 __ Mov(x10, 0xffeeddcc);
10528 __ Mov(x11, 0xbbaa9988);
10529 __ Mov(x12, 0xbbaa9988);
10530 __ Mov(x13, 0xffeeddcc);
10531
10532 __ Mov(x14, 0x77665544);
10533 __ Mov(x15, 0x33221100);
10534 __ Mov(x16, 0x33221100);
10535 __ Mov(x17, 0x77665544);
10536
10537 __ Casp(w2, w3, w0, w1, MemOperand(x21));
10538 __ Casp(w4, w5, w0, w1, MemOperand(x22));
10539 __ Caspa(w6, w7, w0, w1, MemOperand(x23));
10540 __ Caspa(w8, w9, w0, w1, MemOperand(x24));
10541 __ Caspl(w10, w11, w0, w1, MemOperand(x25));
10542 __ Caspl(w12, w13, w0, w1, MemOperand(x26));
10543 __ Caspal(w14, w15, w0, w1, MemOperand(x27));
10544 __ Caspal(w16, w17, w0, w1, MemOperand(x28));
10545
10546 END();
10547
10548 if (CAN_RUN()) {
10549 RUN();
10550
10551 ASSERT_EQUAL_64(0x33221100, x2);
10552 ASSERT_EQUAL_64(0x77665544, x3);
10553 ASSERT_EQUAL_64(0x33221100, x4);
10554 ASSERT_EQUAL_64(0x77665544, x5);
10555 ASSERT_EQUAL_64(0xbbaa9988, x6);
10556 ASSERT_EQUAL_64(0xffeeddcc, x7);
10557 ASSERT_EQUAL_64(0xbbaa9988, x8);
10558 ASSERT_EQUAL_64(0xffeeddcc, x9);
10559 ASSERT_EQUAL_64(0xbbaa9988, x10);
10560 ASSERT_EQUAL_64(0xffeeddcc, x11);
10561 ASSERT_EQUAL_64(0xbbaa9988, x12);
10562 ASSERT_EQUAL_64(0xffeeddcc, x13);
10563 ASSERT_EQUAL_64(0x33221100, x14);
10564 ASSERT_EQUAL_64(0x77665544, x15);
10565 ASSERT_EQUAL_64(0x33221100, x16);
10566 ASSERT_EQUAL_64(0x77665544, x17);
10567
10568 ASSERT_EQUAL_64(0x7766554433221100, data1[0]);
10569 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]);
10570 ASSERT_EQUAL_64(0xfff11ffffff00fff, data2[0]);
10571 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data2[1]);
10572 ASSERT_EQUAL_64(0x7766554433221100, data3[0]);
10573 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]);
10574 ASSERT_EQUAL_64(0x7766554433221100, data4[0]);
10575 ASSERT_EQUAL_64(0xfff11ffffff00fff, data4[1]);
10576 ASSERT_EQUAL_64(0x7766554433221100, data5[0]);
10577 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]);
10578 ASSERT_EQUAL_64(0x7766554433221100, data6[0]);
10579 ASSERT_EQUAL_64(0xfff11ffffff00fff, data6[1]);
10580 ASSERT_EQUAL_64(0x7766554433221100, data7[0]);
10581 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]);
10582 ASSERT_EQUAL_64(0xfff11ffffff00fff, data8[0]);
10583 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data8[1]);
10584 }
10585 }
10586
10587 TEST(casp_caspa_caspl_caspal_x) {
10588 alignas(kXRegSizeInBytes * 2) uint64_t data1[] = {0x7766554433221100,
10589 0xffeeddccbbaa9988,
10590 0xfedcba9876543210,
10591 0x0123456789abcdef};
10592 alignas(kXRegSizeInBytes * 2) uint64_t data2[] = {0x7766554433221100,
10593 0xffeeddccbbaa9988,
10594 0xfedcba9876543210,
10595 0x0123456789abcdef};
10596 alignas(kXRegSizeInBytes * 2) uint64_t data3[] = {0x7766554433221100,
10597 0xffeeddccbbaa9988,
10598 0xfedcba9876543210,
10599 0x0123456789abcdef};
10600 alignas(kXRegSizeInBytes * 2) uint64_t data4[] = {0x7766554433221100,
10601 0xffeeddccbbaa9988,
10602 0xfedcba9876543210,
10603 0x0123456789abcdef};
10604 alignas(kXRegSizeInBytes * 2) uint64_t data5[] = {0x7766554433221100,
10605 0xffeeddccbbaa9988,
10606 0xfedcba9876543210,
10607 0x0123456789abcdef};
10608 alignas(kXRegSizeInBytes * 2) uint64_t data6[] = {0x7766554433221100,
10609 0xffeeddccbbaa9988,
10610 0xfedcba9876543210,
10611 0x0123456789abcdef};
10612 alignas(kXRegSizeInBytes * 2) uint64_t data7[] = {0x7766554433221100,
10613 0xffeeddccbbaa9988,
10614 0xfedcba9876543210,
10615 0x0123456789abcdef};
10616 alignas(kXRegSizeInBytes * 2) uint64_t data8[] = {0x7766554433221100,
10617 0xffeeddccbbaa9988,
10618 0xfedcba9876543210,
10619 0x0123456789abcdef};
10620
10621 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10622
10623 START();
10624
10625 __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0);
10626 __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0);
10627 __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 16);
10628 __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 16);
10629 __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 16);
10630 __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 16);
10631 __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0);
10632 __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0);
10633
10634 __ Mov(x0, 0xfffffff00fffffff);
10635 __ Mov(x1, 0xfffffff11fffffff);
10636
10637 __ Mov(x2, 0xffeeddccbbaa9988);
10638 __ Mov(x3, 0x7766554433221100);
10639 __ Mov(x4, 0x7766554433221100);
10640 __ Mov(x5, 0xffeeddccbbaa9988);
10641
10642 __ Mov(x6, 0x0123456789abcdef);
10643 __ Mov(x7, 0xfedcba9876543210);
10644 __ Mov(x8, 0xfedcba9876543210);
10645 __ Mov(x9, 0x0123456789abcdef);
10646
10647 __ Mov(x10, 0x0123456789abcdef);
10648 __ Mov(x11, 0xfedcba9876543210);
10649 __ Mov(x12, 0xfedcba9876543210);
10650 __ Mov(x13, 0x0123456789abcdef);
10651
10652 __ Mov(x14, 0xffeeddccbbaa9988);
10653 __ Mov(x15, 0x7766554433221100);
10654 __ Mov(x16, 0x7766554433221100);
10655 __ Mov(x17, 0xffeeddccbbaa9988);
10656
10657 __ Casp(x2, x3, x0, x1, MemOperand(x21));
10658 __ Casp(x4, x5, x0, x1, MemOperand(x22));
10659 __ Caspa(x6, x7, x0, x1, MemOperand(x23));
10660 __ Caspa(x8, x9, x0, x1, MemOperand(x24));
10661 __ Caspl(x10, x11, x0, x1, MemOperand(x25));
10662 __ Caspl(x12, x13, x0, x1, MemOperand(x26));
10663 __ Caspal(x14, x15, x0, x1, MemOperand(x27));
10664 __ Caspal(x16, x17, x0, x1, MemOperand(x28));
10665
10666 END();
10667
10668 if (CAN_RUN()) {
10669 RUN();
10670
10671 ASSERT_EQUAL_64(0x7766554433221100, x2);
10672 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x3);
10673 ASSERT_EQUAL_64(0x7766554433221100, x4);
10674 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
10675
10676 ASSERT_EQUAL_64(0xfedcba9876543210, x6);
10677 ASSERT_EQUAL_64(0x0123456789abcdef, x7);
10678 ASSERT_EQUAL_64(0xfedcba9876543210, x8);
10679 ASSERT_EQUAL_64(0x0123456789abcdef, x9);
10680
10681 ASSERT_EQUAL_64(0xfedcba9876543210, x10);
10682 ASSERT_EQUAL_64(0x0123456789abcdef, x11);
10683 ASSERT_EQUAL_64(0xfedcba9876543210, x12);
10684 ASSERT_EQUAL_64(0x0123456789abcdef, x13);
10685
10686 ASSERT_EQUAL_64(0x7766554433221100, x14);
10687 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x15);
10688 ASSERT_EQUAL_64(0x7766554433221100, x16);
10689 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x17);
10690
10691 ASSERT_EQUAL_64(0x7766554433221100, data1[0]);
10692 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]);
10693 ASSERT_EQUAL_64(0xfedcba9876543210, data1[2]);
10694 ASSERT_EQUAL_64(0x0123456789abcdef, data1[3]);
10695
10696 ASSERT_EQUAL_64(0xfffffff00fffffff, data2[0]);
10697 ASSERT_EQUAL_64(0xfffffff11fffffff, data2[1]);
10698 ASSERT_EQUAL_64(0xfedcba9876543210, data2[2]);
10699 ASSERT_EQUAL_64(0x0123456789abcdef, data2[3]);
10700
10701 ASSERT_EQUAL_64(0x7766554433221100, data3[0]);
10702 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]);
10703 ASSERT_EQUAL_64(0xfedcba9876543210, data3[2]);
10704 ASSERT_EQUAL_64(0x0123456789abcdef, data3[3]);
10705
10706 ASSERT_EQUAL_64(0x7766554433221100, data4[0]);
10707 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data4[1]);
10708 ASSERT_EQUAL_64(0xfffffff00fffffff, data4[2]);
10709 ASSERT_EQUAL_64(0xfffffff11fffffff, data4[3]);
10710
10711 ASSERT_EQUAL_64(0x7766554433221100, data5[0]);
10712 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]);
10713 ASSERT_EQUAL_64(0xfedcba9876543210, data5[2]);
10714 ASSERT_EQUAL_64(0x0123456789abcdef, data5[3]);
10715
10716 ASSERT_EQUAL_64(0x7766554433221100, data6[0]);
10717 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data6[1]);
10718 ASSERT_EQUAL_64(0xfffffff00fffffff, data6[2]);
10719 ASSERT_EQUAL_64(0xfffffff11fffffff, data6[3]);
10720
10721 ASSERT_EQUAL_64(0x7766554433221100, data7[0]);
10722 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]);
10723 ASSERT_EQUAL_64(0xfedcba9876543210, data7[2]);
10724 ASSERT_EQUAL_64(0x0123456789abcdef, data7[3]);
10725
10726 ASSERT_EQUAL_64(0xfffffff00fffffff, data8[0]);
10727 ASSERT_EQUAL_64(0xfffffff11fffffff, data8[1]);
10728 ASSERT_EQUAL_64(0xfedcba9876543210, data8[2]);
10729 ASSERT_EQUAL_64(0x0123456789abcdef, data8[3]);
10730 }
10731 }
10732
10733
10734 typedef void (MacroAssembler::*AtomicMemoryLoadSignature)(
10735 const Register& rs, const Register& rt, const MemOperand& src);
10736 typedef void (MacroAssembler::*AtomicMemoryStoreSignature)(
10737 const Register& rs, const MemOperand& src);
10738
10739 void AtomicMemoryWHelper(AtomicMemoryLoadSignature* load_funcs,
10740 AtomicMemoryStoreSignature* store_funcs,
10741 uint64_t arg1,
10742 uint64_t arg2,
10743 uint64_t expected,
10744 uint64_t result_mask) {
10745 uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10746 uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10747 uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10748 uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10749 uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10750 uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10751
10752 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10753 START();
10754
10755 __ Mov(x20, reinterpret_cast<uintptr_t>(data0));
10756 __ Mov(x21, reinterpret_cast<uintptr_t>(data1));
10757 __ Mov(x22, reinterpret_cast<uintptr_t>(data2));
10758 __ Mov(x23, reinterpret_cast<uintptr_t>(data3));
10759
10760 __ Mov(x0, arg1);
10761 __ Mov(x1, arg1);
10762 __ Mov(x2, arg1);
10763 __ Mov(x3, arg1);
10764
10765 (masm.*(load_funcs[0]))(w0, w10, MemOperand(x20));
10766 (masm.*(load_funcs[1]))(w1, w11, MemOperand(x21));
10767 (masm.*(load_funcs[2]))(w2, w12, MemOperand(x22));
10768 (masm.*(load_funcs[3]))(w3, w13, MemOperand(x23));
10769
10770 if (store_funcs != NULL) {
10771 __ Mov(x24, reinterpret_cast<uintptr_t>(data4));
10772 __ Mov(x25, reinterpret_cast<uintptr_t>(data5));
10773 __ Mov(x4, arg1);
10774 __ Mov(x5, arg1);
10775
10776 (masm.*(store_funcs[0]))(w4, MemOperand(x24));
10777 (masm.*(store_funcs[1]))(w5, MemOperand(x25));
10778 }
10779
10780 END();
10781
10782 if (CAN_RUN()) {
10783 RUN();
10784
10785 uint64_t stored_value = arg2 & result_mask;
10786 ASSERT_EQUAL_64(stored_value, x10);
10787 ASSERT_EQUAL_64(stored_value, x11);
10788 ASSERT_EQUAL_64(stored_value, x12);
10789 ASSERT_EQUAL_64(stored_value, x13);
10790
10791 // The data fields contain arg2 already then only the bits masked by
10792 // result_mask are overwritten.
10793 uint64_t final_expected = (arg2 & ~result_mask) | (expected & result_mask);
10794 ASSERT_EQUAL_64(final_expected, data0[0]);
10795 ASSERT_EQUAL_64(final_expected, data1[0]);
10796 ASSERT_EQUAL_64(final_expected, data2[0]);
10797 ASSERT_EQUAL_64(final_expected, data3[0]);
10798
10799 if (store_funcs != NULL) {
10800 ASSERT_EQUAL_64(final_expected, data4[0]);
10801 ASSERT_EQUAL_64(final_expected, data5[0]);
10802 }
10803 }
10804 }
10805
10806 void AtomicMemoryXHelper(AtomicMemoryLoadSignature* load_funcs,
10807 AtomicMemoryStoreSignature* store_funcs,
10808 uint64_t arg1,
10809 uint64_t arg2,
10810 uint64_t expected) {
10811 uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10812 uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10813 uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10814 uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10815 uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10816 uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10817
10818 SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10819 START();
10820
10821 __ Mov(x20, reinterpret_cast<uintptr_t>(data0));
10822 __ Mov(x21, reinterpret_cast<uintptr_t>(data1));
10823 __ Mov(x22, reinterpret_cast<uintptr_t>(data2));
10824 __ Mov(x23, reinterpret_cast<uintptr_t>(data3));
10825
10826 __ Mov(x0, arg1);
10827 __ Mov(x1, arg1);
10828 __ Mov(x2, arg1);
10829 __ Mov(x3, arg1);
10830
10831 (masm.*(load_funcs[0]))(x0, x10, MemOperand(x20));
10832 (masm.*(load_funcs[1]))(x1, x11, MemOperand(x21));
10833 (masm.*(load_funcs[2]))(x2, x12, MemOperand(x22));
10834 (masm.*(load_funcs[3]))(x3, x13, MemOperand(x23));
10835
10836 if (store_funcs != NULL) {
10837 __ Mov(x24, reinterpret_cast<uintptr_t>(data4));
10838 __ Mov(x25, reinterpret_cast<uintptr_t>(data5));
10839 __ Mov(x4, arg1);
10840 __ Mov(x5, arg1);
10841
10842 (masm.*(store_funcs[0]))(x4, MemOperand(x24));
10843 (masm.*(store_funcs[1]))(x5, MemOperand(x25));
10844 }
10845
10846 END();
10847
10848 if (CAN_RUN()) {
10849 RUN();
10850
10851 ASSERT_EQUAL_64(arg2, x10);
10852 ASSERT_EQUAL_64(arg2, x11);
10853 ASSERT_EQUAL_64(arg2, x12);
10854 ASSERT_EQUAL_64(arg2, x13);
10855
10856 ASSERT_EQUAL_64(expected, data0[0]);
10857 ASSERT_EQUAL_64(expected, data1[0]);
10858 ASSERT_EQUAL_64(expected, data2[0]);
10859 ASSERT_EQUAL_64(expected, data3[0]);
10860
10861 if (store_funcs != NULL) {
10862 ASSERT_EQUAL_64(expected, data4[0]);
10863 ASSERT_EQUAL_64(expected, data5[0]);
10864 }
10865 }
10866 }
10867
10868 // clang-format off
10869 #define MAKE_LOADS(NAME) \
10870 {&MacroAssembler::Ld##NAME, \
10871 &MacroAssembler::Ld##NAME##a, \
10872 &MacroAssembler::Ld##NAME##l, \
10873 &MacroAssembler::Ld##NAME##al}
10874 #define MAKE_STORES(NAME) \
10875 {&MacroAssembler::St##NAME, &MacroAssembler::St##NAME##l}
10876
10877 #define MAKE_B_LOADS(NAME) \
10878 {&MacroAssembler::Ld##NAME##b, \
10879 &MacroAssembler::Ld##NAME##ab, \
10880 &MacroAssembler::Ld##NAME##lb, \
10881 &MacroAssembler::Ld##NAME##alb}
10882 #define MAKE_B_STORES(NAME) \
10883 {&MacroAssembler::St##NAME##b, &MacroAssembler::St##NAME##lb}
10884
10885 #define MAKE_H_LOADS(NAME) \
10886 {&MacroAssembler::Ld##NAME##h, \
10887 &MacroAssembler::Ld##NAME##ah, \
10888 &MacroAssembler::Ld##NAME##lh, \
10889 &MacroAssembler::Ld##NAME##alh}
10890 #define MAKE_H_STORES(NAME) \
10891 {&MacroAssembler::St##NAME##h, &MacroAssembler::St##NAME##lh}
10892 // clang-format on
10893
10894 TEST(atomic_memory_add) {
10895 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(add);
10896 AtomicMemoryStoreSignature stores[] = MAKE_STORES(add);
10897 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(add);
10898 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(add);
10899 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(add);
10900 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(add);
10901
10902 // The arguments are chosen to have two useful properties:
10903 // * When multiplied by small values (such as a register index), this value
10904 // is clearly readable in the result.
10905 // * The value is not formed from repeating fixed-size smaller values, so it
10906 // can be used to detect endianness-related errors.
10907 uint64_t arg1 = 0x0100001000100101;
10908 uint64_t arg2 = 0x0200002000200202;
10909 uint64_t expected = arg1 + arg2;
10910
10911 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10912 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10913 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10914 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10915 }
10916
10917 TEST(atomic_memory_clr) {
10918 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(clr);
10919 AtomicMemoryStoreSignature stores[] = MAKE_STORES(clr);
10920 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(clr);
10921 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(clr);
10922 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(clr);
10923 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(clr);
10924
10925 uint64_t arg1 = 0x0300003000300303;
10926 uint64_t arg2 = 0x0500005000500505;
10927 uint64_t expected = arg2 & ~arg1;
10928
10929 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10930 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10931 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10932 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10933 }
10934
10935 TEST(atomic_memory_eor) {
10936 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(eor);
10937 AtomicMemoryStoreSignature stores[] = MAKE_STORES(eor);
10938 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(eor);
10939 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(eor);
10940 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(eor);
10941 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(eor);
10942
10943 uint64_t arg1 = 0x0300003000300303;
10944 uint64_t arg2 = 0x0500005000500505;
10945 uint64_t expected = arg1 ^ arg2;
10946
10947 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10948 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10949 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10950 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10951 }
10952
10953 TEST(atomic_memory_set) {
10954 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(set);
10955 AtomicMemoryStoreSignature stores[] = MAKE_STORES(set);
10956 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(set);
10957 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(set);
10958 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(set);
10959 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(set);
10960
10961 uint64_t arg1 = 0x0300003000300303;
10962 uint64_t arg2 = 0x0500005000500505;
10963 uint64_t expected = arg1 | arg2;
10964
10965 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10966 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10967 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10968 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10969 }
10970
10971 TEST(atomic_memory_smax) {
10972 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smax);
10973 AtomicMemoryStoreSignature stores[] = MAKE_STORES(smax);
10974 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smax);
10975 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smax);
10976 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smax);
10977 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smax);
10978
10979 uint64_t arg1 = 0x8100000080108181;
10980 uint64_t arg2 = 0x0100001000100101;
10981 uint64_t expected = 0x0100001000100101;
10982
10983 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10984 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10985 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10986 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10987 }
10988
10989 TEST(atomic_memory_smin) {
10990 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smin);
10991 AtomicMemoryStoreSignature stores[] = MAKE_STORES(smin);
10992 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smin);
10993 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smin);
10994 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smin);
10995 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smin);
10996
10997 uint64_t arg1 = 0x8100000080108181;
10998 uint64_t arg2 = 0x0100001000100101;
10999 uint64_t expected = 0x8100000080108181;
11000
11001 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11002 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11003 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11004 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11005 }
11006
11007 TEST(atomic_memory_umax) {
11008 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umax);
11009 AtomicMemoryStoreSignature stores[] = MAKE_STORES(umax);
11010 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umax);
11011 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umax);
11012 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umax);
11013 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umax);
11014
11015 uint64_t arg1 = 0x8100000080108181;
11016 uint64_t arg2 = 0x0100001000100101;
11017 uint64_t expected = 0x8100000080108181;
11018
11019 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11020 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11021 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11022 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11023 }
11024
11025 TEST(atomic_memory_umin) {
11026 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umin);
11027 AtomicMemoryStoreSignature stores[] = MAKE_STORES(umin);
11028 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umin);
11029 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umin);
11030 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umin);
11031 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umin);
11032
11033 uint64_t arg1 = 0x8100000080108181;
11034 uint64_t arg2 = 0x0100001000100101;
11035 uint64_t expected = 0x0100001000100101;
11036
11037 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11038 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11039 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11040 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11041 }
11042
11043 TEST(atomic_memory_swp) {
11044 AtomicMemoryLoadSignature loads[] = {&MacroAssembler::Swp,
11045 &MacroAssembler::Swpa,
11046 &MacroAssembler::Swpl,
11047 &MacroAssembler::Swpal};
11048 AtomicMemoryLoadSignature b_loads[] = {&MacroAssembler::Swpb,
11049 &MacroAssembler::Swpab,
11050 &MacroAssembler::Swplb,
11051 &MacroAssembler::Swpalb};
11052 AtomicMemoryLoadSignature h_loads[] = {&MacroAssembler::Swph,
11053 &MacroAssembler::Swpah,
11054 &MacroAssembler::Swplh,
11055 &MacroAssembler::Swpalh};
11056
11057 uint64_t arg1 = 0x0100001000100101;
11058 uint64_t arg2 = 0x0200002000200202;
11059 uint64_t expected = 0x0100001000100101;
11060
11061 // SWP functions have equivalent signatures to the Atomic Memory LD functions
11062 // so we can use the same helper but without the ST aliases.
11063 AtomicMemoryWHelper(b_loads, NULL, arg1, arg2, expected, kByteMask);
11064 AtomicMemoryWHelper(h_loads, NULL, arg1, arg2, expected, kHalfWordMask);
11065 AtomicMemoryWHelper(loads, NULL, arg1, arg2, expected, kWordMask);
11066 AtomicMemoryXHelper(loads, NULL, arg1, arg2, expected);
11067 }
11068
11069
11070 TEST(ldaprb_ldaprh_ldapr) {
11071 uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11072 uint64_t data1[] = {0x1010101010101010, 0x1010101010101010};
11073 uint64_t data2[] = {0x1010101010101010, 0x1010101010101010};
11074 uint64_t data3[] = {0x1010101010101010, 0x1010101010101010};
11075
11076 uint64_t* data0_aligned = AlignUp(data0, kXRegSizeInBytes * 2);
11077 uint64_t* data1_aligned = AlignUp(data1, kXRegSizeInBytes * 2);
11078 uint64_t* data2_aligned = AlignUp(data2, kXRegSizeInBytes * 2);
11079 uint64_t* data3_aligned = AlignUp(data3, kXRegSizeInBytes * 2);
11080
11081 SETUP_WITH_FEATURES(CPUFeatures::kRCpc);
11082 START();
11083
11084 __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned));
11085 __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
11086 __ Mov(x22, reinterpret_cast<uintptr_t>(data2_aligned));
11087 __ Mov(x23, reinterpret_cast<uintptr_t>(data3_aligned));
11088
11089 __ Ldaprb(w0, MemOperand(x20));
11090 __ Ldaprh(w1, MemOperand(x21));
11091 __ Ldapr(w2, MemOperand(x22));
11092 __ Ldapr(x3, MemOperand(x23));
11093
11094 END();
11095
11096 if (CAN_RUN()) {
11097 RUN();
11098 ASSERT_EQUAL_64(0x10, x0);
11099 ASSERT_EQUAL_64(0x1010, x1);
11100 ASSERT_EQUAL_64(0x10101010, x2);
11101 ASSERT_EQUAL_64(0x1010101010101010, x3);
11102 }
11103 }
11104
11105
11106 TEST(ldapurb_ldapurh_ldapur) {
11107 uint64_t data[]
11108 __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef,
11109 0xfedcba9876543210};
11110
11111 uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
11112
11113 SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
11114 START();
11115
11116 __ Mov(x20, data_base);
11117 __ Mov(x21, data_base + 2 * sizeof(data[0]));
11118
11119 __ Ldaprb(w0, MemOperand(x20));
11120 __ Ldaprh(w1, MemOperand(x20));
11121 __ Ldapr(w2, MemOperand(x20));
11122 __ Ldapr(x3, MemOperand(x20));
11123 __ Ldaprb(w4, MemOperand(x20, 12));
11124 __ Ldaprh(w5, MemOperand(x20, 8));
11125 __ Ldapr(w6, MemOperand(x20, 10));
11126 __ Ldapr(x7, MemOperand(x20, 7));
11127 __ Ldaprb(w8, MemOperand(x21, -1));
11128 __ Ldaprh(w9, MemOperand(x21, -3));
11129 __ Ldapr(w10, MemOperand(x21, -9));
11130 __ Ldapr(x11, MemOperand(x21, -12));
11131
11132 END();
11133
11134 if (CAN_RUN()) {
11135 RUN();
11136 ASSERT_EQUAL_64(0xef, x0);
11137 ASSERT_EQUAL_64(0xcdef, x1);
11138 ASSERT_EQUAL_64(0x89abcdef, x2);
11139 ASSERT_EQUAL_64(0x0123456789abcdef, x3);
11140 ASSERT_EQUAL_64(0x98, x4);
11141 ASSERT_EQUAL_64(0x3210, x5);
11142 ASSERT_EQUAL_64(0xba987654, x6);
11143 ASSERT_EQUAL_64(0xdcba987654321001, x7);
11144 ASSERT_EQUAL_64(0xfe, x8);
11145 ASSERT_EQUAL_64(0xdcba, x9);
11146 ASSERT_EQUAL_64(0x54321001, x10);
11147 ASSERT_EQUAL_64(0x7654321001234567, x11);
11148 }
11149 }
11150
11151
11152 TEST(ldapursb_ldapursh_ldapursw) {
11153 uint64_t data[]
11154 __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef,
11155 0xfedcba9876543210};
11156
11157 uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
11158
11159 SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
11160 START();
11161
11162 __ Mov(x20, data_base);
11163 __ Mov(x21, data_base + 2 * sizeof(data[0]));
11164
11165 __ Ldapursb(w0, MemOperand(x20));
11166 __ Ldapursb(x1, MemOperand(x20));
11167 __ Ldapursh(w2, MemOperand(x20));
11168 __ Ldapursh(x3, MemOperand(x20));
11169 __ Ldapursw(x4, MemOperand(x20));
11170 __ Ldapursb(w5, MemOperand(x20, 12));
11171 __ Ldapursb(x6, MemOperand(x20, 12));
11172 __ Ldapursh(w7, MemOperand(x20, 13));
11173 __ Ldapursh(x8, MemOperand(x20, 13));
11174 __ Ldapursw(x9, MemOperand(x20, 10));
11175 __ Ldapursb(w10, MemOperand(x21, -1));
11176 __ Ldapursb(x11, MemOperand(x21, -1));
11177 __ Ldapursh(w12, MemOperand(x21, -4));
11178 __ Ldapursh(x13, MemOperand(x21, -4));
11179 __ Ldapursw(x14, MemOperand(x21, -5));
11180
11181 __ Ldapursb(x15, MemOperand(x20, 8));
11182 __ Ldapursh(x16, MemOperand(x20, 8));
11183 __ Ldapursw(x17, MemOperand(x20, 8));
11184
11185 END();
11186
11187 if (CAN_RUN()) {
11188 RUN();
11189 ASSERT_EQUAL_64(0xffffffef, x0);
11190 ASSERT_EQUAL_64(0xffffffffffffffef, x1);
11191 ASSERT_EQUAL_64(0xffffcdef, x2);
11192 ASSERT_EQUAL_64(0xffffffffffffcdef, x3);
11193 ASSERT_EQUAL_64(0xffffffff89abcdef, x4);
11194 ASSERT_EQUAL_64(0xffffff98, x5);
11195 ASSERT_EQUAL_64(0xffffffffffffff98, x6);
11196 ASSERT_EQUAL_64(0xffffdcba, x7);
11197 ASSERT_EQUAL_64(0xffffffffffffdcba, x8);
11198 ASSERT_EQUAL_64(0xffffffffba987654, x9);
11199 ASSERT_EQUAL_64(0xfffffffe, x10);
11200 ASSERT_EQUAL_64(0xfffffffffffffffe, x11);
11201 ASSERT_EQUAL_64(0xffffba98, x12);
11202 ASSERT_EQUAL_64(0xffffffffffffba98, x13);
11203 ASSERT_EQUAL_64(0xffffffffdcba9876, x14);
11204
11205 ASSERT_EQUAL_64(0x0000000000000010, x15);
11206 ASSERT_EQUAL_64(0x0000000000003210, x16);
11207 ASSERT_EQUAL_64(0x0000000076543210, x17);
11208 }
11209 }
11210
11211
11212 TEST(stlurb_stlurh_strlur) {
11213 uint64_t data[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0, 0x0};
11214
11215 uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
11216
11217 SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
11218 START();
11219
11220 __ Mov(x0, 0x0011223344556677);
11221 __ Mov(x20, data_base);
11222 __ Mov(x21, data_base + 2 * sizeof(data[0]));
11223
11224 __ Stlrb(w0, MemOperand(x20));
11225 __ Stlrh(w0, MemOperand(x20, 1));
11226 __ Stlr(w0, MemOperand(x20, 3));
11227 __ Stlr(x0, MemOperand(x21, -8));
11228
11229 END();
11230
11231 if (CAN_RUN()) {
11232 RUN();
11233 ASSERT_EQUAL_64(0x0044556677667777, data[0]);
11234 ASSERT_EQUAL_64(0x0011223344556677, data[1]);
11235 }
11236 }
11237
11238
11239 #define SIMPLE_ATOMIC_OPS(V, DEF) \
11240 V(DEF, add) \
11241 V(DEF, clr) \
11242 V(DEF, eor) \
11243 V(DEF, set) \
11244 V(DEF, smax) \
11245 V(DEF, smin) \
11246 V(DEF, umax) \
11247 V(DEF, umin)
11248
11249 #define SIMPLE_ATOMIC_STORE_MODES(V, NAME) \
11250 V(NAME) \
11251 V(NAME##l)
11252
11253 #define SIMPLE_ATOMIC_LOAD_MODES(V, NAME) \
11254 SIMPLE_ATOMIC_STORE_MODES(V, NAME) \
11255 V(NAME##a) \
11256 V(NAME##al)
11257
11258
11259 TEST(unaligned_single_copy_atomicity) {
11260 uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11261 uint64_t dst[] = {0x0000000000000000, 0x0000000000000000};
11262
11263 uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule);
11264 uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule);
11265
11266 CPUFeatures features(CPUFeatures::kAtomics,
11267 CPUFeatures::kLORegions,
11268 CPUFeatures::kRCpc,
11269 CPUFeatures::kRCpcImm);
11270 features.Combine(CPUFeatures::kUSCAT);
11271 SETUP_WITH_FEATURES(features);
11272 START();
11273
11274 __ Mov(x0, 0x0123456789abcdef);
11275 __ Mov(x1, 0x456789abcdef0123);
11276 __ Mov(x2, 0x89abcdef01234567);
11277 __ Mov(x3, 0xcdef0123456789ab);
11278 __ Mov(x18, reinterpret_cast<uintptr_t>(data0_aligned));
11279 __ Mov(x19, reinterpret_cast<uintptr_t>(dst_aligned));
11280 __ Mov(x20, x18);
11281 __ Mov(x21, x19);
11282
11283 for (unsigned i = 0; i < kAtomicAccessGranule; i++) {
11284 __ Stxrb(w0, w1, MemOperand(x20));
11285 __ Stlxrb(w0, w1, MemOperand(x20));
11286 __ Ldxrb(w0, MemOperand(x20));
11287 __ Ldaxrb(w0, MemOperand(x20));
11288 __ Stllrb(w0, MemOperand(x20));
11289 __ Stlrb(w0, MemOperand(x20));
11290 __ Casb(w0, w1, MemOperand(x20));
11291 __ Caslb(w0, w1, MemOperand(x20));
11292 __ Ldlarb(w0, MemOperand(x20));
11293 __ Ldarb(w0, MemOperand(x20));
11294 __ Casab(w0, w1, MemOperand(x20));
11295 __ Casalb(w0, w1, MemOperand(x20));
11296
11297 __ Swpb(w0, w1, MemOperand(x20));
11298 __ Swplb(w0, w1, MemOperand(x20));
11299 __ Swpab(w0, w1, MemOperand(x20));
11300 __ Swpalb(w0, w1, MemOperand(x20));
11301 __ Ldaprb(w0, MemOperand(x20));
11302 // Use offset instead of Add to test Stlurb and Ldapurb.
11303 __ Stlrb(w0, MemOperand(x19, i));
11304 __ Ldaprb(w0, MemOperand(x19, i));
11305 __ Ldapursb(w0, MemOperand(x20));
11306 __ Ldapursb(x0, MemOperand(x20));
11307
11308 #define ATOMIC_LOAD_B(NAME) __ Ld##NAME##b(w0, w1, MemOperand(x20));
11309 #define ATOMIC_STORE_B(NAME) __ St##NAME##b(w0, MemOperand(x20));
11310 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_B)
11311 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_B)
11312 #undef ATOMIC_LOAD_B
11313 #undef ATOMIC_STORE_B
11314
11315 if (i <= (kAtomicAccessGranule - kHRegSizeInBytes)) {
11316 __ Stxrh(w0, w1, MemOperand(x20));
11317 __ Stlxrh(w0, w1, MemOperand(x20));
11318 __ Ldxrh(w0, MemOperand(x20));
11319 __ Ldaxrh(w0, MemOperand(x20));
11320 __ Stllrh(w0, MemOperand(x20));
11321 __ Stlrh(w0, MemOperand(x20));
11322 __ Cash(w0, w1, MemOperand(x20));
11323 __ Caslh(w0, w1, MemOperand(x20));
11324 __ Ldlarh(w0, MemOperand(x20));
11325 __ Ldarh(w0, MemOperand(x20));
11326 __ Casah(w0, w1, MemOperand(x20));
11327 __ Casalh(w0, w1, MemOperand(x20));
11328
11329 __ Swph(w0, w1, MemOperand(x20));
11330 __ Swplh(w0, w1, MemOperand(x20));
11331 __ Swpah(w0, w1, MemOperand(x20));
11332 __ Swpalh(w0, w1, MemOperand(x20));
11333 __ Ldaprh(w0, MemOperand(x20));
11334 // Use offset instead of Add to test Stlurh and Ldapurh.
11335 __ Stlrh(w0, MemOperand(x19, i));
11336 __ Ldaprh(w0, MemOperand(x19, i));
11337 __ Ldapursh(w0, MemOperand(x20));
11338 __ Ldapursh(x0, MemOperand(x20));
11339
11340 #define ATOMIC_LOAD_H(NAME) __ Ld##NAME##h(w0, w1, MemOperand(x20));
11341 #define ATOMIC_STORE_H(NAME) __ St##NAME##h(w0, MemOperand(x20));
11342 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H)
11343 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H)
11344 #undef ATOMIC_LOAD_H
11345 #undef ATOMIC_STORE_H
11346 }
11347
11348 if (i <= (kAtomicAccessGranule - kWRegSizeInBytes)) {
11349 __ Stxr(w0, w1, MemOperand(x20));
11350 __ Stlxr(w0, w1, MemOperand(x20));
11351 __ Ldxr(w0, MemOperand(x20));
11352 __ Ldaxr(w0, MemOperand(x20));
11353 __ Stllr(w0, MemOperand(x20));
11354 __ Stlr(w0, MemOperand(x20));
11355 __ Cas(w0, w1, MemOperand(x20));
11356 __ Casl(w0, w1, MemOperand(x20));
11357 __ Ldlar(w0, MemOperand(x20));
11358 __ Ldar(w0, MemOperand(x20));
11359 __ Casa(w0, w1, MemOperand(x20));
11360 __ Casal(w0, w1, MemOperand(x20));
11361
11362 __ Swp(w0, w1, MemOperand(x20));
11363 __ Swpl(w0, w1, MemOperand(x20));
11364 __ Swpa(w0, w1, MemOperand(x20));
11365 __ Swpal(w0, w1, MemOperand(x20));
11366 __ Ldapr(w0, MemOperand(x20));
11367 // Use offset instead of Add to test Stlur and Ldapur.
11368 __ Stlr(w0, MemOperand(x19, i));
11369 __ Ldapr(w0, MemOperand(x19, i));
11370 __ Ldapursw(x0, MemOperand(x20));
11371
11372 #define ATOMIC_LOAD_W(NAME) __ Ld##NAME(w0, w1, MemOperand(x20));
11373 #define ATOMIC_STORE_W(NAME) __ St##NAME(w0, MemOperand(x20));
11374 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W)
11375 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W)
11376 #undef ATOMIC_LOAD_W
11377 #undef ATOMIC_STORE_W
11378 }
11379
11380 if (i <= (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) {
11381 __ Casp(w0, w1, w2, w3, MemOperand(x20));
11382 __ Caspl(w0, w1, w2, w3, MemOperand(x20));
11383 __ Caspa(w0, w1, w2, w3, MemOperand(x20));
11384 __ Caspal(w0, w1, w2, w3, MemOperand(x20));
11385 __ Stxp(w0, w1, w2, MemOperand(x20));
11386 __ Stlxp(w0, w1, w2, MemOperand(x20));
11387 __ Ldxp(w0, w1, MemOperand(x20));
11388 __ Ldaxp(w0, w1, MemOperand(x20));
11389 }
11390
11391 if (i <= (kAtomicAccessGranule - kXRegSizeInBytes)) {
11392 __ Stxr(x0, x1, MemOperand(x20));
11393 __ Stlxr(x0, x1, MemOperand(x20));
11394 __ Ldxr(x0, MemOperand(x20));
11395 __ Ldaxr(x0, MemOperand(x20));
11396 __ Stllr(x0, MemOperand(x20));
11397 __ Stlr(x0, MemOperand(x20));
11398 __ Cas(x0, x1, MemOperand(x20));
11399 __ Casl(x0, x1, MemOperand(x20));
11400 __ Ldlar(x0, MemOperand(x20));
11401 __ Ldar(x0, MemOperand(x20));
11402 __ Casa(x0, x1, MemOperand(x20));
11403 __ Casal(x0, x1, MemOperand(x20));
11404
11405 __ Swp(x0, x1, MemOperand(x20));
11406 __ Swpl(x0, x1, MemOperand(x20));
11407 __ Swpa(x0, x1, MemOperand(x20));
11408 __ Swpal(x0, x1, MemOperand(x20));
11409 __ Ldapr(x0, MemOperand(x20));
11410 // Use offset instead of Add to test Stlur and Ldapur.
11411 __ Stlr(x0, MemOperand(x19, i));
11412 __ Ldapr(x0, MemOperand(x19, i));
11413
11414 #define ATOMIC_LOAD_X(NAME) __ Ld##NAME(x0, x1, MemOperand(x20));
11415 #define ATOMIC_STORE_X(NAME) __ St##NAME(x0, MemOperand(x20));
11416 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X)
11417 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X)
11418 #undef ATOMIC_LOAD_X
11419 #undef ATOMIC_STORE_X
11420 }
11421
11422 if (i <= (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) {
11423 __ Casp(x0, x1, x2, x3, MemOperand(x20));
11424 __ Caspl(x0, x1, x2, x3, MemOperand(x20));
11425 __ Caspa(x0, x1, x2, x3, MemOperand(x20));
11426 __ Caspal(x0, x1, x2, x3, MemOperand(x20));
11427 __ Stxp(x0, x1, x2, MemOperand(x20));
11428 __ Stlxp(x0, x1, x2, MemOperand(x20));
11429 __ Ldxp(x0, x1, MemOperand(x20));
11430 __ Ldaxp(x0, x1, MemOperand(x20));
11431 }
11432
11433 __ Add(x20, x20, 1);
11434 __ Add(x21, x21, 1);
11435 }
11436 END();
11437
11438 if (CAN_RUN()) {
11439 // We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the seen
11440 // check.
11441 RUN_WITHOUT_SEEN_FEATURE_CHECK();
11442 }
11443 }
11444
11445
11446 #if defined(VIXL_NEGATIVE_TESTING) && defined(VIXL_INCLUDE_SIMULATOR_AARCH64)
11447
11448 #define CHECK_ALIGN_FAIL(i, expr) \
11449 { \
11450 CPUFeatures features(CPUFeatures::kAtomics, \
11451 CPUFeatures::kLORegions, \
11452 CPUFeatures::kRCpc, \
11453 CPUFeatures::kRCpcImm); \
11454 features.Combine(CPUFeatures::kUSCAT); \
11455 SETUP_WITH_FEATURES(features); \
11456 START(); \
11457 __ Mov(x0, 0x0123456789abcdef); \
11458 __ Mov(x1, 0x456789abcdef0123); \
11459 __ Mov(x2, 0x89abcdef01234567); \
11460 __ Mov(x3, 0xcdef0123456789ab); \
11461 __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned)); \
11462 __ Mov(x21, reinterpret_cast<uintptr_t>(dst_aligned)); \
11463 __ Add(x20, x20, i); \
11464 __ Add(x21, x21, i); \
11465 expr; \
11466 END(); \
11467 if (CAN_RUN()) { \
11468 /* We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the */ \
11469 /* seen check. */ \
11470 MUST_FAIL_WITH_MESSAGE(RUN_WITHOUT_SEEN_FEATURE_CHECK(), \
11471 "ALIGNMENT EXCEPTION"); \
11472 } \
11473 }
11474
11475 TEST(unaligned_single_copy_atomicity_negative_test) {
11476 uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11477 uint64_t dst[] = {0x0000000000000000, 0x0000000000000000};
11478
11479 uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule);
11480 uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule);
11481
11482 for (unsigned i = 0; i < kAtomicAccessGranule; i++) {
11483 if (i > (kAtomicAccessGranule - kHRegSizeInBytes)) {
11484 CHECK_ALIGN_FAIL(i, __ Stxrh(w0, w1, MemOperand(x20)));
11485 CHECK_ALIGN_FAIL(i, __ Stlxrh(w0, w1, MemOperand(x20)));
11486 CHECK_ALIGN_FAIL(i, __ Ldxrh(w0, MemOperand(x20)));
11487 CHECK_ALIGN_FAIL(i, __ Ldaxrh(w0, MemOperand(x20)));
11488 CHECK_ALIGN_FAIL(i, __ Stllrh(w0, MemOperand(x20)));
11489 CHECK_ALIGN_FAIL(i, __ Stlrh(w0, MemOperand(x20)));
11490 CHECK_ALIGN_FAIL(i, __ Cash(w0, w1, MemOperand(x20)));
11491 CHECK_ALIGN_FAIL(i, __ Caslh(w0, w1, MemOperand(x20)));
11492 CHECK_ALIGN_FAIL(i, __ Ldlarh(w0, MemOperand(x20)));
11493 CHECK_ALIGN_FAIL(i, __ Ldarh(w0, MemOperand(x20)));
11494 CHECK_ALIGN_FAIL(i, __ Casah(w0, w1, MemOperand(x20)));
11495 CHECK_ALIGN_FAIL(i, __ Casalh(w0, w1, MemOperand(x20)));
11496
11497 CHECK_ALIGN_FAIL(i, __ Swph(w0, w1, MemOperand(x20)));
11498 CHECK_ALIGN_FAIL(i, __ Swplh(w0, w1, MemOperand(x20)));
11499 CHECK_ALIGN_FAIL(i, __ Swpah(w0, w1, MemOperand(x20)));
11500 CHECK_ALIGN_FAIL(i, __ Swpalh(w0, w1, MemOperand(x20)));
11501 CHECK_ALIGN_FAIL(i, __ Ldaprh(w0, MemOperand(x20)));
11502 // Use offset instead of Add to test Stlurh and Ldapurh.
11503 CHECK_ALIGN_FAIL(0, __ Stlrh(w0, MemOperand(x20, i)));
11504 CHECK_ALIGN_FAIL(0, __ Ldaprh(w0, MemOperand(x20, i)));
11505 CHECK_ALIGN_FAIL(i, __ Ldapursh(w0, MemOperand(x20)));
11506 CHECK_ALIGN_FAIL(i, __ Ldapursh(x0, MemOperand(x20)));
11507
11508 #define ATOMIC_LOAD_H(NAME) \
11509 CHECK_ALIGN_FAIL(i, __ Ld##NAME##h(w0, w1, MemOperand(x20)));
11510 #define ATOMIC_STORE_H(NAME) \
11511 CHECK_ALIGN_FAIL(i, __ St##NAME##h(w0, MemOperand(x20)));
11512 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H)
11513 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H)
11514 #undef ATOMIC_LOAD_H
11515 #undef ATOMIC_STORE_H
11516 }
11517
11518 if (i > (kAtomicAccessGranule - kWRegSizeInBytes)) {
11519 CHECK_ALIGN_FAIL(i, __ Stxr(w0, w1, MemOperand(x20)));
11520 CHECK_ALIGN_FAIL(i, __ Stlxr(w0, w1, MemOperand(x20)));
11521 CHECK_ALIGN_FAIL(i, __ Ldxr(w0, MemOperand(x20)));
11522 CHECK_ALIGN_FAIL(i, __ Ldaxr(w0, MemOperand(x20)));
11523 CHECK_ALIGN_FAIL(i, __ Stllr(w0, MemOperand(x20)));
11524 CHECK_ALIGN_FAIL(i, __ Stlr(w0, MemOperand(x20)));
11525 CHECK_ALIGN_FAIL(i, __ Cas(w0, w1, MemOperand(x20)));
11526 CHECK_ALIGN_FAIL(i, __ Casl(w0, w1, MemOperand(x20)));
11527 CHECK_ALIGN_FAIL(i, __ Ldlar(w0, MemOperand(x20)));
11528 CHECK_ALIGN_FAIL(i, __ Ldar(w0, MemOperand(x20)));
11529 CHECK_ALIGN_FAIL(i, __ Casa(w0, w1, MemOperand(x20)));
11530 CHECK_ALIGN_FAIL(i, __ Casal(w0, w1, MemOperand(x20)));
11531
11532 CHECK_ALIGN_FAIL(i, __ Swp(w0, w1, MemOperand(x20)));
11533 CHECK_ALIGN_FAIL(i, __ Swpl(w0, w1, MemOperand(x20)));
11534 CHECK_ALIGN_FAIL(i, __ Swpa(w0, w1, MemOperand(x20)));
11535 CHECK_ALIGN_FAIL(i, __ Swpal(w0, w1, MemOperand(x20)));
11536 CHECK_ALIGN_FAIL(i, __ Ldapr(w0, MemOperand(x20)));
11537 // Use offset instead of add to test Stlur and Ldapur.
11538 CHECK_ALIGN_FAIL(0, __ Stlr(w0, MemOperand(x20, i)));
11539 CHECK_ALIGN_FAIL(0, __ Ldapr(w0, MemOperand(x20, i)));
11540 CHECK_ALIGN_FAIL(i, __ Ldapursw(x0, MemOperand(x20)));
11541
11542 #define ATOMIC_LOAD_W(NAME) \
11543 CHECK_ALIGN_FAIL(i, __ Ld##NAME(w0, w1, MemOperand(x20)));
11544 #define ATOMIC_STORE_W(NAME) \
11545 CHECK_ALIGN_FAIL(i, __ St##NAME(w0, MemOperand(x20)));
11546 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W)
11547 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W)
11548 #undef ATOMIC_LOAD_W
11549 #undef ATOMIC_STORE_W
11550 }
11551
11552 if (i > (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) {
11553 CHECK_ALIGN_FAIL(i, __ Casp(w0, w1, w2, w3, MemOperand(x20)));
11554 CHECK_ALIGN_FAIL(i, __ Caspl(w0, w1, w2, w3, MemOperand(x20)));
11555 CHECK_ALIGN_FAIL(i, __ Caspa(w0, w1, w2, w3, MemOperand(x20)));
11556 CHECK_ALIGN_FAIL(i, __ Caspal(w0, w1, w2, w3, MemOperand(x20)));
11557 CHECK_ALIGN_FAIL(i, __ Stxp(w0, w1, w2, MemOperand(x20)));
11558 CHECK_ALIGN_FAIL(i, __ Stlxp(w0, w1, w2, MemOperand(x20)));
11559 CHECK_ALIGN_FAIL(i, __ Ldxp(w0, w1, MemOperand(x20)));
11560 CHECK_ALIGN_FAIL(i, __ Ldaxp(w0, w1, MemOperand(x20)));
11561 }
11562
11563 if (i > (kAtomicAccessGranule - kXRegSizeInBytes)) {
11564 CHECK_ALIGN_FAIL(i, __ Stxr(x0, x1, MemOperand(x20)));
11565 CHECK_ALIGN_FAIL(i, __ Stlxr(x0, x1, MemOperand(x20)));
11566 CHECK_ALIGN_FAIL(i, __ Ldxr(x0, MemOperand(x20)));
11567 CHECK_ALIGN_FAIL(i, __ Ldaxr(x0, MemOperand(x20)));
11568 CHECK_ALIGN_FAIL(i, __ Stllr(x0, MemOperand(x20)));
11569 CHECK_ALIGN_FAIL(i, __ Stlr(x0, MemOperand(x20)));
11570 CHECK_ALIGN_FAIL(i, __ Cas(x0, x1, MemOperand(x20)));
11571 CHECK_ALIGN_FAIL(i, __ Casl(x0, x1, MemOperand(x20)));
11572 CHECK_ALIGN_FAIL(i, __ Ldlar(x0, MemOperand(x20)));
11573 CHECK_ALIGN_FAIL(i, __ Ldar(x0, MemOperand(x20)));
11574 CHECK_ALIGN_FAIL(i, __ Casa(x0, x1, MemOperand(x20)));
11575 CHECK_ALIGN_FAIL(i, __ Casal(x0, x1, MemOperand(x20)));
11576
11577 CHECK_ALIGN_FAIL(i, __ Swp(x0, x1, MemOperand(x20)));
11578 CHECK_ALIGN_FAIL(i, __ Swpl(x0, x1, MemOperand(x20)));
11579 CHECK_ALIGN_FAIL(i, __ Swpa(x0, x1, MemOperand(x20)));
11580 CHECK_ALIGN_FAIL(i, __ Swpal(x0, x1, MemOperand(x20)));
11581 CHECK_ALIGN_FAIL(i, __ Ldapr(x0, MemOperand(x20)));
11582 // Use offset instead of add to test Stlur and Ldapur.
11583 CHECK_ALIGN_FAIL(0, __ Stlr(x0, MemOperand(x20, i)));
11584 CHECK_ALIGN_FAIL(0, __ Ldapr(x0, MemOperand(x20, i)));
11585
11586 #define ATOMIC_LOAD_X(NAME) \
11587 CHECK_ALIGN_FAIL(i, __ Ld##NAME(x0, x1, MemOperand(x20)));
11588 #define ATOMIC_STORE_X(NAME) \
11589 CHECK_ALIGN_FAIL(i, __ St##NAME(x0, MemOperand(x20)));
11590 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X)
11591 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X)
11592 #undef ATOMIC_LOAD_X
11593 #undef ATOMIC_STORE_X
11594 }
11595
11596 if (i > (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) {
11597 CHECK_ALIGN_FAIL(i, __ Casp(x0, x1, x2, x3, MemOperand(x20)));
11598 CHECK_ALIGN_FAIL(i, __ Caspl(x0, x1, x2, x3, MemOperand(x20)));
11599 CHECK_ALIGN_FAIL(i, __ Caspa(x0, x1, x2, x3, MemOperand(x20)));
11600 CHECK_ALIGN_FAIL(i, __ Caspal(x0, x1, x2, x3, MemOperand(x20)));
11601 CHECK_ALIGN_FAIL(i, __ Stxp(x0, x1, x2, MemOperand(x20)));
11602 CHECK_ALIGN_FAIL(i, __ Stlxp(x0, x1, x2, MemOperand(x20)));
11603 CHECK_ALIGN_FAIL(i, __ Ldxp(x0, x1, MemOperand(x20)));
11604 CHECK_ALIGN_FAIL(i, __ Ldaxp(x0, x1, MemOperand(x20)));
11605 }
11606 }
11607 }
11608
11609 TEST(unaligned_single_copy_atomicity_negative_test_2) {
11610 uint64_t data[] = {0x1010101010101010, 0x1010101010101010};
11611
11612 uint64_t* data_aligned = AlignUp(data, kAtomicAccessGranule);
11613
11614 // Check that the same code doesn't fail with USCAT enabled but does
11615 // fail when not enabled.
11616 {
11617 SETUP_WITH_FEATURES(CPUFeatures::kUSCAT);
11618 START();
11619 __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned));
11620 __ Add(x0, x0, 1);
11621 __ Ldxrh(w1, MemOperand(x0));
11622 END();
11623 if (CAN_RUN()) {
11624 RUN_WITHOUT_SEEN_FEATURE_CHECK();
11625 }
11626 }
11627 {
11628 SETUP();
11629 START();
11630 __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned));
11631 __ Add(x0, x0, 1);
11632 __ Ldxrh(w1, MemOperand(x0));
11633 END();
11634 if (CAN_RUN()) {
11635 MUST_FAIL_WITH_MESSAGE(RUN(), "ALIGNMENT EXCEPTION");
11636 }
11637 }
11638 }
11639 #endif // VIXL_NEGATIVE_TESTING && VIXL_INCLUDE_SIMULATOR_AARCH64
11640
11641
11642 TEST(load_store_tagged_immediate_offset) {
11643 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11644 int tag_count = sizeof(tags) / sizeof(tags[0]);
11645
11646 const int kMaxDataLength = 160;
11647
11648 for (int i = 0; i < tag_count; i++) {
11649 unsigned char src[kMaxDataLength];
11650 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11651 uint64_t src_tag = tags[i];
11652 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11653
11654 for (int k = 0; k < kMaxDataLength; k++) {
11655 src[k] = k + 1;
11656 }
11657
11658 for (int j = 0; j < tag_count; j++) {
11659 unsigned char dst[kMaxDataLength];
11660 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11661 uint64_t dst_tag = tags[j];
11662 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11663
11664 memset(dst, 0, kMaxDataLength);
11665
11666 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11667 START();
11668
11669 __ Mov(x0, src_tagged);
11670 __ Mov(x1, dst_tagged);
11671
11672 int offset = 0;
11673
11674 // Scaled-immediate offsets.
11675 {
11676 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11677 __ ldp(q0, q1, MemOperand(x0, offset));
11678 __ stp(q0, q1, MemOperand(x1, offset));
11679 }
11680 offset += 2 * kQRegSizeInBytes;
11681
11682 {
11683 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11684 __ ldp(x2, x3, MemOperand(x0, offset));
11685 __ stp(x2, x3, MemOperand(x1, offset));
11686 }
11687 offset += 2 * kXRegSizeInBytes;
11688
11689 {
11690 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11691 __ ldpsw(x2, x3, MemOperand(x0, offset));
11692 __ stp(w2, w3, MemOperand(x1, offset));
11693 }
11694 offset += 2 * kWRegSizeInBytes;
11695
11696 {
11697 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11698 __ ldp(d0, d1, MemOperand(x0, offset));
11699 __ stp(d0, d1, MemOperand(x1, offset));
11700 }
11701 offset += 2 * kDRegSizeInBytes;
11702
11703 {
11704 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11705 __ ldp(w2, w3, MemOperand(x0, offset));
11706 __ stp(w2, w3, MemOperand(x1, offset));
11707 }
11708 offset += 2 * kWRegSizeInBytes;
11709
11710 {
11711 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11712 __ ldp(s0, s1, MemOperand(x0, offset));
11713 __ stp(s0, s1, MemOperand(x1, offset));
11714 }
11715 offset += 2 * kSRegSizeInBytes;
11716
11717 {
11718 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11719 __ ldr(x2, MemOperand(x0, offset), RequireScaledOffset);
11720 __ str(x2, MemOperand(x1, offset), RequireScaledOffset);
11721 }
11722 offset += kXRegSizeInBytes;
11723
11724 {
11725 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11726 __ ldr(d0, MemOperand(x0, offset), RequireScaledOffset);
11727 __ str(d0, MemOperand(x1, offset), RequireScaledOffset);
11728 }
11729 offset += kDRegSizeInBytes;
11730
11731 {
11732 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11733 __ ldr(w2, MemOperand(x0, offset), RequireScaledOffset);
11734 __ str(w2, MemOperand(x1, offset), RequireScaledOffset);
11735 }
11736 offset += kWRegSizeInBytes;
11737
11738 {
11739 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11740 __ ldr(s0, MemOperand(x0, offset), RequireScaledOffset);
11741 __ str(s0, MemOperand(x1, offset), RequireScaledOffset);
11742 }
11743 offset += kSRegSizeInBytes;
11744
11745 {
11746 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11747 __ ldrh(w2, MemOperand(x0, offset), RequireScaledOffset);
11748 __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11749 }
11750 offset += 2;
11751
11752 {
11753 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11754 __ ldrsh(w2, MemOperand(x0, offset), RequireScaledOffset);
11755 __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11756 }
11757 offset += 2;
11758
11759 {
11760 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11761 __ ldrb(w2, MemOperand(x0, offset), RequireScaledOffset);
11762 __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11763 }
11764 offset += 1;
11765
11766 {
11767 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11768 __ ldrsb(w2, MemOperand(x0, offset), RequireScaledOffset);
11769 __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11770 }
11771 offset += 1;
11772
11773 // Unscaled-immediate offsets.
11774
11775 {
11776 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11777 __ ldur(x2, MemOperand(x0, offset), RequireUnscaledOffset);
11778 __ stur(x2, MemOperand(x1, offset), RequireUnscaledOffset);
11779 }
11780 offset += kXRegSizeInBytes;
11781
11782 {
11783 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11784 __ ldur(d0, MemOperand(x0, offset), RequireUnscaledOffset);
11785 __ stur(d0, MemOperand(x1, offset), RequireUnscaledOffset);
11786 }
11787 offset += kDRegSizeInBytes;
11788
11789 {
11790 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11791 __ ldur(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11792 __ stur(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11793 }
11794 offset += kWRegSizeInBytes;
11795
11796 {
11797 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11798 __ ldur(s0, MemOperand(x0, offset), RequireUnscaledOffset);
11799 __ stur(s0, MemOperand(x1, offset), RequireUnscaledOffset);
11800 }
11801 offset += kSRegSizeInBytes;
11802
11803 {
11804 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11805 __ ldurh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11806 __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11807 }
11808 offset += 2;
11809
11810 {
11811 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11812 __ ldursh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11813 __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11814 }
11815 offset += 2;
11816
11817 {
11818 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11819 __ ldurb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11820 __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11821 }
11822 offset += 1;
11823
11824 {
11825 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11826 __ ldursb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11827 __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11828 }
11829 offset += 1;
11830
11831 // Extract the tag (so we can test that it was preserved correctly).
11832 __ Ubfx(x0, x0, kAddressTagOffset, kAddressTagWidth);
11833 __ Ubfx(x1, x1, kAddressTagOffset, kAddressTagWidth);
11834
11835 VIXL_ASSERT(kMaxDataLength >= offset);
11836
11837 END();
11838 if (CAN_RUN()) {
11839 RUN();
11840
11841 ASSERT_EQUAL_64(src_tag, x0);
11842 ASSERT_EQUAL_64(dst_tag, x1);
11843
11844 for (int k = 0; k < offset; k++) {
11845 VIXL_CHECK(src[k] == dst[k]);
11846 }
11847 }
11848 }
11849 }
11850 }
11851
11852
11853 TEST(load_store_tagged_immediate_preindex) {
11854 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11855 int tag_count = sizeof(tags) / sizeof(tags[0]);
11856
11857 const int kMaxDataLength = 128;
11858
11859 for (int i = 0; i < tag_count; i++) {
11860 unsigned char src[kMaxDataLength];
11861 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11862 uint64_t src_tag = tags[i];
11863 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11864
11865 for (int k = 0; k < kMaxDataLength; k++) {
11866 src[k] = k + 1;
11867 }
11868
11869 for (int j = 0; j < tag_count; j++) {
11870 unsigned char dst[kMaxDataLength];
11871 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11872 uint64_t dst_tag = tags[j];
11873 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11874
11875 for (int k = 0; k < kMaxDataLength; k++) {
11876 dst[k] = 0;
11877 }
11878
11879 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11880 START();
11881
11882 // Each MemOperand must apply a pre-index equal to the size of the
11883 // previous access.
11884
11885 // Start with a non-zero preindex.
11886 int preindex = 62 * kXRegSizeInBytes;
11887 int data_length = 0;
11888
11889 __ Mov(x0, src_tagged - preindex);
11890 __ Mov(x1, dst_tagged - preindex);
11891
11892 {
11893 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11894 __ ldp(q0, q1, MemOperand(x0, preindex, PreIndex));
11895 __ stp(q0, q1, MemOperand(x1, preindex, PreIndex));
11896 }
11897 preindex = 2 * kQRegSizeInBytes;
11898 data_length = preindex;
11899
11900 {
11901 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11902 __ ldp(x2, x3, MemOperand(x0, preindex, PreIndex));
11903 __ stp(x2, x3, MemOperand(x1, preindex, PreIndex));
11904 }
11905 preindex = 2 * kXRegSizeInBytes;
11906 data_length += preindex;
11907
11908 {
11909 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11910 __ ldpsw(x2, x3, MemOperand(x0, preindex, PreIndex));
11911 __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
11912 }
11913 preindex = 2 * kWRegSizeInBytes;
11914 data_length += preindex;
11915
11916 {
11917 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11918 __ ldp(d0, d1, MemOperand(x0, preindex, PreIndex));
11919 __ stp(d0, d1, MemOperand(x1, preindex, PreIndex));
11920 }
11921 preindex = 2 * kDRegSizeInBytes;
11922 data_length += preindex;
11923
11924 {
11925 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11926 __ ldp(w2, w3, MemOperand(x0, preindex, PreIndex));
11927 __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
11928 }
11929 preindex = 2 * kWRegSizeInBytes;
11930 data_length += preindex;
11931
11932 {
11933 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11934 __ ldp(s0, s1, MemOperand(x0, preindex, PreIndex));
11935 __ stp(s0, s1, MemOperand(x1, preindex, PreIndex));
11936 }
11937 preindex = 2 * kSRegSizeInBytes;
11938 data_length += preindex;
11939
11940 {
11941 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11942 __ ldr(x2, MemOperand(x0, preindex, PreIndex));
11943 __ str(x2, MemOperand(x1, preindex, PreIndex));
11944 }
11945 preindex = kXRegSizeInBytes;
11946 data_length += preindex;
11947
11948 {
11949 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11950 __ ldr(d0, MemOperand(x0, preindex, PreIndex));
11951 __ str(d0, MemOperand(x1, preindex, PreIndex));
11952 }
11953 preindex = kDRegSizeInBytes;
11954 data_length += preindex;
11955
11956 {
11957 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11958 __ ldr(w2, MemOperand(x0, preindex, PreIndex));
11959 __ str(w2, MemOperand(x1, preindex, PreIndex));
11960 }
11961 preindex = kWRegSizeInBytes;
11962 data_length += preindex;
11963
11964 {
11965 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11966 __ ldr(s0, MemOperand(x0, preindex, PreIndex));
11967 __ str(s0, MemOperand(x1, preindex, PreIndex));
11968 }
11969 preindex = kSRegSizeInBytes;
11970 data_length += preindex;
11971
11972 {
11973 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11974 __ ldrh(w2, MemOperand(x0, preindex, PreIndex));
11975 __ strh(w2, MemOperand(x1, preindex, PreIndex));
11976 }
11977 preindex = 2;
11978 data_length += preindex;
11979
11980 {
11981 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11982 __ ldrsh(w2, MemOperand(x0, preindex, PreIndex));
11983 __ strh(w2, MemOperand(x1, preindex, PreIndex));
11984 }
11985 preindex = 2;
11986 data_length += preindex;
11987
11988 {
11989 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11990 __ ldrb(w2, MemOperand(x0, preindex, PreIndex));
11991 __ strb(w2, MemOperand(x1, preindex, PreIndex));
11992 }
11993 preindex = 1;
11994 data_length += preindex;
11995
11996 {
11997 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11998 __ ldrsb(w2, MemOperand(x0, preindex, PreIndex));
11999 __ strb(w2, MemOperand(x1, preindex, PreIndex));
12000 }
12001 preindex = 1;
12002 data_length += preindex;
12003
12004 VIXL_ASSERT(kMaxDataLength >= data_length);
12005
12006 END();
12007 if (CAN_RUN()) {
12008 RUN();
12009
12010 // Check that the preindex was correctly applied in each operation, and
12011 // that the tag was preserved.
12012 ASSERT_EQUAL_64(src_tagged + data_length - preindex, x0);
12013 ASSERT_EQUAL_64(dst_tagged + data_length - preindex, x1);
12014
12015 for (int k = 0; k < data_length; k++) {
12016 VIXL_CHECK(src[k] == dst[k]);
12017 }
12018 }
12019 }
12020 }
12021 }
12022
12023
12024 TEST(load_store_tagged_immediate_postindex) {
12025 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12026 int tag_count = sizeof(tags) / sizeof(tags[0]);
12027
12028 const int kMaxDataLength = 128;
12029
12030 for (int i = 0; i < tag_count; i++) {
12031 unsigned char src[kMaxDataLength];
12032 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
12033 uint64_t src_tag = tags[i];
12034 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
12035
12036 for (int k = 0; k < kMaxDataLength; k++) {
12037 src[k] = k + 1;
12038 }
12039
12040 for (int j = 0; j < tag_count; j++) {
12041 unsigned char dst[kMaxDataLength];
12042 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
12043 uint64_t dst_tag = tags[j];
12044 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
12045
12046 for (int k = 0; k < kMaxDataLength; k++) {
12047 dst[k] = 0;
12048 }
12049
12050 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12051 START();
12052
12053 int postindex = 2 * kXRegSizeInBytes;
12054 int data_length = 0;
12055
12056 __ Mov(x0, src_tagged);
12057 __ Mov(x1, dst_tagged);
12058
12059 {
12060 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12061 __ ldp(x2, x3, MemOperand(x0, postindex, PostIndex));
12062 __ stp(x2, x3, MemOperand(x1, postindex, PostIndex));
12063 }
12064 data_length = postindex;
12065
12066 postindex = 2 * kQRegSizeInBytes;
12067 {
12068 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12069 __ ldp(q0, q1, MemOperand(x0, postindex, PostIndex));
12070 __ stp(q0, q1, MemOperand(x1, postindex, PostIndex));
12071 }
12072 data_length += postindex;
12073
12074 postindex = 2 * kWRegSizeInBytes;
12075 {
12076 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12077 __ ldpsw(x2, x3, MemOperand(x0, postindex, PostIndex));
12078 __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
12079 }
12080 data_length += postindex;
12081
12082 postindex = 2 * kDRegSizeInBytes;
12083 {
12084 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12085 __ ldp(d0, d1, MemOperand(x0, postindex, PostIndex));
12086 __ stp(d0, d1, MemOperand(x1, postindex, PostIndex));
12087 }
12088 data_length += postindex;
12089
12090 postindex = 2 * kWRegSizeInBytes;
12091 {
12092 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12093 __ ldp(w2, w3, MemOperand(x0, postindex, PostIndex));
12094 __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
12095 }
12096 data_length += postindex;
12097
12098 postindex = 2 * kSRegSizeInBytes;
12099 {
12100 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12101 __ ldp(s0, s1, MemOperand(x0, postindex, PostIndex));
12102 __ stp(s0, s1, MemOperand(x1, postindex, PostIndex));
12103 }
12104 data_length += postindex;
12105
12106 postindex = kXRegSizeInBytes;
12107 {
12108 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12109 __ ldr(x2, MemOperand(x0, postindex, PostIndex));
12110 __ str(x2, MemOperand(x1, postindex, PostIndex));
12111 }
12112 data_length += postindex;
12113
12114 postindex = kDRegSizeInBytes;
12115 {
12116 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12117 __ ldr(d0, MemOperand(x0, postindex, PostIndex));
12118 __ str(d0, MemOperand(x1, postindex, PostIndex));
12119 }
12120 data_length += postindex;
12121
12122 postindex = kWRegSizeInBytes;
12123 {
12124 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12125 __ ldr(w2, MemOperand(x0, postindex, PostIndex));
12126 __ str(w2, MemOperand(x1, postindex, PostIndex));
12127 }
12128 data_length += postindex;
12129
12130 postindex = kSRegSizeInBytes;
12131 {
12132 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12133 __ ldr(s0, MemOperand(x0, postindex, PostIndex));
12134 __ str(s0, MemOperand(x1, postindex, PostIndex));
12135 }
12136 data_length += postindex;
12137
12138 postindex = 2;
12139 {
12140 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12141 __ ldrh(w2, MemOperand(x0, postindex, PostIndex));
12142 __ strh(w2, MemOperand(x1, postindex, PostIndex));
12143 }
12144 data_length += postindex;
12145
12146 postindex = 2;
12147 {
12148 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12149 __ ldrsh(w2, MemOperand(x0, postindex, PostIndex));
12150 __ strh(w2, MemOperand(x1, postindex, PostIndex));
12151 }
12152 data_length += postindex;
12153
12154 postindex = 1;
12155 {
12156 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12157 __ ldrb(w2, MemOperand(x0, postindex, PostIndex));
12158 __ strb(w2, MemOperand(x1, postindex, PostIndex));
12159 }
12160 data_length += postindex;
12161
12162 postindex = 1;
12163 {
12164 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12165 __ ldrsb(w2, MemOperand(x0, postindex, PostIndex));
12166 __ strb(w2, MemOperand(x1, postindex, PostIndex));
12167 }
12168 data_length += postindex;
12169
12170 VIXL_ASSERT(kMaxDataLength >= data_length);
12171
12172 END();
12173 if (CAN_RUN()) {
12174 RUN();
12175
12176 // Check that the postindex was correctly applied in each operation, and
12177 // that the tag was preserved.
12178 ASSERT_EQUAL_64(src_tagged + data_length, x0);
12179 ASSERT_EQUAL_64(dst_tagged + data_length, x1);
12180
12181 for (int k = 0; k < data_length; k++) {
12182 VIXL_CHECK(src[k] == dst[k]);
12183 }
12184 }
12185 }
12186 }
12187 }
12188
12189
12190 TEST(load_store_tagged_register_offset) {
12191 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12192 int tag_count = sizeof(tags) / sizeof(tags[0]);
12193
12194 const int kMaxDataLength = 128;
12195
12196 for (int i = 0; i < tag_count; i++) {
12197 unsigned char src[kMaxDataLength];
12198 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
12199 uint64_t src_tag = tags[i];
12200 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
12201
12202 for (int k = 0; k < kMaxDataLength; k++) {
12203 src[k] = k + 1;
12204 }
12205
12206 for (int j = 0; j < tag_count; j++) {
12207 unsigned char dst[kMaxDataLength];
12208 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
12209 uint64_t dst_tag = tags[j];
12210 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
12211
12212 // Also tag the offset register; the operation should still succeed.
12213 for (int o = 0; o < tag_count; o++) {
12214 uint64_t offset_base = CPU::SetPointerTag(UINT64_C(0), tags[o]);
12215 int data_length = 0;
12216
12217 for (int k = 0; k < kMaxDataLength; k++) {
12218 dst[k] = 0;
12219 }
12220
12221 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12222 START();
12223
12224 __ Mov(x0, src_tagged);
12225 __ Mov(x1, dst_tagged);
12226
12227 __ Mov(x10, offset_base + data_length);
12228 {
12229 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12230 __ ldr(x2, MemOperand(x0, x10));
12231 __ str(x2, MemOperand(x1, x10));
12232 }
12233 data_length += kXRegSizeInBytes;
12234
12235 __ Mov(x10, offset_base + data_length);
12236 {
12237 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12238 __ ldr(d0, MemOperand(x0, x10));
12239 __ str(d0, MemOperand(x1, x10));
12240 }
12241 data_length += kDRegSizeInBytes;
12242
12243 __ Mov(x10, offset_base + data_length);
12244 {
12245 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12246 __ ldr(w2, MemOperand(x0, x10));
12247 __ str(w2, MemOperand(x1, x10));
12248 }
12249 data_length += kWRegSizeInBytes;
12250
12251 __ Mov(x10, offset_base + data_length);
12252 {
12253 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12254 __ ldr(s0, MemOperand(x0, x10));
12255 __ str(s0, MemOperand(x1, x10));
12256 }
12257 data_length += kSRegSizeInBytes;
12258
12259 __ Mov(x10, offset_base + data_length);
12260 {
12261 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12262 __ ldrh(w2, MemOperand(x0, x10));
12263 __ strh(w2, MemOperand(x1, x10));
12264 }
12265 data_length += 2;
12266
12267 __ Mov(x10, offset_base + data_length);
12268 {
12269 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12270 __ ldrsh(w2, MemOperand(x0, x10));
12271 __ strh(w2, MemOperand(x1, x10));
12272 }
12273 data_length += 2;
12274
12275 __ Mov(x10, offset_base + data_length);
12276 {
12277 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12278 __ ldrb(w2, MemOperand(x0, x10));
12279 __ strb(w2, MemOperand(x1, x10));
12280 }
12281 data_length += 1;
12282
12283 __ Mov(x10, offset_base + data_length);
12284 {
12285 ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12286 __ ldrsb(w2, MemOperand(x0, x10));
12287 __ strb(w2, MemOperand(x1, x10));
12288 }
12289 data_length += 1;
12290
12291 VIXL_ASSERT(kMaxDataLength >= data_length);
12292
12293 END();
12294 if (CAN_RUN()) {
12295 RUN();
12296
12297 // Check that the postindex was correctly applied in each operation,
12298 // and that the tag was preserved.
12299 ASSERT_EQUAL_64(src_tagged, x0);
12300 ASSERT_EQUAL_64(dst_tagged, x1);
12301 ASSERT_EQUAL_64(offset_base + data_length - 1, x10);
12302
12303 for (int k = 0; k < data_length; k++) {
12304 VIXL_CHECK(src[k] == dst[k]);
12305 }
12306 }
12307 }
12308 }
12309 }
12310 }
12311
12312
12313 TEST(load_store_tagged_register_postindex) {
12314 uint64_t src[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
12315 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12316 int tag_count = sizeof(tags) / sizeof(tags[0]);
12317
12318 for (int j = 0; j < tag_count; j++) {
12319 for (int i = 0; i < tag_count; i++) {
12320 SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12321
12322 uint64_t src_base = reinterpret_cast<uint64_t>(src);
12323 uint64_t src_tagged = CPU::SetPointerTag(src_base, tags[i]);
12324 uint64_t offset_tagged = CPU::SetPointerTag(UINT64_C(0), tags[j]);
12325
12326 START();
12327 __ Mov(x10, src_tagged);
12328 __ Mov(x11, offset_tagged);
12329 __ Ld1(v0.V16B(), MemOperand(x10, x11, PostIndex));
12330 // TODO: add other instructions (ld2-4, st1-4) as they become available.
12331 END();
12332
12333 if (CAN_RUN()) {
12334 RUN();
12335
12336 ASSERT_EQUAL_128(0x0f0e0d0c0b0a0908, 0x0706050403020100, q0);
12337 ASSERT_EQUAL_64(src_tagged + offset_tagged, x10);
12338 }
12339 }
12340 }
12341 }
12342
12343
12344 TEST(branch_tagged) {
12345 SETUP();
12346 START();
12347
12348 Label loop, loop_entry, done;
12349 __ Adr(x0, &loop);
12350 __ Mov(x1, 0);
12351 __ B(&loop_entry);
12352
12353 __ Bind(&loop);
12354 __ Add(x1, x1, 1); // Count successful jumps.
12355
12356 // Advance to the next tag, then bail out if we've come back around to tag 0.
12357 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12358 __ Tst(x0, kAddressTagMask);
12359 __ B(eq, &done);
12360
12361 __ Bind(&loop_entry);
12362 __ Br(x0);
12363
12364 __ Bind(&done);
12365
12366 END();
12367 if (CAN_RUN()) {
12368 RUN();
12369
12370 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12371 }
12372 }
12373
12374
12375 TEST(branch_and_link_tagged) {
12376 SETUP();
12377 START();
12378
12379 Label loop, loop_entry, done;
12380 __ Adr(x0, &loop);
12381 __ Mov(x1, 0);
12382 __ B(&loop_entry);
12383
12384 __ Bind(&loop);
12385
12386 // Bail out (before counting a successful jump) if lr appears to be tagged.
12387 __ Tst(lr, kAddressTagMask);
12388 __ B(ne, &done);
12389
12390 __ Add(x1, x1, 1); // Count successful jumps.
12391
12392 // Advance to the next tag, then bail out if we've come back around to tag 0.
12393 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12394 __ Tst(x0, kAddressTagMask);
12395 __ B(eq, &done);
12396
12397 __ Bind(&loop_entry);
12398 __ Blr(x0);
12399
12400 __ Bind(&done);
12401
12402 END();
12403 if (CAN_RUN()) {
12404 RUN();
12405
12406 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12407 }
12408 }
12409
12410
12411 TEST(branch_tagged_and_adr_adrp) {
12412 SETUP_CUSTOM(kPageSize, PageOffsetDependentCode);
12413 START();
12414
12415 Label loop, loop_entry, done;
12416 __ Adr(x0, &loop);
12417 __ Mov(x1, 0);
12418 __ B(&loop_entry);
12419
12420 __ Bind(&loop);
12421
12422 // Bail out (before counting a successful jump) if `adr x10, ...` is tagged.
12423 __ Adr(x10, &done);
12424 __ Tst(x10, kAddressTagMask);
12425 __ B(ne, &done);
12426
12427 // Bail out (before counting a successful jump) if `adrp x11, ...` is tagged.
12428 __ Adrp(x11, &done);
12429 __ Tst(x11, kAddressTagMask);
12430 __ B(ne, &done);
12431
12432 __ Add(x1, x1, 1); // Count successful iterations.
12433
12434 // Advance to the next tag, then bail out if we've come back around to tag 0.
12435 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12436 __ Tst(x0, kAddressTagMask);
12437 __ B(eq, &done);
12438
12439 __ Bind(&loop_entry);
12440 __ Br(x0);
12441
12442 __ Bind(&done);
12443
12444 END();
12445 if (CAN_RUN()) {
12446 RUN();
12447
12448 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12449 }
12450 }
12451
12452 TEST(system_sys) {
12453 SETUP();
12454 const char* msg = "SYS test!";
12455 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12456
12457 START();
12458 __ Mov(x4, msg_addr);
12459 __ Sys(3, 0x7, 0x5, 1, x4);
12460 __ Mov(x3, x4);
12461 __ Sys(3, 0x7, 0xa, 1, x3);
12462 __ Mov(x2, x3);
12463 __ Sys(3, 0x7, 0xb, 1, x2);
12464 __ Mov(x1, x2);
12465 __ Sys(3, 0x7, 0xe, 1, x1);
12466 // TODO: Add tests to check ZVA equivalent.
12467 END();
12468
12469 if (CAN_RUN()) {
12470 RUN();
12471 }
12472 }
12473
12474
12475 TEST(system_ic) {
12476 SETUP();
12477 const char* msg = "IC test!";
12478 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12479
12480 START();
12481 __ Mov(x11, msg_addr);
12482 __ Ic(IVAU, x11);
12483 END();
12484
12485 if (CAN_RUN()) {
12486 RUN();
12487 }
12488 }
12489
12490
12491 TEST(system_dc) {
12492 SETUP();
12493 const char* msg = "DC test!";
12494 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12495
12496 START();
12497 __ Mov(x20, msg_addr);
12498 __ Dc(CVAC, x20);
12499 __ Mov(x21, msg_addr);
12500 __ Dc(CVAU, x21);
12501 __ Mov(x22, msg_addr);
12502 __ Dc(CIVAC, x22);
12503 // TODO: Add tests to check ZVA.
12504 END();
12505
12506 if (CAN_RUN()) {
12507 RUN();
12508 ASSERT_EQUAL_64(msg_addr, x20);
12509 ASSERT_EQUAL_64(msg_addr, x21);
12510 ASSERT_EQUAL_64(msg_addr, x22);
12511 }
12512 }
12513
12514
12515 TEST(system_dcpop) {
12516 SETUP_WITH_FEATURES(CPUFeatures::kDCPoP);
12517 const char* msg = "DCPoP test!";
12518 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12519
12520 START();
12521 __ Mov(x20, msg_addr);
12522 __ Dc(CVAP, x20);
12523 END();
12524
12525 if (CAN_RUN()) {
12526 RUN();
12527 ASSERT_EQUAL_64(msg_addr, x20);
12528 }
12529 }
12530
12531 TEST(system_dccvadp) {
12532 SETUP_WITH_FEATURES(CPUFeatures::kDCCVADP);
12533 const char* msg = "DCCVADP test!";
12534 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12535
12536 START();
12537 __ Mov(x20, msg_addr);
12538 __ Dc(CVADP, x20);
12539 END();
12540
12541 if (CAN_RUN()) {
12542 RUN();
12543 ASSERT_EQUAL_64(msg_addr, x20);
12544 }
12545 }
12546
12547 TEST(system_dc_mte) {
12548 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
12549 const char* msg = "DC MTE test!";
12550 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12551
12552 START();
12553 __ Mov(x20, msg_addr);
12554 __ Dc(CGVAC, x20);
12555 __ Dc(CGDVAC, x20);
12556 __ Dc(CGVAP, x20);
12557 __ Dc(CGDVAP, x20);
12558 __ Dc(CIGVAC, x20);
12559 __ Dc(CIGDVAC, x20);
12560 END();
12561
12562 if (CAN_RUN()) {
12563 RUN();
12564 ASSERT_EQUAL_64(msg_addr, x20);
12565 }
12566 }
12567
12568 // We currently disable tests for CRC32 instructions when running natively.
12569 // Support for this family of instruction is optional, and so native platforms
12570 // may simply fail to execute the test.
12571 TEST(crc32b) {
12572 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12573
12574 START();
12575
12576 __ Mov(w0, 0);
12577 __ Mov(w1, 0);
12578 __ Crc32b(w10, w0, w1);
12579
12580 __ Mov(w0, 0x1);
12581 __ Mov(w1, 0x138);
12582 __ Crc32b(w11, w0, w1);
12583
12584 __ Mov(w0, 0x1);
12585 __ Mov(w1, 0x38);
12586 __ Crc32b(w12, w0, w1);
12587
12588 __ Mov(w0, 0);
12589 __ Mov(w1, 128);
12590 __ Crc32b(w13, w0, w1);
12591
12592 __ Mov(w0, UINT32_MAX);
12593 __ Mov(w1, 255);
12594 __ Crc32b(w14, w0, w1);
12595
12596 __ Mov(w0, 0x00010001);
12597 __ Mov(w1, 0x10001000);
12598 __ Crc32b(w15, w0, w1);
12599
12600 END();
12601
12602 if (CAN_RUN()) {
12603 RUN();
12604
12605 ASSERT_EQUAL_64(0x0, x10);
12606 ASSERT_EQUAL_64(0x5f058808, x11);
12607 ASSERT_EQUAL_64(0x5f058808, x12);
12608 ASSERT_EQUAL_64(0xedb88320, x13);
12609 ASSERT_EQUAL_64(0x00ffffff, x14);
12610 ASSERT_EQUAL_64(0x77073196, x15);
12611 }
12612 }
12613
12614
12615 TEST(crc32h) {
12616 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12617
12618 START();
12619
12620 __ Mov(w0, 0);
12621 __ Mov(w1, 0);
12622 __ Crc32h(w10, w0, w1);
12623
12624 __ Mov(w0, 0x1);
12625 __ Mov(w1, 0x10038);
12626 __ Crc32h(w11, w0, w1);
12627
12628 __ Mov(w0, 0x1);
12629 __ Mov(w1, 0x38);
12630 __ Crc32h(w12, w0, w1);
12631
12632 __ Mov(w0, 0);
12633 __ Mov(w1, 128);
12634 __ Crc32h(w13, w0, w1);
12635
12636 __ Mov(w0, UINT32_MAX);
12637 __ Mov(w1, 255);
12638 __ Crc32h(w14, w0, w1);
12639
12640 __ Mov(w0, 0x00010001);
12641 __ Mov(w1, 0x10001000);
12642 __ Crc32h(w15, w0, w1);
12643
12644 END();
12645
12646 if (CAN_RUN()) {
12647 RUN();
12648
12649 ASSERT_EQUAL_64(0x0, x10);
12650 ASSERT_EQUAL_64(0x0e848dba, x11);
12651 ASSERT_EQUAL_64(0x0e848dba, x12);
12652 ASSERT_EQUAL_64(0x3b83984b, x13);
12653 ASSERT_EQUAL_64(0x2d021072, x14);
12654 ASSERT_EQUAL_64(0x04ac2124, x15);
12655 }
12656 }
12657
12658
12659 TEST(crc32w) {
12660 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12661
12662 START();
12663
12664 __ Mov(w0, 0);
12665 __ Mov(w1, 0);
12666 __ Crc32w(w10, w0, w1);
12667
12668 __ Mov(w0, 0x1);
12669 __ Mov(w1, 0x80000031);
12670 __ Crc32w(w11, w0, w1);
12671
12672 __ Mov(w0, 0);
12673 __ Mov(w1, 128);
12674 __ Crc32w(w13, w0, w1);
12675
12676 __ Mov(w0, UINT32_MAX);
12677 __ Mov(w1, 255);
12678 __ Crc32w(w14, w0, w1);
12679
12680 __ Mov(w0, 0x00010001);
12681 __ Mov(w1, 0x10001000);
12682 __ Crc32w(w15, w0, w1);
12683
12684 END();
12685
12686 if (CAN_RUN()) {
12687 RUN();
12688
12689 ASSERT_EQUAL_64(0x0, x10);
12690 ASSERT_EQUAL_64(0x1d937b81, x11);
12691 ASSERT_EQUAL_64(0xed59b63b, x13);
12692 ASSERT_EQUAL_64(0x00be2612, x14);
12693 ASSERT_EQUAL_64(0xa036e530, x15);
12694 }
12695 }
12696
12697
12698 TEST(crc32x) {
12699 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12700
12701 START();
12702
12703 __ Mov(w0, 0);
12704 __ Mov(x1, 0);
12705 __ Crc32x(w10, w0, x1);
12706
12707 __ Mov(w0, 0x1);
12708 __ Mov(x1, UINT64_C(0x0000000800000031));
12709 __ Crc32x(w11, w0, x1);
12710
12711 __ Mov(w0, 0);
12712 __ Mov(x1, 128);
12713 __ Crc32x(w13, w0, x1);
12714
12715 __ Mov(w0, UINT32_MAX);
12716 __ Mov(x1, 255);
12717 __ Crc32x(w14, w0, x1);
12718
12719 __ Mov(w0, 0x00010001);
12720 __ Mov(x1, UINT64_C(0x1000100000000000));
12721 __ Crc32x(w15, w0, x1);
12722
12723 END();
12724
12725 if (CAN_RUN()) {
12726 RUN();
12727
12728 ASSERT_EQUAL_64(0x0, x10);
12729 ASSERT_EQUAL_64(0x40797b92, x11);
12730 ASSERT_EQUAL_64(0x533b85da, x13);
12731 ASSERT_EQUAL_64(0xbc962670, x14);
12732 ASSERT_EQUAL_64(0x0667602f, x15);
12733 }
12734 }
12735
12736
12737 TEST(crc32cb) {
12738 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12739
12740 START();
12741
12742 __ Mov(w0, 0);
12743 __ Mov(w1, 0);
12744 __ Crc32cb(w10, w0, w1);
12745
12746 __ Mov(w0, 0x1);
12747 __ Mov(w1, 0x138);
12748 __ Crc32cb(w11, w0, w1);
12749
12750 __ Mov(w0, 0x1);
12751 __ Mov(w1, 0x38);
12752 __ Crc32cb(w12, w0, w1);
12753
12754 __ Mov(w0, 0);
12755 __ Mov(w1, 128);
12756 __ Crc32cb(w13, w0, w1);
12757
12758 __ Mov(w0, UINT32_MAX);
12759 __ Mov(w1, 255);
12760 __ Crc32cb(w14, w0, w1);
12761
12762 __ Mov(w0, 0x00010001);
12763 __ Mov(w1, 0x10001000);
12764 __ Crc32cb(w15, w0, w1);
12765
12766 END();
12767
12768 if (CAN_RUN()) {
12769 RUN();
12770
12771 ASSERT_EQUAL_64(0x0, x10);
12772 ASSERT_EQUAL_64(0x4851927d, x11);
12773 ASSERT_EQUAL_64(0x4851927d, x12);
12774 ASSERT_EQUAL_64(0x82f63b78, x13);
12775 ASSERT_EQUAL_64(0x00ffffff, x14);
12776 ASSERT_EQUAL_64(0xf26b8203, x15);
12777 }
12778 }
12779
12780
12781 TEST(crc32ch) {
12782 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12783
12784 START();
12785
12786 __ Mov(w0, 0);
12787 __ Mov(w1, 0);
12788 __ Crc32ch(w10, w0, w1);
12789
12790 __ Mov(w0, 0x1);
12791 __ Mov(w1, 0x10038);
12792 __ Crc32ch(w11, w0, w1);
12793
12794 __ Mov(w0, 0x1);
12795 __ Mov(w1, 0x38);
12796 __ Crc32ch(w12, w0, w1);
12797
12798 __ Mov(w0, 0);
12799 __ Mov(w1, 128);
12800 __ Crc32ch(w13, w0, w1);
12801
12802 __ Mov(w0, UINT32_MAX);
12803 __ Mov(w1, 255);
12804 __ Crc32ch(w14, w0, w1);
12805
12806 __ Mov(w0, 0x00010001);
12807 __ Mov(w1, 0x10001000);
12808 __ Crc32ch(w15, w0, w1);
12809
12810 END();
12811
12812 if (CAN_RUN()) {
12813 RUN();
12814
12815 ASSERT_EQUAL_64(0x0, x10);
12816 ASSERT_EQUAL_64(0xcef8494c, x11);
12817 ASSERT_EQUAL_64(0xcef8494c, x12);
12818 ASSERT_EQUAL_64(0xfbc3faf9, x13);
12819 ASSERT_EQUAL_64(0xad7dacae, x14);
12820 ASSERT_EQUAL_64(0x03fc5f19, x15);
12821 }
12822 }
12823
12824
12825 TEST(crc32cw) {
12826 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12827
12828 START();
12829
12830 __ Mov(w0, 0);
12831 __ Mov(w1, 0);
12832 __ Crc32cw(w10, w0, w1);
12833
12834 __ Mov(w0, 0x1);
12835 __ Mov(w1, 0x80000031);
12836 __ Crc32cw(w11, w0, w1);
12837
12838 __ Mov(w0, 0);
12839 __ Mov(w1, 128);
12840 __ Crc32cw(w13, w0, w1);
12841
12842 __ Mov(w0, UINT32_MAX);
12843 __ Mov(w1, 255);
12844 __ Crc32cw(w14, w0, w1);
12845
12846 __ Mov(w0, 0x00010001);
12847 __ Mov(w1, 0x10001000);
12848 __ Crc32cw(w15, w0, w1);
12849
12850 END();
12851
12852 if (CAN_RUN()) {
12853 RUN();
12854
12855 ASSERT_EQUAL_64(0x0, x10);
12856 ASSERT_EQUAL_64(0xbcb79ece, x11);
12857 ASSERT_EQUAL_64(0x52a0c93f, x13);
12858 ASSERT_EQUAL_64(0x9f9b5c7a, x14);
12859 ASSERT_EQUAL_64(0xae1b882a, x15);
12860 }
12861 }
12862
12863
12864 TEST(crc32cx) {
12865 SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12866
12867 START();
12868
12869 __ Mov(w0, 0);
12870 __ Mov(x1, 0);
12871 __ Crc32cx(w10, w0, x1);
12872
12873 __ Mov(w0, 0x1);
12874 __ Mov(x1, UINT64_C(0x0000000800000031));
12875 __ Crc32cx(w11, w0, x1);
12876
12877 __ Mov(w0, 0);
12878 __ Mov(x1, 128);
12879 __ Crc32cx(w13, w0, x1);
12880
12881 __ Mov(w0, UINT32_MAX);
12882 __ Mov(x1, 255);
12883 __ Crc32cx(w14, w0, x1);
12884
12885 __ Mov(w0, 0x00010001);
12886 __ Mov(x1, UINT64_C(0x1000100000000000));
12887 __ Crc32cx(w15, w0, x1);
12888
12889 END();
12890
12891 if (CAN_RUN()) {
12892 RUN();
12893
12894 ASSERT_EQUAL_64(0x0, x10);
12895 ASSERT_EQUAL_64(0x7f320fcb, x11);
12896 ASSERT_EQUAL_64(0x34019664, x13);
12897 ASSERT_EQUAL_64(0x6cc27dd0, x14);
12898 ASSERT_EQUAL_64(0xc6f0acdb, x15);
12899 }
12900 }
12901
12902 TEST(regress_cmp_shift_imm) {
12903 SETUP();
12904
12905 START();
12906
12907 __ Mov(x0, 0x3d720c8d);
12908 __ Cmp(x0, Operand(0x3d720c8d));
12909
12910 END();
12911 if (CAN_RUN()) {
12912 RUN();
12913
12914 ASSERT_EQUAL_NZCV(ZCFlag);
12915 }
12916 }
12917
12918
12919 TEST(compute_address) {
12920 SETUP();
12921
12922 START();
12923 int64_t base_address = INT64_C(0x123000000abc);
12924 int64_t reg_offset = INT64_C(0x1087654321);
12925 Register base = x0;
12926 Register offset = x1;
12927
12928 __ Mov(base, base_address);
12929 __ Mov(offset, reg_offset);
12930
12931
12932 __ ComputeAddress(x2, MemOperand(base, 0));
12933 __ ComputeAddress(x3, MemOperand(base, 8));
12934 __ ComputeAddress(x4, MemOperand(base, -100));
12935
12936 __ ComputeAddress(x5, MemOperand(base, offset));
12937 __ ComputeAddress(x6, MemOperand(base, offset, LSL, 2));
12938 __ ComputeAddress(x7, MemOperand(base, offset, LSL, 4));
12939 __ ComputeAddress(x8, MemOperand(base, offset, LSL, 8));
12940
12941 __ ComputeAddress(x9, MemOperand(base, offset, SXTW));
12942 __ ComputeAddress(x10, MemOperand(base, offset, UXTW, 1));
12943 __ ComputeAddress(x11, MemOperand(base, offset, SXTW, 2));
12944 __ ComputeAddress(x12, MemOperand(base, offset, UXTW, 3));
12945
12946 END();
12947
12948 if (CAN_RUN()) {
12949 RUN();
12950
12951 ASSERT_EQUAL_64(base_address, base);
12952
12953 ASSERT_EQUAL_64(INT64_C(0x123000000abc), x2);
12954 ASSERT_EQUAL_64(INT64_C(0x123000000ac4), x3);
12955 ASSERT_EQUAL_64(INT64_C(0x123000000a58), x4);
12956
12957 ASSERT_EQUAL_64(INT64_C(0x124087654ddd), x5);
12958 ASSERT_EQUAL_64(INT64_C(0x12721d951740), x6);
12959 ASSERT_EQUAL_64(INT64_C(0x133876543ccc), x7);
12960 ASSERT_EQUAL_64(INT64_C(0x22b765432bbc), x8);
12961
12962 ASSERT_EQUAL_64(INT64_C(0x122f87654ddd), x9);
12963 ASSERT_EQUAL_64(INT64_C(0x12310eca90fe), x10);
12964 ASSERT_EQUAL_64(INT64_C(0x122e1d951740), x11);
12965 ASSERT_EQUAL_64(INT64_C(0x12343b2a23c4), x12);
12966 }
12967 }
12968
12969
12970 TEST(far_branch_backward) {
12971 // Test that the MacroAssembler correctly resolves backward branches to labels
12972 // that are outside the immediate range of branch instructions.
12973 // Take into account that backward branches can reach one instruction further
12974 // than forward branches.
12975 const int overflow_size =
12976 kInstructionSize +
12977 std::max(Instruction::GetImmBranchForwardRange(TestBranchType),
12978 std::max(Instruction::GetImmBranchForwardRange(
12979 CompareBranchType),
12980 Instruction::GetImmBranchForwardRange(CondBranchType)));
12981
12982 SETUP();
12983 START();
12984
12985 Label done, fail;
12986 Label test_tbz, test_cbz, test_bcond;
12987 Label success_tbz, success_cbz, success_bcond;
12988
12989 __ Mov(x0, 0);
12990 __ Mov(x1, 1);
12991 __ Mov(x10, 0);
12992
12993 __ B(&test_tbz);
12994 __ Bind(&success_tbz);
12995 __ Orr(x0, x0, 1 << 0);
12996 __ B(&test_cbz);
12997 __ Bind(&success_cbz);
12998 __ Orr(x0, x0, 1 << 1);
12999 __ B(&test_bcond);
13000 __ Bind(&success_bcond);
13001 __ Orr(x0, x0, 1 << 2);
13002
13003 __ B(&done);
13004
13005 // Generate enough code to overflow the immediate range of the three types of
13006 // branches below.
13007 for (unsigned i = 0; i < overflow_size / kInstructionSize; ++i) {
13008 if (i % 100 == 0) {
13009 // If we do land in this code, we do not want to execute so many nops
13010 // before reaching the end of test (especially if tracing is activated).
13011 __ B(&fail);
13012 } else {
13013 __ Nop();
13014 }
13015 }
13016 __ B(&fail);
13017
13018 __ Bind(&test_tbz);
13019 __ Tbz(x10, 7, &success_tbz);
13020 __ Bind(&test_cbz);
13021 __ Cbz(x10, &success_cbz);
13022 __ Bind(&test_bcond);
13023 __ Cmp(x10, 0);
13024 __ B(eq, &success_bcond);
13025
13026 // For each out-of-range branch instructions, at least two instructions should
13027 // have been generated.
13028 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&test_tbz) >=
13029 7 * kInstructionSize);
13030
13031 __ Bind(&fail);
13032 __ Mov(x1, 0);
13033 __ Bind(&done);
13034
13035 END();
13036 if (CAN_RUN()) {
13037 RUN();
13038
13039 ASSERT_EQUAL_64(0x7, x0);
13040 ASSERT_EQUAL_64(0x1, x1);
13041 }
13042 }
13043
13044
13045 TEST(single_veneer) {
13046 SETUP();
13047 START();
13048
13049 const int max_range = Instruction::GetImmBranchForwardRange(TestBranchType);
13050
13051 Label success, fail, done;
13052
13053 __ Mov(x0, 0);
13054 __ Mov(x1, 1);
13055 __ Mov(x10, 0);
13056
13057 __ Tbz(x10, 7, &success);
13058
13059 // Generate enough code to overflow the immediate range of the `tbz`.
13060 for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) {
13061 if (i % 100 == 0) {
13062 // If we do land in this code, we do not want to execute so many nops
13063 // before reaching the end of test (especially if tracing is activated).
13064 __ B(&fail);
13065 } else {
13066 __ Nop();
13067 }
13068 }
13069 __ B(&fail);
13070
13071 __ Bind(&success);
13072 __ Mov(x0, 1);
13073
13074 __ B(&done);
13075 __ Bind(&fail);
13076 __ Mov(x1, 0);
13077 __ Bind(&done);
13078
13079 END();
13080 if (CAN_RUN()) {
13081 RUN();
13082
13083 ASSERT_EQUAL_64(1, x0);
13084 ASSERT_EQUAL_64(1, x1);
13085 }
13086 }
13087
13088
13089 TEST(simple_veneers) {
13090 // Test that the MacroAssembler correctly emits veneers for forward branches
13091 // to labels that are outside the immediate range of branch instructions.
13092 const int max_range =
13093 std::max(Instruction::GetImmBranchForwardRange(TestBranchType),
13094 std::max(Instruction::GetImmBranchForwardRange(
13095 CompareBranchType),
13096 Instruction::GetImmBranchForwardRange(CondBranchType)));
13097
13098 SETUP();
13099 START();
13100
13101 Label done, fail;
13102 Label test_tbz, test_cbz, test_bcond;
13103 Label success_tbz, success_cbz, success_bcond;
13104
13105 __ Mov(x0, 0);
13106 __ Mov(x1, 1);
13107 __ Mov(x10, 0);
13108
13109 __ Bind(&test_tbz);
13110 __ Tbz(x10, 7, &success_tbz);
13111 __ Bind(&test_cbz);
13112 __ Cbz(x10, &success_cbz);
13113 __ Bind(&test_bcond);
13114 __ Cmp(x10, 0);
13115 __ B(eq, &success_bcond);
13116
13117 // Generate enough code to overflow the immediate range of the three types of
13118 // branches below.
13119 for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) {
13120 if (i % 100 == 0) {
13121 // If we do land in this code, we do not want to execute so many nops
13122 // before reaching the end of test (especially if tracing is activated).
13123 __ B(&fail);
13124 } else {
13125 __ Nop();
13126 }
13127 }
13128 __ B(&fail);
13129
13130 __ Bind(&success_tbz);
13131 __ Orr(x0, x0, 1 << 0);
13132 __ B(&test_cbz);
13133 __ Bind(&success_cbz);
13134 __ Orr(x0, x0, 1 << 1);
13135 __ B(&test_bcond);
13136 __ Bind(&success_bcond);
13137 __ Orr(x0, x0, 1 << 2);
13138
13139 __ B(&done);
13140 __ Bind(&fail);
13141 __ Mov(x1, 0);
13142 __ Bind(&done);
13143
13144 END();
13145 if (CAN_RUN()) {
13146 RUN();
13147
13148 ASSERT_EQUAL_64(0x7, x0);
13149 ASSERT_EQUAL_64(0x1, x1);
13150 }
13151 }
13152
13153
13154 TEST(veneers_stress) {
13155 SETUP();
13156 START();
13157
13158 // This is a code generation test stressing the emission of veneers. The code
13159 // generated is not executed.
13160
13161 Label target;
13162 const unsigned max_range =
13163 Instruction::GetImmBranchForwardRange(CondBranchType);
13164 const unsigned iterations =
13165 (max_range + max_range / 4) / (4 * kInstructionSize);
13166 for (unsigned i = 0; i < iterations; i++) {
13167 __ B(&target);
13168 __ B(eq, &target);
13169 __ Cbz(x0, &target);
13170 __ Tbz(x0, 0, &target);
13171 }
13172 __ Bind(&target);
13173
13174 END();
13175 }
13176
13177
13178 TEST(veneers_two_out_of_range) {
13179 SETUP();
13180 START();
13181
13182 // This is a code generation test. The code generated is not executed.
13183 // Ensure that the MacroAssembler considers unresolved branches to chose when
13184 // a veneer pool should be emitted. We generate two branches that go out of
13185 // range at the same offset. When the MacroAssembler decides to emit the
13186 // veneer pool, the emission of a first veneer should not cause the other
13187 // branch to go out of range.
13188
13189 int range_cbz = Instruction::GetImmBranchForwardRange(CompareBranchType);
13190 int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
13191 int max_target = static_cast<int>(masm.GetCursorOffset()) + range_cbz;
13192
13193 Label done;
13194
13195 // We use different labels to prevent the MacroAssembler from sharing veneers.
13196 Label target_cbz, target_tbz;
13197
13198 __ Cbz(x0, &target_cbz);
13199 while (masm.GetCursorOffset() < max_target - range_tbz) {
13200 __ Nop();
13201 }
13202 __ Tbz(x0, 0, &target_tbz);
13203 while (masm.GetCursorOffset() < max_target) {
13204 __ Nop();
13205 }
13206
13207 // This additional nop makes the branches go out of range.
13208 __ Nop();
13209
13210 __ Bind(&target_cbz);
13211 __ Bind(&target_tbz);
13212
13213 END();
13214 }
13215
13216
13217 TEST(veneers_hanging) {
13218 SETUP();
13219 START();
13220
13221 // This is a code generation test. The code generated is not executed.
13222 // Ensure that the MacroAssembler considers unresolved branches to chose when
13223 // a veneer pool should be emitted. This is similar to the
13224 // 'veneers_two_out_of_range' test. We try to trigger the following situation:
13225 // b.eq label
13226 // b.eq label
13227 // ...
13228 // nop
13229 // ...
13230 // cbz x0, label
13231 // cbz x0, label
13232 // ...
13233 // tbz x0, 0 label
13234 // nop
13235 // ...
13236 // nop <- From here the `b.eq` and `cbz` instructions run out of range,
13237 // so a literal pool is required.
13238 // veneer
13239 // veneer
13240 // veneer <- The `tbz` runs out of range somewhere in the middle of the
13241 // veneer veneer pool.
13242 // veneer
13243
13244 const int range_bcond = Instruction::GetImmBranchForwardRange(CondBranchType);
13245 const int range_cbz =
13246 Instruction::GetImmBranchForwardRange(CompareBranchType);
13247 const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
13248 const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_bcond;
13249
13250 Label done;
13251 const int n_bcond = 100;
13252 const int n_cbz = 100;
13253 const int n_tbz = 1;
13254 const int kNTotalBranches = n_bcond + n_cbz + n_tbz;
13255
13256 // We use different labels to prevent the MacroAssembler from sharing veneers.
13257 Label labels[kNTotalBranches];
13258 for (int i = 0; i < kNTotalBranches; i++) {
13259 new (&labels[i]) Label();
13260 }
13261
13262 for (int i = 0; i < n_bcond; i++) {
13263 __ B(eq, &labels[i]);
13264 }
13265
13266 while (masm.GetCursorOffset() < max_target - range_cbz) {
13267 __ Nop();
13268 }
13269
13270 for (int i = 0; i < n_cbz; i++) {
13271 __ Cbz(x0, &labels[n_bcond + i]);
13272 }
13273
13274 // Ensure the 'tbz' will go out of range after some of the previously
13275 // generated branches.
13276 int margin = (n_bcond / 2) * kInstructionSize;
13277 while (masm.GetCursorOffset() < max_target - range_tbz + margin) {
13278 __ Nop();
13279 }
13280
13281 __ Tbz(x0, 0, &labels[n_bcond + n_cbz]);
13282
13283 while (masm.GetCursorOffset() < max_target) {
13284 __ Nop();
13285 }
13286
13287 // This additional nop makes the 'b.eq' and 'cbz' instructions go out of range
13288 // and forces the emission of a veneer pool. The 'tbz' is not yet out of
13289 // range, but will go out of range while veneers are emitted for the other
13290 // branches.
13291 // The MacroAssembler should ensure that veneers are correctly emitted for all
13292 // the branches, including the 'tbz'. Checks will fail if the target of a
13293 // branch is out of range.
13294 __ Nop();
13295
13296 for (int i = 0; i < kNTotalBranches; i++) {
13297 __ Bind(&labels[i]);
13298 }
13299
13300 END();
13301 }
13302
13303
13304 TEST(collision_literal_veneer_pools) {
13305 SETUP_WITH_FEATURES(CPUFeatures::kFP);
13306 START();
13307
13308 // This is a code generation test. The code generated is not executed.
13309
13310 // Make sure the literal pool is empty;
13311 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13312 ASSERT_LITERAL_POOL_SIZE(0);
13313
13314 // We chose the offsets below to (try to) trigger the following situation:
13315 // buffer offset
13316 // 0: tbz x0, 0, target_tbz ----------------------------------.
13317 // 4: nop |
13318 // ... |
13319 // nop |
13320 // literal gen: ldr s0, [pc + ...] ; load from `pool start + 0` |
13321 // ldr s0, [pc + ...] ; load from `pool start + 4` |
13322 // ... |
13323 // ldr s0, [pc + ...] |
13324 // pool start: floating-point literal (0.1) |
13325 // floating-point literal (1.1) |
13326 // ... |
13327 // floating-point literal (<n>.1) <-----tbz-max-range--'
13328 // floating-point literal (<n+1>.1)
13329 // ...
13330
13331 const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
13332 const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_tbz;
13333
13334 const size_t target_literal_pool_size = 100 * kInstructionSize;
13335 const int offset_start_literal_gen =
13336 target_literal_pool_size + target_literal_pool_size / 2;
13337
13338
13339 Label target_tbz;
13340
13341 __ Tbz(x0, 0, &target_tbz);
13342 VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1);
13343 while (masm.GetCursorOffset() < max_target - offset_start_literal_gen) {
13344 __ Nop();
13345 }
13346 VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1);
13347
13348 for (int i = 0; i < 100; i++) {
13349 // Use a different value to force one literal pool entry per iteration.
13350 __ Ldr(s0, i + 0.1);
13351 }
13352 VIXL_CHECK(masm.GetLiteralPoolSize() >= target_literal_pool_size);
13353
13354 // Force emission of a literal pool.
13355 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13356 ASSERT_LITERAL_POOL_SIZE(0);
13357
13358 // The branch should not have gone out of range during the emission of the
13359 // literal pool.
13360 __ Bind(&target_tbz);
13361
13362 VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 0);
13363
13364 END();
13365 }
13366
13367
13368 TEST(ldr_literal_explicit) {
13369 SETUP();
13370
13371 START();
13372 Literal<int64_t> automatically_placed_literal(1, masm.GetLiteralPool());
13373 Literal<int64_t> manually_placed_literal(2);
13374 {
13375 ExactAssemblyScope scope(&masm, kInstructionSize + sizeof(int64_t));
13376 Label over_literal;
13377 __ b(&over_literal);
13378 __ place(&manually_placed_literal);
13379 __ bind(&over_literal);
13380 }
13381 __ Ldr(x1, &manually_placed_literal);
13382 __ Ldr(x2, &automatically_placed_literal);
13383 __ Add(x0, x1, x2);
13384 END();
13385
13386 if (CAN_RUN()) {
13387 RUN();
13388
13389 ASSERT_EQUAL_64(3, x0);
13390 }
13391 }
13392
13393
13394 TEST(ldr_literal_automatically_placed) {
13395 SETUP_WITH_FEATURES(CPUFeatures::kFP);
13396
13397 START();
13398
13399 // We start with an empty literal pool.
13400 ASSERT_LITERAL_POOL_SIZE(0);
13401
13402 // Create a literal that should be placed by the literal pool.
13403 Literal<int64_t> explicit_literal(2, masm.GetLiteralPool());
13404 // It should not appear in the literal pool until its first use.
13405 ASSERT_LITERAL_POOL_SIZE(0);
13406
13407 // Check that using standard literals does not break the use of explicitly
13408 // created literals.
13409 __ Ldr(d1, 1.1);
13410 ASSERT_LITERAL_POOL_SIZE(8);
13411 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13412 ASSERT_LITERAL_POOL_SIZE(0);
13413
13414 __ Ldr(x2, &explicit_literal);
13415 ASSERT_LITERAL_POOL_SIZE(8);
13416 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13417 ASSERT_LITERAL_POOL_SIZE(0);
13418
13419 __ Ldr(d3, 3.3);
13420 ASSERT_LITERAL_POOL_SIZE(8);
13421 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13422 ASSERT_LITERAL_POOL_SIZE(0);
13423
13424 // Re-use our explicitly created literal. It has already been placed, so it
13425 // should not impact the literal pool.
13426 __ Ldr(x4, &explicit_literal);
13427 ASSERT_LITERAL_POOL_SIZE(0);
13428
13429 END();
13430
13431 if (CAN_RUN()) {
13432 RUN();
13433
13434 ASSERT_EQUAL_FP64(1.1, d1);
13435 ASSERT_EQUAL_64(2, x2);
13436 ASSERT_EQUAL_FP64(3.3, d3);
13437 ASSERT_EQUAL_64(2, x4);
13438 }
13439 }
13440
13441
13442 TEST(literal_update_overwrite) {
13443 SETUP();
13444
13445 START();
13446
13447 ASSERT_LITERAL_POOL_SIZE(0);
13448 LiteralPool* literal_pool = masm.GetLiteralPool();
13449
13450 Literal<int32_t> lit_32_update_before_pool(0xbad, literal_pool);
13451 Literal<int32_t> lit_32_update_after_pool(0xbad, literal_pool);
13452 Literal<int64_t> lit_64_update_before_pool(0xbad, literal_pool);
13453 Literal<int64_t> lit_64_update_after_pool(0xbad, literal_pool);
13454
13455 ASSERT_LITERAL_POOL_SIZE(0);
13456
13457 lit_32_update_before_pool.UpdateValue(32);
13458 lit_64_update_before_pool.UpdateValue(64);
13459
13460 __ Ldr(w1, &lit_32_update_before_pool);
13461 __ Ldr(x2, &lit_64_update_before_pool);
13462 __ Ldr(w3, &lit_32_update_after_pool);
13463 __ Ldr(x4, &lit_64_update_after_pool);
13464
13465 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13466
13467 VIXL_ASSERT(lit_32_update_after_pool.IsPlaced());
13468 VIXL_ASSERT(lit_64_update_after_pool.IsPlaced());
13469 lit_32_update_after_pool.UpdateValue(128, &masm);
13470 lit_64_update_after_pool.UpdateValue(256, &masm);
13471
13472 END();
13473
13474 if (CAN_RUN()) {
13475 RUN();
13476
13477 ASSERT_EQUAL_64(32, x1);
13478 ASSERT_EQUAL_64(64, x2);
13479 ASSERT_EQUAL_64(128, x3);
13480 ASSERT_EQUAL_64(256, x4);
13481 }
13482 }
13483
13484
13485 TEST(literal_deletion_policies) {
13486 SETUP();
13487
13488 START();
13489
13490 // We cannot check exactly when the deletion of the literals occur, but we
13491 // check that usage of the deletion policies is not broken.
13492
13493 ASSERT_LITERAL_POOL_SIZE(0);
13494 LiteralPool* literal_pool = masm.GetLiteralPool();
13495
13496 Literal<int32_t> lit_manual(0xbad, literal_pool);
13497 Literal<int32_t>* lit_deleted_on_placement =
13498 new Literal<int32_t>(0xbad,
13499 literal_pool,
13500 RawLiteral::kDeletedOnPlacementByPool);
13501 Literal<int32_t>* lit_deleted_on_pool_destruction =
13502 new Literal<int32_t>(0xbad,
13503 literal_pool,
13504 RawLiteral::kDeletedOnPoolDestruction);
13505
13506 ASSERT_LITERAL_POOL_SIZE(0);
13507
13508 lit_manual.UpdateValue(32);
13509 lit_deleted_on_placement->UpdateValue(64);
13510
13511 __ Ldr(w1, &lit_manual);
13512 __ Ldr(w2, lit_deleted_on_placement);
13513 __ Ldr(w3, lit_deleted_on_pool_destruction);
13514
13515 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13516
13517 VIXL_ASSERT(lit_manual.IsPlaced());
13518 VIXL_ASSERT(lit_deleted_on_pool_destruction->IsPlaced());
13519 lit_deleted_on_pool_destruction->UpdateValue(128, &masm);
13520
13521 END();
13522
13523 if (CAN_RUN()) {
13524 RUN();
13525
13526 ASSERT_EQUAL_64(32, x1);
13527 ASSERT_EQUAL_64(64, x2);
13528 ASSERT_EQUAL_64(128, x3);
13529 }
13530 }
13531
13532
13533 TEST(generic_operand) {
13534 SETUP_WITH_FEATURES(CPUFeatures::kFP);
13535
13536 int32_t data_32_array[5] = {0xbadbeef,
13537 0x11111111,
13538 0xbadbeef,
13539 0x33333333,
13540 0xbadbeef};
13541 int64_t data_64_array[5] = {INT64_C(0xbadbadbadbeef),
13542 INT64_C(0x1111111111111111),
13543 INT64_C(0xbadbadbadbeef),
13544 INT64_C(0x3333333333333333),
13545 INT64_C(0xbadbadbadbeef)};
13546 size_t size_32 = sizeof(data_32_array[0]);
13547 size_t size_64 = sizeof(data_64_array[0]);
13548
13549 START();
13550
13551 intptr_t data_32_address = reinterpret_cast<intptr_t>(&data_32_array[0]);
13552 intptr_t data_64_address = reinterpret_cast<intptr_t>(&data_64_array[0]);
13553 Register data_32 = x27;
13554 Register data_64 = x28;
13555 __ Mov(data_32, data_32_address);
13556 __ Mov(data_64, data_64_address);
13557
13558 __ Move(GenericOperand(w0),
13559 GenericOperand(MemOperand(data_32, 1 * size_32), size_32));
13560 __ Move(GenericOperand(s0),
13561 GenericOperand(MemOperand(data_32, 3 * size_32), size_32));
13562 __ Move(GenericOperand(x10),
13563 GenericOperand(MemOperand(data_64, 1 * size_64), size_64));
13564 __ Move(GenericOperand(d10),
13565 GenericOperand(MemOperand(data_64, 3 * size_64), size_64));
13566
13567 __ Move(GenericOperand(w1), GenericOperand(w0));
13568 __ Move(GenericOperand(s1), GenericOperand(s0));
13569 __ Move(GenericOperand(x11), GenericOperand(x10));
13570 __ Move(GenericOperand(d11), GenericOperand(d10));
13571
13572 __ Move(GenericOperand(MemOperand(data_32, 0 * size_32), size_32),
13573 GenericOperand(w1));
13574 __ Move(GenericOperand(MemOperand(data_32, 2 * size_32), size_32),
13575 GenericOperand(s1));
13576 __ Move(GenericOperand(MemOperand(data_64, 0 * size_64), size_64),
13577 GenericOperand(x11));
13578 __ Move(GenericOperand(MemOperand(data_64, 2 * size_64), size_64),
13579 GenericOperand(d11));
13580
13581 __ Move(GenericOperand(MemOperand(data_32, 4 * size_32), size_32),
13582 GenericOperand(MemOperand(data_32, 0 * size_32), size_32));
13583 __ Move(GenericOperand(MemOperand(data_64, 4 * size_64), size_64),
13584 GenericOperand(MemOperand(data_64, 0 * size_64), size_64));
13585 END();
13586
13587 if (CAN_RUN()) {
13588 RUN();
13589
13590 ASSERT_EQUAL_64(data_32_address, data_32);
13591 ASSERT_EQUAL_64(data_64_address, data_64);
13592
13593 ASSERT_EQUAL_32(0x11111111, w0);
13594 ASSERT_EQUAL_32(0x33333333, core.sreg_bits(0));
13595 ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x10);
13596 ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(10));
13597
13598 ASSERT_EQUAL_32(0x11111111, w1);
13599 ASSERT_EQUAL_32(0x33333333, core.sreg_bits(1));
13600 ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x11);
13601 ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(11));
13602
13603 VIXL_CHECK(data_32_array[0] == 0x11111111);
13604 VIXL_CHECK(data_32_array[1] == 0x11111111);
13605 VIXL_CHECK(data_32_array[2] == 0x33333333);
13606 VIXL_CHECK(data_32_array[3] == 0x33333333);
13607 VIXL_CHECK(data_32_array[4] == 0x11111111);
13608
13609 VIXL_CHECK(data_64_array[0] == INT64_C(0x1111111111111111));
13610 VIXL_CHECK(data_64_array[1] == INT64_C(0x1111111111111111));
13611 VIXL_CHECK(data_64_array[2] == INT64_C(0x3333333333333333));
13612 VIXL_CHECK(data_64_array[3] == INT64_C(0x3333333333333333));
13613 VIXL_CHECK(data_64_array[4] == INT64_C(0x1111111111111111));
13614 }
13615 }
13616
13617
13618 // Test feature detection of calls to runtime functions.
13619
13620 // C++11 should be sufficient to provide simulated runtime calls, except for a
13621 // GCC bug before 4.9.1.
13622 #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && (__cplusplus >= 201103L) && \
13623 (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1)) && \
13624 !defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT)
13625 #error \
13626 "C++11 should be sufficient to provide support for simulated runtime calls."
13627 #endif // #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && ...
13628
13629 #if (__cplusplus >= 201103L) && \
13630 !defined(VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT)
13631 #error \
13632 "C++11 should be sufficient to provide support for `MacroAssembler::CallRuntime()`."
13633 #endif // #if (__cplusplus >= 201103L) && ...
13634
13635 #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
13636 int32_t runtime_call_add_one(int32_t a) { return a + 1; }
13637
13638 double runtime_call_add_doubles(double a, double b, double c) {
13639 return a + b + c;
13640 }
13641
13642 int64_t runtime_call_one_argument_on_stack(int64_t arg1 __attribute__((unused)),
13643 int64_t arg2 __attribute__((unused)),
13644 int64_t arg3 __attribute__((unused)),
13645 int64_t arg4 __attribute__((unused)),
13646 int64_t arg5 __attribute__((unused)),
13647 int64_t arg6 __attribute__((unused)),
13648 int64_t arg7 __attribute__((unused)),
13649 int64_t arg8 __attribute__((unused)),
13650 int64_t arg9) {
13651 return arg9;
13652 }
13653
13654 double runtime_call_two_arguments_on_stack(int64_t arg1 __attribute__((unused)),
13655 int64_t arg2 __attribute__((unused)),
13656 int64_t arg3 __attribute__((unused)),
13657 int64_t arg4 __attribute__((unused)),
13658 int64_t arg5 __attribute__((unused)),
13659 int64_t arg6 __attribute__((unused)),
13660 int64_t arg7 __attribute__((unused)),
13661 int64_t arg8 __attribute__((unused)),
13662 double arg9,
13663 double arg10) {
13664 return arg9 - arg10;
13665 }
13666
13667 void runtime_call_store_at_address(int64_t* address) { *address = 0xf00d; }
13668
13669 int32_t runtime_call_no_args() { return 1; }
13670
13671 enum RuntimeCallTestEnum { Enum0 };
13672
13673 RuntimeCallTestEnum runtime_call_enum(RuntimeCallTestEnum e) { return e; }
13674
13675 enum class RuntimeCallTestEnumClass { Enum0 };
13676
13677 RuntimeCallTestEnumClass runtime_call_enum_class(RuntimeCallTestEnumClass e) {
13678 return e;
13679 }
13680
13681 int8_t test_int8_t(int8_t x) { return x; }
13682 uint8_t test_uint8_t(uint8_t x) { return x; }
13683 int16_t test_int16_t(int16_t x) { return x; }
13684 uint16_t test_uint16_t(uint16_t x) { return x; }
13685
13686 TEST(runtime_calls) {
13687 SETUP_WITH_FEATURES(CPUFeatures::kFP);
13688
13689 #ifndef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
13690 if (masm.GenerateSimulatorCode()) {
13691 // This configuration is unsupported and a `VIXL_UNREACHABLE()` would fire
13692 // while trying to generate `CallRuntime`. This configuration should only be
13693 // reachable with C++11 and a (buggy) version of GCC pre-4.9.1.
13694 return;
13695 }
13696 #endif
13697
13698 START();
13699
13700 // Test `CallRuntime`.
13701
13702 __ Mov(w0, 0);
13703 __ CallRuntime(runtime_call_add_one);
13704 __ Mov(w20, w0);
13705
13706 __ Fmov(d0, 0.0);
13707 __ Fmov(d1, 1.5);
13708 __ Fmov(d2, 2.5);
13709 __ CallRuntime(runtime_call_add_doubles);
13710 __ Fmov(d20, d0);
13711
13712 __ Mov(x0, 0x123);
13713 __ Push(x0, x0);
13714 __ CallRuntime(runtime_call_one_argument_on_stack);
13715 __ Mov(x21, x0);
13716 __ Pop(x0, x1);
13717
13718 __ Fmov(d0, 314.0);
13719 __ Fmov(d1, 4.0);
13720 __ Push(d1, d0);
13721 __ CallRuntime(runtime_call_two_arguments_on_stack);
13722 __ Fmov(d21, d0);
13723 __ Pop(d1, d0);
13724
13725 // Test that the template mechanisms don't break with enums.
13726 __ Mov(w0, 0);
13727 __ CallRuntime(runtime_call_enum);
13728 __ Mov(w0, 0);
13729 __ CallRuntime(runtime_call_enum_class);
13730
13731 // Test `TailCallRuntime`.
13732
13733 Label function, after_function;
13734 __ B(&after_function);
13735 __ Bind(&function);
13736 __ Mov(x22, 0);
13737 __ Mov(w0, 123);
13738 __ TailCallRuntime(runtime_call_add_one);
13739 // Control should not fall through.
13740 __ Mov(x22, 0xbad);
13741 __ Ret();
13742 __ Bind(&after_function);
13743
13744 // Call our placeholder function, taking care to preserve the link register.
13745 __ Push(ip0, lr);
13746 __ Bl(&function);
13747 __ Pop(lr, ip0);
13748 // Save the result.
13749 __ Mov(w23, w0);
13750
13751 __ Mov(x24, 0);
13752 int test_values[] = {static_cast<int8_t>(-1),
13753 static_cast<uint8_t>(-1),
13754 static_cast<int16_t>(-1),
13755 static_cast<uint16_t>(-1),
13756 -256,
13757 -1,
13758 0,
13759 1,
13760 256};
13761 for (size_t i = 0; i < sizeof(test_values) / sizeof(test_values[0]); ++i) {
13762 Label pass_int8, pass_uint8, pass_int16, pass_uint16;
13763 int x = test_values[i];
13764 __ Mov(w0, x);
13765 __ CallRuntime(test_int8_t);
13766 __ Sxtb(w0, w0);
13767 __ Cmp(w0, ExtractSignedBitfield32(7, 0, x));
13768 __ Cinc(x24, x24, ne);
13769 __ Mov(w0, x);
13770 __ CallRuntime(test_uint8_t);
13771 __ Uxtb(w0, w0);
13772 __ Cmp(w0, ExtractUnsignedBitfield32(7, 0, x));
13773 __ Cinc(x24, x24, ne);
13774 __ Mov(w0, x);
13775 __ CallRuntime(test_int16_t);
13776 __ Sxth(w0, w0);
13777 __ Cmp(w0, ExtractSignedBitfield32(15, 0, x));
13778 __ Cinc(x24, x24, ne);
13779 __ Mov(w0, x);
13780 __ CallRuntime(test_uint16_t);
13781 __ Uxth(w0, w0);
13782 __ Cmp(w0, ExtractUnsignedBitfield32(15, 0, x));
13783 __ Cinc(x24, x24, ne);
13784 }
13785
13786
13787 int64_t value = 0xbadbeef;
13788 __ Mov(x0, reinterpret_cast<uint64_t>(&value));
13789 __ CallRuntime(runtime_call_store_at_address);
13790
13791 __ Mov(w0, 0);
13792 __ CallRuntime(runtime_call_no_args);
13793 __ Mov(w25, w0);
13794
13795 END();
13796
13797 #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || \
13798 !defined(VIXL_INCLUDE_SIMULATOR_AARCH64)
13799 if (CAN_RUN()) {
13800 RUN();
13801
13802 ASSERT_EQUAL_32(1, w20);
13803 ASSERT_EQUAL_FP64(4.0, d20);
13804 ASSERT_EQUAL_64(0x123, x21);
13805 ASSERT_EQUAL_FP64(310.0, d21);
13806 VIXL_CHECK(value == 0xf00d);
13807 ASSERT_EQUAL_64(0, x22);
13808 ASSERT_EQUAL_32(124, w23);
13809 ASSERT_EQUAL_64(0, x24);
13810 ASSERT_EQUAL_32(1, w25);
13811 }
13812 #endif // #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || ...
13813 }
13814
13815 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
13816 void void_func() {}
13817 uint32_t uint32_func() { return 2; }
13818 void void_param_func(uint32_t x) { USE(x); }
13819 uint32_t uint32_param_func(uint32_t x) { return ++x; }
13820
13821 void void_placeholder() {}
13822 uint32_t uint32_placeholder() { return 4; }
13823 void void_param_placeholder(uint32_t x) { USE(x); }
13824 uint32_t uint32_param_placeholder(uint32_t x) { return ++x; }
13825
13826 #define DO_TEST_BRANCH_INTERCEPTION(func) \
13827 __ Mov(x16, reinterpret_cast<uint64_t>(func)); \
13828 __ Blr(x16);
13829
13830 TEST(branch_interception) {
13831 SETUP();
13832 START();
13833
13834 // Test default branch interception, i.e: do a runtime call to the function.
13835 DO_TEST_BRANCH_INTERCEPTION(void_func);
13836 DO_TEST_BRANCH_INTERCEPTION(uint32_func);
13837 __ Mov(w20, w0);
13838 DO_TEST_BRANCH_INTERCEPTION(void_param_func);
13839 __ Mov(w0, 2);
13840 DO_TEST_BRANCH_INTERCEPTION(uint32_param_func);
13841 __ Mov(w21, w0);
13842
13843 // Test interceptions with callbacks.
13844 DO_TEST_BRANCH_INTERCEPTION(void_placeholder);
13845 __ Mov(w22, w0);
13846 DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder);
13847 __ Mov(w23, w0);
13848 __ Mov(w0, 4);
13849 DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder);
13850 __ Mov(w24, w0);
13851 DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder);
13852 __ Mov(w25, w0);
13853
13854 END();
13855
13856 simulator.RegisterBranchInterception(void_func);
13857 simulator.RegisterBranchInterception(uint32_func);
13858 simulator.RegisterBranchInterception(void_param_func);
13859 simulator.RegisterBranchInterception(uint32_param_func);
13860
13861 auto callback = [&simulator](uint64_t original_target) {
13862 USE(original_target);
13863 simulator.WriteWRegister(0, 1);
13864 };
13865
13866 simulator.RegisterBranchInterception(void_placeholder, callback);
13867 simulator.RegisterBranchInterception(uint32_placeholder, callback);
13868 simulator.RegisterBranchInterception(void_param_placeholder, callback);
13869 simulator.RegisterBranchInterception(uint32_param_placeholder, callback);
13870
13871 if (CAN_RUN()) {
13872 RUN();
13873
13874 ASSERT_EQUAL_32(2, w20);
13875 ASSERT_EQUAL_32(3, w21);
13876 ASSERT_EQUAL_32(1, w22);
13877 ASSERT_EQUAL_32(1, w23);
13878 ASSERT_EQUAL_32(1, w24);
13879 ASSERT_EQUAL_32(1, w25);
13880 }
13881 }
13882 #endif // #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
13883 #endif // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
13884
13885
13886 TEST(optimised_mov_register) {
13887 SETUP();
13888
13889 START();
13890 Label start;
13891 __ Bind(&start);
13892 __ Mov(x0, x0);
13893 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0);
13894 __ Mov(w0, w0, kDiscardForSameWReg);
13895 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0);
13896 __ Mov(w0, w0);
13897 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == kInstructionSize);
13898
13899 END();
13900
13901 if (CAN_RUN()) {
13902 RUN();
13903 }
13904 }
13905
13906
13907 TEST(nop) {
13908 MacroAssembler masm;
13909
13910 Label start;
13911 __ Bind(&start);
13912 __ Nop();
13913 // `MacroAssembler::Nop` must generate at least one nop.
13914 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= kInstructionSize);
13915
13916 masm.FinalizeCode();
13917 }
13918
13919
13920 TEST(mte_addg_subg) {
13921 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
13922
13923 START();
13924 __ Mov(x0, 0x5555000055555555);
13925
13926 // Add/subtract an address offset, changing tag each time.
13927 __ Addg(x1, x0, 16, 2);
13928 __ Subg(x2, x1, 16, 1);
13929
13930 // Add/subtract address offsets, keep tag.
13931 __ Addg(x3, x0, 1008, 0);
13932 __ Subg(x4, x3, 1008, 0);
13933
13934 // Change tag only. Check wraparound.
13935 __ Addg(x5, x0, 0, 15);
13936 __ Subg(x6, x0, 0, 14);
13937
13938 // Do nothing.
13939 __ Addg(x7, x0, 0, 0);
13940 __ Subg(x8, x0, 0, 0);
13941
13942 // Use stack pointer as source/destination.
13943 __ Mov(x20, sp); // Store original sp.
13944
13945 __ Subg(sp, sp, 32, 0); // Claim 32 bytes.
13946 __ Sub(x9, sp, x20); // Subtract original sp and store difference.
13947
13948 __ Mov(sp, x20); // Restore original sp.
13949 __ Claim(32);
13950 __ Addg(sp, sp, 32, 0); // Drop 32 bytes.
13951 __ Sub(x10, sp, x20); // Subtract original sp and store difference.
13952
13953 __ Mov(sp, x20); // Restore sp (should be no-op)
13954 __ Addg(sp, sp, 0, 1); // Tag the sp.
13955 __ Sub(x11, sp, x20); // Subtract original sp and store for later comparison.
13956 __ Mov(sp, x20); // Restore sp.
13957
13958 END();
13959
13960 if (CAN_RUN()) {
13961 RUN();
13962
13963 ASSERT_EQUAL_64(0x5755000055555565, x1);
13964 ASSERT_EQUAL_64(0x5855000055555555, x2);
13965 ASSERT_EQUAL_64(0x5555000055555945, x3);
13966 ASSERT_EQUAL_64(0x5555000055555555, x4);
13967 ASSERT_EQUAL_64(0x5455000055555555, x5);
13968 ASSERT_EQUAL_64(0x5355000055555555, x6);
13969 ASSERT_EQUAL_64(0x5555000055555555, x7);
13970 ASSERT_EQUAL_64(0x5555000055555555, x8);
13971 ASSERT_EQUAL_64(-32, x9);
13972 ASSERT_EQUAL_64(0, x10);
13973 ASSERT_EQUAL_64(UINT64_C(1) << 56, x11);
13974 }
13975 }
13976
13977 TEST(mte_subp) {
13978 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
13979
13980 START();
13981 __ Mov(x0, 0x5555555555555555);
13982 __ Mov(x1, -42);
13983
13984 // Test subp with equivalent sbfx/sub(s) operations.
13985 __ Sbfx(x10, x0, 0, 56);
13986 __ Sbfx(x11, x1, 0, 56);
13987
13988 __ Subp(x4, x0, x1);
13989 __ Sub(x5, x10, x11);
13990
13991 __ Subp(x6, x1, x0);
13992 __ Sub(x7, x11, x10);
13993
13994 __ Subps(x8, x0, x1);
13995 __ Mrs(x18, NZCV);
13996 __ Subs(x9, x10, x11);
13997 __ Mrs(x19, NZCV);
13998
13999 __ Cmpp(x1, x0);
14000 __ Mrs(x20, NZCV);
14001 __ Cmp(x11, x10);
14002 __ Mrs(x21, NZCV);
14003
14004 // Test equal pointers with mismatched tags compare equal and produce a zero
14005 // difference with subps.
14006 __ Mov(x2, 0x20); // Exclude tag 5.
14007 __ Irg(x3, x0, x2);
14008 __ Subps(x22, x0, x3);
14009
14010 END();
14011
14012 if (CAN_RUN()) {
14013 RUN();
14014
14015 ASSERT_EQUAL_64(x5, x4);
14016 ASSERT_EQUAL_64(x7, x6);
14017 ASSERT_EQUAL_64(x9, x8);
14018 ASSERT_EQUAL_64(x19, x18);
14019 ASSERT_EQUAL_64(x20, x21);
14020 ASSERT_EQUAL_64(0, x22);
14021 ASSERT_EQUAL_NZCV(ZCFlag);
14022 }
14023 }
14024
14025 TEST(mte_gmi) {
14026 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
14027
14028 START();
14029 __ Mov(x0, 0xaaaa);
14030 __ Mov(x20, 0x12345678);
14031
14032 __ Gmi(x0, x20, x0); // Add mask bit 0.
14033 __ Addg(x20, x20, 0, 1);
14034 __ Gmi(x1, x20, x0); // No effect.
14035 __ Addg(x20, x20, 0, 1);
14036 __ Gmi(x2, x20, x1); // Add mask bit 2.
14037 __ Addg(x20, x20, 0, 1);
14038 __ Gmi(x3, x20, x2); // No effect.
14039 __ Addg(x20, x20, 0, 1);
14040 __ Gmi(x4, x20, x3); // Add mask bit 4.
14041 __ Addg(x20, x20, 0, 1);
14042 __ Gmi(x5, x20, x4); // No effect.
14043 __ Addg(x20, x20, 0, 9);
14044 __ Gmi(x6, x20, x5); // Add mask bit 14.
14045 __ Gmi(x7, x20, xzr); // Only mask bit 14.
14046 END();
14047
14048 if (CAN_RUN()) {
14049 RUN();
14050
14051 ASSERT_EQUAL_64(0xaaab, x0);
14052 ASSERT_EQUAL_64(0xaaab, x1);
14053 ASSERT_EQUAL_64(0xaaaf, x2);
14054 ASSERT_EQUAL_64(0xaaaf, x3);
14055 ASSERT_EQUAL_64(0xaabf, x4);
14056 ASSERT_EQUAL_64(0xaabf, x5);
14057 ASSERT_EQUAL_64(0xeabf, x6);
14058 ASSERT_EQUAL_64(0x4000, x7);
14059 }
14060 }
14061
14062 TEST(mte_irg) {
14063 SETUP_WITH_FEATURES(CPUFeatures::kMTE);
14064
14065 START();
14066 __ Mov(x10, 8);
14067 __ Mov(x0, 0x5555555555555555);
14068 // Insert a random tag repeatedly. If the loop doesn't exit in the expected
14069 // way, it's statistically likely that a random tag was never inserted.
14070 Label loop, failed, done;
14071 __ Bind(&loop);
14072 __ Irg(x1, x0);
14073 __ Sub(x10, x10, 1);
14074 __ Cbz(x10, &failed); // Exit if loop count exceeded.
14075 __ Cmp(x1, 0x5555555555555555);
14076 __ B(eq, &loop); // Loop if the tag hasn't changed.
14077
14078 // Check non-tag bits have not changed.
14079 __ Bic(x1, x1, 0x0f00000000000000);
14080 __ Subs(x1, x1, 0x5055555555555555);
14081 __ B(&done);
14082
14083 __ Bind(&failed);
14084 __ Mov(x1, 1);
14085
14086 __ Bind(&done);
14087
14088 // Insert random tags, excluding oddly-numbered tags, then orr them together.
14089 // After 128 rounds, it's statistically likely that all but the least
14090 // significant bit will be set.
14091 __ Mov(x3, 0);
14092 __ Mov(x10, 128);
14093 __ Mov(x11, 0xaaaa);
14094
14095 Label loop2;
14096 __ Bind(&loop2);
14097 __ Irg(x2, x1, x11);
14098 __ Orr(x3, x3, x2);
14099 __ Subs(x10, x10, 1);
14100 __ B(ne, &loop2);
14101 __ Lsr(x2, x3, 56);
14102
14103 // Check that excluding all tags results in zero tag insertion.
14104 __ Mov(x3, 0xffffffffffffffff);
14105 __ Irg(x3, x3, x3);
14106 END();
14107
14108 if (CAN_RUN()) {
14109 RUN();
14110
14111 ASSERT_EQUAL_64(0, x1);
14112 ASSERT_EQUAL_64(0xe, x2);
14113 ASSERT_EQUAL_64(0xf0ffffffffffffff, x3);
14114 }
14115 }
14116
14117 TEST(mops_set) {
14118 SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14119
14120 uint8_t dst[16];
14121 memset(dst, 0x55, ArrayLength(dst));
14122 uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst);
14123
14124 START();
14125 __ Mov(x0, dst_addr);
14126 __ Add(x1, x0, 1);
14127 __ Mov(x2, 13);
14128 __ Mov(x3, 0x1234aa);
14129
14130 // Set 13 bytes dst[1] onwards to 0xaa.
14131 __ Setp(x1, x2, x3);
14132 __ Setm(x1, x2, x3);
14133 __ Sete(x1, x2, x3);
14134
14135 // x2 is now zero, so this should do nothing.
14136 __ Setp(x1, x2, x3);
14137 __ Setm(x1, x2, x3);
14138 __ Sete(x1, x2, x3);
14139
14140 // Set dst[15] to zero using the masm helper.
14141 __ Add(x1, x0, 15);
14142 __ Mov(x2, 1);
14143 __ Set(x1, x2, xzr);
14144
14145 // Load dst for comparison.
14146 __ Ldp(x10, x11, MemOperand(x0));
14147 END();
14148
14149 if (CAN_RUN()) {
14150 RUN();
14151 ASSERT_EQUAL_64(dst_addr + 16, x1);
14152 ASSERT_EQUAL_64(0, x2);
14153 ASSERT_EQUAL_64(0x1234aa, x3);
14154 ASSERT_EQUAL_64(0xaaaa'aaaa'aaaa'aa55, x10);
14155 ASSERT_EQUAL_64(0x0055'aaaa'aaaa'aaaa, x11);
14156 }
14157 }
14158
14159 TEST(mops_setn) {
14160 SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14161
14162 // In simulation, non-temporal set is handled by the same code as normal set,
14163 // so only a basic test is required beyond that already provided above.
14164
14165 uint8_t dst[16] = {0x55};
14166 uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst);
14167
14168 START();
14169 __ Mov(x0, dst_addr);
14170 __ Mov(x1, x0);
14171 __ Mov(x2, 16);
14172 __ Mov(x3, 0x42);
14173 __ Setn(x1, x2, x3);
14174 __ Ldp(x10, x11, MemOperand(x0));
14175 END();
14176
14177 if (CAN_RUN()) {
14178 RUN();
14179 ASSERT_EQUAL_64(dst_addr + 16, x1);
14180 ASSERT_EQUAL_64(0, x2);
14181 ASSERT_EQUAL_64(0x42, x3);
14182 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x10);
14183 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x11);
14184 }
14185 }
14186
14187 TEST(mops_setg) {
14188 SETUP_WITH_FEATURES(CPUFeatures::kMOPS, CPUFeatures::kMTE);
14189
14190 uint8_t* dst_addr = nullptr;
14191 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14192 const int dst_size = 32;
14193 dst_addr = reinterpret_cast<uint8_t*>(
14194 simulator.Mmap(NULL,
14195 dst_size * sizeof(uint8_t),
14196 PROT_READ | PROT_WRITE | PROT_MTE,
14197 MAP_PRIVATE | MAP_ANONYMOUS,
14198 -1,
14199 0));
14200
14201 VIXL_ASSERT(dst_addr != nullptr);
14202 uint8_t* untagged_ptr = AddressUntag(dst_addr);
14203 memset(untagged_ptr, 0xc9, dst_size);
14204 #else
14205 // TODO: Port the memory allocation to work on MTE supported platform natively.
14206 // Note that `CAN_RUN` prevents running in MTE-unsupported environments.
14207 #endif
14208
14209 START();
14210 __ Mov(x0, reinterpret_cast<uint64_t>(dst_addr));
14211 __ Gmi(x2, x0, xzr);
14212 __ Irg(x1, x0, x2); // Choose new tag for setg destination.
14213 __ Mov(x2, 16);
14214 __ Mov(x3, 0x42);
14215 __ Setg(x1, x2, x3);
14216
14217 __ Ubfx(x4, x1, 56, 4); // Extract new tag.
14218 __ Bfi(x0, x4, 56, 4); // Tag dst_addr so set region can be loaded.
14219 __ Ldp(x10, x11, MemOperand(x0));
14220
14221 __ Mov(x0, reinterpret_cast<uint64_t>(dst_addr));
14222 __ Ldp(x12, x13, MemOperand(x0, 16)); // Unset region has original tag.
14223 END();
14224
14225 if (CAN_RUN()) {
14226 RUN();
14227 ASSERT_EQUAL_64(0, x2);
14228 ASSERT_EQUAL_64(0x42, x3);
14229 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x10);
14230 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x11);
14231 ASSERT_EQUAL_64(0xc9c9'c9c9'c9c9'c9c9, x12);
14232 ASSERT_EQUAL_64(0xc9c9'c9c9'c9c9'c9c9, x13);
14233 }
14234
14235 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14236 simulator.Munmap(dst_addr, dst_size, PROT_MTE);
14237 #endif
14238 }
14239
14240 TEST(mops_cpy) {
14241 SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14242
14243 uint8_t buf[16];
14244 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14245
14246 for (unsigned i = 0; i < ArrayLength(buf); i++) {
14247 buf[i] = i;
14248 }
14249
14250 START();
14251 __ Mov(x0, buf_addr);
14252
14253 // Copy first eight bytes into second eight.
14254 __ Mov(x2, x0); // src = &buf[0]
14255 __ Add(x3, x0, 8); // dst = &buf[8]
14256 __ Mov(x4, 8); // count = 8
14257 __ Cpyp(x3, x2, x4);
14258 __ Cpym(x3, x2, x4);
14259 __ Cpye(x3, x2, x4);
14260 __ Ldp(x10, x11, MemOperand(x0));
14261 __ Mrs(x20, NZCV);
14262
14263 // Copy first eight bytes to overlapping offset, causing reverse copy.
14264 __ Mov(x5, x0); // src = &buf[0]
14265 __ Add(x6, x0, 4); // dst = &buf[4]
14266 __ Mov(x7, 8); // count = 8
14267 __ Cpy(x6, x5, x7);
14268 __ Ldp(x12, x13, MemOperand(x0));
14269 END();
14270
14271 if (CAN_RUN()) {
14272 RUN();
14273 ASSERT_EQUAL_64(buf_addr + 8, x2);
14274 ASSERT_EQUAL_64(buf_addr + 16, x3);
14275 ASSERT_EQUAL_64(0, x4);
14276 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x10);
14277 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x11);
14278 ASSERT_EQUAL_64(CFlag, x20);
14279
14280 ASSERT_EQUAL_64(buf_addr, x5);
14281 ASSERT_EQUAL_64(buf_addr + 4, x6);
14282 ASSERT_EQUAL_64(0, x7);
14283 ASSERT_EQUAL_64(0x0302'0100'0302'0100, x12);
14284 ASSERT_EQUAL_64(0x0706'0504'0706'0504, x13);
14285 ASSERT_EQUAL_NZCV(NCFlag);
14286 }
14287 }
14288
14289 TEST(mops_cpyn) {
14290 SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14291
14292 // In simulation, non-temporal cpy is handled by the same code as normal cpy,
14293 // so only a basic test is required beyond that already provided above.
14294
14295 uint8_t buf[16];
14296 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14297
14298 for (unsigned i = 0; i < ArrayLength(buf); i++) {
14299 buf[i] = i;
14300 }
14301
14302 START();
14303 __ Mov(x0, buf_addr);
14304
14305 __ Add(x2, x0, 1); // src = &buf[1]
14306 __ Mov(x3, x0); // dst = &buf[0]
14307 __ Mov(x4, 15); // count = 15
14308 __ Cpyn(x3, x2, x4);
14309 __ Ldp(x10, x11, MemOperand(x0));
14310
14311 __ Add(x5, x0, 1); // src = &buf[1]
14312 __ Mov(x6, x0); // dst = &buf[0]
14313 __ Mov(x4, 15); // count = 15
14314 __ Cpyrn(x6, x5, x4);
14315 __ Ldp(x12, x13, MemOperand(x0));
14316
14317 __ Add(x7, x0, 1); // src = &buf[1]
14318 __ Mov(x8, x0); // dst = &buf[0]
14319 __ Mov(x4, 15); // count = 15
14320 __ Cpywn(x8, x7, x4);
14321 __ Ldp(x14, x15, MemOperand(x0));
14322 END();
14323
14324 if (CAN_RUN()) {
14325 RUN();
14326 ASSERT_EQUAL_64(buf_addr + 16, x2);
14327 ASSERT_EQUAL_64(buf_addr + 15, x3);
14328 ASSERT_EQUAL_64(0x0807'0605'0403'0201, x10);
14329 ASSERT_EQUAL_64(0x0f0f'0e0d'0c0b'0a09, x11);
14330
14331 ASSERT_EQUAL_64(buf_addr + 16, x5);
14332 ASSERT_EQUAL_64(buf_addr + 15, x6);
14333 ASSERT_EQUAL_64(0x0908'0706'0504'0302, x12);
14334 ASSERT_EQUAL_64(0x0f0f'0f0e'0d0c'0b0a, x13);
14335
14336 ASSERT_EQUAL_64(buf_addr + 16, x7);
14337 ASSERT_EQUAL_64(buf_addr + 15, x8);
14338 ASSERT_EQUAL_64(0x0a09'0807'0605'0403, x14);
14339 ASSERT_EQUAL_64(0x0f0f'0f0f'0e0d'0c0b, x15);
14340
14341 ASSERT_EQUAL_64(0, x4);
14342 ASSERT_EQUAL_NZCV(CFlag);
14343 }
14344 }
14345
14346 TEST(mops_cpyf) {
14347 SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14348
14349 uint8_t buf[16];
14350 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14351
14352 for (unsigned i = 0; i < ArrayLength(buf); i++) {
14353 buf[i] = i;
14354 }
14355
14356 // This test matches the cpy variant above, but using cpyf will result in a
14357 // different answer for the overlapping copy.
14358 START();
14359 __ Mov(x0, buf_addr);
14360
14361 // Copy first eight bytes into second eight.
14362 __ Mov(x2, x0); // src = &buf[0]
14363 __ Add(x3, x0, 8); // dst = &buf[8]
14364 __ Mov(x4, 8); // count = 8
14365 __ Cpyf(x3, x2, x4);
14366 __ Ldp(x10, x11, MemOperand(x0));
14367 __ Mrs(x20, NZCV);
14368
14369 // Copy first eight bytes to overlapping offset.
14370 __ Mov(x5, x0); // src = &buf[0]
14371 __ Add(x6, x0, 4); // dst = &buf[4]
14372 __ Mov(x7, 8); // count = 8
14373 __ Cpyf(x6, x5, x7);
14374 __ Ldp(x12, x13, MemOperand(x0));
14375 END();
14376
14377 if (CAN_RUN()) {
14378 RUN();
14379 ASSERT_EQUAL_64(buf_addr + 8, x2);
14380 ASSERT_EQUAL_64(buf_addr + 16, x3);
14381 ASSERT_EQUAL_64(0, x4);
14382 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x10);
14383 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x11);
14384 ASSERT_EQUAL_64(CFlag, x20);
14385
14386 ASSERT_EQUAL_64(buf_addr + 8, x5);
14387 ASSERT_EQUAL_64(buf_addr + 12, x6);
14388 ASSERT_EQUAL_64(0, x7);
14389 ASSERT_EQUAL_NZCV(CFlag);
14390
14391 // These results are not architecturally defined. They may change if the
14392 // simulator is implemented in a different, but still architecturally
14393 // correct, way.
14394 ASSERT_EQUAL_64(0x0302'0100'0302'0100, x12);
14395 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x13);
14396 }
14397 }
14398
14399 TEST(mops_cpyfn) {
14400 SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14401
14402 // In simulation, non-temporal cpy is handled by the same code as normal cpy,
14403 // so only a basic test is required beyond that already provided above.
14404
14405 uint8_t buf[16];
14406 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14407
14408 for (unsigned i = 0; i < ArrayLength(buf); i++) {
14409 buf[i] = i;
14410 }
14411
14412 START();
14413 __ Mov(x0, buf_addr);
14414
14415 __ Add(x2, x0, 1); // src = &buf[1]
14416 __ Mov(x3, x0); // dst = &buf[0]
14417 __ Mov(x4, 15); // count = 15
14418 __ Cpyfn(x3, x2, x4);
14419 __ Ldp(x10, x11, MemOperand(x0));
14420
14421 __ Add(x5, x0, 1); // src = &buf[1]
14422 __ Mov(x6, x0); // dst = &buf[0]
14423 __ Mov(x4, 15); // count = 15
14424 __ Cpyfrn(x6, x5, x4);
14425 __ Ldp(x12, x13, MemOperand(x0));
14426
14427 __ Add(x7, x0, 1); // src = &buf[1]
14428 __ Mov(x8, x0); // dst = &buf[0]
14429 __ Mov(x4, 15); // count = 15
14430 __ Cpyfwn(x8, x7, x4);
14431 __ Ldp(x14, x15, MemOperand(x0));
14432 END();
14433
14434 if (CAN_RUN()) {
14435 RUN();
14436 ASSERT_EQUAL_64(buf_addr + 16, x2);
14437 ASSERT_EQUAL_64(buf_addr + 15, x3);
14438 ASSERT_EQUAL_64(0x0807'0605'0403'0201, x10);
14439 ASSERT_EQUAL_64(0x0f0f'0e0d'0c0b'0a09, x11);
14440
14441 ASSERT_EQUAL_64(buf_addr + 16, x5);
14442 ASSERT_EQUAL_64(buf_addr + 15, x6);
14443 ASSERT_EQUAL_64(0x0908'0706'0504'0302, x12);
14444 ASSERT_EQUAL_64(0x0f0f'0f0e'0d0c'0b0a, x13);
14445
14446 ASSERT_EQUAL_64(buf_addr + 16, x7);
14447 ASSERT_EQUAL_64(buf_addr + 15, x8);
14448 ASSERT_EQUAL_64(0x0a09'0807'0605'0403, x14);
14449 ASSERT_EQUAL_64(0x0f0f'0f0f'0e0d'0c0b, x15);
14450
14451 ASSERT_EQUAL_64(0, x4);
14452 ASSERT_EQUAL_NZCV(CFlag);
14453 }
14454 }
14455
14456 TEST(cssc_abs) {
14457 SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14458
14459 START();
14460 __ Mov(x0, -1);
14461 __ Mov(x1, 1);
14462 __ Mov(x2, 0);
14463 __ Mov(x3, 0x7fff'ffff);
14464 __ Mov(x4, 0x8000'0000);
14465 __ Mov(x5, 0x8000'0001);
14466 __ Mov(x6, 0x7fff'ffff'ffff'ffff);
14467 __ Mov(x7, 0x8000'0000'0000'0000);
14468 __ Mov(x8, 0x8000'0000'0000'0001);
14469
14470 __ Abs(w10, w0);
14471 __ Abs(x11, x0);
14472 __ Abs(w12, w1);
14473 __ Abs(x13, x1);
14474 __ Abs(w14, w2);
14475 __ Abs(x15, x2);
14476
14477 __ Abs(w19, w3);
14478 __ Abs(x20, x3);
14479 __ Abs(w21, w4);
14480 __ Abs(x22, x4);
14481 __ Abs(w23, w5);
14482 __ Abs(x24, x5);
14483 __ Abs(w25, w6);
14484 __ Abs(x26, x6);
14485 __ Abs(w27, w7);
14486 __ Abs(x28, x7);
14487 __ Abs(w29, w8);
14488 __ Abs(x30, x8);
14489 END();
14490
14491 if (CAN_RUN()) {
14492 RUN();
14493
14494 ASSERT_EQUAL_64(1, x10);
14495 ASSERT_EQUAL_64(1, x11);
14496 ASSERT_EQUAL_64(1, x12);
14497 ASSERT_EQUAL_64(1, x13);
14498 ASSERT_EQUAL_64(0, x14);
14499 ASSERT_EQUAL_64(0, x15);
14500 ASSERT_EQUAL_64(0x7fff'ffff, x19);
14501 ASSERT_EQUAL_64(0x7fff'ffff, x20);
14502 ASSERT_EQUAL_64(0x8000'0000, x21);
14503 ASSERT_EQUAL_64(0x8000'0000, x22);
14504 ASSERT_EQUAL_64(0x7fff'ffff, x23);
14505 ASSERT_EQUAL_64(0x8000'0001, x24);
14506 ASSERT_EQUAL_64(1, x25);
14507 ASSERT_EQUAL_64(0x7fff'ffff'ffff'ffff, x26);
14508 ASSERT_EQUAL_64(0, x27);
14509 ASSERT_EQUAL_64(0x8000'0000'0000'0000, x28);
14510 ASSERT_EQUAL_64(1, x29);
14511 ASSERT_EQUAL_64(0x7fff'ffff'ffff'ffff, x30);
14512 }
14513 }
14514
14515 TEST(cssc_cnt) {
14516 SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14517
14518 START();
14519 __ Mov(x0, -1);
14520 __ Mov(x1, 1);
14521 __ Mov(x2, 0);
14522 __ Mov(x3, 0x7fff'ffff);
14523 __ Mov(x4, 0x8000'0000);
14524 __ Mov(x5, 0x8000'0001);
14525 __ Mov(x6, 0x7fff'ffff'ffff'ffff);
14526 __ Mov(x7, 0x4242'4242'aaaa'aaaa);
14527
14528 __ Cnt(w10, w0);
14529 __ Cnt(x11, x0);
14530 __ Cnt(w12, w1);
14531 __ Cnt(x13, x1);
14532 __ Cnt(w14, w2);
14533 __ Cnt(x15, x2);
14534 __ Cnt(w19, w3);
14535 __ Cnt(x20, x3);
14536 __ Cnt(w21, w4);
14537 __ Cnt(x22, x4);
14538 __ Cnt(w23, w5);
14539 __ Cnt(x24, x5);
14540 __ Cnt(w25, w6);
14541 __ Cnt(x26, x6);
14542 __ Cnt(w27, w7);
14543 __ Cnt(x28, x7);
14544 END();
14545
14546 if (CAN_RUN()) {
14547 RUN();
14548
14549 ASSERT_EQUAL_64(32, x10);
14550 ASSERT_EQUAL_64(64, x11);
14551 ASSERT_EQUAL_64(1, x12);
14552 ASSERT_EQUAL_64(1, x13);
14553 ASSERT_EQUAL_64(0, x14);
14554 ASSERT_EQUAL_64(0, x15);
14555 ASSERT_EQUAL_64(31, x19);
14556 ASSERT_EQUAL_64(31, x20);
14557 ASSERT_EQUAL_64(1, x21);
14558 ASSERT_EQUAL_64(1, x22);
14559 ASSERT_EQUAL_64(2, x23);
14560 ASSERT_EQUAL_64(2, x24);
14561 ASSERT_EQUAL_64(32, x25);
14562 ASSERT_EQUAL_64(63, x26);
14563 ASSERT_EQUAL_64(16, x27);
14564 ASSERT_EQUAL_64(24, x28);
14565 }
14566 }
14567
14568 TEST(cssc_ctz) {
14569 SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14570
14571 START();
14572 __ Mov(x0, -1);
14573 __ Mov(x1, 1);
14574 __ Mov(x2, 2);
14575 __ Mov(x3, 0x7fff'ff00);
14576 __ Mov(x4, 0x8000'4000);
14577 __ Mov(x5, 0x4000'0001);
14578 __ Mov(x6, 0x0000'0001'0000'0000);
14579 __ Mov(x7, 0x4200'0000'0000'0000);
14580
14581 __ Ctz(w10, w0);
14582 __ Ctz(x11, x0);
14583 __ Ctz(w12, w1);
14584 __ Ctz(x13, x1);
14585 __ Ctz(w14, w2);
14586 __ Ctz(x15, x2);
14587 __ Ctz(w19, w3);
14588 __ Ctz(x20, x3);
14589 __ Ctz(w21, w4);
14590 __ Ctz(x22, x4);
14591 __ Ctz(w23, w5);
14592 __ Ctz(x24, x5);
14593 __ Ctz(w25, w6);
14594 __ Ctz(x26, x6);
14595 __ Ctz(w27, w7);
14596 __ Ctz(x28, x7);
14597 END();
14598
14599 if (CAN_RUN()) {
14600 RUN();
14601
14602 ASSERT_EQUAL_64(0, x10);
14603 ASSERT_EQUAL_64(0, x11);
14604 ASSERT_EQUAL_64(0, x12);
14605 ASSERT_EQUAL_64(0, x13);
14606 ASSERT_EQUAL_64(1, x14);
14607 ASSERT_EQUAL_64(1, x15);
14608 ASSERT_EQUAL_64(8, x19);
14609 ASSERT_EQUAL_64(8, x20);
14610 ASSERT_EQUAL_64(14, x21);
14611 ASSERT_EQUAL_64(14, x22);
14612 ASSERT_EQUAL_64(0, x23);
14613 ASSERT_EQUAL_64(0, x24);
14614 ASSERT_EQUAL_64(32, x25);
14615 ASSERT_EQUAL_64(32, x26);
14616 ASSERT_EQUAL_64(32, x27);
14617 ASSERT_EQUAL_64(57, x28);
14618 }
14619 }
14620
14621 using MinMaxOp = void (MacroAssembler::*)(const Register&,
14622 const Register&,
14623 const Operand&);
14624
14625 static void MinMaxHelper(MinMaxOp op,
14626 bool is_signed,
14627 uint64_t a,
14628 uint64_t b,
14629 uint32_t wexp,
14630 uint64_t xexp) {
14631 SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14632
14633 START();
14634 __ Mov(x0, a);
14635 __ Mov(x1, b);
14636 if ((is_signed && IsInt8(b)) || (!is_signed && IsUint8(b))) {
14637 (masm.*op)(w10, w0, b);
14638 (masm.*op)(x11, x0, b);
14639 } else {
14640 (masm.*op)(w10, w0, w1);
14641 (masm.*op)(x11, x0, x1);
14642 }
14643 END();
14644
14645 if (CAN_RUN()) {
14646 RUN();
14647 ASSERT_EQUAL_64(wexp, x10);
14648 ASSERT_EQUAL_64(xexp, x11);
14649 }
14650 }
14651
14652 TEST(cssc_umin) {
14653 MinMaxOp op = &MacroAssembler::Umin;
14654 uint32_t s32min = 0x8000'0000;
14655 uint32_t s32max = 0x7fff'ffff;
14656 uint64_t s64min = 0x8000'0000'0000'0000;
14657 uint64_t s64max = 0x7fff'ffff'ffff'ffff;
14658
14659 MinMaxHelper(op, false, 0, 0, 0, 0);
14660 MinMaxHelper(op, false, 128, 255, 128, 128);
14661 MinMaxHelper(op, false, 0, 0xffff'ffff'ffff'ffff, 0, 0);
14662 MinMaxHelper(op, false, s32max, s32min, s32max, s32max);
14663 MinMaxHelper(op, false, s32min, s32max, s32max, s32max);
14664 MinMaxHelper(op, false, s64max, s32min, s32min, s32min);
14665 MinMaxHelper(op, false, s64min, s64max, 0, s64max);
14666 }
14667
14668 TEST(cssc_umax) {
14669 MinMaxOp op = &MacroAssembler::Umax;
14670 uint32_t s32min = 0x8000'0000;
14671 uint32_t s32max = 0x7fff'ffff;
14672 uint64_t s64min = 0x8000'0000'0000'0000;
14673 uint64_t s64max = 0x7fff'ffff'ffff'ffff;
14674
14675 MinMaxHelper(op, false, 0, 0, 0, 0);
14676 MinMaxHelper(op, false, 128, 255, 255, 255);
14677 MinMaxHelper(op,
14678 false,
14679 0,
14680 0xffff'ffff'ffff'ffff,
14681 0xffff'ffff,
14682 0xffff'ffff'ffff'ffff);
14683 MinMaxHelper(op, false, s32max, s32min, s32min, s32min);
14684 MinMaxHelper(op, false, s32min, s32max, s32min, s32min);
14685 MinMaxHelper(op, false, s64max, s32min, 0xffff'ffff, s64max);
14686 MinMaxHelper(op, false, s64min, s64max, 0xffff'ffff, s64min);
14687 }
14688
14689 TEST(cssc_smin) {
14690 MinMaxOp op = &MacroAssembler::Smin;
14691 uint32_t s32min = 0x8000'0000;
14692 uint32_t s32max = 0x7fff'ffff;
14693 uint64_t s64min = 0x8000'0000'0000'0000;
14694 uint64_t s64max = 0x7fff'ffff'ffff'ffff;
14695
14696 MinMaxHelper(op, true, 0, 0, 0, 0);
14697 MinMaxHelper(op, true, 128, 255, 128, 128);
14698 MinMaxHelper(op,
14699 true,
14700 0,
14701 0xffff'ffff'ffff'ffff,
14702 0xffff'ffff,
14703 0xffff'ffff'ffff'ffff);
14704 MinMaxHelper(op, true, s32max, s32min, s32min, s32max);
14705 MinMaxHelper(op, true, s32min, s32max, s32min, s32max);
14706 MinMaxHelper(op, true, s64max, s32min, s32min, s32min);
14707 MinMaxHelper(op, true, s64min, s64max, 0xffff'ffff, s64min);
14708 }
14709
14710 TEST(cssc_smax) {
14711 MinMaxOp op = &MacroAssembler::Smax;
14712 uint32_t s32min = 0x8000'0000;
14713 uint32_t s32max = 0x7fff'ffff;
14714 uint64_t s64min = 0x8000'0000'0000'0000;
14715 uint64_t s64max = 0x7fff'ffff'ffff'ffff;
14716
14717 MinMaxHelper(op, true, 0, 0, 0, 0);
14718 MinMaxHelper(op, true, 128, 255, 255, 255);
14719 MinMaxHelper(op, true, 0, 0xffff'ffff'ffff'ffff, 0, 0);
14720 MinMaxHelper(op, true, s32max, s32min, s32max, s32min);
14721 MinMaxHelper(op, true, s32min, s32max, s32max, s32min);
14722 MinMaxHelper(op, true, s64max, s32min, 0xffff'ffff, s64max);
14723 MinMaxHelper(op, true, s64min, s64max, 0, s64max);
14724 }
14725
14726 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14727 // Test the pseudo-instructions that control CPUFeatures dynamically in the
14728 // Simulator. These are used by the test infrastructure itself, but in a fairly
14729 // limited way.
14730
14731 static void RunHelperWithFeatureCombinations(
14732 void (*helper)(const CPUFeatures& base, const CPUFeatures& f)) {
14733 // Iterate, testing the first n features in this list.
14734 CPUFeatures::Feature features[] = {
14735 // Put kNone first, so that the first iteration uses an empty feature set.
14736 CPUFeatures::kNone,
14737 // The remaining features used are arbitrary.
14738 CPUFeatures::kIDRegisterEmulation,
14739 CPUFeatures::kDCPoP,
14740 CPUFeatures::kPAuth,
14741 CPUFeatures::kFcma,
14742 CPUFeatures::kAES,
14743 CPUFeatures::kNEON,
14744 CPUFeatures::kCRC32,
14745 CPUFeatures::kFP,
14746 CPUFeatures::kPmull1Q,
14747 CPUFeatures::kSM4,
14748 CPUFeatures::kSM3,
14749 CPUFeatures::kDotProduct,
14750 };
14751 VIXL_ASSERT(CPUFeatures(CPUFeatures::kNone) == CPUFeatures::None());
14752 // The features are not necessarily encoded in kInstructionSize-sized slots,
14753 // so the MacroAssembler must pad the list to align the following instruction.
14754 // Ensure that we have enough features in the list to cover all interesting
14755 // alignment cases, even if the highest common factor of kInstructionSize and
14756 // an encoded feature is one.
14757 VIXL_STATIC_ASSERT(ARRAY_SIZE(features) > kInstructionSize);
14758
14759 CPUFeatures base = CPUFeatures::None();
14760 for (size_t i = 0; i < ARRAY_SIZE(features); i++) {
14761 base.Combine(features[i]);
14762 CPUFeatures f = CPUFeatures::None();
14763 for (size_t j = 0; j < ARRAY_SIZE(features); j++) {
14764 f.Combine(features[j]);
14765 helper(base, f);
14766 }
14767 }
14768 }
14769
14770 static void SetSimulatorCPUFeaturesHelper(const CPUFeatures& base,
14771 const CPUFeatures& f) {
14772 SETUP_WITH_FEATURES(base);
14773 START();
14774
14775 __ SetSimulatorCPUFeatures(f);
14776
14777 END();
14778 if (CAN_RUN()) {
14779 RUN_WITHOUT_SEEN_FEATURE_CHECK();
14780 VIXL_CHECK(*(simulator.GetCPUFeatures()) == f);
14781 }
14782 }
14783
14784 TEST(configure_cpu_features_set) {
14785 RunHelperWithFeatureCombinations(SetSimulatorCPUFeaturesHelper);
14786 }
14787
14788 static void EnableSimulatorCPUFeaturesHelper(const CPUFeatures& base,
14789 const CPUFeatures& f) {
14790 SETUP_WITH_FEATURES(base);
14791 START();
14792
14793 __ EnableSimulatorCPUFeatures(f);
14794
14795 END();
14796 if (CAN_RUN()) {
14797 RUN_WITHOUT_SEEN_FEATURE_CHECK();
14798 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.With(f));
14799 }
14800 }
14801
14802 TEST(configure_cpu_features_enable) {
14803 RunHelperWithFeatureCombinations(EnableSimulatorCPUFeaturesHelper);
14804 }
14805
14806 static void DisableSimulatorCPUFeaturesHelper(const CPUFeatures& base,
14807 const CPUFeatures& f) {
14808 SETUP_WITH_FEATURES(base);
14809 START();
14810
14811 __ DisableSimulatorCPUFeatures(f);
14812
14813 END();
14814 if (CAN_RUN()) {
14815 RUN_WITHOUT_SEEN_FEATURE_CHECK();
14816 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.Without(f));
14817 }
14818 }
14819
14820 TEST(configure_cpu_features_disable) {
14821 RunHelperWithFeatureCombinations(DisableSimulatorCPUFeaturesHelper);
14822 }
14823
14824 static void SaveRestoreSimulatorCPUFeaturesHelper(const CPUFeatures& base,
14825 const CPUFeatures& f) {
14826 SETUP_WITH_FEATURES(base);
14827 START();
14828
14829 {
14830 __ SaveSimulatorCPUFeatures();
14831 __ SetSimulatorCPUFeatures(f);
14832 {
14833 __ SaveSimulatorCPUFeatures();
14834 __ SetSimulatorCPUFeatures(CPUFeatures::All());
14835 __ RestoreSimulatorCPUFeatures();
14836 }
14837 __ RestoreSimulatorCPUFeatures();
14838 }
14839
14840 END();
14841 if (CAN_RUN()) {
14842 RUN_WITHOUT_SEEN_FEATURE_CHECK();
14843 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base);
14844 }
14845 }
14846
14847 TEST(configure_cpu_features_save_restore) {
14848 RunHelperWithFeatureCombinations(SaveRestoreSimulatorCPUFeaturesHelper);
14849 }
14850
14851 static void SimulationCPUFeaturesScopeHelper(const CPUFeatures& base,
14852 const CPUFeatures& f) {
14853 SETUP_WITH_FEATURES(base);
14854 START();
14855
14856 {
14857 SimulationCPUFeaturesScope scope_a(&masm, f);
14858 {
14859 SimulationCPUFeaturesScope scope_b(&masm, CPUFeatures::All());
14860 {
14861 SimulationCPUFeaturesScope scope_c(&masm, CPUFeatures::None());
14862 // The scope arguments should combine with 'Enable', so we should be
14863 // able to use any CPUFeatures here.
14864 __ Fadd(v0.V4S(), v1.V4S(), v2.V4S()); // Requires {FP, NEON}.
14865 }
14866 }
14867 }
14868
14869 END();
14870 if (CAN_RUN()) {
14871 RUN_WITHOUT_SEEN_FEATURE_CHECK();
14872 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base);
14873 }
14874 }
14875
14876 TEST(configure_cpu_features_scope) {
14877 RunHelperWithFeatureCombinations(SimulationCPUFeaturesScopeHelper);
14878 }
14879 #endif
14880
14881
14882 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14883 TEST(large_sim_stack) {
14884 SimStack builder;
14885 builder.SetUsableSize(16 * 1024); // The default is 8kB.
14886 SimStack::Allocated stack = builder.Allocate();
14887 uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
14888 uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
14889 SETUP_CUSTOM_SIM(std::move(stack));
14890 START();
14891
14892 // Check that we can access the extremes of the stack.
14893 __ Mov(x0, base);
14894 __ Mov(x1, limit);
14895 __ Mov(x2, sp);
14896 __ Add(sp, x1, 1); // Avoid accessing memory below `sp`.
14897
14898 __ Mov(x10, 42);
14899 __ Poke(x10, 0);
14900 __ Peek(x10, base - limit - kXRegSizeInBytes - 1);
14901
14902 __ Mov(sp, x2);
14903
14904 END();
14905 if (CAN_RUN()) {
14906 RUN();
14907 }
14908 }
14909
14910 #ifdef VIXL_NEGATIVE_TESTING
14911 TEST(sim_stack_limit_guard_read) {
14912 SimStack builder;
14913 SimStack::Allocated stack = builder.Allocate();
14914 uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
14915 SETUP_CUSTOM_SIM(std::move(stack));
14916 START();
14917
14918 __ Mov(x1, limit);
14919 __ Mov(x2, sp);
14920 __ Add(sp, x1, 1); // Avoid accessing memory below `sp`.
14921
14922 // `sp` points to the lowest usable byte of the stack.
14923 __ Mov(w10, 42);
14924 __ Ldrb(w10, MemOperand(sp, -1));
14925
14926 __ Mov(sp, x2);
14927
14928 END();
14929 if (CAN_RUN()) {
14930 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
14931 }
14932 }
14933
14934 TEST(sim_stack_limit_guard_write) {
14935 SimStack builder;
14936 SimStack::Allocated stack = builder.Allocate();
14937 uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
14938 SETUP_CUSTOM_SIM(std::move(stack));
14939 START();
14940
14941 __ Mov(x1, limit);
14942 __ Mov(x2, sp);
14943 __ Add(sp, x1, 1); // Avoid accessing memory below `sp`.
14944
14945 // `sp` points to the lowest usable byte of the stack.
14946 __ Mov(w10, 42);
14947 __ Strb(w10, MemOperand(sp, -1));
14948
14949 __ Mov(sp, x2);
14950
14951 END();
14952 if (CAN_RUN()) {
14953 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
14954 }
14955 }
14956
14957 TEST(sim_stack_base_guard_read) {
14958 SimStack builder;
14959 SimStack::Allocated stack = builder.Allocate();
14960 uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
14961 SETUP_CUSTOM_SIM(std::move(stack));
14962 START();
14963
14964 __ Mov(x0, base);
14965 // `base` (x0) is the byte after the highest usable byte of the stack.
14966 // The last byte of this access will hit the guard region.
14967 __ Mov(x10, 42);
14968 __ Ldr(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
14969
14970 END();
14971 if (CAN_RUN()) {
14972 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
14973 }
14974 }
14975
14976 TEST(sim_stack_base_guard_write) {
14977 SimStack builder;
14978 SimStack::Allocated stack = builder.Allocate();
14979 uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
14980 SETUP_CUSTOM_SIM(std::move(stack));
14981 START();
14982
14983 __ Mov(x0, base);
14984 // `base` (x0) is the byte after the highest usable byte of the stack.
14985 // The last byte of this access will hit the guard region.
14986 __ Mov(x10, 42);
14987 __ Str(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
14988
14989 END();
14990 if (CAN_RUN()) {
14991 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
14992 }
14993 }
14994 #endif
14995 #endif
14996
14997 TEST(scalar_movi) {
14998 SETUP_WITH_FEATURES(CPUFeatures::kFP, CPUFeatures::kNEON);
14999 START();
15000
15001 // Make sure that V0 is initialized to a non-zero value.
15002 __ Movi(v0.V16B(), 0xFF);
15003 // This constant value can't be encoded in a MOVI instruction,
15004 // so the program would use a fallback path that must set the
15005 // upper 64 bits of the destination vector to 0.
15006 __ Movi(v0.V1D(), 0xDECAFC0FFEE);
15007 __ Mov(x0, v0.V2D(), 1);
15008
15009 END();
15010
15011 if (CAN_RUN()) {
15012 RUN();
15013
15014 ASSERT_EQUAL_64(0, x0);
15015 }
15016 }
15017
15018 } // namespace aarch64
15019 } // namespace vixl
15020