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
45namespace vixl {
46namespace aarch64 {
47
48TEST(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
119TEST(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
174TEST(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
219TEST(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
252TEST(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
318TEST(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
405TEST(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
455TEST(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
491TEST(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
522TEST(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
549TEST(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
585TEST(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
616TEST(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
652TEST(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
683TEST(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
750TEST(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
798TEST(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
829TEST(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
895TEST(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
930TEST(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
961TEST(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
997TEST(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
1028TEST(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
1084static 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
1098TEST(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
1108TEST(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
1177TEST(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
1246TEST(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
1294TEST(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
1342TEST(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
1381TEST(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
1416TEST(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
1498TEST(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
1527typedef void (MacroAssembler::*TestBranchSignature)(const Register& rt,
1528                                                    unsigned bit_pos,
1529                                                    Label* label);
1530
1531static 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
1583TEST(test_branch_limits_literal_pool_size_tbz) {
1584  TbzRangePoolLimitHelper(&MacroAssembler::Tbz);
1585}
1586
1587TEST(test_branch_limits_literal_pool_size_tbnz) {
1588  TbzRangePoolLimitHelper(&MacroAssembler::Tbnz);
1589}
1590
1591TEST(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
1631TEST(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
1691TEST(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
1749TEST(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
1809TEST(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
1867TEST(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
1919TEST(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
1948TEST(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
1986TEST(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
2026TEST(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.
2074TEST(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
2138static 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.
2217TEST(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
2227static 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.
2274TEST(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
2286TEST(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
2385TEST(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
2436TEST(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
2490TEST(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
2537TEST(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
2590TEST(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
2624TEST(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
2659TEST(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
2713TEST(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
2785TEST(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
2835TEST(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
2889enum MTEStgAttribute {
2890  StgNoSideEffect = 0,
2891  StgPairTag = 1,
2892  StgZeroing = 2,
2893  StgPairReg = 4
2894};
2895
2896// Support st2g, stg, stz2g and stzg.
2897template <typename Op>
2898static 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
3084TEST(st2g_ldg) {
3085  MTEStoreTagHelper(&MacroAssembler::St2g, Offset, StgPairTag);
3086  MTEStoreTagHelper(&MacroAssembler::St2g, PreIndex, StgPairTag);
3087  MTEStoreTagHelper(&MacroAssembler::St2g, PostIndex, StgPairTag);
3088}
3089
3090TEST(stg_ldg) {
3091  MTEStoreTagHelper(&MacroAssembler::Stg, Offset);
3092  MTEStoreTagHelper(&MacroAssembler::Stg, PreIndex);
3093  MTEStoreTagHelper(&MacroAssembler::Stg, PostIndex);
3094}
3095
3096TEST(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
3102TEST(stzg_ldg) {
3103  MTEStoreTagHelper(&MacroAssembler::Stzg, Offset, StgZeroing);
3104  MTEStoreTagHelper(&MacroAssembler::Stzg, PreIndex, StgZeroing);
3105  MTEStoreTagHelper(&MacroAssembler::Stzg, PostIndex, StgZeroing);
3106}
3107
3108TEST(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
3256TEST(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
3298TEST(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
3346TEST(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
3404TEST(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
3462TEST(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
3507TEST(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
3544TEST(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
3591TEST(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
3637TEST(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
3663TEST(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
3718TEST(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
3776TEST(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
3853TEST(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
3908TEST(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
3971TEST(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
4027TEST(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
4091TEST(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
4111TEST(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
4155TEST(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
4194TEST(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
4221TEST(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
4282template <typename T>
4283void 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
4312TEST(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
4324TEST(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
4336TEST(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
4425TEST(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
4510static 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
4531TEST(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
4569TEST(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
4625TEST(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
4655TEST(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
4703TEST(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
4724TEST(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
4839TEST(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
4895TEST(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
4934TEST(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
4986TEST(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
5056TEST(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
5101TEST(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
5138TEST(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
5159TEST(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
5207template <typename T, typename Op>
5208static 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
5237TEST(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
5427TEST(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
5617TEST(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
5688TEST(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
5787TEST(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
5834TEST(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
5872TEST(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
5933TEST(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
6106TEST(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
6161TEST(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
6213TEST(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
6264TEST(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
6288TEST(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
6331TEST(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
6396TEST(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
6457TEST(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
6491TEST(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
6544TEST(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
6600TEST(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
6658TEST(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
6716TEST(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
6772TEST(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
6815TEST(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
6877TEST(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
6933TEST(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
6968TEST(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
7006TEST(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
7044TEST(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
7073TEST(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
7134TEST(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
7224TEST(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
7324TEST(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
7424TEST(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
7469TEST(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
7489static 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
7523TEST(bti) {
7524  BtiHelper(x16);
7525  BtiHelper(x17);
7526}
7527
7528TEST(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
7568TEST(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
7594TEST(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
7618TEST(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
7642TEST(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
7665TEST(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
7689TEST(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
7718TEST(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
7788TEST(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
7864TEST(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
7886TEST(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
7953TEST(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
8032TEST(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
8081TEST(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
8155TEST(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
8246TEST(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.
8363enum 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).
8375static 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.
8386static 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
8519TEST(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
8568TEST(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).
8618static 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.
8629static 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
8770TEST(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
8819TEST(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.
8870static 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
8959TEST(push_pop_xreg_mixed_methods_64) {
8960  for (int claim = 0; claim <= 8; claim++) {
8961    PushPopMixedMethodsHelper(claim, kXRegSize);
8962  }
8963}
8964
8965
8966TEST(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.
8974static 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
9164TEST(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
9175TEST(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
9267TEST(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
9380TEST(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
9512TEST(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
9532TEST(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
9551TEST(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
9580TEST(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
9639TEST(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
9692TEST(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
9747TEST(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
9848TEST(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
9949TEST(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.
10054TEST(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.
10138TEST(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
10219TEST(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
10287TEST(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
10355TEST(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
10423TEST(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
10491TEST(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
10587TEST(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
10734typedef void (MacroAssembler::*AtomicMemoryLoadSignature)(
10735    const Register& rs, const Register& rt, const MemOperand& src);
10736typedef void (MacroAssembler::*AtomicMemoryStoreSignature)(
10737    const Register& rs, const MemOperand& src);
10738
10739void 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
10806void 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
10894TEST(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
10917TEST(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
10935TEST(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
10953TEST(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
10971TEST(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
10989TEST(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
11007TEST(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
11025TEST(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
11043TEST(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
11070TEST(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
11106TEST(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
11152TEST(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
11212TEST(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
11259TEST(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
11475TEST(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
11609TEST(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
11642TEST(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
11853TEST(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
12024TEST(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
12190TEST(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
12313TEST(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
12344TEST(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
12375TEST(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
12411TEST(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
12452TEST(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
12475TEST(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
12491TEST(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
12515TEST(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
12531TEST(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
12547TEST(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.
12571TEST(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
12615TEST(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
12659TEST(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
12698TEST(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
12737TEST(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
12781TEST(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
12825TEST(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
12864TEST(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
12902TEST(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
12919TEST(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
12970TEST(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
13045TEST(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
13089TEST(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
13154TEST(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
13178TEST(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
13217TEST(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
13304TEST(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
13368TEST(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
13394TEST(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
13442TEST(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
13485TEST(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
13533TEST(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
13636int32_t runtime_call_add_one(int32_t a) { return a + 1; }
13637
13638double runtime_call_add_doubles(double a, double b, double c) {
13639  return a + b + c;
13640}
13641
13642int64_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
13654double 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
13667void runtime_call_store_at_address(int64_t* address) { *address = 0xf00d; }
13668
13669int32_t runtime_call_no_args() { return 1; }
13670
13671enum RuntimeCallTestEnum { Enum0 };
13672
13673RuntimeCallTestEnum runtime_call_enum(RuntimeCallTestEnum e) { return e; }
13674
13675enum class RuntimeCallTestEnumClass { Enum0 };
13676
13677RuntimeCallTestEnumClass runtime_call_enum_class(RuntimeCallTestEnumClass e) {
13678  return e;
13679}
13680
13681int8_t test_int8_t(int8_t x) { return x; }
13682uint8_t test_uint8_t(uint8_t x) { return x; }
13683int16_t test_int16_t(int16_t x) { return x; }
13684uint16_t test_uint16_t(uint16_t x) { return x; }
13685
13686TEST(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
13816void void_func() {}
13817uint32_t uint32_func() { return 2; }
13818void void_param_func(uint32_t x) { USE(x); }
13819uint32_t uint32_param_func(uint32_t x) { return ++x; }
13820
13821void void_placeholder() {}
13822uint32_t uint32_placeholder() { return 4; }
13823void void_param_placeholder(uint32_t x) { USE(x); }
13824uint32_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
13830TEST(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
13886TEST(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
13907TEST(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
13920TEST(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
13977TEST(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
14025TEST(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
14062TEST(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
14117TEST(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
14159TEST(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
14187TEST(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
14240TEST(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
14289TEST(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
14346TEST(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
14399TEST(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
14456TEST(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
14515TEST(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
14568TEST(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
14621using MinMaxOp = void (MacroAssembler::*)(const Register&,
14622                                          const Register&,
14623                                          const Operand&);
14624
14625static 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
14652TEST(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
14668TEST(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
14689TEST(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
14710TEST(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
14731static 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
14770static 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
14784TEST(configure_cpu_features_set) {
14785  RunHelperWithFeatureCombinations(SetSimulatorCPUFeaturesHelper);
14786}
14787
14788static 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
14802TEST(configure_cpu_features_enable) {
14803  RunHelperWithFeatureCombinations(EnableSimulatorCPUFeaturesHelper);
14804}
14805
14806static 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
14820TEST(configure_cpu_features_disable) {
14821  RunHelperWithFeatureCombinations(DisableSimulatorCPUFeaturesHelper);
14822}
14823
14824static 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
14847TEST(configure_cpu_features_save_restore) {
14848  RunHelperWithFeatureCombinations(SaveRestoreSimulatorCPUFeaturesHelper);
14849}
14850
14851static 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
14876TEST(configure_cpu_features_scope) {
14877  RunHelperWithFeatureCombinations(SimulationCPUFeaturesScopeHelper);
14878}
14879#endif
14880
14881
14882#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14883TEST(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
14911TEST(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
14934TEST(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
14957TEST(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
14976TEST(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
14997TEST(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