• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include "test-assembler-aarch64.h"
28 
29 #include <cfloat>
30 #include <cmath>
31 #include <cstdio>
32 #include <cstdlib>
33 #include <cstring>
34 #include <sys/mman.h>
35 
36 #include "test-runner.h"
37 #include "test-utils.h"
38 
39 #include "aarch64/cpu-aarch64.h"
40 #include "aarch64/disasm-aarch64.h"
41 #include "aarch64/macro-assembler-aarch64.h"
42 #include "aarch64/simulator-aarch64.h"
43 #include "aarch64/test-utils-aarch64.h"
44 
45 namespace vixl {
46 namespace aarch64 {
47 
TEST(preshift_immediates)48 TEST(preshift_immediates) {
49   SETUP();
50 
51   START();
52   // Test operations involving immediates that could be generated using a
53   // pre-shifted encodable immediate followed by a post-shift applied to
54   // the arithmetic or logical operation.
55 
56   // Save sp.
57   __ Mov(x29, sp);
58 
59   // Set the registers to known values.
60   __ Mov(x0, 0x1000);
61   __ Mov(sp, 0x1004);
62 
63   // Arithmetic ops.
64   __ Add(x1, x0, 0x1f7de);
65   __ Add(w2, w0, 0xffffff1);
66   __ Adds(x3, x0, 0x18001);
67   __ Adds(w4, w0, 0xffffff1);
68   __ Sub(x5, x0, 0x1f7de);
69   __ Sub(w6, w0, 0xffffff1);
70   __ Subs(x7, x0, 0x18001);
71   __ Subs(w8, w0, 0xffffff1);
72 
73   // Logical ops.
74   __ And(x9, x0, 0x1f7de);
75   __ Orr(w10, w0, 0xffffff1);
76   __ Eor(x11, x0, 0x18001);
77 
78   // Ops using the stack pointer.
79   __ Add(sp, sp, 0x18001);
80   __ Mov(x12, sp);
81   __ Mov(sp, 0x1004);
82 
83   __ Add(sp, sp, 0x1f7de);
84   __ Mov(x13, sp);
85   __ Mov(sp, 0x1004);
86 
87   __ Adds(x14, sp, 0x1f7de);
88 
89   __ Orr(sp, x0, 0x1f7de);
90   __ Mov(x15, sp);
91 
92   //  Restore sp.
93   __ Mov(sp, x29);
94   END();
95 
96   if (CAN_RUN()) {
97     RUN();
98 
99     ASSERT_EQUAL_64(0x1000, x0);
100     ASSERT_EQUAL_64(0x207de, x1);
101     ASSERT_EQUAL_64(0x10000ff1, x2);
102     ASSERT_EQUAL_64(0x19001, x3);
103     ASSERT_EQUAL_64(0x10000ff1, x4);
104     ASSERT_EQUAL_64(0xfffffffffffe1822, x5);
105     ASSERT_EQUAL_64(0xf000100f, x6);
106     ASSERT_EQUAL_64(0xfffffffffffe8fff, x7);
107     ASSERT_EQUAL_64(0xf000100f, x8);
108     ASSERT_EQUAL_64(0x1000, x9);
109     ASSERT_EQUAL_64(0xffffff1, x10);
110     ASSERT_EQUAL_64(0x19001, x11);
111     ASSERT_EQUAL_64(0x19005, x12);
112     ASSERT_EQUAL_64(0x207e2, x13);
113     ASSERT_EQUAL_64(0x207e2, x14);
114     ASSERT_EQUAL_64(0x1f7de, x15);
115   }
116 }
117 
118 
TEST(stack_ops)119 TEST(stack_ops) {
120   SETUP();
121 
122   START();
123   // save sp.
124   __ Mov(x29, sp);
125 
126   // Set the sp to a known value.
127   __ Mov(sp, 0x1004);
128   __ Mov(x0, sp);
129 
130   // Add immediate to the sp, and move the result to a normal register.
131   __ Add(sp, sp, 0x50);
132   __ Mov(x1, sp);
133 
134   // Add extended to the sp, and move the result to a normal register.
135   __ Mov(x17, 0xfff);
136   __ Add(sp, sp, Operand(x17, SXTB));
137   __ Mov(x2, sp);
138 
139   // Create an sp using a logical instruction, and move to normal register.
140   __ Orr(sp, xzr, 0x1fff);
141   __ Mov(x3, sp);
142 
143   // Write wsp using a logical instruction.
144   __ Orr(wsp, wzr, 0xfffffff8);
145   __ Mov(x4, sp);
146 
147   // Write sp, and read back wsp.
148   __ Orr(sp, xzr, 0xfffffff8);
149   __ Mov(w5, wsp);
150 
151   // Test writing into wsp in cases where the immediate isn't encodable.
152   VIXL_ASSERT(!Assembler::IsImmLogical(0x1234, kWRegSize));
153   __ Orr(wsp, w5, 0x1234);
154   __ Mov(w6, wsp);
155 
156   //  restore sp.
157   __ Mov(sp, x29);
158   END();
159 
160   if (CAN_RUN()) {
161     RUN();
162 
163     ASSERT_EQUAL_64(0x1004, x0);
164     ASSERT_EQUAL_64(0x1054, x1);
165     ASSERT_EQUAL_64(0x1053, x2);
166     ASSERT_EQUAL_64(0x1fff, x3);
167     ASSERT_EQUAL_64(0xfffffff8, x4);
168     ASSERT_EQUAL_64(0xfffffff8, x5);
169     ASSERT_EQUAL_64(0xfffffffc, x6);
170   }
171 }
172 
173 
TEST(mvn)174 TEST(mvn) {
175   SETUP();
176 
177   START();
178   __ Mvn(w0, 0xfff);
179   __ Mvn(x1, 0xfff);
180   __ Mvn(w2, Operand(w0, LSL, 1));
181   __ Mvn(x3, Operand(x1, LSL, 2));
182   __ Mvn(w4, Operand(w0, LSR, 3));
183   __ Mvn(x5, Operand(x1, LSR, 4));
184   __ Mvn(w6, Operand(w0, ASR, 11));
185   __ Mvn(x7, Operand(x1, ASR, 12));
186   __ Mvn(w8, Operand(w0, ROR, 13));
187   __ Mvn(x9, Operand(x1, ROR, 14));
188   __ Mvn(w10, Operand(w2, UXTB));
189   __ Mvn(x11, Operand(x2, SXTB, 1));
190   __ Mvn(w12, Operand(w2, UXTH, 2));
191   __ Mvn(x13, Operand(x2, SXTH, 3));
192   __ Mvn(x14, Operand(w2, UXTW, 4));
193   __ Mvn(x15, Operand(w2, SXTW, 4));
194   END();
195 
196   if (CAN_RUN()) {
197     RUN();
198 
199     ASSERT_EQUAL_64(0xfffff000, x0);
200     ASSERT_EQUAL_64(0xfffffffffffff000, x1);
201     ASSERT_EQUAL_64(0x00001fff, x2);
202     ASSERT_EQUAL_64(0x0000000000003fff, x3);
203     ASSERT_EQUAL_64(0xe00001ff, x4);
204     ASSERT_EQUAL_64(0xf0000000000000ff, x5);
205     ASSERT_EQUAL_64(0x00000001, x6);
206     ASSERT_EQUAL_64(0x0000000000000000, x7);
207     ASSERT_EQUAL_64(0x7ff80000, x8);
208     ASSERT_EQUAL_64(0x3ffc000000000000, x9);
209     ASSERT_EQUAL_64(0xffffff00, x10);
210     ASSERT_EQUAL_64(0x0000000000000001, x11);
211     ASSERT_EQUAL_64(0xffff8003, x12);
212     ASSERT_EQUAL_64(0xffffffffffff0007, x13);
213     ASSERT_EQUAL_64(0xfffffffffffe000f, x14);
214     ASSERT_EQUAL_64(0xfffffffffffe000f, x15);
215   }
216 }
217 
218 
TEST(mov_imm_w)219 TEST(mov_imm_w) {
220   SETUP();
221 
222   START();
223   __ Mov(w0, 0xffffffff);
224   __ Mov(w1, 0xffff1234);
225   __ Mov(w2, 0x1234ffff);
226   __ Mov(w3, 0x00000000);
227   __ Mov(w4, 0x00001234);
228   __ Mov(w5, 0x12340000);
229   __ Mov(w6, 0x12345678);
230   __ Mov(w7, (int32_t)0x80000000);
231   __ Mov(w8, (int32_t)0xffff0000);
232   __ Mov(w9, kWMinInt);
233   END();
234 
235   if (CAN_RUN()) {
236     RUN();
237 
238     ASSERT_EQUAL_64(0xffffffff, x0);
239     ASSERT_EQUAL_64(0xffff1234, x1);
240     ASSERT_EQUAL_64(0x1234ffff, x2);
241     ASSERT_EQUAL_64(0x00000000, x3);
242     ASSERT_EQUAL_64(0x00001234, x4);
243     ASSERT_EQUAL_64(0x12340000, x5);
244     ASSERT_EQUAL_64(0x12345678, x6);
245     ASSERT_EQUAL_64(0x80000000, x7);
246     ASSERT_EQUAL_64(0xffff0000, x8);
247     ASSERT_EQUAL_32(kWMinInt, w9);
248   }
249 }
250 
251 
TEST(mov_imm_x)252 TEST(mov_imm_x) {
253   SETUP();
254 
255   START();
256   __ Mov(x0, 0xffffffffffffffff);
257   __ Mov(x1, 0xffffffffffff1234);
258   __ Mov(x2, 0xffffffff12345678);
259   __ Mov(x3, 0xffff1234ffff5678);
260   __ Mov(x4, 0x1234ffffffff5678);
261   __ Mov(x5, 0x1234ffff5678ffff);
262   __ Mov(x6, 0x12345678ffffffff);
263   __ Mov(x7, 0x1234ffffffffffff);
264   __ Mov(x8, 0x123456789abcffff);
265   __ Mov(x9, 0x12345678ffff9abc);
266   __ Mov(x10, 0x1234ffff56789abc);
267   __ Mov(x11, 0xffff123456789abc);
268   __ Mov(x12, 0x0000000000000000);
269   __ Mov(x13, 0x0000000000001234);
270   __ Mov(x14, 0x0000000012345678);
271   __ Mov(x15, 0x0000123400005678);
272   __ Mov(x18, 0x1234000000005678);
273   __ Mov(x19, 0x1234000056780000);
274   __ Mov(x20, 0x1234567800000000);
275   __ Mov(x21, 0x1234000000000000);
276   __ Mov(x22, 0x123456789abc0000);
277   __ Mov(x23, 0x1234567800009abc);
278   __ Mov(x24, 0x1234000056789abc);
279   __ Mov(x25, 0x0000123456789abc);
280   __ Mov(x26, 0x123456789abcdef0);
281   __ Mov(x27, 0xffff000000000001);
282   __ Mov(x28, 0x8000ffff00000000);
283   END();
284 
285   if (CAN_RUN()) {
286     RUN();
287 
288     ASSERT_EQUAL_64(0xffffffffffff1234, x1);
289     ASSERT_EQUAL_64(0xffffffff12345678, x2);
290     ASSERT_EQUAL_64(0xffff1234ffff5678, x3);
291     ASSERT_EQUAL_64(0x1234ffffffff5678, x4);
292     ASSERT_EQUAL_64(0x1234ffff5678ffff, x5);
293     ASSERT_EQUAL_64(0x12345678ffffffff, x6);
294     ASSERT_EQUAL_64(0x1234ffffffffffff, x7);
295     ASSERT_EQUAL_64(0x123456789abcffff, x8);
296     ASSERT_EQUAL_64(0x12345678ffff9abc, x9);
297     ASSERT_EQUAL_64(0x1234ffff56789abc, x10);
298     ASSERT_EQUAL_64(0xffff123456789abc, x11);
299     ASSERT_EQUAL_64(0x0000000000000000, x12);
300     ASSERT_EQUAL_64(0x0000000000001234, x13);
301     ASSERT_EQUAL_64(0x0000000012345678, x14);
302     ASSERT_EQUAL_64(0x0000123400005678, x15);
303     ASSERT_EQUAL_64(0x1234000000005678, x18);
304     ASSERT_EQUAL_64(0x1234000056780000, x19);
305     ASSERT_EQUAL_64(0x1234567800000000, x20);
306     ASSERT_EQUAL_64(0x1234000000000000, x21);
307     ASSERT_EQUAL_64(0x123456789abc0000, x22);
308     ASSERT_EQUAL_64(0x1234567800009abc, x23);
309     ASSERT_EQUAL_64(0x1234000056789abc, x24);
310     ASSERT_EQUAL_64(0x0000123456789abc, x25);
311     ASSERT_EQUAL_64(0x123456789abcdef0, x26);
312     ASSERT_EQUAL_64(0xffff000000000001, x27);
313     ASSERT_EQUAL_64(0x8000ffff00000000, x28);
314   }
315 }
316 
317 
TEST(mov)318 TEST(mov) {
319   SETUP();
320 
321   START();
322   __ Mov(x0, 0xffffffffffffffff);
323   __ Mov(x1, 0xffffffffffffffff);
324   __ Mov(x2, 0xffffffffffffffff);
325   __ Mov(x3, 0xffffffffffffffff);
326 
327   __ Mov(x0, 0x0123456789abcdef);
328 
329   {
330     ExactAssemblyScope scope(&masm, 3 * kInstructionSize);
331     __ movz(x1, UINT64_C(0xabcd) << 16);
332     __ movk(x2, UINT64_C(0xabcd) << 32);
333     __ movn(x3, UINT64_C(0xabcd) << 48);
334   }
335 
336   __ Mov(x4, 0x0123456789abcdef);
337   __ Mov(x5, x4);
338 
339   __ Mov(w6, -1);
340 
341   // Test that moves back to the same register have the desired effect. This
342   // is a no-op for X registers, and a truncation for W registers.
343   __ Mov(x7, 0x0123456789abcdef);
344   __ Mov(x7, x7);
345   __ Mov(x8, 0x0123456789abcdef);
346   __ Mov(w8, w8);
347   __ Mov(x9, 0x0123456789abcdef);
348   __ Mov(x9, Operand(x9));
349   __ Mov(x10, 0x0123456789abcdef);
350   __ Mov(w10, Operand(w10));
351 
352   __ Mov(w11, 0xfff);
353   __ Mov(x12, 0xfff);
354   __ Mov(w13, Operand(w11, LSL, 1));
355   __ Mov(x14, Operand(x12, LSL, 2));
356   __ Mov(w15, Operand(w11, LSR, 3));
357   __ Mov(x18, Operand(x12, LSR, 4));
358   __ Mov(w19, Operand(w11, ASR, 11));
359   __ Mov(x20, Operand(x12, ASR, 12));
360   __ Mov(w21, Operand(w11, ROR, 13));
361   __ Mov(x22, Operand(x12, ROR, 14));
362   __ Mov(w23, Operand(w13, UXTB));
363   __ Mov(x24, Operand(x13, SXTB, 1));
364   __ Mov(w25, Operand(w13, UXTH, 2));
365   __ Mov(x26, Operand(x13, SXTH, 3));
366   __ Mov(x27, Operand(w13, UXTW, 4));
367 
368   __ Mov(x28, 0x0123456789abcdef);
369   __ Mov(w28, w28, kDiscardForSameWReg);
370   END();
371 
372   if (CAN_RUN()) {
373     RUN();
374 
375     ASSERT_EQUAL_64(0x0123456789abcdef, x0);
376     ASSERT_EQUAL_64(0x00000000abcd0000, x1);
377     ASSERT_EQUAL_64(0xffffabcdffffffff, x2);
378     ASSERT_EQUAL_64(0x5432ffffffffffff, x3);
379     ASSERT_EQUAL_64(x4, x5);
380     ASSERT_EQUAL_32(-1, w6);
381     ASSERT_EQUAL_64(0x0123456789abcdef, x7);
382     ASSERT_EQUAL_32(0x89abcdef, w8);
383     ASSERT_EQUAL_64(0x0123456789abcdef, x9);
384     ASSERT_EQUAL_32(0x89abcdef, w10);
385     ASSERT_EQUAL_64(0x00000fff, x11);
386     ASSERT_EQUAL_64(0x0000000000000fff, x12);
387     ASSERT_EQUAL_64(0x00001ffe, x13);
388     ASSERT_EQUAL_64(0x0000000000003ffc, x14);
389     ASSERT_EQUAL_64(0x000001ff, x15);
390     ASSERT_EQUAL_64(0x00000000000000ff, x18);
391     ASSERT_EQUAL_64(0x00000001, x19);
392     ASSERT_EQUAL_64(0x0000000000000000, x20);
393     ASSERT_EQUAL_64(0x7ff80000, x21);
394     ASSERT_EQUAL_64(0x3ffc000000000000, x22);
395     ASSERT_EQUAL_64(0x000000fe, x23);
396     ASSERT_EQUAL_64(0xfffffffffffffffc, x24);
397     ASSERT_EQUAL_64(0x00007ff8, x25);
398     ASSERT_EQUAL_64(0x000000000000fff0, x26);
399     ASSERT_EQUAL_64(0x000000000001ffe0, x27);
400     ASSERT_EQUAL_64(0x0123456789abcdef, x28);
401   }
402 }
403 
404 
TEST(mov_negative)405 TEST(mov_negative) {
406   SETUP();
407 
408   START();
409   __ Mov(w11, 0xffffffff);
410   __ Mov(x12, 0xffffffffffffffff);
411 
412   __ Mov(w13, Operand(w11, LSL, 1));
413   __ Mov(w14, Operand(w11, LSR, 1));
414   __ Mov(w15, Operand(w11, ASR, 1));
415   __ Mov(w18, Operand(w11, ROR, 1));
416   __ Mov(w19, Operand(w11, UXTB, 1));
417   __ Mov(w20, Operand(w11, SXTB, 1));
418   __ Mov(w21, Operand(w11, UXTH, 1));
419   __ Mov(w22, Operand(w11, SXTH, 1));
420 
421   __ Mov(x23, Operand(x12, LSL, 1));
422   __ Mov(x24, Operand(x12, LSR, 1));
423   __ Mov(x25, Operand(x12, ASR, 1));
424   __ Mov(x26, Operand(x12, ROR, 1));
425   __ Mov(x27, Operand(x12, UXTH, 1));
426   __ Mov(x28, Operand(x12, SXTH, 1));
427   __ Mov(x29, Operand(x12, UXTW, 1));
428   __ Mov(x30, Operand(x12, SXTW, 1));
429   END();
430 
431   if (CAN_RUN()) {
432     RUN();
433 
434     ASSERT_EQUAL_64(0xfffffffe, x13);
435     ASSERT_EQUAL_64(0x7fffffff, x14);
436     ASSERT_EQUAL_64(0xffffffff, x15);
437     ASSERT_EQUAL_64(0xffffffff, x18);
438     ASSERT_EQUAL_64(0x000001fe, x19);
439     ASSERT_EQUAL_64(0xfffffffe, x20);
440     ASSERT_EQUAL_64(0x0001fffe, x21);
441     ASSERT_EQUAL_64(0xfffffffe, x22);
442 
443     ASSERT_EQUAL_64(0xfffffffffffffffe, x23);
444     ASSERT_EQUAL_64(0x7fffffffffffffff, x24);
445     ASSERT_EQUAL_64(0xffffffffffffffff, x25);
446     ASSERT_EQUAL_64(0xffffffffffffffff, x26);
447     ASSERT_EQUAL_64(0x000000000001fffe, x27);
448     ASSERT_EQUAL_64(0xfffffffffffffffe, x28);
449     ASSERT_EQUAL_64(0x00000001fffffffe, x29);
450     ASSERT_EQUAL_64(0xfffffffffffffffe, x30);
451   }
452 }
453 
454 
TEST(orr)455 TEST(orr) {
456   SETUP();
457 
458   START();
459   __ Mov(x0, 0xf0f0);
460   __ Mov(x1, 0xf00000ff);
461 
462   __ Orr(x2, x0, Operand(x1));
463   __ Orr(w3, w0, Operand(w1, LSL, 28));
464   __ Orr(x4, x0, Operand(x1, LSL, 32));
465   __ Orr(x5, x0, Operand(x1, LSR, 4));
466   __ Orr(w6, w0, Operand(w1, ASR, 4));
467   __ Orr(x7, x0, Operand(x1, ASR, 4));
468   __ Orr(w8, w0, Operand(w1, ROR, 12));
469   __ Orr(x9, x0, Operand(x1, ROR, 12));
470   __ Orr(w10, w0, 0xf);
471   __ Orr(x11, x0, 0xf0000000f0000000);
472   END();
473 
474   if (CAN_RUN()) {
475     RUN();
476 
477     ASSERT_EQUAL_64(0x00000000f000f0ff, x2);
478     ASSERT_EQUAL_64(0xf000f0f0, x3);
479     ASSERT_EQUAL_64(0xf00000ff0000f0f0, x4);
480     ASSERT_EQUAL_64(0x000000000f00f0ff, x5);
481     ASSERT_EQUAL_64(0xff00f0ff, x6);
482     ASSERT_EQUAL_64(0x000000000f00f0ff, x7);
483     ASSERT_EQUAL_64(0x0ffff0f0, x8);
484     ASSERT_EQUAL_64(0x0ff00000000ff0f0, x9);
485     ASSERT_EQUAL_64(0x0000f0ff, x10);
486     ASSERT_EQUAL_64(0xf0000000f000f0f0, x11);
487   }
488 }
489 
490 
TEST(orr_extend)491 TEST(orr_extend) {
492   SETUP();
493 
494   START();
495   __ Mov(x0, 1);
496   __ Mov(x1, 0x8000000080008080);
497   __ Orr(w6, w0, Operand(w1, UXTB));
498   __ Orr(x7, x0, Operand(x1, UXTH, 1));
499   __ Orr(w8, w0, Operand(w1, UXTW, 2));
500   __ Orr(x9, x0, Operand(x1, UXTX, 3));
501   __ Orr(w10, w0, Operand(w1, SXTB));
502   __ Orr(x11, x0, Operand(x1, SXTH, 1));
503   __ Orr(x12, x0, Operand(x1, SXTW, 2));
504   __ Orr(x13, x0, Operand(x1, SXTX, 3));
505   END();
506 
507   if (CAN_RUN()) {
508     RUN();
509 
510     ASSERT_EQUAL_64(0x00000081, x6);
511     ASSERT_EQUAL_64(0x0000000000010101, x7);
512     ASSERT_EQUAL_64(0x00020201, x8);
513     ASSERT_EQUAL_64(0x0000000400040401, x9);
514     ASSERT_EQUAL_64(0xffffff81, x10);
515     ASSERT_EQUAL_64(0xffffffffffff0101, x11);
516     ASSERT_EQUAL_64(0xfffffffe00020201, x12);
517     ASSERT_EQUAL_64(0x0000000400040401, x13);
518   }
519 }
520 
521 
TEST(bitwise_wide_imm)522 TEST(bitwise_wide_imm) {
523   SETUP();
524 
525   START();
526   __ Mov(x0, 0);
527   __ Mov(x1, 0xf0f0f0f0f0f0f0f0);
528 
529   __ Orr(x10, x0, 0x1234567890abcdef);
530   __ Orr(w11, w1, 0x90abcdef);
531 
532   __ Orr(w12, w0, kWMinInt);
533   __ Eor(w13, w0, kWMinInt);
534   END();
535 
536   if (CAN_RUN()) {
537     RUN();
538 
539     ASSERT_EQUAL_64(0, x0);
540     ASSERT_EQUAL_64(0xf0f0f0f0f0f0f0f0, x1);
541     ASSERT_EQUAL_64(0x1234567890abcdef, x10);
542     ASSERT_EQUAL_64(0x00000000f0fbfdff, x11);
543     ASSERT_EQUAL_32(kWMinInt, w12);
544     ASSERT_EQUAL_32(kWMinInt, w13);
545   }
546 }
547 
548 
TEST(orn)549 TEST(orn) {
550   SETUP();
551 
552   START();
553   __ Mov(x0, 0xf0f0);
554   __ Mov(x1, 0xf00000ff);
555 
556   __ Orn(x2, x0, Operand(x1));
557   __ Orn(w3, w0, Operand(w1, LSL, 4));
558   __ Orn(x4, x0, Operand(x1, LSL, 4));
559   __ Orn(x5, x0, Operand(x1, LSR, 1));
560   __ Orn(w6, w0, Operand(w1, ASR, 1));
561   __ Orn(x7, x0, Operand(x1, ASR, 1));
562   __ Orn(w8, w0, Operand(w1, ROR, 16));
563   __ Orn(x9, x0, Operand(x1, ROR, 16));
564   __ Orn(w10, w0, 0x0000ffff);
565   __ Orn(x11, x0, 0x0000ffff0000ffff);
566   END();
567 
568   if (CAN_RUN()) {
569     RUN();
570 
571     ASSERT_EQUAL_64(0xffffffff0ffffff0, x2);
572     ASSERT_EQUAL_64(0xfffff0ff, x3);
573     ASSERT_EQUAL_64(0xfffffff0fffff0ff, x4);
574     ASSERT_EQUAL_64(0xffffffff87fffff0, x5);
575     ASSERT_EQUAL_64(0x07fffff0, x6);
576     ASSERT_EQUAL_64(0xffffffff87fffff0, x7);
577     ASSERT_EQUAL_64(0xff00ffff, x8);
578     ASSERT_EQUAL_64(0xff00ffffffffffff, x9);
579     ASSERT_EQUAL_64(0xfffff0f0, x10);
580     ASSERT_EQUAL_64(0xffff0000fffff0f0, x11);
581   }
582 }
583 
584 
TEST(orn_extend)585 TEST(orn_extend) {
586   SETUP();
587 
588   START();
589   __ Mov(x0, 1);
590   __ Mov(x1, 0x8000000080008081);
591   __ Orn(w6, w0, Operand(w1, UXTB));
592   __ Orn(x7, x0, Operand(x1, UXTH, 1));
593   __ Orn(w8, w0, Operand(w1, UXTW, 2));
594   __ Orn(x9, x0, Operand(x1, UXTX, 3));
595   __ Orn(w10, w0, Operand(w1, SXTB));
596   __ Orn(x11, x0, Operand(x1, SXTH, 1));
597   __ Orn(x12, x0, Operand(x1, SXTW, 2));
598   __ Orn(x13, x0, Operand(x1, SXTX, 3));
599   END();
600 
601   if (CAN_RUN()) {
602     RUN();
603 
604     ASSERT_EQUAL_64(0xffffff7f, x6);
605     ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
606     ASSERT_EQUAL_64(0xfffdfdfb, x8);
607     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
608     ASSERT_EQUAL_64(0x0000007f, x10);
609     ASSERT_EQUAL_64(0x000000000000fefd, x11);
610     ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
611     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
612   }
613 }
614 
615 
TEST(and_)616 TEST(and_) {
617   SETUP();
618 
619   START();
620   __ Mov(x0, 0xfff0);
621   __ Mov(x1, 0xf00000ff);
622 
623   __ And(x2, x0, Operand(x1));
624   __ And(w3, w0, Operand(w1, LSL, 4));
625   __ And(x4, x0, Operand(x1, LSL, 4));
626   __ And(x5, x0, Operand(x1, LSR, 1));
627   __ And(w6, w0, Operand(w1, ASR, 20));
628   __ And(x7, x0, Operand(x1, ASR, 20));
629   __ And(w8, w0, Operand(w1, ROR, 28));
630   __ And(x9, x0, Operand(x1, ROR, 28));
631   __ And(w10, w0, Operand(0xff00));
632   __ And(x11, x0, Operand(0xff));
633   END();
634 
635   if (CAN_RUN()) {
636     RUN();
637 
638     ASSERT_EQUAL_64(0x000000f0, x2);
639     ASSERT_EQUAL_64(0x00000ff0, x3);
640     ASSERT_EQUAL_64(0x00000ff0, x4);
641     ASSERT_EQUAL_64(0x00000070, x5);
642     ASSERT_EQUAL_64(0x0000ff00, x6);
643     ASSERT_EQUAL_64(0x00000f00, x7);
644     ASSERT_EQUAL_64(0x00000ff0, x8);
645     ASSERT_EQUAL_64(0x00000000, x9);
646     ASSERT_EQUAL_64(0x0000ff00, x10);
647     ASSERT_EQUAL_64(0x000000f0, x11);
648   }
649 }
650 
651 
TEST(and_extend)652 TEST(and_extend) {
653   SETUP();
654 
655   START();
656   __ Mov(x0, 0xffffffffffffffff);
657   __ Mov(x1, 0x8000000080008081);
658   __ And(w6, w0, Operand(w1, UXTB));
659   __ And(x7, x0, Operand(x1, UXTH, 1));
660   __ And(w8, w0, Operand(w1, UXTW, 2));
661   __ And(x9, x0, Operand(x1, UXTX, 3));
662   __ And(w10, w0, Operand(w1, SXTB));
663   __ And(x11, x0, Operand(x1, SXTH, 1));
664   __ And(x12, x0, Operand(x1, SXTW, 2));
665   __ And(x13, x0, Operand(x1, SXTX, 3));
666   END();
667 
668   if (CAN_RUN()) {
669     RUN();
670 
671     ASSERT_EQUAL_64(0x00000081, x6);
672     ASSERT_EQUAL_64(0x0000000000010102, x7);
673     ASSERT_EQUAL_64(0x00020204, x8);
674     ASSERT_EQUAL_64(0x0000000400040408, x9);
675     ASSERT_EQUAL_64(0xffffff81, x10);
676     ASSERT_EQUAL_64(0xffffffffffff0102, x11);
677     ASSERT_EQUAL_64(0xfffffffe00020204, x12);
678     ASSERT_EQUAL_64(0x0000000400040408, x13);
679   }
680 }
681 
682 
TEST(ands)683 TEST(ands) {
684   SETUP();
685 
686   START();
687   __ Mov(x1, 0xf00000ff);
688   __ Ands(w0, w1, Operand(w1));
689   END();
690 
691   if (CAN_RUN()) {
692     RUN();
693 
694     ASSERT_EQUAL_NZCV(NFlag);
695     ASSERT_EQUAL_64(0xf00000ff, x0);
696   }
697 
698   START();
699   __ Mov(x0, 0xfff0);
700   __ Mov(x1, 0xf00000ff);
701   __ Ands(w0, w0, Operand(w1, LSR, 4));
702   END();
703 
704   if (CAN_RUN()) {
705     RUN();
706 
707     ASSERT_EQUAL_NZCV(ZFlag);
708     ASSERT_EQUAL_64(0x00000000, x0);
709   }
710 
711   START();
712   __ Mov(x0, 0x8000000000000000);
713   __ Mov(x1, 0x00000001);
714   __ Ands(x0, x0, Operand(x1, ROR, 1));
715   END();
716 
717   if (CAN_RUN()) {
718     RUN();
719 
720     ASSERT_EQUAL_NZCV(NFlag);
721     ASSERT_EQUAL_64(0x8000000000000000, x0);
722   }
723 
724   START();
725   __ Mov(x0, 0xfff0);
726   __ Ands(w0, w0, Operand(0xf));
727   END();
728 
729   if (CAN_RUN()) {
730     RUN();
731 
732     ASSERT_EQUAL_NZCV(ZFlag);
733     ASSERT_EQUAL_64(0x00000000, x0);
734   }
735 
736   START();
737   __ Mov(x0, 0xff000000);
738   __ Ands(w0, w0, Operand(0x80000000));
739   END();
740 
741   if (CAN_RUN()) {
742     RUN();
743 
744     ASSERT_EQUAL_NZCV(NFlag);
745     ASSERT_EQUAL_64(0x80000000, x0);
746   }
747 }
748 
749 
TEST(bic)750 TEST(bic) {
751   SETUP();
752 
753   START();
754   __ Mov(x0, 0xfff0);
755   __ Mov(x1, 0xf00000ff);
756 
757   __ Bic(x2, x0, Operand(x1));
758   __ Bic(w3, w0, Operand(w1, LSL, 4));
759   __ Bic(x4, x0, Operand(x1, LSL, 4));
760   __ Bic(x5, x0, Operand(x1, LSR, 1));
761   __ Bic(w6, w0, Operand(w1, ASR, 20));
762   __ Bic(x7, x0, Operand(x1, ASR, 20));
763   __ Bic(w8, w0, Operand(w1, ROR, 28));
764   __ Bic(x9, x0, Operand(x1, ROR, 24));
765   __ Bic(x10, x0, Operand(0x1f));
766   __ Bic(x11, x0, Operand(0x100));
767 
768   // Test bic into sp when the constant cannot be encoded in the immediate
769   // field.
770   // Use x20 to preserve sp. We check for the result via x21 because the
771   // test infrastructure requires that sp be restored to its original value.
772   __ Mov(x20, sp);
773   __ Mov(x0, 0xffffff);
774   __ Bic(sp, x0, Operand(0xabcdef));
775   __ Mov(x21, sp);
776   __ Mov(sp, x20);
777   END();
778 
779   if (CAN_RUN()) {
780     RUN();
781 
782     ASSERT_EQUAL_64(0x0000ff00, x2);
783     ASSERT_EQUAL_64(0x0000f000, x3);
784     ASSERT_EQUAL_64(0x0000f000, x4);
785     ASSERT_EQUAL_64(0x0000ff80, x5);
786     ASSERT_EQUAL_64(0x000000f0, x6);
787     ASSERT_EQUAL_64(0x0000f0f0, x7);
788     ASSERT_EQUAL_64(0x0000f000, x8);
789     ASSERT_EQUAL_64(0x0000ff00, x9);
790     ASSERT_EQUAL_64(0x0000ffe0, x10);
791     ASSERT_EQUAL_64(0x0000fef0, x11);
792 
793     ASSERT_EQUAL_64(0x543210, x21);
794   }
795 }
796 
797 
TEST(bic_extend)798 TEST(bic_extend) {
799   SETUP();
800 
801   START();
802   __ Mov(x0, 0xffffffffffffffff);
803   __ Mov(x1, 0x8000000080008081);
804   __ Bic(w6, w0, Operand(w1, UXTB));
805   __ Bic(x7, x0, Operand(x1, UXTH, 1));
806   __ Bic(w8, w0, Operand(w1, UXTW, 2));
807   __ Bic(x9, x0, Operand(x1, UXTX, 3));
808   __ Bic(w10, w0, Operand(w1, SXTB));
809   __ Bic(x11, x0, Operand(x1, SXTH, 1));
810   __ Bic(x12, x0, Operand(x1, SXTW, 2));
811   __ Bic(x13, x0, Operand(x1, SXTX, 3));
812   END();
813 
814   if (CAN_RUN()) {
815     RUN();
816 
817     ASSERT_EQUAL_64(0xffffff7e, x6);
818     ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
819     ASSERT_EQUAL_64(0xfffdfdfb, x8);
820     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
821     ASSERT_EQUAL_64(0x0000007e, x10);
822     ASSERT_EQUAL_64(0x000000000000fefd, x11);
823     ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
824     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
825   }
826 }
827 
828 
TEST(bics)829 TEST(bics) {
830   SETUP();
831 
832   START();
833   __ Mov(x1, 0xffff);
834   __ Bics(w0, w1, Operand(w1));
835   END();
836 
837   if (CAN_RUN()) {
838     RUN();
839 
840     ASSERT_EQUAL_NZCV(ZFlag);
841     ASSERT_EQUAL_64(0x00000000, x0);
842   }
843 
844   START();
845   __ Mov(x0, 0xffffffff);
846   __ Bics(w0, w0, Operand(w0, LSR, 1));
847   END();
848 
849   if (CAN_RUN()) {
850     RUN();
851 
852     ASSERT_EQUAL_NZCV(NFlag);
853     ASSERT_EQUAL_64(0x80000000, x0);
854   }
855 
856   START();
857   __ Mov(x0, 0x8000000000000000);
858   __ Mov(x1, 0x00000001);
859   __ Bics(x0, x0, Operand(x1, ROR, 1));
860   END();
861 
862   if (CAN_RUN()) {
863     RUN();
864 
865     ASSERT_EQUAL_NZCV(ZFlag);
866     ASSERT_EQUAL_64(0x00000000, x0);
867   }
868 
869   START();
870   __ Mov(x0, 0xffffffffffffffff);
871   __ Bics(x0, x0, 0x7fffffffffffffff);
872   END();
873 
874   if (CAN_RUN()) {
875     RUN();
876 
877     ASSERT_EQUAL_NZCV(NFlag);
878     ASSERT_EQUAL_64(0x8000000000000000, x0);
879   }
880 
881   START();
882   __ Mov(w0, 0xffff0000);
883   __ Bics(w0, w0, 0xfffffff0);
884   END();
885 
886   if (CAN_RUN()) {
887     RUN();
888 
889     ASSERT_EQUAL_NZCV(ZFlag);
890     ASSERT_EQUAL_64(0x00000000, x0);
891   }
892 }
893 
894 
TEST(eor)895 TEST(eor) {
896   SETUP();
897 
898   START();
899   __ Mov(x0, 0xfff0);
900   __ Mov(x1, 0xf00000ff);
901 
902   __ Eor(x2, x0, Operand(x1));
903   __ Eor(w3, w0, Operand(w1, LSL, 4));
904   __ Eor(x4, x0, Operand(x1, LSL, 4));
905   __ Eor(x5, x0, Operand(x1, LSR, 1));
906   __ Eor(w6, w0, Operand(w1, ASR, 20));
907   __ Eor(x7, x0, Operand(x1, ASR, 20));
908   __ Eor(w8, w0, Operand(w1, ROR, 28));
909   __ Eor(x9, x0, Operand(x1, ROR, 28));
910   __ Eor(w10, w0, 0xff00ff00);
911   __ Eor(x11, x0, 0xff00ff00ff00ff00);
912   END();
913 
914   if (CAN_RUN()) {
915     RUN();
916 
917     ASSERT_EQUAL_64(0x00000000f000ff0f, x2);
918     ASSERT_EQUAL_64(0x0000f000, x3);
919     ASSERT_EQUAL_64(0x0000000f0000f000, x4);
920     ASSERT_EQUAL_64(0x000000007800ff8f, x5);
921     ASSERT_EQUAL_64(0xffff00f0, x6);
922     ASSERT_EQUAL_64(0x000000000000f0f0, x7);
923     ASSERT_EQUAL_64(0x0000f00f, x8);
924     ASSERT_EQUAL_64(0x00000ff00000ffff, x9);
925     ASSERT_EQUAL_64(0xff0000f0, x10);
926     ASSERT_EQUAL_64(0xff00ff00ff0000f0, x11);
927   }
928 }
929 
TEST(eor_extend)930 TEST(eor_extend) {
931   SETUP();
932 
933   START();
934   __ Mov(x0, 0x1111111111111111);
935   __ Mov(x1, 0x8000000080008081);
936   __ Eor(w6, w0, Operand(w1, UXTB));
937   __ Eor(x7, x0, Operand(x1, UXTH, 1));
938   __ Eor(w8, w0, Operand(w1, UXTW, 2));
939   __ Eor(x9, x0, Operand(x1, UXTX, 3));
940   __ Eor(w10, w0, Operand(w1, SXTB));
941   __ Eor(x11, x0, Operand(x1, SXTH, 1));
942   __ Eor(x12, x0, Operand(x1, SXTW, 2));
943   __ Eor(x13, x0, Operand(x1, SXTX, 3));
944   END();
945 
946   if (CAN_RUN()) {
947     RUN();
948 
949     ASSERT_EQUAL_64(0x11111190, x6);
950     ASSERT_EQUAL_64(0x1111111111101013, x7);
951     ASSERT_EQUAL_64(0x11131315, x8);
952     ASSERT_EQUAL_64(0x1111111511151519, x9);
953     ASSERT_EQUAL_64(0xeeeeee90, x10);
954     ASSERT_EQUAL_64(0xeeeeeeeeeeee1013, x11);
955     ASSERT_EQUAL_64(0xeeeeeeef11131315, x12);
956     ASSERT_EQUAL_64(0x1111111511151519, x13);
957   }
958 }
959 
960 
TEST(eon)961 TEST(eon) {
962   SETUP();
963 
964   START();
965   __ Mov(x0, 0xfff0);
966   __ Mov(x1, 0xf00000ff);
967 
968   __ Eon(x2, x0, Operand(x1));
969   __ Eon(w3, w0, Operand(w1, LSL, 4));
970   __ Eon(x4, x0, Operand(x1, LSL, 4));
971   __ Eon(x5, x0, Operand(x1, LSR, 1));
972   __ Eon(w6, w0, Operand(w1, ASR, 20));
973   __ Eon(x7, x0, Operand(x1, ASR, 20));
974   __ Eon(w8, w0, Operand(w1, ROR, 28));
975   __ Eon(x9, x0, Operand(x1, ROR, 28));
976   __ Eon(w10, w0, 0x03c003c0);
977   __ Eon(x11, x0, 0x0000100000001000);
978   END();
979 
980   if (CAN_RUN()) {
981     RUN();
982 
983     ASSERT_EQUAL_64(0xffffffff0fff00f0, x2);
984     ASSERT_EQUAL_64(0xffff0fff, x3);
985     ASSERT_EQUAL_64(0xfffffff0ffff0fff, x4);
986     ASSERT_EQUAL_64(0xffffffff87ff0070, x5);
987     ASSERT_EQUAL_64(0x0000ff0f, x6);
988     ASSERT_EQUAL_64(0xffffffffffff0f0f, x7);
989     ASSERT_EQUAL_64(0xffff0ff0, x8);
990     ASSERT_EQUAL_64(0xfffff00fffff0000, x9);
991     ASSERT_EQUAL_64(0xfc3f03cf, x10);
992     ASSERT_EQUAL_64(0xffffefffffff100f, x11);
993   }
994 }
995 
996 
TEST(eon_extend)997 TEST(eon_extend) {
998   SETUP();
999 
1000   START();
1001   __ Mov(x0, 0x1111111111111111);
1002   __ Mov(x1, 0x8000000080008081);
1003   __ Eon(w6, w0, Operand(w1, UXTB));
1004   __ Eon(x7, x0, Operand(x1, UXTH, 1));
1005   __ Eon(w8, w0, Operand(w1, UXTW, 2));
1006   __ Eon(x9, x0, Operand(x1, UXTX, 3));
1007   __ Eon(w10, w0, Operand(w1, SXTB));
1008   __ Eon(x11, x0, Operand(x1, SXTH, 1));
1009   __ Eon(x12, x0, Operand(x1, SXTW, 2));
1010   __ Eon(x13, x0, Operand(x1, SXTX, 3));
1011   END();
1012 
1013   if (CAN_RUN()) {
1014     RUN();
1015 
1016     ASSERT_EQUAL_64(0xeeeeee6f, x6);
1017     ASSERT_EQUAL_64(0xeeeeeeeeeeefefec, x7);
1018     ASSERT_EQUAL_64(0xeeececea, x8);
1019     ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x9);
1020     ASSERT_EQUAL_64(0x1111116f, x10);
1021     ASSERT_EQUAL_64(0x111111111111efec, x11);
1022     ASSERT_EQUAL_64(0x11111110eeececea, x12);
1023     ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x13);
1024   }
1025 }
1026 
1027 
TEST(mul)1028 TEST(mul) {
1029   SETUP();
1030 
1031   START();
1032   __ Mov(x25, 0);
1033   __ Mov(x26, 1);
1034   __ Mov(x18, 0xffffffff);
1035   __ Mov(x19, 0xffffffffffffffff);
1036 
1037   __ Mul(w0, w25, w25);
1038   __ Mul(w1, w25, w26);
1039   __ Mul(w2, w26, w18);
1040   __ Mul(w3, w18, w19);
1041   __ Mul(x4, x25, x25);
1042   __ Mul(x5, x26, x18);
1043   __ Mul(x6, x18, x19);
1044   __ Mul(x7, x19, x19);
1045   __ Smull(x8, w26, w18);
1046   __ Smull(x9, w18, w18);
1047   __ Smull(x10, w19, w19);
1048   __ Mneg(w11, w25, w25);
1049   __ Mneg(w12, w25, w26);
1050   __ Mneg(w13, w26, w18);
1051   __ Mneg(w14, w18, w19);
1052   __ Mneg(x20, x25, x25);
1053   __ Mneg(x21, x26, x18);
1054   __ Mneg(x22, x18, x19);
1055   __ Mneg(x23, x19, x19);
1056   END();
1057 
1058   if (CAN_RUN()) {
1059     RUN();
1060 
1061     ASSERT_EQUAL_64(0, x0);
1062     ASSERT_EQUAL_64(0, x1);
1063     ASSERT_EQUAL_64(0xffffffff, x2);
1064     ASSERT_EQUAL_64(1, x3);
1065     ASSERT_EQUAL_64(0, x4);
1066     ASSERT_EQUAL_64(0xffffffff, x5);
1067     ASSERT_EQUAL_64(0xffffffff00000001, x6);
1068     ASSERT_EQUAL_64(1, x7);
1069     ASSERT_EQUAL_64(0xffffffffffffffff, x8);
1070     ASSERT_EQUAL_64(1, x9);
1071     ASSERT_EQUAL_64(1, x10);
1072     ASSERT_EQUAL_64(0, x11);
1073     ASSERT_EQUAL_64(0, x12);
1074     ASSERT_EQUAL_64(1, x13);
1075     ASSERT_EQUAL_64(0xffffffff, x14);
1076     ASSERT_EQUAL_64(0, x20);
1077     ASSERT_EQUAL_64(0xffffffff00000001, x21);
1078     ASSERT_EQUAL_64(0xffffffff, x22);
1079     ASSERT_EQUAL_64(0xffffffffffffffff, x23);
1080   }
1081 }
1082 
1083 
SmullHelper(int64_t expected,int64_t a,int64_t b)1084 static void SmullHelper(int64_t expected, int64_t a, int64_t b) {
1085   SETUP();
1086   START();
1087   __ Mov(w0, a);
1088   __ Mov(w1, b);
1089   __ Smull(x2, w0, w1);
1090   END();
1091   if (CAN_RUN()) {
1092     RUN();
1093     ASSERT_EQUAL_64(expected, x2);
1094   }
1095 }
1096 
1097 
TEST(smull)1098 TEST(smull) {
1099   SmullHelper(0, 0, 0);
1100   SmullHelper(1, 1, 1);
1101   SmullHelper(-1, -1, 1);
1102   SmullHelper(1, -1, -1);
1103   SmullHelper(0xffffffff80000000, 0x80000000, 1);
1104   SmullHelper(0x0000000080000000, 0x00010000, 0x00008000);
1105 }
1106 
1107 
TEST(madd)1108 TEST(madd) {
1109   SETUP();
1110 
1111   START();
1112   __ Mov(x16, 0);
1113   __ Mov(x17, 1);
1114   __ Mov(x18, 0xffffffff);
1115   __ Mov(x19, 0xffffffffffffffff);
1116 
1117   __ Madd(w0, w16, w16, w16);
1118   __ Madd(w1, w16, w16, w17);
1119   __ Madd(w2, w16, w16, w18);
1120   __ Madd(w3, w16, w16, w19);
1121   __ Madd(w4, w16, w17, w17);
1122   __ Madd(w5, w17, w17, w18);
1123   __ Madd(w6, w17, w17, w19);
1124   __ Madd(w7, w17, w18, w16);
1125   __ Madd(w8, w17, w18, w18);
1126   __ Madd(w9, w18, w18, w17);
1127   __ Madd(w10, w18, w19, w18);
1128   __ Madd(w11, w19, w19, w19);
1129 
1130   __ Madd(x12, x16, x16, x16);
1131   __ Madd(x13, x16, x16, x17);
1132   __ Madd(x14, x16, x16, x18);
1133   __ Madd(x15, x16, x16, x19);
1134   __ Madd(x20, x16, x17, x17);
1135   __ Madd(x21, x17, x17, x18);
1136   __ Madd(x22, x17, x17, x19);
1137   __ Madd(x23, x17, x18, x16);
1138   __ Madd(x24, x17, x18, x18);
1139   __ Madd(x25, x18, x18, x17);
1140   __ Madd(x26, x18, x19, x18);
1141   __ Madd(x27, x19, x19, x19);
1142 
1143   END();
1144 
1145   if (CAN_RUN()) {
1146     RUN();
1147 
1148     ASSERT_EQUAL_64(0, x0);
1149     ASSERT_EQUAL_64(1, x1);
1150     ASSERT_EQUAL_64(0xffffffff, x2);
1151     ASSERT_EQUAL_64(0xffffffff, x3);
1152     ASSERT_EQUAL_64(1, x4);
1153     ASSERT_EQUAL_64(0, x5);
1154     ASSERT_EQUAL_64(0, x6);
1155     ASSERT_EQUAL_64(0xffffffff, x7);
1156     ASSERT_EQUAL_64(0xfffffffe, x8);
1157     ASSERT_EQUAL_64(2, x9);
1158     ASSERT_EQUAL_64(0, x10);
1159     ASSERT_EQUAL_64(0, x11);
1160 
1161     ASSERT_EQUAL_64(0, x12);
1162     ASSERT_EQUAL_64(1, x13);
1163     ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1164     ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1165     ASSERT_EQUAL_64(1, x20);
1166     ASSERT_EQUAL_64(0x0000000100000000, x21);
1167     ASSERT_EQUAL_64(0, x22);
1168     ASSERT_EQUAL_64(0x00000000ffffffff, x23);
1169     ASSERT_EQUAL_64(0x00000001fffffffe, x24);
1170     ASSERT_EQUAL_64(0xfffffffe00000002, x25);
1171     ASSERT_EQUAL_64(0, x26);
1172     ASSERT_EQUAL_64(0, x27);
1173   }
1174 }
1175 
1176 
TEST(msub)1177 TEST(msub) {
1178   SETUP();
1179 
1180   START();
1181   __ Mov(x16, 0);
1182   __ Mov(x17, 1);
1183   __ Mov(x18, 0xffffffff);
1184   __ Mov(x19, 0xffffffffffffffff);
1185 
1186   __ Msub(w0, w16, w16, w16);
1187   __ Msub(w1, w16, w16, w17);
1188   __ Msub(w2, w16, w16, w18);
1189   __ Msub(w3, w16, w16, w19);
1190   __ Msub(w4, w16, w17, w17);
1191   __ Msub(w5, w17, w17, w18);
1192   __ Msub(w6, w17, w17, w19);
1193   __ Msub(w7, w17, w18, w16);
1194   __ Msub(w8, w17, w18, w18);
1195   __ Msub(w9, w18, w18, w17);
1196   __ Msub(w10, w18, w19, w18);
1197   __ Msub(w11, w19, w19, w19);
1198 
1199   __ Msub(x12, x16, x16, x16);
1200   __ Msub(x13, x16, x16, x17);
1201   __ Msub(x14, x16, x16, x18);
1202   __ Msub(x15, x16, x16, x19);
1203   __ Msub(x20, x16, x17, x17);
1204   __ Msub(x21, x17, x17, x18);
1205   __ Msub(x22, x17, x17, x19);
1206   __ Msub(x23, x17, x18, x16);
1207   __ Msub(x24, x17, x18, x18);
1208   __ Msub(x25, x18, x18, x17);
1209   __ Msub(x26, x18, x19, x18);
1210   __ Msub(x27, x19, x19, x19);
1211 
1212   END();
1213 
1214   if (CAN_RUN()) {
1215     RUN();
1216 
1217     ASSERT_EQUAL_64(0, x0);
1218     ASSERT_EQUAL_64(1, x1);
1219     ASSERT_EQUAL_64(0xffffffff, x2);
1220     ASSERT_EQUAL_64(0xffffffff, x3);
1221     ASSERT_EQUAL_64(1, x4);
1222     ASSERT_EQUAL_64(0xfffffffe, x5);
1223     ASSERT_EQUAL_64(0xfffffffe, x6);
1224     ASSERT_EQUAL_64(1, x7);
1225     ASSERT_EQUAL_64(0, x8);
1226     ASSERT_EQUAL_64(0, x9);
1227     ASSERT_EQUAL_64(0xfffffffe, x10);
1228     ASSERT_EQUAL_64(0xfffffffe, x11);
1229 
1230     ASSERT_EQUAL_64(0, x12);
1231     ASSERT_EQUAL_64(1, x13);
1232     ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1233     ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1234     ASSERT_EQUAL_64(1, x20);
1235     ASSERT_EQUAL_64(0x00000000fffffffe, x21);
1236     ASSERT_EQUAL_64(0xfffffffffffffffe, x22);
1237     ASSERT_EQUAL_64(0xffffffff00000001, x23);
1238     ASSERT_EQUAL_64(0, x24);
1239     ASSERT_EQUAL_64(0x0000000200000000, x25);
1240     ASSERT_EQUAL_64(0x00000001fffffffe, x26);
1241     ASSERT_EQUAL_64(0xfffffffffffffffe, x27);
1242   }
1243 }
1244 
1245 
TEST(smulh)1246 TEST(smulh) {
1247   SETUP();
1248 
1249   START();
1250   __ Mov(x20, 0);
1251   __ Mov(x21, 1);
1252   __ Mov(x22, 0x0000000100000000);
1253   __ Mov(x23, 0x0000000012345678);
1254   __ Mov(x24, 0x0123456789abcdef);
1255   __ Mov(x25, 0x0000000200000000);
1256   __ Mov(x26, 0x8000000000000000);
1257   __ Mov(x27, 0xffffffffffffffff);
1258   __ Mov(x28, 0x5555555555555555);
1259   __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
1260 
1261   __ Smulh(x0, x20, x24);
1262   __ Smulh(x1, x21, x24);
1263   __ Smulh(x2, x22, x23);
1264   __ Smulh(x3, x22, x24);
1265   __ Smulh(x4, x24, x25);
1266   __ Smulh(x5, x23, x27);
1267   __ Smulh(x6, x26, x26);
1268   __ Smulh(x7, x26, x27);
1269   __ Smulh(x8, x27, x27);
1270   __ Smulh(x9, x28, x28);
1271   __ Smulh(x10, x28, x29);
1272   __ Smulh(x11, x29, x29);
1273   END();
1274 
1275   if (CAN_RUN()) {
1276     RUN();
1277 
1278     ASSERT_EQUAL_64(0, x0);
1279     ASSERT_EQUAL_64(0, x1);
1280     ASSERT_EQUAL_64(0, x2);
1281     ASSERT_EQUAL_64(0x0000000001234567, x3);
1282     ASSERT_EQUAL_64(0x0000000002468acf, x4);
1283     ASSERT_EQUAL_64(0xffffffffffffffff, x5);
1284     ASSERT_EQUAL_64(0x4000000000000000, x6);
1285     ASSERT_EQUAL_64(0, x7);
1286     ASSERT_EQUAL_64(0, x8);
1287     ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1288     ASSERT_EQUAL_64(0xe38e38e38e38e38e, x10);
1289     ASSERT_EQUAL_64(0x1c71c71c71c71c72, x11);
1290   }
1291 }
1292 
1293 
TEST(umulh)1294 TEST(umulh) {
1295   SETUP();
1296 
1297   START();
1298   __ Mov(x20, 0);
1299   __ Mov(x21, 1);
1300   __ Mov(x22, 0x0000000100000000);
1301   __ Mov(x23, 0x0000000012345678);
1302   __ Mov(x24, 0x0123456789abcdef);
1303   __ Mov(x25, 0x0000000200000000);
1304   __ Mov(x26, 0x8000000000000000);
1305   __ Mov(x27, 0xffffffffffffffff);
1306   __ Mov(x28, 0x5555555555555555);
1307   __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
1308 
1309   __ Umulh(x0, x20, x24);
1310   __ Umulh(x1, x21, x24);
1311   __ Umulh(x2, x22, x23);
1312   __ Umulh(x3, x22, x24);
1313   __ Umulh(x4, x24, x25);
1314   __ Umulh(x5, x23, x27);
1315   __ Umulh(x6, x26, x26);
1316   __ Umulh(x7, x26, x27);
1317   __ Umulh(x8, x27, x27);
1318   __ Umulh(x9, x28, x28);
1319   __ Umulh(x10, x28, x29);
1320   __ Umulh(x11, x29, x29);
1321   END();
1322 
1323   if (CAN_RUN()) {
1324     RUN();
1325 
1326     ASSERT_EQUAL_64(0, x0);
1327     ASSERT_EQUAL_64(0, x1);
1328     ASSERT_EQUAL_64(0, x2);
1329     ASSERT_EQUAL_64(0x0000000001234567, x3);
1330     ASSERT_EQUAL_64(0x0000000002468acf, x4);
1331     ASSERT_EQUAL_64(0x0000000012345677, x5);
1332     ASSERT_EQUAL_64(0x4000000000000000, x6);
1333     ASSERT_EQUAL_64(0x7fffffffffffffff, x7);
1334     ASSERT_EQUAL_64(0xfffffffffffffffe, x8);
1335     ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1336     ASSERT_EQUAL_64(0x38e38e38e38e38e3, x10);
1337     ASSERT_EQUAL_64(0x71c71c71c71c71c6, x11);
1338   }
1339 }
1340 
1341 
TEST(smaddl_umaddl_umull)1342 TEST(smaddl_umaddl_umull) {
1343   SETUP();
1344 
1345   START();
1346   __ Mov(x17, 1);
1347   __ Mov(x18, 0x00000000ffffffff);
1348   __ Mov(x19, 0xffffffffffffffff);
1349   __ Mov(x20, 4);
1350   __ Mov(x21, 0x0000000200000000);
1351 
1352   __ Smaddl(x9, w17, w18, x20);
1353   __ Smaddl(x10, w18, w18, x20);
1354   __ Smaddl(x11, w19, w19, x20);
1355   __ Smaddl(x12, w19, w19, x21);
1356   __ Umaddl(x13, w17, w18, x20);
1357   __ Umaddl(x14, w18, w18, x20);
1358   __ Umaddl(x15, w19, w19, x20);
1359   __ Umaddl(x22, w19, w19, x21);
1360   __ Umull(x24, w19, w19);
1361   __ Umull(x25, w17, w18);
1362   END();
1363 
1364   if (CAN_RUN()) {
1365     RUN();
1366 
1367     ASSERT_EQUAL_64(3, x9);
1368     ASSERT_EQUAL_64(5, x10);
1369     ASSERT_EQUAL_64(5, x11);
1370     ASSERT_EQUAL_64(0x0000000200000001, x12);
1371     ASSERT_EQUAL_64(0x0000000100000003, x13);
1372     ASSERT_EQUAL_64(0xfffffffe00000005, x14);
1373     ASSERT_EQUAL_64(0xfffffffe00000005, x15);
1374     ASSERT_EQUAL_64(1, x22);
1375     ASSERT_EQUAL_64(0xfffffffe00000001, x24);
1376     ASSERT_EQUAL_64(0x00000000ffffffff, x25);
1377   }
1378 }
1379 
1380 
TEST(smsubl_umsubl)1381 TEST(smsubl_umsubl) {
1382   SETUP();
1383 
1384   START();
1385   __ Mov(x17, 1);
1386   __ Mov(x18, 0x00000000ffffffff);
1387   __ Mov(x19, 0xffffffffffffffff);
1388   __ Mov(x20, 4);
1389   __ Mov(x21, 0x0000000200000000);
1390 
1391   __ Smsubl(x9, w17, w18, x20);
1392   __ Smsubl(x10, w18, w18, x20);
1393   __ Smsubl(x11, w19, w19, x20);
1394   __ Smsubl(x12, w19, w19, x21);
1395   __ Umsubl(x13, w17, w18, x20);
1396   __ Umsubl(x14, w18, w18, x20);
1397   __ Umsubl(x15, w19, w19, x20);
1398   __ Umsubl(x22, w19, w19, x21);
1399   END();
1400 
1401   if (CAN_RUN()) {
1402     RUN();
1403 
1404     ASSERT_EQUAL_64(5, x9);
1405     ASSERT_EQUAL_64(3, x10);
1406     ASSERT_EQUAL_64(3, x11);
1407     ASSERT_EQUAL_64(0x00000001ffffffff, x12);
1408     ASSERT_EQUAL_64(0xffffffff00000005, x13);
1409     ASSERT_EQUAL_64(0x0000000200000003, x14);
1410     ASSERT_EQUAL_64(0x0000000200000003, x15);
1411     ASSERT_EQUAL_64(0x00000003ffffffff, x22);
1412   }
1413 }
1414 
1415 
TEST(div)1416 TEST(div) {
1417   SETUP();
1418 
1419   START();
1420   __ Mov(x16, 1);
1421   __ Mov(x17, 0xffffffff);
1422   __ Mov(x18, 0xffffffffffffffff);
1423   __ Mov(x19, 0x80000000);
1424   __ Mov(x20, 0x8000000000000000);
1425   __ Mov(x21, 2);
1426 
1427   __ Udiv(w0, w16, w16);
1428   __ Udiv(w1, w17, w16);
1429   __ Sdiv(w2, w16, w16);
1430   __ Sdiv(w3, w16, w17);
1431   __ Sdiv(w4, w17, w18);
1432 
1433   __ Udiv(x5, x16, x16);
1434   __ Udiv(x6, x17, x18);
1435   __ Sdiv(x7, x16, x16);
1436   __ Sdiv(x8, x16, x17);
1437   __ Sdiv(x9, x17, x18);
1438 
1439   __ Udiv(w10, w19, w21);
1440   __ Sdiv(w11, w19, w21);
1441   __ Udiv(x12, x19, x21);
1442   __ Sdiv(x13, x19, x21);
1443   __ Udiv(x14, x20, x21);
1444   __ Sdiv(x15, x20, x21);
1445 
1446   __ Udiv(w22, w19, w17);
1447   __ Sdiv(w23, w19, w17);
1448   __ Udiv(x24, x20, x18);
1449   __ Sdiv(x25, x20, x18);
1450 
1451   __ Udiv(x26, x16, x21);
1452   __ Sdiv(x27, x16, x21);
1453   __ Udiv(x28, x18, x21);
1454   __ Sdiv(x29, x18, x21);
1455 
1456   __ Mov(x17, 0);
1457   __ Udiv(w18, w16, w17);
1458   __ Sdiv(w19, w16, w17);
1459   __ Udiv(x20, x16, x17);
1460   __ Sdiv(x21, x16, x17);
1461   END();
1462 
1463   if (CAN_RUN()) {
1464     RUN();
1465 
1466     ASSERT_EQUAL_64(1, x0);
1467     ASSERT_EQUAL_64(0xffffffff, x1);
1468     ASSERT_EQUAL_64(1, x2);
1469     ASSERT_EQUAL_64(0xffffffff, x3);
1470     ASSERT_EQUAL_64(1, x4);
1471     ASSERT_EQUAL_64(1, x5);
1472     ASSERT_EQUAL_64(0, x6);
1473     ASSERT_EQUAL_64(1, x7);
1474     ASSERT_EQUAL_64(0, x8);
1475     ASSERT_EQUAL_64(0xffffffff00000001, x9);
1476     ASSERT_EQUAL_64(0x40000000, x10);
1477     ASSERT_EQUAL_64(0xc0000000, x11);
1478     ASSERT_EQUAL_64(0x0000000040000000, x12);
1479     ASSERT_EQUAL_64(0x0000000040000000, x13);
1480     ASSERT_EQUAL_64(0x4000000000000000, x14);
1481     ASSERT_EQUAL_64(0xc000000000000000, x15);
1482     ASSERT_EQUAL_64(0, x22);
1483     ASSERT_EQUAL_64(0x80000000, x23);
1484     ASSERT_EQUAL_64(0, x24);
1485     ASSERT_EQUAL_64(0x8000000000000000, x25);
1486     ASSERT_EQUAL_64(0, x26);
1487     ASSERT_EQUAL_64(0, x27);
1488     ASSERT_EQUAL_64(0x7fffffffffffffff, x28);
1489     ASSERT_EQUAL_64(0, x29);
1490     ASSERT_EQUAL_64(0, x18);
1491     ASSERT_EQUAL_64(0, x19);
1492     ASSERT_EQUAL_64(0, x20);
1493     ASSERT_EQUAL_64(0, x21);
1494   }
1495 }
1496 
1497 
TEST(rbit_rev)1498 TEST(rbit_rev) {
1499   SETUP();
1500 
1501   START();
1502   __ Mov(x24, 0xfedcba9876543210);
1503   __ Rbit(w0, w24);
1504   __ Rbit(x1, x24);
1505   __ Rev16(w2, w24);
1506   __ Rev16(x3, x24);
1507   __ Rev(w4, w24);
1508   __ Rev32(x5, x24);
1509   __ Rev64(x6, x24);
1510   __ Rev(x7, x24);
1511   END();
1512 
1513   if (CAN_RUN()) {
1514     RUN();
1515 
1516     ASSERT_EQUAL_64(0x084c2a6e, x0);
1517     ASSERT_EQUAL_64(0x084c2a6e195d3b7f, x1);
1518     ASSERT_EQUAL_64(0x54761032, x2);
1519     ASSERT_EQUAL_64(0xdcfe98ba54761032, x3);
1520     ASSERT_EQUAL_64(0x10325476, x4);
1521     ASSERT_EQUAL_64(0x98badcfe10325476, x5);
1522     ASSERT_EQUAL_64(0x1032547698badcfe, x6);
1523     ASSERT_EQUAL_64(0x1032547698badcfe, x7);
1524   }
1525 }
1526 
1527 typedef void (MacroAssembler::*TestBranchSignature)(const Register& rt,
1528                                                     unsigned bit_pos,
1529                                                     Label* label);
1530 
TbzRangePoolLimitHelper(TestBranchSignature test_branch)1531 static void TbzRangePoolLimitHelper(TestBranchSignature test_branch) {
1532   const int kTbzRange = 32768;
1533   const int kNumLdrLiteral = kTbzRange / 4;
1534   const int fuzz_range = 2;
1535   for (int n = kNumLdrLiteral - fuzz_range; n <= kNumLdrLiteral + fuzz_range;
1536        ++n) {
1537     for (int margin = -32; margin < 32; margin += 4) {
1538       SETUP();
1539 
1540       START();
1541 
1542       // Emit 32KB of literals (equal to the range of TBZ).
1543       for (int i = 0; i < n; ++i) {
1544         __ Ldr(w0, 0x12345678);
1545       }
1546 
1547       const int kLiteralMargin = 128 * KBytes;
1548 
1549       // Emit enough NOPs to be just about to emit the literal pool.
1550       ptrdiff_t end =
1551           masm.GetCursorOffset() + (kLiteralMargin - n * 4 + margin);
1552       while (masm.GetCursorOffset() < end) {
1553         __ Nop();
1554       }
1555 
1556       // Add a TBZ instruction.
1557       Label label;
1558 
1559       (masm.*test_branch)(x0, 2, &label);
1560 
1561       // Add enough NOPs to surpass its range, to make sure we can encode the
1562       // veneer.
1563       end = masm.GetCursorOffset() + (kTbzRange - 4);
1564       {
1565         ExactAssemblyScope scope(&masm,
1566                                  kTbzRange,
1567                                  ExactAssemblyScope::kMaximumSize);
1568         while (masm.GetCursorOffset() < end) __ nop();
1569       }
1570 
1571       // Finally, bind the label.
1572       __ Bind(&label);
1573 
1574       END();
1575 
1576       if (CAN_RUN()) {
1577         RUN();
1578       }
1579     }
1580   }
1581 }
1582 
TEST(test_branch_limits_literal_pool_size_tbz)1583 TEST(test_branch_limits_literal_pool_size_tbz) {
1584   TbzRangePoolLimitHelper(&MacroAssembler::Tbz);
1585 }
1586 
TEST(test_branch_limits_literal_pool_size_tbnz)1587 TEST(test_branch_limits_literal_pool_size_tbnz) {
1588   TbzRangePoolLimitHelper(&MacroAssembler::Tbnz);
1589 }
1590 
TEST(clz_cls)1591 TEST(clz_cls) {
1592   SETUP();
1593 
1594   START();
1595   __ Mov(x24, 0x0008000000800000);
1596   __ Mov(x25, 0xff800000fff80000);
1597   __ Mov(x26, 0);
1598   __ Clz(w0, w24);
1599   __ Clz(x1, x24);
1600   __ Clz(w2, w25);
1601   __ Clz(x3, x25);
1602   __ Clz(w4, w26);
1603   __ Clz(x5, x26);
1604   __ Cls(w6, w24);
1605   __ Cls(x7, x24);
1606   __ Cls(w8, w25);
1607   __ Cls(x9, x25);
1608   __ Cls(w10, w26);
1609   __ Cls(x11, x26);
1610   END();
1611 
1612   if (CAN_RUN()) {
1613     RUN();
1614 
1615     ASSERT_EQUAL_64(8, x0);
1616     ASSERT_EQUAL_64(12, x1);
1617     ASSERT_EQUAL_64(0, x2);
1618     ASSERT_EQUAL_64(0, x3);
1619     ASSERT_EQUAL_64(32, x4);
1620     ASSERT_EQUAL_64(64, x5);
1621     ASSERT_EQUAL_64(7, x6);
1622     ASSERT_EQUAL_64(11, x7);
1623     ASSERT_EQUAL_64(12, x8);
1624     ASSERT_EQUAL_64(8, x9);
1625     ASSERT_EQUAL_64(31, x10);
1626     ASSERT_EQUAL_64(63, x11);
1627   }
1628 }
1629 
1630 
TEST(pacia_pacib_autia_autib)1631 TEST(pacia_pacib_autia_autib) {
1632   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1633 
1634   START();
1635 
1636   Register pointer = x24;
1637   Register retry_limit = x25;
1638   Register modifier = x26;
1639   Label retry;
1640 
1641   // There is a small but not negligible chance (1 in 127 runs) that the PAC
1642   // codes for keys A and B will collide, so retry a few times with different
1643   // pointers.
1644   __ Mov(pointer, 0x0000000012345678);
1645   __ Mov(retry_limit, 0x0000000012345678 + 32);
1646   __ Mov(modifier, 0x477d469dec0b8760);
1647 
1648   __ Bind(&retry);
1649 
1650   // Generate PACs using keys A and B.
1651   __ Mov(x0, pointer);
1652   __ Pacia(x0, modifier);
1653 
1654   __ Mov(x1, pointer);
1655   __ Pacib(x1, modifier);
1656 
1657   // Authenticate the pointers above.
1658   __ Mov(x2, x0);
1659   __ Autia(x2, modifier);
1660 
1661   __ Mov(x3, x1);
1662   __ Autib(x3, modifier);
1663 
1664   // Attempt to authenticate incorrect pointers.
1665   __ Mov(x4, x1);
1666   __ Autia(x4, modifier);
1667 
1668   __ Mov(x5, x0);
1669   __ Autib(x5, modifier);
1670 
1671   // Retry on collisions.
1672   __ Cmp(x0, x1);
1673   __ Ccmp(pointer, x0, ZFlag, ne);
1674   __ Ccmp(pointer, x1, ZFlag, ne);
1675   __ Ccmp(pointer, x4, ZFlag, ne);
1676   __ Ccmp(pointer, x5, ZFlag, ne);
1677   __ Ccmp(pointer, retry_limit, ZFlag, eq);
1678   __ Cinc(pointer, pointer, ne);
1679   __ B(ne, &retry);
1680 
1681   END();
1682 
1683   if (CAN_RUN()) {
1684     RUN();
1685 
1686     // Check PAC codes have been generated.
1687     ASSERT_NOT_EQUAL_64(pointer, x0);
1688     ASSERT_NOT_EQUAL_64(pointer, x1);
1689     ASSERT_NOT_EQUAL_64(x0, x1);
1690 
1691     // Pointers correctly authenticated.
1692     ASSERT_EQUAL_64(pointer, x2);
1693     ASSERT_EQUAL_64(pointer, x3);
1694 
1695     // Pointers corrupted after failing to authenticate.
1696 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
1697     ASSERT_EQUAL_64(0x0020000012345678, x4);
1698     ASSERT_EQUAL_64(0x0040000012345678, x5);
1699 #else
1700     ASSERT_NOT_EQUAL_64(pointer, x4);
1701     ASSERT_NOT_EQUAL_64(pointer, x5);
1702 #endif
1703   }
1704 }
1705 
1706 
TEST(paciza_pacizb_autiza_autizb)1707 TEST(paciza_pacizb_autiza_autizb) {
1708   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1709 
1710   START();
1711 
1712   Register pointer = x24;
1713   Register retry_limit = x25;
1714   Label retry;
1715 
1716   // There is a small but not negligible chance (1 in 127 runs) that the PAC
1717   // codes for keys A and B will collide, so retry a few times with different
1718   // pointers.
1719   __ Mov(pointer, 0x0000000012345678);
1720   __ Mov(retry_limit, 0x0000000012345678 + 32);
1721 
1722   __ Bind(&retry);
1723 
1724   // Generate PACs using keys A and B.
1725   __ Mov(x0, pointer);
1726   __ Paciza(x0);
1727 
1728   __ Mov(x1, pointer);
1729   __ Pacizb(x1);
1730 
1731   // Authenticate the pointers above.
1732   __ Mov(x2, x0);
1733   __ Autiza(x2);
1734 
1735   __ Mov(x3, x1);
1736   __ Autizb(x3);
1737 
1738   // Attempt to authenticate incorrect pointers.
1739   __ Mov(x4, x1);
1740   __ Autiza(x4);
1741 
1742   __ Mov(x5, x0);
1743   __ Autizb(x5);
1744 
1745   // Retry on collisions.
1746   __ Cmp(x0, x1);
1747   __ Ccmp(pointer, x0, ZFlag, ne);
1748   __ Ccmp(pointer, x1, ZFlag, ne);
1749   __ Ccmp(pointer, x4, ZFlag, ne);
1750   __ Ccmp(pointer, x5, ZFlag, ne);
1751   __ Ccmp(pointer, retry_limit, ZFlag, eq);
1752   __ Cinc(pointer, pointer, ne);
1753   __ B(ne, &retry);
1754 
1755   END();
1756 
1757   if (CAN_RUN()) {
1758     RUN();
1759 
1760     // Check PAC codes have been generated.
1761     ASSERT_NOT_EQUAL_64(pointer, x0);
1762     ASSERT_NOT_EQUAL_64(pointer, x1);
1763     ASSERT_NOT_EQUAL_64(x0, x1);
1764 
1765     // Pointers correctly authenticated.
1766     ASSERT_EQUAL_64(pointer, x2);
1767     ASSERT_EQUAL_64(pointer, x3);
1768 
1769     // Pointers corrupted after failing to authenticate.
1770 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
1771     ASSERT_EQUAL_64(0x0020000012345678, x4);
1772     ASSERT_EQUAL_64(0x0040000012345678, x5);
1773 #else
1774     ASSERT_NOT_EQUAL_64(pointer, x4);
1775     ASSERT_NOT_EQUAL_64(pointer, x5);
1776 #endif
1777   }
1778 }
1779 
1780 
TEST(pacda_pacdb_autda_autdb)1781 TEST(pacda_pacdb_autda_autdb) {
1782   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1783 
1784   START();
1785 
1786   Register pointer = x24;
1787   Register retry_limit = x25;
1788   Register modifier = x26;
1789   Label retry;
1790 
1791   // There is a small but not negligible chance (1 in 127 runs) that the PAC
1792   // codes for keys A and B will collide, so retry a few times with different
1793   // pointers.
1794   __ Mov(pointer, 0x0000000012345678);
1795   __ Mov(retry_limit, 0x0000000012345678 + 32);
1796   __ Mov(modifier, 0x477d469dec0b8760);
1797 
1798   __ Bind(&retry);
1799 
1800   // Generate PACs using keys A and B.
1801   __ Mov(x0, pointer);
1802   __ Pacda(x0, modifier);
1803 
1804   __ Mov(x1, pointer);
1805   __ Pacdb(x1, modifier);
1806 
1807   // Authenticate the pointers above.
1808   __ Mov(x2, x0);
1809   __ Autda(x2, modifier);
1810 
1811   __ Mov(x3, x1);
1812   __ Autdb(x3, modifier);
1813 
1814   // Attempt to authenticate incorrect pointers.
1815   __ Mov(x4, x1);
1816   __ Autda(x4, modifier);
1817 
1818   __ Mov(x5, x0);
1819   __ Autdb(x5, modifier);
1820 
1821   // Retry on collisions.
1822   __ Cmp(x0, x1);
1823   __ Ccmp(pointer, x0, ZFlag, ne);
1824   __ Ccmp(pointer, x1, ZFlag, ne);
1825   __ Ccmp(pointer, x4, ZFlag, ne);
1826   __ Ccmp(pointer, x5, ZFlag, ne);
1827   __ Ccmp(pointer, retry_limit, ZFlag, eq);
1828   __ Cinc(pointer, pointer, ne);
1829   __ B(ne, &retry);
1830 
1831   END();
1832 
1833   if (CAN_RUN()) {
1834     RUN();
1835 
1836     // Check PAC codes have been generated.
1837     ASSERT_NOT_EQUAL_64(pointer, x0);
1838     ASSERT_NOT_EQUAL_64(pointer, x1);
1839     ASSERT_NOT_EQUAL_64(x0, x1);
1840 
1841     // Pointers correctly authenticated.
1842     ASSERT_EQUAL_64(pointer, x2);
1843     ASSERT_EQUAL_64(pointer, x3);
1844 
1845     // Pointers corrupted after failing to authenticate.
1846 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
1847     ASSERT_EQUAL_64(0x0020000012345678, x4);
1848     ASSERT_EQUAL_64(0x0040000012345678, x5);
1849 #else
1850     ASSERT_NOT_EQUAL_64(pointer, x4);
1851     ASSERT_NOT_EQUAL_64(pointer, x5);
1852 #endif
1853   }
1854 }
1855 
1856 
TEST(pacdza_pacdzb_autdza_autdzb)1857 TEST(pacdza_pacdzb_autdza_autdzb) {
1858   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1859 
1860   START();
1861 
1862   Register pointer = x24;
1863   Register retry_limit = x25;
1864   Label retry;
1865 
1866   // There is a small but not negligible chance (1 in 127 runs) that the PAC
1867   // codes for keys A and B will collide, so retry a few times with different
1868   // pointers.
1869   __ Mov(pointer, 0x0000000012345678);
1870   __ Mov(retry_limit, 0x0000000012345678 + 32);
1871 
1872   __ Bind(&retry);
1873 
1874   // Generate PACs using keys A and B.
1875   __ Mov(x0, pointer);
1876   __ Pacdza(x0);
1877 
1878   __ Mov(x1, pointer);
1879   __ Pacdzb(x1);
1880 
1881   // Authenticate the pointers above.
1882   __ Mov(x2, x0);
1883   __ Autdza(x2);
1884 
1885   __ Mov(x3, x1);
1886   __ Autdzb(x3);
1887 
1888   // Attempt to authenticate incorrect pointers.
1889   __ Mov(x4, x1);
1890   __ Autdza(x4);
1891 
1892   __ Mov(x5, x0);
1893   __ Autdzb(x5);
1894 
1895   // Retry on collisions.
1896   __ Cmp(x0, x1);
1897   __ Ccmp(pointer, x0, ZFlag, ne);
1898   __ Ccmp(pointer, x1, ZFlag, ne);
1899   __ Ccmp(pointer, x4, ZFlag, ne);
1900   __ Ccmp(pointer, x5, ZFlag, ne);
1901   __ Ccmp(pointer, retry_limit, ZFlag, eq);
1902   __ Cinc(pointer, pointer, ne);
1903   __ B(ne, &retry);
1904 
1905   END();
1906 
1907   if (CAN_RUN()) {
1908     RUN();
1909 
1910     // Check PAC codes have been generated.
1911     ASSERT_NOT_EQUAL_64(pointer, x0);
1912     ASSERT_NOT_EQUAL_64(pointer, x1);
1913     ASSERT_NOT_EQUAL_64(x0, x1);
1914 
1915     // Pointers correctly authenticated.
1916     ASSERT_EQUAL_64(pointer, x2);
1917     ASSERT_EQUAL_64(pointer, x3);
1918 
1919     // Pointers corrupted after failing to authenticate.
1920 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
1921     ASSERT_EQUAL_64(0x0020000012345678, x4);
1922     ASSERT_EQUAL_64(0x0040000012345678, x5);
1923 #else
1924     ASSERT_NOT_EQUAL_64(pointer, x4);
1925     ASSERT_NOT_EQUAL_64(pointer, x5);
1926 #endif
1927   }
1928 }
1929 
1930 
TEST(pacga_xpaci_xpacd)1931 TEST(pacga_xpaci_xpacd) {
1932   SETUP_WITH_FEATURES(CPUFeatures::kPAuth, CPUFeatures::kPAuthGeneric);
1933 
1934   START();
1935 
1936   Register pointer = x24;
1937   Register retry_limit = x25;
1938   Register modifier = x26;
1939   Label retry;
1940 
1941   // There is a small but not negligible chance (1 in 127 runs) that the PAC
1942   // codes for keys A and B will collide, so retry a few times with different
1943   // pointers.
1944   __ Mov(pointer, 0x0000000012345678);
1945   __ Mov(retry_limit, 0x0000000012345678 + 32);
1946   __ Mov(modifier, 0x477d469dec0b8760);
1947 
1948   __ Bind(&retry);
1949 
1950   // Generate generic PAC.
1951   __ Pacga(x0, pointer, modifier);
1952 
1953   // Generate PACs using key A.
1954   __ Mov(x1, pointer);
1955   __ Mov(x2, pointer);
1956   __ Pacia(x1, modifier);
1957   __ Pacda(x2, modifier);
1958 
1959   // Strip PACs.
1960   __ Mov(x3, x1);
1961   __ Mov(x4, x2);
1962   __ Xpaci(x3);
1963   __ Xpacd(x4);
1964 
1965   // Retry on collisions.
1966   __ Cmp(x1, x2);
1967   __ Ccmp(pointer, x0, ZFlag, ne);
1968   __ Ccmp(pointer, x1, ZFlag, ne);
1969   __ Ccmp(pointer, x2, ZFlag, ne);
1970   __ Ccmp(pointer, retry_limit, ZFlag, eq);
1971   __ Cinc(pointer, pointer, ne);
1972   __ B(ne, &retry);
1973 
1974   END();
1975 
1976   if (CAN_RUN()) {
1977     RUN();
1978 
1979     // Check PAC codes have been generated.
1980     ASSERT_NOT_EQUAL_64(pointer, x0);
1981     ASSERT_NOT_EQUAL_64(pointer, x1);
1982     ASSERT_NOT_EQUAL_64(pointer, x2);
1983     ASSERT_NOT_EQUAL_64(x1, x2);
1984 
1985     ASSERT_EQUAL_64(pointer, x3);
1986     ASSERT_EQUAL_64(pointer, x4);
1987   }
1988 }
1989 
TEST(pac_sp_modifier)1990 TEST(pac_sp_modifier) {
1991   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1992 
1993   START();
1994 
1995   __ Mov(x0, 0x0000000012345678);
1996   __ Mov(x1, x0);
1997   __ Mov(x10, sp);
1998 
1999   // Generate PACs using sp and register containing a copy of sp.
2000   __ Pacia(x0, x10);
2001   __ Pacia(x1, sp);
2002 
2003   // Authenticate the pointers, exchanging (equal) modifiers.
2004   __ Mov(x2, x0);
2005   __ Mov(x3, x1);
2006   __ Autia(x2, sp);
2007   __ Autia(x3, x10);
2008 
2009   END();
2010 
2011   if (CAN_RUN()) {
2012     RUN();
2013 
2014     ASSERT_EQUAL_64(x0, x1);
2015     ASSERT_EQUAL_64(x2, x3);
2016   }
2017 }
2018 
TEST(label)2019 TEST(label) {
2020   SETUP();
2021 
2022   Label label_1, label_2, label_3, label_4;
2023 
2024   START();
2025   __ Mov(x0, 0x1);
2026   __ Mov(x1, 0x0);
2027   __ Mov(x22, lr);  // Save lr.
2028 
2029   __ B(&label_1);
2030   __ B(&label_1);
2031   __ B(&label_1);  // Multiple branches to the same label.
2032   __ Mov(x0, 0x0);
2033   __ Bind(&label_2);
2034   __ B(&label_3);  // Forward branch.
2035   __ Mov(x0, 0x0);
2036   __ Bind(&label_1);
2037   __ B(&label_2);  // Backward branch.
2038   __ Mov(x0, 0x0);
2039   __ Bind(&label_3);
2040   __ Bl(&label_4);
2041   END();
2042 
2043   __ Bind(&label_4);
2044   __ Mov(x1, 0x1);
2045   __ Mov(lr, x22);
2046   END();
2047 
2048   if (CAN_RUN()) {
2049     RUN();
2050 
2051     ASSERT_EQUAL_64(0x1, x0);
2052     ASSERT_EQUAL_64(0x1, x1);
2053   }
2054 }
2055 
2056 
TEST(label_2)2057 TEST(label_2) {
2058   SETUP();
2059 
2060   Label label_1, label_2, label_3;
2061   Label first_jump_to_3;
2062 
2063   START();
2064   __ Mov(x0, 0x0);
2065 
2066   __ B(&label_1);
2067   ptrdiff_t offset_2 = masm.GetCursorOffset();
2068   __ Orr(x0, x0, 1 << 1);
2069   __ B(&label_3);
2070   ptrdiff_t offset_1 = masm.GetCursorOffset();
2071   __ Orr(x0, x0, 1 << 0);
2072   __ B(&label_2);
2073   ptrdiff_t offset_3 = masm.GetCursorOffset();
2074   __ Tbz(x0, 2, &first_jump_to_3);
2075   __ Orr(x0, x0, 1 << 3);
2076   __ Bind(&first_jump_to_3);
2077   __ Orr(x0, x0, 1 << 2);
2078   __ Tbz(x0, 3, &label_3);
2079 
2080   // Labels 1, 2, and 3 are bound before the current buffer offset. Branches to
2081   // label_1 and label_2 branch respectively forward and backward. Branches to
2082   // label 3 include both forward and backward branches.
2083   masm.BindToOffset(&label_1, offset_1);
2084   masm.BindToOffset(&label_2, offset_2);
2085   masm.BindToOffset(&label_3, offset_3);
2086 
2087   END();
2088 
2089   if (CAN_RUN()) {
2090     RUN();
2091 
2092     ASSERT_EQUAL_64(0xf, x0);
2093   }
2094 }
2095 
2096 
TEST(adr)2097 TEST(adr) {
2098   SETUP();
2099 
2100   Label label_1, label_2, label_3, label_4;
2101 
2102   START();
2103   __ Mov(x0, 0x0);       // Set to non-zero to indicate failure.
2104   __ Adr(x1, &label_3);  // Set to zero to indicate success.
2105 
2106   __ Adr(x2, &label_1);  // Multiple forward references to the same label.
2107   __ Adr(x3, &label_1);
2108   __ Adr(x4, &label_1);
2109 
2110   __ Bind(&label_2);
2111   __ Eor(x5, x2, Operand(x3));  // Ensure that x2,x3 and x4 are identical.
2112   __ Eor(x6, x2, Operand(x4));
2113   __ Orr(x0, x0, Operand(x5));
2114   __ Orr(x0, x0, Operand(x6));
2115   __ Br(x2);  // label_1, label_3
2116 
2117   __ Bind(&label_3);
2118   __ Adr(x2, &label_3);  // Self-reference (offset 0).
2119   __ Eor(x1, x1, Operand(x2));
2120   __ Adr(x2, &label_4);  // Simple forward reference.
2121   __ Br(x2);             // label_4
2122 
2123   __ Bind(&label_1);
2124   __ Adr(x2, &label_3);  // Multiple reverse references to the same label.
2125   __ Adr(x3, &label_3);
2126   __ Adr(x4, &label_3);
2127   __ Adr(x5, &label_2);  // Simple reverse reference.
2128   __ Br(x5);             // label_2
2129 
2130   __ Bind(&label_4);
2131   END();
2132 
2133   if (CAN_RUN()) {
2134     RUN();
2135 
2136     ASSERT_EQUAL_64(0x0, x0);
2137     ASSERT_EQUAL_64(0x0, x1);
2138   }
2139 }
2140 
2141 
2142 // Simple adrp tests: check that labels are linked and handled properly.
2143 // This is similar to the adr test, but all the adrp instructions are put on the
2144 // same page so that they return the same value.
TEST(adrp)2145 TEST(adrp) {
2146   Label start;
2147   Label label_1, label_2, label_3;
2148 
2149   SETUP_CUSTOM(2 * kPageSize, PageOffsetDependentCode);
2150   START();
2151 
2152   // Waste space until the start of a page.
2153   {
2154     ExactAssemblyScope scope(&masm,
2155                              kPageSize,
2156                              ExactAssemblyScope::kMaximumSize);
2157     const uintptr_t kPageOffsetMask = kPageSize - 1;
2158     while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2159       __ b(&start);
2160     }
2161     __ bind(&start);
2162   }
2163 
2164   // Simple forward reference.
2165   __ Adrp(x0, &label_2);
2166 
2167   __ Bind(&label_1);
2168 
2169   // Multiple forward references to the same label.
2170   __ Adrp(x1, &label_3);
2171   __ Adrp(x2, &label_3);
2172   __ Adrp(x3, &label_3);
2173 
2174   __ Bind(&label_2);
2175 
2176   // Self-reference (offset 0).
2177   __ Adrp(x4, &label_2);
2178 
2179   __ Bind(&label_3);
2180 
2181   // Simple reverse reference.
2182   __ Adrp(x5, &label_1);
2183 
2184   // Multiple reverse references to the same label.
2185   __ Adrp(x6, &label_2);
2186   __ Adrp(x7, &label_2);
2187   __ Adrp(x8, &label_2);
2188 
2189   VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&start) < kPageSize);
2190   END();
2191   if (CAN_RUN()) {
2192     RUN();
2193 
2194     uint64_t expected = reinterpret_cast<uint64_t>(
2195         AlignDown(masm.GetLabelAddress<uint64_t*>(&start), kPageSize));
2196     ASSERT_EQUAL_64(expected, x0);
2197     ASSERT_EQUAL_64(expected, x1);
2198     ASSERT_EQUAL_64(expected, x2);
2199     ASSERT_EQUAL_64(expected, x3);
2200     ASSERT_EQUAL_64(expected, x4);
2201     ASSERT_EQUAL_64(expected, x5);
2202     ASSERT_EQUAL_64(expected, x6);
2203     ASSERT_EQUAL_64(expected, x7);
2204     ASSERT_EQUAL_64(expected, x8);
2205   }
2206 }
2207 
2208 
AdrpPageBoundaryHelper(unsigned offset_into_page)2209 static void AdrpPageBoundaryHelper(unsigned offset_into_page) {
2210   VIXL_ASSERT(offset_into_page < kPageSize);
2211   VIXL_ASSERT((offset_into_page % kInstructionSize) == 0);
2212 
2213   const uintptr_t kPageOffsetMask = kPageSize - 1;
2214 
2215   // The test label is always bound on page 0. Adrp instructions are generated
2216   // on pages from kStartPage to kEndPage (inclusive).
2217   const int kStartPage = -16;
2218   const int kEndPage = 16;
2219   const int kMaxCodeSize = (kEndPage - kStartPage + 2) * kPageSize;
2220 
2221   SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
2222   START();
2223 
2224   Label test;
2225   Label start;
2226 
2227   {
2228     ExactAssemblyScope scope(&masm,
2229                              kMaxCodeSize,
2230                              ExactAssemblyScope::kMaximumSize);
2231     // Initialize NZCV with `eq` flags.
2232     __ cmp(wzr, wzr);
2233     // Waste space until the start of a page.
2234     while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2235       __ b(&start);
2236     }
2237 
2238     // The first page.
2239     VIXL_STATIC_ASSERT(kStartPage < 0);
2240     {
2241       ExactAssemblyScope scope_page(&masm, kPageSize);
2242       __ bind(&start);
2243       __ adrp(x0, &test);
2244       __ adrp(x1, &test);
2245       for (size_t i = 2; i < (kPageSize / kInstructionSize); i += 2) {
2246         __ ccmp(x0, x1, NoFlag, eq);
2247         __ adrp(x1, &test);
2248       }
2249     }
2250 
2251     // Subsequent pages.
2252     VIXL_STATIC_ASSERT(kEndPage >= 0);
2253     for (int page = (kStartPage + 1); page <= kEndPage; page++) {
2254       ExactAssemblyScope scope_page(&masm, kPageSize);
2255       if (page == 0) {
2256         for (size_t i = 0; i < (kPageSize / kInstructionSize);) {
2257           if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
2258           __ ccmp(x0, x1, NoFlag, eq);
2259           if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
2260           __ adrp(x1, &test);
2261         }
2262       } else {
2263         for (size_t i = 0; i < (kPageSize / kInstructionSize); i += 2) {
2264           __ ccmp(x0, x1, NoFlag, eq);
2265           __ adrp(x1, &test);
2266         }
2267       }
2268     }
2269   }
2270 
2271   // Every adrp instruction pointed to the same label (`test`), so they should
2272   // all have produced the same result.
2273 
2274   END();
2275   if (CAN_RUN()) {
2276     RUN();
2277 
2278     uintptr_t expected =
2279         AlignDown(masm.GetLabelAddress<uintptr_t>(&test), kPageSize);
2280     ASSERT_EQUAL_64(expected, x0);
2281     ASSERT_EQUAL_64(expected, x1);
2282     ASSERT_EQUAL_NZCV(ZCFlag);
2283   }
2284 }
2285 
2286 
2287 // Test that labels are correctly referenced by adrp across page boundaries.
TEST(adrp_page_boundaries)2288 TEST(adrp_page_boundaries) {
2289   VIXL_STATIC_ASSERT(kPageSize == 4096);
2290   AdrpPageBoundaryHelper(kInstructionSize * 0);
2291   AdrpPageBoundaryHelper(kInstructionSize * 1);
2292   AdrpPageBoundaryHelper(kInstructionSize * 512);
2293   AdrpPageBoundaryHelper(kInstructionSize * 1022);
2294   AdrpPageBoundaryHelper(kInstructionSize * 1023);
2295 }
2296 
2297 
AdrpOffsetHelper(int64_t offset)2298 static void AdrpOffsetHelper(int64_t offset) {
2299   const size_t kPageOffsetMask = kPageSize - 1;
2300   const int kMaxCodeSize = 2 * kPageSize;
2301 
2302   SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
2303   START();
2304 
2305   Label page;
2306 
2307   {
2308     ExactAssemblyScope scope(&masm,
2309                              kMaxCodeSize,
2310                              ExactAssemblyScope::kMaximumSize);
2311     // Initialize NZCV with `eq` flags.
2312     __ cmp(wzr, wzr);
2313     // Waste space until the start of a page.
2314     while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2315       __ b(&page);
2316     }
2317     __ bind(&page);
2318 
2319     {
2320       ExactAssemblyScope scope_page(&masm, kPageSize);
2321       // Every adrp instruction on this page should return the same value.
2322       __ adrp(x0, offset);
2323       __ adrp(x1, offset);
2324       for (size_t i = 2; i < kPageSize / kInstructionSize; i += 2) {
2325         __ ccmp(x0, x1, NoFlag, eq);
2326         __ adrp(x1, offset);
2327       }
2328     }
2329   }
2330 
2331   END();
2332   if (CAN_RUN()) {
2333     RUN();
2334 
2335     uintptr_t expected =
2336         masm.GetLabelAddress<uintptr_t>(&page) + (kPageSize * offset);
2337     ASSERT_EQUAL_64(expected, x0);
2338     ASSERT_EQUAL_64(expected, x1);
2339     ASSERT_EQUAL_NZCV(ZCFlag);
2340   }
2341 }
2342 
2343 
2344 // Check that adrp produces the correct result for a specific offset.
TEST(adrp_offset)2345 TEST(adrp_offset) {
2346   AdrpOffsetHelper(0);
2347   AdrpOffsetHelper(1);
2348   AdrpOffsetHelper(-1);
2349   AdrpOffsetHelper(4);
2350   AdrpOffsetHelper(-4);
2351   AdrpOffsetHelper(0x000fffff);
2352   AdrpOffsetHelper(-0x000fffff);
2353   AdrpOffsetHelper(-0x00100000);
2354 }
2355 
2356 
TEST(branch_cond)2357 TEST(branch_cond) {
2358   SETUP();
2359 
2360   Label done, wrong;
2361 
2362   START();
2363   __ Mov(x0, 0x1);
2364   __ Mov(x1, 0x1);
2365   __ Mov(x2, 0x8000000000000000);
2366 
2367   // For each 'cmp' instruction below, condition codes other than the ones
2368   // following it would branch.
2369 
2370   __ Cmp(x1, 0);
2371   __ B(&wrong, eq);
2372   __ B(&wrong, lo);
2373   __ B(&wrong, mi);
2374   __ B(&wrong, vs);
2375   __ B(&wrong, ls);
2376   __ B(&wrong, lt);
2377   __ B(&wrong, le);
2378   Label ok_1;
2379   __ B(&ok_1, ne);
2380   __ Mov(x0, 0x0);
2381   __ Bind(&ok_1);
2382 
2383   __ Cmp(x1, 1);
2384   __ B(&wrong, ne);
2385   __ B(&wrong, lo);
2386   __ B(&wrong, mi);
2387   __ B(&wrong, vs);
2388   __ B(&wrong, hi);
2389   __ B(&wrong, lt);
2390   __ B(&wrong, gt);
2391   Label ok_2;
2392   __ B(&ok_2, pl);
2393   __ Mov(x0, 0x0);
2394   __ Bind(&ok_2);
2395 
2396   __ Cmp(x1, 2);
2397   __ B(&wrong, eq);
2398   __ B(&wrong, hs);
2399   __ B(&wrong, pl);
2400   __ B(&wrong, vs);
2401   __ B(&wrong, hi);
2402   __ B(&wrong, ge);
2403   __ B(&wrong, gt);
2404   Label ok_3;
2405   __ B(&ok_3, vc);
2406   __ Mov(x0, 0x0);
2407   __ Bind(&ok_3);
2408 
2409   __ Cmp(x2, 1);
2410   __ B(&wrong, eq);
2411   __ B(&wrong, lo);
2412   __ B(&wrong, mi);
2413   __ B(&wrong, vc);
2414   __ B(&wrong, ls);
2415   __ B(&wrong, ge);
2416   __ B(&wrong, gt);
2417   Label ok_4;
2418   __ B(&ok_4, le);
2419   __ Mov(x0, 0x0);
2420   __ Bind(&ok_4);
2421 
2422   // The MacroAssembler does not allow al as a branch condition.
2423   Label ok_5;
2424   {
2425     ExactAssemblyScope scope(&masm, kInstructionSize);
2426     __ b(&ok_5, al);
2427   }
2428   __ Mov(x0, 0x0);
2429   __ Bind(&ok_5);
2430 
2431   // The MacroAssembler does not allow nv as a branch condition.
2432   Label ok_6;
2433   {
2434     ExactAssemblyScope scope(&masm, kInstructionSize);
2435     __ b(&ok_6, nv);
2436   }
2437   __ Mov(x0, 0x0);
2438   __ Bind(&ok_6);
2439 
2440   __ B(&done);
2441 
2442   __ Bind(&wrong);
2443   __ Mov(x0, 0x0);
2444 
2445   __ Bind(&done);
2446   END();
2447 
2448   if (CAN_RUN()) {
2449     RUN();
2450 
2451     ASSERT_EQUAL_64(0x1, x0);
2452   }
2453 }
2454 
2455 
TEST(branch_to_reg)2456 TEST(branch_to_reg) {
2457   SETUP();
2458 
2459   // Test br.
2460   Label fn1, after_fn1;
2461 
2462   START();
2463   __ Mov(x29, lr);
2464 
2465   __ Mov(x1, 0);
2466   __ B(&after_fn1);
2467 
2468   __ Bind(&fn1);
2469   __ Mov(x0, lr);
2470   __ Mov(x1, 42);
2471   __ Br(x0);
2472 
2473   __ Bind(&after_fn1);
2474   __ Bl(&fn1);
2475 
2476   // Test blr.
2477   Label fn2, after_fn2, after_bl2;
2478 
2479   __ Mov(x2, 0);
2480   __ B(&after_fn2);
2481 
2482   __ Bind(&fn2);
2483   __ Mov(x0, lr);
2484   __ Mov(x2, 84);
2485   __ Blr(x0);
2486 
2487   __ Bind(&after_fn2);
2488   __ Bl(&fn2);
2489   __ Bind(&after_bl2);
2490   __ Mov(x3, lr);
2491   __ Adr(x4, &after_bl2);
2492   __ Adr(x5, &after_fn2);
2493 
2494   __ Mov(lr, x29);
2495   END();
2496 
2497   if (CAN_RUN()) {
2498     RUN();
2499 
2500     ASSERT_EQUAL_64(x4, x0);
2501     ASSERT_EQUAL_64(x5, x3);
2502     ASSERT_EQUAL_64(42, x1);
2503     ASSERT_EQUAL_64(84, x2);
2504   }
2505 }
2506 
TEST(branch_to_reg_auth_a)2507 TEST(branch_to_reg_auth_a) {
2508   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2509 
2510   START();
2511 
2512   Label fn1, after_fn1;
2513 
2514   __ Mov(x28, 0x477d469dec0b8760);
2515   __ Mov(x29, lr);
2516 
2517   __ Mov(x1, 0);
2518   __ B(&after_fn1);
2519 
2520   __ Bind(&fn1);
2521   __ Mov(x0, lr);
2522   __ Mov(x1, 42);
2523   __ Pacia(x0, x28);
2524   __ Braa(x0, x28);
2525 
2526   __ Bind(&after_fn1);
2527   __ Bl(&fn1);
2528 
2529   Label fn2, after_fn2, after_bl2;
2530 
2531   __ Mov(x2, 0);
2532   __ B(&after_fn2);
2533 
2534   __ Bind(&fn2);
2535   __ Mov(x0, lr);
2536   __ Mov(x2, 84);
2537   __ Pacia(x0, x28);
2538   __ Blraa(x0, x28);
2539 
2540   __ Bind(&after_fn2);
2541   __ Bl(&fn2);
2542   __ Bind(&after_bl2);
2543   __ Mov(x3, lr);
2544   __ Adr(x4, &after_bl2);
2545   __ Adr(x5, &after_fn2);
2546 
2547   __ Xpaci(x0);
2548   __ Mov(lr, x29);
2549   END();
2550 
2551   if (CAN_RUN()) {
2552     RUN();
2553 
2554     ASSERT_EQUAL_64(x4, x0);
2555     ASSERT_EQUAL_64(x5, x3);
2556     ASSERT_EQUAL_64(42, x1);
2557     ASSERT_EQUAL_64(84, x2);
2558   }
2559 }
2560 
TEST(return_to_reg_auth)2561 TEST(return_to_reg_auth) {
2562   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2563 
2564   START();
2565 
2566   Label fn1, after_fn1;
2567 
2568   __ Mov(x28, sp);
2569   __ Mov(x29, lr);
2570   __ Mov(sp, 0x477d469dec0b8760);
2571 
2572   __ Mov(x0, 0);
2573   __ B(&after_fn1);
2574 
2575   __ Bind(&fn1);
2576   __ Mov(x0, 42);
2577   __ Paciasp();
2578   __ Retaa();
2579 
2580   __ Bind(&after_fn1);
2581   __ Bl(&fn1);
2582 
2583   Label fn2, after_fn2;
2584 
2585   __ Mov(x1, 0);
2586   __ B(&after_fn2);
2587 
2588   __ Bind(&fn2);
2589   __ Mov(x1, 84);
2590   __ Pacibsp();
2591   __ Retab();
2592 
2593   __ Bind(&after_fn2);
2594   __ Bl(&fn2);
2595 
2596   __ Mov(sp, x28);
2597   __ Mov(lr, x29);
2598   END();
2599 
2600   if (CAN_RUN()) {
2601     RUN();
2602 
2603     ASSERT_EQUAL_64(42, x0);
2604     ASSERT_EQUAL_64(84, x1);
2605   }
2606 }
2607 
TEST(return_to_reg_auth_guarded)2608 TEST(return_to_reg_auth_guarded) {
2609   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2610 
2611   START();
2612 
2613   Label fn1, after_fn1;
2614 
2615   __ Mov(x28, sp);
2616   __ Mov(x29, lr);
2617   __ Mov(sp, 0x477d469dec0b8760);
2618 
2619   __ Mov(x0, 0);
2620   __ B(&after_fn1);
2621 
2622   __ Bind(&fn1, EmitPACIASP);
2623   __ Mov(x0, 42);
2624   __ Retaa();
2625 
2626   __ Bind(&after_fn1);
2627   __ Adr(x2, &fn1);
2628   __ Blr(x2);
2629 
2630   Label fn2, after_fn2;
2631 
2632   __ Mov(x1, 0);
2633   __ B(&after_fn2);
2634 
2635   __ Bind(&fn2, EmitPACIBSP);
2636   __ Mov(x1, 84);
2637   __ Retab();
2638 
2639   __ Bind(&after_fn2);
2640   __ Adr(x2, &fn2);
2641   __ Blr(x2);
2642 
2643   __ Mov(sp, x28);
2644   __ Mov(lr, x29);
2645   END();
2646 
2647   if (CAN_RUN()) {
2648 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
2649     simulator.SetGuardedPages(true);
2650 #endif
2651     // On hardware, we'll run the test anyway, but mark it as SKIPPED until
2652     // we've implemented a mechanism for marking Guarded pages.
2653 
2654     RUN();
2655 
2656     ASSERT_EQUAL_64(42, x0);
2657     ASSERT_EQUAL_64(84, x1);
2658 
2659 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
2660     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
2661 #endif
2662   }
2663 }
2664 
2665 #ifdef VIXL_NEGATIVE_TESTING
TEST(branch_to_reg_auth_fail)2666 TEST(branch_to_reg_auth_fail) {
2667   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2668 
2669   START();
2670 
2671   Label fn1, after_fn1;
2672 
2673   __ Mov(x29, lr);
2674 
2675   __ B(&after_fn1);
2676 
2677   __ Bind(&fn1);
2678   __ Mov(x0, lr);
2679   __ Pacizb(x0);
2680   __ Blraaz(x0);
2681 
2682   __ Bind(&after_fn1);
2683   // There is a small but not negligible chance (1 in 127 runs) that the PAC
2684   // codes for keys A and B will collide and BLRAAZ won't abort. To mitigate
2685   // this, we simply repeat the test a few more times.
2686   for (unsigned i = 0; i < 32; i++) {
2687     __ Bl(&fn1);
2688   }
2689 
2690   __ Mov(lr, x29);
2691   END();
2692 
2693   if (CAN_RUN()) {
2694 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
2695     MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
2696 #else
2697     printf("SKIPPED: negative PAuth tests are unimplemented on hardware.");
2698 #endif
2699   }
2700 }
2701 #endif  // VIXL_NEGATIVE_TESTING
2702 
2703 #ifdef VIXL_NEGATIVE_TESTING
TEST(return_to_reg_auth_fail)2704 TEST(return_to_reg_auth_fail) {
2705   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2706 
2707   START();
2708 
2709   Label fn1, after_fn1;
2710 
2711   __ Mov(x28, sp);
2712   __ Mov(x29, lr);
2713   __ Mov(sp, 0x477d469dec0b8760);
2714 
2715   __ B(&after_fn1);
2716 
2717   __ Bind(&fn1);
2718   __ Paciasp();
2719   __ Retab();
2720 
2721   __ Bind(&after_fn1);
2722   // There is a small but not negligible chance (1 in 127 runs) that the PAC
2723   // codes for keys A and B will collide and RETAB won't abort. To mitigate
2724   // this, we simply repeat the test a few more times.
2725   for (unsigned i = 0; i < 32; i++) {
2726     __ Bl(&fn1);
2727   }
2728 
2729   __ Mov(sp, x28);
2730   __ Mov(lr, x29);
2731   END();
2732 
2733   if (CAN_RUN()) {
2734 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
2735     MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
2736 #else
2737     printf("SKIPPED: negative PAuth tests are unimplemented on hardware.");
2738 #endif
2739   }
2740 }
2741 #endif  // VIXL_NEGATIVE_TESTING
2742 
TEST(branch_to_reg_auth_a_zero)2743 TEST(branch_to_reg_auth_a_zero) {
2744   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2745 
2746   START();
2747 
2748   Label fn1, after_fn1;
2749 
2750   __ Mov(x29, lr);
2751 
2752   __ Mov(x1, 0);
2753   __ B(&after_fn1);
2754 
2755   __ Bind(&fn1);
2756   __ Mov(x0, lr);
2757   __ Mov(x1, 42);
2758   __ Paciza(x0);
2759   __ Braaz(x0);
2760 
2761   __ Bind(&after_fn1);
2762   __ Bl(&fn1);
2763 
2764   Label fn2, after_fn2, after_bl2;
2765 
2766   __ Mov(x2, 0);
2767   __ B(&after_fn2);
2768 
2769   __ Bind(&fn2);
2770   __ Mov(x0, lr);
2771   __ Mov(x2, 84);
2772   __ Paciza(x0);
2773   __ Blraaz(x0);
2774 
2775   __ Bind(&after_fn2);
2776   __ Bl(&fn2);
2777   __ Bind(&after_bl2);
2778   __ Mov(x3, lr);
2779   __ Adr(x4, &after_bl2);
2780   __ Adr(x5, &after_fn2);
2781 
2782   __ Xpaci(x0);
2783   __ Mov(lr, x29);
2784   END();
2785 
2786   if (CAN_RUN()) {
2787     RUN();
2788 
2789     ASSERT_EQUAL_64(x4, x0);
2790     ASSERT_EQUAL_64(x5, x3);
2791     ASSERT_EQUAL_64(42, x1);
2792     ASSERT_EQUAL_64(84, x2);
2793   }
2794 }
2795 
2796 
TEST(compare_branch)2797 TEST(compare_branch) {
2798   SETUP();
2799 
2800   START();
2801   __ Mov(x0, 0);
2802   __ Mov(x1, 0);
2803   __ Mov(x2, 0);
2804   __ Mov(x3, 0);
2805   __ Mov(x4, 0);
2806   __ Mov(x5, 0);
2807   __ Mov(x16, 0);
2808   __ Mov(x17, 42);
2809 
2810   Label zt, zt_end;
2811   __ Cbz(w16, &zt);
2812   __ B(&zt_end);
2813   __ Bind(&zt);
2814   __ Mov(x0, 1);
2815   __ Bind(&zt_end);
2816 
2817   Label zf, zf_end;
2818   __ Cbz(x17, &zf);
2819   __ B(&zf_end);
2820   __ Bind(&zf);
2821   __ Mov(x1, 1);
2822   __ Bind(&zf_end);
2823 
2824   Label nzt, nzt_end;
2825   __ Cbnz(w17, &nzt);
2826   __ B(&nzt_end);
2827   __ Bind(&nzt);
2828   __ Mov(x2, 1);
2829   __ Bind(&nzt_end);
2830 
2831   Label nzf, nzf_end;
2832   __ Cbnz(x16, &nzf);
2833   __ B(&nzf_end);
2834   __ Bind(&nzf);
2835   __ Mov(x3, 1);
2836   __ Bind(&nzf_end);
2837 
2838   __ Mov(x18, 0xffffffff00000000);
2839 
2840   Label a, a_end;
2841   __ Cbz(w18, &a);
2842   __ B(&a_end);
2843   __ Bind(&a);
2844   __ Mov(x4, 1);
2845   __ Bind(&a_end);
2846 
2847   Label b, b_end;
2848   __ Cbnz(w18, &b);
2849   __ B(&b_end);
2850   __ Bind(&b);
2851   __ Mov(x5, 1);
2852   __ Bind(&b_end);
2853 
2854   END();
2855 
2856   if (CAN_RUN()) {
2857     RUN();
2858 
2859     ASSERT_EQUAL_64(1, x0);
2860     ASSERT_EQUAL_64(0, x1);
2861     ASSERT_EQUAL_64(1, x2);
2862     ASSERT_EQUAL_64(0, x3);
2863     ASSERT_EQUAL_64(1, x4);
2864     ASSERT_EQUAL_64(0, x5);
2865   }
2866 }
2867 
2868 
TEST(test_branch)2869 TEST(test_branch) {
2870   SETUP();
2871 
2872   START();
2873   __ Mov(x0, 0);
2874   __ Mov(x1, 0);
2875   __ Mov(x2, 0);
2876   __ Mov(x3, 0);
2877   __ Mov(x16, 0xaaaaaaaaaaaaaaaa);
2878 
2879   Label bz, bz_end;
2880   __ Tbz(w16, 0, &bz);
2881   __ B(&bz_end);
2882   __ Bind(&bz);
2883   __ Mov(x0, 1);
2884   __ Bind(&bz_end);
2885 
2886   Label bo, bo_end;
2887   __ Tbz(x16, 63, &bo);
2888   __ B(&bo_end);
2889   __ Bind(&bo);
2890   __ Mov(x1, 1);
2891   __ Bind(&bo_end);
2892 
2893   Label nbz, nbz_end;
2894   __ Tbnz(x16, 61, &nbz);
2895   __ B(&nbz_end);
2896   __ Bind(&nbz);
2897   __ Mov(x2, 1);
2898   __ Bind(&nbz_end);
2899 
2900   Label nbo, nbo_end;
2901   __ Tbnz(w16, 2, &nbo);
2902   __ B(&nbo_end);
2903   __ Bind(&nbo);
2904   __ Mov(x3, 1);
2905   __ Bind(&nbo_end);
2906   END();
2907 
2908   if (CAN_RUN()) {
2909     RUN();
2910 
2911     ASSERT_EQUAL_64(1, x0);
2912     ASSERT_EQUAL_64(0, x1);
2913     ASSERT_EQUAL_64(1, x2);
2914     ASSERT_EQUAL_64(0, x3);
2915   }
2916 }
2917 
2918 
TEST(branch_type)2919 TEST(branch_type) {
2920   SETUP();
2921 
2922   Label fail, done;
2923 
2924   START();
2925   __ Mov(x0, 0x0);
2926   __ Mov(x10, 0x7);
2927   __ Mov(x11, 0x0);
2928 
2929   // Test non taken branches.
2930   __ Cmp(x10, 0x7);
2931   __ B(&fail, ne);
2932   __ B(&fail, never);
2933   __ B(&fail, reg_zero, x10);
2934   __ B(&fail, reg_not_zero, x11);
2935   __ B(&fail, reg_bit_clear, x10, 0);
2936   __ B(&fail, reg_bit_set, x10, 3);
2937 
2938   // Test taken branches.
2939   Label l1, l2, l3, l4, l5;
2940   __ Cmp(x10, 0x7);
2941   __ B(&l1, eq);
2942   __ B(&fail);
2943   __ Bind(&l1);
2944   __ B(&l2, always);
2945   __ B(&fail);
2946   __ Bind(&l2);
2947   __ B(&l3, reg_not_zero, x10);
2948   __ B(&fail);
2949   __ Bind(&l3);
2950   __ B(&l4, reg_bit_clear, x10, 15);
2951   __ B(&fail);
2952   __ Bind(&l4);
2953   __ B(&l5, reg_bit_set, x10, 1);
2954   __ B(&fail);
2955   __ Bind(&l5);
2956 
2957   __ B(&done);
2958 
2959   __ Bind(&fail);
2960   __ Mov(x0, 0x1);
2961 
2962   __ Bind(&done);
2963 
2964   END();
2965 
2966   if (CAN_RUN()) {
2967     RUN();
2968 
2969     ASSERT_EQUAL_64(0x0, x0);
2970   }
2971 }
2972 
2973 enum MTEStgAttribute {
2974   StgNoSideEffect = 0,
2975   StgPairTag = 1,
2976   StgZeroing = 2,
2977   StgPairReg = 4
2978 };
2979 
2980 // Support st2g, stg, stz2g and stzg.
2981 template <typename Op>
MTEStoreTagHelper(Op op,AddrMode addr_mode,int attr=StgNoSideEffect)2982 static void MTEStoreTagHelper(Op op,
2983                               AddrMode addr_mode,
2984                               int attr = StgNoSideEffect) {
2985   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
2986   START();
2987 
2988   // This method does nothing when the size is zero. i.e. stg and st2g.
2989   // Reserve x9 and x10.
2990   auto LoadDataAndSum = [&](Register reg, int off, unsigned size_in_bytes) {
2991     for (unsigned j = 0; j < size_in_bytes / kXRegSizeInBytes; j++) {
2992       __ Ldr(x9, MemOperand(reg, off));
2993       __ Add(x10, x9, x10);
2994       off += kXRegSizeInBytes;
2995     }
2996   };
2997 
2998   // Initialize registers to zero.
2999   for (int i = 0; i < 29; i++) {
3000     __ Mov(XRegister(i), 0);
3001   }
3002 
3003   Register base = x28;
3004   Register base_tag = x27;
3005   uint32_t* data_ptr = nullptr;
3006   const int data_size = 640;
3007 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3008   data_ptr = reinterpret_cast<uint32_t*>(
3009       simulator.Mmap(NULL,
3010                      data_size * sizeof(uint32_t),
3011                      PROT_READ | PROT_WRITE | PROT_MTE,
3012                      MAP_PRIVATE | MAP_ANONYMOUS,
3013                      -1,
3014                      0));
3015 
3016   VIXL_ASSERT(data_ptr != nullptr);
3017   uint32_t* untagged_ptr = AddressUntag(data_ptr);
3018   memset(untagged_ptr, 0xae, data_size * sizeof(uint32_t));
3019 #else
3020 // TODO: Port the memory allocation to work on MTE supported platform natively.
3021 // Note that `CAN_RUN` prevents running in MTE-unsupported environments.
3022 #endif
3023 
3024   __ Mov(base, reinterpret_cast<uint64_t>(&data_ptr[data_size / 2]));
3025 
3026   VIXL_STATIC_ASSERT(kMTETagGranuleInBytes == 16);
3027   const int tag_granule = kMTETagGranuleInBytes;
3028   int size = ((attr & StgZeroing) != 0) ? tag_granule : 0;
3029   // lsb of MTE tag field.
3030   const int tag_lsb = 56;
3031 
3032   for (int i = 1; i < 7; i++) {
3033     uint64_t tag = static_cast<uint64_t>(i) << tag_lsb;
3034     int offset = 2 * i * tag_granule;
3035     __ Mov(XRegister(i), tag);
3036     (masm.*op)(XRegister(i), MemOperand(base, offset, addr_mode));
3037 
3038     // The address tag has been changed after the execution of store tag
3039     // instructions, so update the pointer tag as well.
3040     __ Bic(base_tag, base, 0x0f00000000000000);
3041     __ Orr(base_tag, base_tag, XRegister(i));
3042 
3043     switch (addr_mode) {
3044       case Offset:
3045         __ Ldg(XRegister(i + 10), MemOperand(base_tag, offset));
3046         LoadDataAndSum(base_tag, offset, size);
3047         if ((attr & StgPairTag) != 0) {
3048           __ Ldg(XRegister(i + 20), MemOperand(base_tag, offset + tag_granule));
3049           LoadDataAndSum(base_tag, offset + tag_granule, size);
3050         }
3051         break;
3052 
3053       case PreIndex:
3054         __ Ldg(XRegister(i + 10), MemOperand(base_tag));
3055         LoadDataAndSum(base_tag, 0, size);
3056         if ((attr & StgPairTag) != 0) {
3057           __ Ldg(XRegister(i + 20), MemOperand(base_tag, tag_granule));
3058           LoadDataAndSum(base_tag, tag_granule, size);
3059         }
3060         break;
3061 
3062       case PostIndex:
3063         __ Ldg(XRegister(i + 10), MemOperand(base_tag, -offset));
3064         LoadDataAndSum(base_tag, -offset, size);
3065         if ((attr & StgPairTag) != 0) {
3066           __ Ldg(XRegister(i + 20),
3067                  MemOperand(base_tag, -offset + tag_granule));
3068           LoadDataAndSum(base_tag, -offset + tag_granule, size);
3069         }
3070         break;
3071 
3072       default:
3073         VIXL_UNIMPLEMENTED();
3074         break;
3075     }
3076 
3077     // Switch the sign to test both positive and negative offsets.
3078     offset = -offset;
3079   }
3080 
3081   int pos_offset = 304;
3082   int neg_offset = -256;
3083 
3084   // Backup stack pointer and others.
3085   __ Mov(x7, sp);
3086   __ Mov(base_tag, base);
3087 
3088   // Test the cases where operand is the stack pointer.
3089   __ Mov(x8, 11UL << tag_lsb);
3090   __ Mov(sp, x8);
3091   (masm.*op)(sp, MemOperand(base, neg_offset, addr_mode));
3092 
3093   // Synthesise a new address with new tag and assign to the stack pointer.
3094   __ Add(sp, base_tag, 32);
3095   (masm.*op)(x8, MemOperand(sp, pos_offset, addr_mode));
3096 
3097   switch (addr_mode) {
3098     case Offset:
3099       __ Ldg(x17, MemOperand(base, neg_offset));
3100       __ Ldg(x19, MemOperand(sp, pos_offset));
3101       if ((attr & StgPairTag) != 0) {
3102         __ Ldg(x18, MemOperand(base, neg_offset + tag_granule));
3103         __ Ldg(x20, MemOperand(sp, pos_offset + tag_granule));
3104       }
3105       break;
3106     case PreIndex:
3107       __ Ldg(x17, MemOperand(base));
3108       __ Ldg(x19, MemOperand(sp));
3109       if ((attr & StgPairTag) != 0) {
3110         __ Ldg(x18, MemOperand(base, tag_granule));
3111         __ Ldg(x20, MemOperand(sp, tag_granule));
3112       }
3113       break;
3114     case PostIndex:
3115       __ Ldg(x17, MemOperand(base, -neg_offset));
3116       __ Ldg(x19, MemOperand(sp, -pos_offset));
3117       if ((attr & StgPairTag) != 0) {
3118         __ Ldg(x18, MemOperand(base, -neg_offset + tag_granule));
3119         __ Ldg(x20, MemOperand(sp, -pos_offset + tag_granule));
3120       }
3121       break;
3122     default:
3123       VIXL_UNIMPLEMENTED();
3124       break;
3125   }
3126 
3127   // Restore stack pointer.
3128   __ Mov(sp, x7);
3129 
3130   END();
3131 
3132   if (CAN_RUN()) {
3133 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
3134     VIXL_UNIMPLEMENTED();
3135 #endif
3136     RUN();
3137 
3138     ASSERT_EQUAL_64(1UL << tag_lsb, x11);
3139     ASSERT_EQUAL_64(2UL << tag_lsb, x12);
3140     ASSERT_EQUAL_64(3UL << tag_lsb, x13);
3141     ASSERT_EQUAL_64(4UL << tag_lsb, x14);
3142     ASSERT_EQUAL_64(5UL << tag_lsb, x15);
3143     ASSERT_EQUAL_64(6UL << tag_lsb, x16);
3144     ASSERT_EQUAL_64(11UL << tag_lsb, x17);
3145     ASSERT_EQUAL_64(11UL << tag_lsb, x19);
3146 
3147     if ((attr & StgPairTag) != 0) {
3148       ASSERT_EQUAL_64(1UL << tag_lsb, x21);
3149       ASSERT_EQUAL_64(2UL << tag_lsb, x22);
3150       ASSERT_EQUAL_64(3UL << tag_lsb, x23);
3151       ASSERT_EQUAL_64(4UL << tag_lsb, x24);
3152       ASSERT_EQUAL_64(5UL << tag_lsb, x25);
3153       ASSERT_EQUAL_64(6UL << tag_lsb, x26);
3154       ASSERT_EQUAL_64(11UL << tag_lsb, x18);
3155       ASSERT_EQUAL_64(11UL << tag_lsb, x20);
3156     }
3157 
3158     if ((attr & StgZeroing) != 0) {
3159       ASSERT_EQUAL_64(0, x10);
3160     }
3161   }
3162 
3163 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3164   simulator.Munmap(data_ptr, data_size, PROT_MTE);
3165 #endif
3166 }
3167 
TEST(st2g_ldg)3168 TEST(st2g_ldg) {
3169   MTEStoreTagHelper(&MacroAssembler::St2g, Offset, StgPairTag);
3170   MTEStoreTagHelper(&MacroAssembler::St2g, PreIndex, StgPairTag);
3171   MTEStoreTagHelper(&MacroAssembler::St2g, PostIndex, StgPairTag);
3172 }
3173 
TEST(stg_ldg)3174 TEST(stg_ldg) {
3175   MTEStoreTagHelper(&MacroAssembler::Stg, Offset);
3176   MTEStoreTagHelper(&MacroAssembler::Stg, PreIndex);
3177   MTEStoreTagHelper(&MacroAssembler::Stg, PostIndex);
3178 }
3179 
TEST(stz2g_ldg)3180 TEST(stz2g_ldg) {
3181   MTEStoreTagHelper(&MacroAssembler::Stz2g, Offset, StgPairTag | StgZeroing);
3182   MTEStoreTagHelper(&MacroAssembler::Stz2g, PreIndex, StgPairTag | StgZeroing);
3183   MTEStoreTagHelper(&MacroAssembler::Stz2g, PostIndex, StgPairTag | StgZeroing);
3184 }
3185 
TEST(stzg_ldg)3186 TEST(stzg_ldg) {
3187   MTEStoreTagHelper(&MacroAssembler::Stzg, Offset, StgZeroing);
3188   MTEStoreTagHelper(&MacroAssembler::Stzg, PreIndex, StgZeroing);
3189   MTEStoreTagHelper(&MacroAssembler::Stzg, PostIndex, StgZeroing);
3190 }
3191 
TEST(stgp_ldg)3192 TEST(stgp_ldg) {
3193   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
3194   START();
3195 
3196   // Initialize registers to zero.
3197   for (int i = 0; i < 29; i++) {
3198     __ Mov(XRegister(i), 0);
3199   }
3200 
3201   // Reserve x14 and x15.
3202   auto LoadDataAndSum = [&](Register reg, int off) {
3203     __ Ldr(x14, MemOperand(reg, off));
3204     __ Add(x15, x14, x15);
3205     __ Ldr(x14, MemOperand(reg, off + static_cast<int>(kXRegSizeInBytes)));
3206     __ Add(x15, x14, x15);
3207   };
3208 
3209   Register base = x28;
3210   uint32_t* data_ptr = nullptr;
3211   const int data_size = 640;
3212   uint64_t init_tag = 17;
3213 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3214   data_ptr = reinterpret_cast<uint32_t*>(
3215       simulator.Mmap(NULL,
3216                      data_size * sizeof(uint32_t),
3217                      PROT_READ | PROT_WRITE | PROT_MTE,
3218                      MAP_PRIVATE | MAP_ANONYMOUS,
3219                      -1,
3220                      0));
3221 
3222   VIXL_ASSERT(data_ptr != nullptr);
3223   init_tag = CPU::GetPointerTag(data_ptr);
3224   uint32_t* untagged_ptr = AddressUntag(data_ptr);
3225   memset(untagged_ptr, 0xc9, data_size * sizeof(uint32_t));
3226 #else
3227 // TODO: Port the memory allocation to work on MTE supported platform natively.
3228 // Note that `CAN_RUN` prevents running in MTE-unsupported environments.
3229 #endif
3230 
3231   __ Mov(base, reinterpret_cast<uint64_t>(&data_ptr[data_size / 2]));
3232 
3233   // lsb of MTE tag field.
3234   const int tag_lsb = 56;
3235   for (int i = 0; i < 11; i++) {
3236     // <63..60> <59..56> <55........5> <4..0>
3237     //        0       i             0      i
3238     __ Mov(XRegister(i), i | (static_cast<uint64_t>(i) << tag_lsb));
3239   }
3240 
3241   // Backup stack pointer.
3242   __ Mov(x0, sp);
3243 
3244   int offset = -16;
3245   __ Addg(base, base, 0, 1);
3246   __ Stgp(x1, x2, MemOperand(base, offset, Offset));
3247   // Make sure `ldg` works well with address that isn't tag-granule aligned.
3248   __ Add(x29, base, 8);
3249   __ Ldg(x18, MemOperand(x29, offset));
3250   LoadDataAndSum(base, offset);
3251 
3252   offset = -304;
3253   __ Addg(base, base, 0, 1);
3254   __ Stgp(x2, x3, MemOperand(base, offset, Offset));
3255   __ Add(x29, base, 4);
3256   __ Ldg(x19, MemOperand(x29, offset));
3257   LoadDataAndSum(base, offset);
3258 
3259   offset = 128;
3260   __ Addg(base, base, 0, 1);
3261   __ Stgp(x3, x4, MemOperand(base, offset, Offset));
3262   __ Mov(sp, base);
3263   __ Ldg(x20, MemOperand(sp, offset));
3264   LoadDataAndSum(base, offset);
3265 
3266   offset = -48;
3267   __ Addg(base, base, 0, 1);
3268   __ Stgp(x4, x5, MemOperand(base, offset, PreIndex));
3269   __ Add(x29, base, 8);
3270   __ Ldg(x21, MemOperand(x29));
3271   LoadDataAndSum(base, 0);
3272 
3273   offset = 64;
3274   __ Addg(base, base, 0, 1);
3275   __ Stgp(x5, x6, MemOperand(base, offset, PreIndex));
3276   __ Add(x29, base, 4);
3277   __ Ldg(x22, MemOperand(x29));
3278   LoadDataAndSum(base, 0);
3279 
3280   offset = -288;
3281   __ Addg(base, base, 0, 1);
3282   __ Stgp(x6, x7, MemOperand(base, offset, PreIndex));
3283   __ Mov(sp, base);
3284   __ Ldg(x23, MemOperand(sp));
3285   LoadDataAndSum(base, 0);
3286 
3287   offset = -96;
3288   __ Addg(base, base, 0, 1);
3289   __ Stgp(x7, x8, MemOperand(base, offset, PostIndex));
3290   __ Add(x29, base, 8);
3291   __ Ldg(x24, MemOperand(x29, -offset));
3292   LoadDataAndSum(base, -offset);
3293 
3294   offset = 80;
3295   __ Addg(base, base, 0, 1);
3296   __ Stgp(x8, x9, MemOperand(base, offset, PostIndex));
3297   __ Add(x29, base, 4);
3298   __ Ldg(x25, MemOperand(x29, -offset));
3299   LoadDataAndSum(base, -offset);
3300 
3301   offset = -224;
3302   __ Addg(base, base, 0, 1);
3303   __ Stgp(x9, x10, MemOperand(base, offset, PostIndex));
3304   __ Mov(sp, base);
3305   __ Ldg(x26, MemOperand(sp, -offset));
3306   LoadDataAndSum(base, -offset);
3307 
3308   __ Mov(sp, x0);
3309 
3310   END();
3311 
3312   if (CAN_RUN()) {
3313 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
3314     VIXL_UNIMPLEMENTED();
3315 #endif
3316     RUN();
3317 
3318     const uint64_t k = kMTETagGranuleInBytes;
3319     USE(k);
3320     ASSERT_EQUAL_64(((init_tag + 1) % k) << tag_lsb, x18);
3321     ASSERT_EQUAL_64(((init_tag + 2) % k) << tag_lsb, x19);
3322     ASSERT_EQUAL_64(((init_tag + 3) % k) << tag_lsb, x20);
3323     ASSERT_EQUAL_64(((init_tag + 4) % k) << tag_lsb, x21);
3324     ASSERT_EQUAL_64(((init_tag + 5) % k) << tag_lsb, x22);
3325     ASSERT_EQUAL_64(((init_tag + 6) % k) << tag_lsb, x23);
3326     ASSERT_EQUAL_64(((init_tag + 7) % k) << tag_lsb, x24);
3327     ASSERT_EQUAL_64(((init_tag + 8) % k) << tag_lsb, x25);
3328     ASSERT_EQUAL_64(((init_tag + 9) % k) << tag_lsb, x26);
3329 
3330     // We store 1, 2, 2, 3, 3, 4, ....9, 9, 10 to memory, so the total sum of
3331     // these values is 1 + (2 * (2 + 9) * 8 / 2) + 10 = 99.
3332     ASSERT_EQUAL_64((99UL << tag_lsb | 99UL), x15);
3333   }
3334 
3335 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3336   simulator.Munmap(data_ptr, data_size, PROT_MTE);
3337 #endif
3338 }
3339 
TEST(ldr_str_offset)3340 TEST(ldr_str_offset) {
3341   SETUP();
3342 
3343   uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3344   uint64_t dst[5] = {0, 0, 0, 0, 0};
3345   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3346   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3347 
3348   START();
3349   __ Mov(x17, src_base);
3350   __ Mov(x18, dst_base);
3351   __ Ldr(w0, MemOperand(x17));
3352   __ Str(w0, MemOperand(x18));
3353   __ Ldr(w1, MemOperand(x17, 4));
3354   __ Str(w1, MemOperand(x18, 12));
3355   __ Ldr(x2, MemOperand(x17, 8));
3356   __ Str(x2, MemOperand(x18, 16));
3357   __ Ldrb(w3, MemOperand(x17, 1));
3358   __ Strb(w3, MemOperand(x18, 25));
3359   __ Ldrh(w4, MemOperand(x17, 2));
3360   __ Strh(w4, MemOperand(x18, 33));
3361   END();
3362 
3363   if (CAN_RUN()) {
3364     RUN();
3365 
3366     ASSERT_EQUAL_64(0x76543210, x0);
3367     ASSERT_EQUAL_64(0x76543210, dst[0]);
3368     ASSERT_EQUAL_64(0xfedcba98, x1);
3369     ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3370     ASSERT_EQUAL_64(0x0123456789abcdef, x2);
3371     ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3372     ASSERT_EQUAL_64(0x32, x3);
3373     ASSERT_EQUAL_64(0x3200, dst[3]);
3374     ASSERT_EQUAL_64(0x7654, x4);
3375     ASSERT_EQUAL_64(0x765400, dst[4]);
3376     ASSERT_EQUAL_64(src_base, x17);
3377     ASSERT_EQUAL_64(dst_base, x18);
3378   }
3379 }
3380 
3381 
TEST(ldr_str_wide)3382 TEST(ldr_str_wide) {
3383   SETUP();
3384 
3385   uint32_t src[8192];
3386   uint32_t dst[8192];
3387   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3388   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3389   memset(src, 0xaa, 8192 * sizeof(src[0]));
3390   memset(dst, 0xaa, 8192 * sizeof(dst[0]));
3391   src[0] = 0;
3392   src[6144] = 6144;
3393   src[8191] = 8191;
3394 
3395   START();
3396   __ Mov(x22, src_base);
3397   __ Mov(x23, dst_base);
3398   __ Mov(x24, src_base);
3399   __ Mov(x25, dst_base);
3400   __ Mov(x26, src_base);
3401   __ Mov(x27, dst_base);
3402 
3403   __ Ldr(w0, MemOperand(x22, 8191 * sizeof(src[0])));
3404   __ Str(w0, MemOperand(x23, 8191 * sizeof(dst[0])));
3405   __ Ldr(w1, MemOperand(x24, 4096 * sizeof(src[0]), PostIndex));
3406   __ Str(w1, MemOperand(x25, 4096 * sizeof(dst[0]), PostIndex));
3407   __ Ldr(w2, MemOperand(x26, 6144 * sizeof(src[0]), PreIndex));
3408   __ Str(w2, MemOperand(x27, 6144 * sizeof(dst[0]), PreIndex));
3409   END();
3410 
3411   if (CAN_RUN()) {
3412     RUN();
3413 
3414     ASSERT_EQUAL_32(8191, w0);
3415     ASSERT_EQUAL_32(8191, dst[8191]);
3416     ASSERT_EQUAL_64(src_base, x22);
3417     ASSERT_EQUAL_64(dst_base, x23);
3418     ASSERT_EQUAL_32(0, w1);
3419     ASSERT_EQUAL_32(0, dst[0]);
3420     ASSERT_EQUAL_64(src_base + 4096 * sizeof(src[0]), x24);
3421     ASSERT_EQUAL_64(dst_base + 4096 * sizeof(dst[0]), x25);
3422     ASSERT_EQUAL_32(6144, w2);
3423     ASSERT_EQUAL_32(6144, dst[6144]);
3424     ASSERT_EQUAL_64(src_base + 6144 * sizeof(src[0]), x26);
3425     ASSERT_EQUAL_64(dst_base + 6144 * sizeof(dst[0]), x27);
3426   }
3427 }
3428 
3429 
TEST(ldr_str_preindex)3430 TEST(ldr_str_preindex) {
3431   SETUP();
3432 
3433   uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3434   uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
3435   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3436   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3437 
3438   START();
3439   __ Mov(x17, src_base);
3440   __ Mov(x18, dst_base);
3441   __ Mov(x19, src_base);
3442   __ Mov(x20, dst_base);
3443   __ Mov(x21, src_base + 16);
3444   __ Mov(x22, dst_base + 40);
3445   __ Mov(x23, src_base);
3446   __ Mov(x24, dst_base);
3447   __ Mov(x25, src_base);
3448   __ Mov(x26, dst_base);
3449   __ Ldr(w0, MemOperand(x17, 4, PreIndex));
3450   __ Str(w0, MemOperand(x18, 12, PreIndex));
3451   __ Ldr(x1, MemOperand(x19, 8, PreIndex));
3452   __ Str(x1, MemOperand(x20, 16, PreIndex));
3453   __ Ldr(w2, MemOperand(x21, -4, PreIndex));
3454   __ Str(w2, MemOperand(x22, -4, PreIndex));
3455   __ Ldrb(w3, MemOperand(x23, 1, PreIndex));
3456   __ Strb(w3, MemOperand(x24, 25, PreIndex));
3457   __ Ldrh(w4, MemOperand(x25, 3, PreIndex));
3458   __ Strh(w4, MemOperand(x26, 41, PreIndex));
3459   END();
3460 
3461   if (CAN_RUN()) {
3462     RUN();
3463 
3464     ASSERT_EQUAL_64(0xfedcba98, x0);
3465     ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3466     ASSERT_EQUAL_64(0x0123456789abcdef, x1);
3467     ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3468     ASSERT_EQUAL_64(0x01234567, x2);
3469     ASSERT_EQUAL_64(0x0123456700000000, dst[4]);
3470     ASSERT_EQUAL_64(0x32, x3);
3471     ASSERT_EQUAL_64(0x3200, dst[3]);
3472     ASSERT_EQUAL_64(0x9876, x4);
3473     ASSERT_EQUAL_64(0x987600, dst[5]);
3474     ASSERT_EQUAL_64(src_base + 4, x17);
3475     ASSERT_EQUAL_64(dst_base + 12, x18);
3476     ASSERT_EQUAL_64(src_base + 8, x19);
3477     ASSERT_EQUAL_64(dst_base + 16, x20);
3478     ASSERT_EQUAL_64(src_base + 12, x21);
3479     ASSERT_EQUAL_64(dst_base + 36, x22);
3480     ASSERT_EQUAL_64(src_base + 1, x23);
3481     ASSERT_EQUAL_64(dst_base + 25, x24);
3482     ASSERT_EQUAL_64(src_base + 3, x25);
3483     ASSERT_EQUAL_64(dst_base + 41, x26);
3484   }
3485 }
3486 
3487 
TEST(ldr_str_postindex)3488 TEST(ldr_str_postindex) {
3489   SETUP();
3490 
3491   uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3492   uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
3493   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3494   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3495 
3496   START();
3497   __ Mov(x17, src_base + 4);
3498   __ Mov(x18, dst_base + 12);
3499   __ Mov(x19, src_base + 8);
3500   __ Mov(x20, dst_base + 16);
3501   __ Mov(x21, src_base + 8);
3502   __ Mov(x22, dst_base + 32);
3503   __ Mov(x23, src_base + 1);
3504   __ Mov(x24, dst_base + 25);
3505   __ Mov(x25, src_base + 3);
3506   __ Mov(x26, dst_base + 41);
3507   __ Ldr(w0, MemOperand(x17, 4, PostIndex));
3508   __ Str(w0, MemOperand(x18, 12, PostIndex));
3509   __ Ldr(x1, MemOperand(x19, 8, PostIndex));
3510   __ Str(x1, MemOperand(x20, 16, PostIndex));
3511   __ Ldr(x2, MemOperand(x21, -8, PostIndex));
3512   __ Str(x2, MemOperand(x22, -32, PostIndex));
3513   __ Ldrb(w3, MemOperand(x23, 1, PostIndex));
3514   __ Strb(w3, MemOperand(x24, 5, PostIndex));
3515   __ Ldrh(w4, MemOperand(x25, -3, PostIndex));
3516   __ Strh(w4, MemOperand(x26, -41, PostIndex));
3517   END();
3518 
3519   if (CAN_RUN()) {
3520     RUN();
3521 
3522     ASSERT_EQUAL_64(0xfedcba98, x0);
3523     ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3524     ASSERT_EQUAL_64(0x0123456789abcdef, x1);
3525     ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3526     ASSERT_EQUAL_64(0x0123456789abcdef, x2);
3527     ASSERT_EQUAL_64(0x0123456789abcdef, dst[4]);
3528     ASSERT_EQUAL_64(0x32, x3);
3529     ASSERT_EQUAL_64(0x3200, dst[3]);
3530     ASSERT_EQUAL_64(0x9876, x4);
3531     ASSERT_EQUAL_64(0x987600, dst[5]);
3532     ASSERT_EQUAL_64(src_base + 8, x17);
3533     ASSERT_EQUAL_64(dst_base + 24, x18);
3534     ASSERT_EQUAL_64(src_base + 16, x19);
3535     ASSERT_EQUAL_64(dst_base + 32, x20);
3536     ASSERT_EQUAL_64(src_base, x21);
3537     ASSERT_EQUAL_64(dst_base, x22);
3538     ASSERT_EQUAL_64(src_base + 2, x23);
3539     ASSERT_EQUAL_64(dst_base + 30, x24);
3540     ASSERT_EQUAL_64(src_base, x25);
3541     ASSERT_EQUAL_64(dst_base, x26);
3542   }
3543 }
3544 
3545 
TEST(ldr_str_largeindex)3546 TEST(ldr_str_largeindex) {
3547   SETUP();
3548 
3549   // This value won't fit in the immediate offset field of ldr/str instructions.
3550   int largeoffset = 0xabcdef;
3551 
3552   int64_t data[3] = {0x1122334455667788, 0, 0};
3553   uint64_t base_addr = reinterpret_cast<uintptr_t>(data);
3554   uint64_t drifted_addr = base_addr - largeoffset;
3555 
3556   // This test checks that we we can use large immediate offsets when
3557   // using PreIndex or PostIndex addressing mode of the MacroAssembler
3558   // Ldr/Str instructions.
3559 
3560   START();
3561   __ Mov(x19, drifted_addr);
3562   __ Ldr(x0, MemOperand(x19, largeoffset, PreIndex));
3563 
3564   __ Mov(x20, base_addr);
3565   __ Ldr(x1, MemOperand(x20, largeoffset, PostIndex));
3566 
3567   __ Mov(x21, drifted_addr);
3568   __ Str(x0, MemOperand(x21, largeoffset + 8, PreIndex));
3569 
3570   __ Mov(x22, base_addr + 16);
3571   __ Str(x0, MemOperand(x22, largeoffset, PostIndex));
3572   END();
3573 
3574   if (CAN_RUN()) {
3575     RUN();
3576 
3577     ASSERT_EQUAL_64(0x1122334455667788, data[0]);
3578     ASSERT_EQUAL_64(0x1122334455667788, data[1]);
3579     ASSERT_EQUAL_64(0x1122334455667788, data[2]);
3580     ASSERT_EQUAL_64(0x1122334455667788, x0);
3581     ASSERT_EQUAL_64(0x1122334455667788, x1);
3582 
3583     ASSERT_EQUAL_64(base_addr, x19);
3584     ASSERT_EQUAL_64(base_addr + largeoffset, x20);
3585     ASSERT_EQUAL_64(base_addr + 8, x21);
3586     ASSERT_EQUAL_64(base_addr + 16 + largeoffset, x22);
3587   }
3588 }
3589 
3590 
TEST(load_signed)3591 TEST(load_signed) {
3592   SETUP();
3593 
3594   uint32_t src[2] = {0x80008080, 0x7fff7f7f};
3595   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3596 
3597   START();
3598   __ Mov(x24, src_base);
3599   __ Ldrsb(w0, MemOperand(x24));
3600   __ Ldrsb(w1, MemOperand(x24, 4));
3601   __ Ldrsh(w2, MemOperand(x24));
3602   __ Ldrsh(w3, MemOperand(x24, 4));
3603   __ Ldrsb(x4, MemOperand(x24));
3604   __ Ldrsb(x5, MemOperand(x24, 4));
3605   __ Ldrsh(x6, MemOperand(x24));
3606   __ Ldrsh(x7, MemOperand(x24, 4));
3607   __ Ldrsw(x8, MemOperand(x24));
3608   __ Ldrsw(x9, MemOperand(x24, 4));
3609   END();
3610 
3611   if (CAN_RUN()) {
3612     RUN();
3613 
3614     ASSERT_EQUAL_64(0xffffff80, x0);
3615     ASSERT_EQUAL_64(0x0000007f, x1);
3616     ASSERT_EQUAL_64(0xffff8080, x2);
3617     ASSERT_EQUAL_64(0x00007f7f, x3);
3618     ASSERT_EQUAL_64(0xffffffffffffff80, x4);
3619     ASSERT_EQUAL_64(0x000000000000007f, x5);
3620     ASSERT_EQUAL_64(0xffffffffffff8080, x6);
3621     ASSERT_EQUAL_64(0x0000000000007f7f, x7);
3622     ASSERT_EQUAL_64(0xffffffff80008080, x8);
3623     ASSERT_EQUAL_64(0x000000007fff7f7f, x9);
3624   }
3625 }
3626 
3627 
TEST(load_store_regoffset)3628 TEST(load_store_regoffset) {
3629   SETUP();
3630 
3631   uint32_t src[3] = {1, 2, 3};
3632   uint32_t dst[4] = {0, 0, 0, 0};
3633   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3634   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3635 
3636   START();
3637   __ Mov(x16, src_base);
3638   __ Mov(x17, dst_base);
3639   __ Mov(x18, src_base + 3 * sizeof(src[0]));
3640   __ Mov(x19, dst_base + 3 * sizeof(dst[0]));
3641   __ Mov(x20, dst_base + 4 * sizeof(dst[0]));
3642   __ Mov(x24, 0);
3643   __ Mov(x25, 4);
3644   __ Mov(x26, -4);
3645   __ Mov(x27, 0xfffffffc);  // 32-bit -4.
3646   __ Mov(x28, 0xfffffffe);  // 32-bit -2.
3647   __ Mov(x29, 0xffffffff);  // 32-bit -1.
3648 
3649   __ Ldr(w0, MemOperand(x16, x24));
3650   __ Ldr(x1, MemOperand(x16, x25));
3651   __ Ldr(w2, MemOperand(x18, x26));
3652   __ Ldr(w3, MemOperand(x18, x27, SXTW));
3653   __ Ldr(w4, MemOperand(x18, x28, SXTW, 2));
3654   __ Str(w0, MemOperand(x17, x24));
3655   __ Str(x1, MemOperand(x17, x25));
3656   __ Str(w2, MemOperand(x20, x29, SXTW, 2));
3657   END();
3658 
3659   if (CAN_RUN()) {
3660     RUN();
3661 
3662     ASSERT_EQUAL_64(1, x0);
3663     ASSERT_EQUAL_64(0x0000000300000002, x1);
3664     ASSERT_EQUAL_64(3, x2);
3665     ASSERT_EQUAL_64(3, x3);
3666     ASSERT_EQUAL_64(2, x4);
3667     ASSERT_EQUAL_32(1, dst[0]);
3668     ASSERT_EQUAL_32(2, dst[1]);
3669     ASSERT_EQUAL_32(3, dst[2]);
3670     ASSERT_EQUAL_32(3, dst[3]);
3671   }
3672 }
3673 
3674 
TEST(load_pauth)3675 TEST(load_pauth) {
3676   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
3677 
3678   uint64_t src[4] = {1, 2, 3, 4};
3679   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3680 
3681   START();
3682   __ Mov(x16, src_base);
3683   __ Mov(x17, src_base);
3684   __ Mov(x18, src_base + 4 * sizeof(src[0]));
3685   __ Mov(x19, src_base + 4 * sizeof(src[0]));
3686 
3687   // Add PAC codes to addresses
3688   __ Pacdza(x16);
3689   __ Pacdzb(x17);
3690   __ Pacdza(x18);
3691   __ Pacdzb(x19);
3692 
3693   __ Ldraa(x0, MemOperand(x16));
3694   __ Ldraa(x1, MemOperand(x16, sizeof(src[0])));
3695   __ Ldraa(x2, MemOperand(x16, 2 * sizeof(src[0]), PreIndex));
3696   __ Ldraa(x3, MemOperand(x18, -sizeof(src[0])));
3697   __ Ldrab(x4, MemOperand(x17));
3698   __ Ldrab(x5, MemOperand(x17, sizeof(src[0])));
3699   __ Ldrab(x6, MemOperand(x17, 2 * sizeof(src[0]), PreIndex));
3700   __ Ldrab(x7, MemOperand(x19, -sizeof(src[0])));
3701   END();
3702 
3703   if (CAN_RUN()) {
3704     RUN();
3705 
3706     ASSERT_EQUAL_64(1, x0);
3707     ASSERT_EQUAL_64(2, x1);
3708     ASSERT_EQUAL_64(3, x2);
3709     ASSERT_EQUAL_64(4, x3);
3710     ASSERT_EQUAL_64(1, x4);
3711     ASSERT_EQUAL_64(2, x5);
3712     ASSERT_EQUAL_64(3, x6);
3713     ASSERT_EQUAL_64(4, x7);
3714     ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x16);
3715     ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x17);
3716   }
3717 }
3718 
3719 
3720 #ifdef VIXL_NEGATIVE_TESTING
TEST(load_pauth_negative_test)3721 TEST(load_pauth_negative_test) {
3722   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
3723 
3724   uint64_t src[4] = {1, 2, 3, 4};
3725   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3726 
3727   START();
3728   __ Mov(x16, src_base);
3729 
3730   // There is a small but not negligible chance (1 in 127 runs) that the PAC
3731   // codes for keys A and B will collide and LDRAB won't abort. To mitigate
3732   // this, we simply repeat the test a few more times.
3733   for (unsigned i = 0; i < 32; i++) {
3734     __ Add(x17, x16, i);
3735     __ Pacdza(x17);
3736     __ Ldrab(x0, MemOperand(x17));
3737   }
3738   END();
3739 
3740   if (CAN_RUN()) {
3741 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
3742     MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
3743 #else
3744     printf("SKIPPED: negative PAuth tests are unimplemented on hardware.");
3745 #endif
3746   }
3747 }
3748 #endif  // VIXL_NEGATIVE_TESTING
3749 
3750 
TEST(ldp_stp_offset)3751 TEST(ldp_stp_offset) {
3752   SETUP();
3753 
3754   uint64_t src[3] = {0x0011223344556677,
3755                      0x8899aabbccddeeff,
3756                      0xffeeddccbbaa9988};
3757   uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
3758   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3759   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3760 
3761   START();
3762   __ Mov(x16, src_base);
3763   __ Mov(x17, dst_base);
3764   __ Mov(x18, src_base + 24);
3765   __ Mov(x19, dst_base + 56);
3766   __ Ldp(w0, w1, MemOperand(x16));
3767   __ Ldp(w2, w3, MemOperand(x16, 4));
3768   __ Ldp(x4, x5, MemOperand(x16, 8));
3769   __ Ldp(w6, w7, MemOperand(x18, -12));
3770   __ Ldp(x8, x9, MemOperand(x18, -16));
3771   __ Stp(w0, w1, MemOperand(x17));
3772   __ Stp(w2, w3, MemOperand(x17, 8));
3773   __ Stp(x4, x5, MemOperand(x17, 16));
3774   __ Stp(w6, w7, MemOperand(x19, -24));
3775   __ Stp(x8, x9, MemOperand(x19, -16));
3776   END();
3777 
3778   if (CAN_RUN()) {
3779     RUN();
3780 
3781     ASSERT_EQUAL_64(0x44556677, x0);
3782     ASSERT_EQUAL_64(0x00112233, x1);
3783     ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3784     ASSERT_EQUAL_64(0x00112233, x2);
3785     ASSERT_EQUAL_64(0xccddeeff, x3);
3786     ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3787     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3788     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3789     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3790     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3791     ASSERT_EQUAL_64(0x8899aabb, x6);
3792     ASSERT_EQUAL_64(0xbbaa9988, x7);
3793     ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3794     ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3795     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3796     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3797     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3798     ASSERT_EQUAL_64(src_base, x16);
3799     ASSERT_EQUAL_64(dst_base, x17);
3800     ASSERT_EQUAL_64(src_base + 24, x18);
3801     ASSERT_EQUAL_64(dst_base + 56, x19);
3802   }
3803 }
3804 
3805 
TEST(ldp_stp_offset_wide)3806 TEST(ldp_stp_offset_wide) {
3807   SETUP();
3808 
3809   uint64_t src[3] = {0x0011223344556677,
3810                      0x8899aabbccddeeff,
3811                      0xffeeddccbbaa9988};
3812   uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
3813   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3814   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3815   // Move base too far from the array to force multiple instructions
3816   // to be emitted.
3817   const int64_t base_offset = 1024;
3818 
3819   START();
3820   __ Mov(x20, src_base - base_offset);
3821   __ Mov(x21, dst_base - base_offset);
3822   __ Mov(x18, src_base + base_offset + 24);
3823   __ Mov(x19, dst_base + base_offset + 56);
3824   __ Ldp(w0, w1, MemOperand(x20, base_offset));
3825   __ Ldp(w2, w3, MemOperand(x20, base_offset + 4));
3826   __ Ldp(x4, x5, MemOperand(x20, base_offset + 8));
3827   __ Ldp(w6, w7, MemOperand(x18, -12 - base_offset));
3828   __ Ldp(x8, x9, MemOperand(x18, -16 - base_offset));
3829   __ Stp(w0, w1, MemOperand(x21, base_offset));
3830   __ Stp(w2, w3, MemOperand(x21, base_offset + 8));
3831   __ Stp(x4, x5, MemOperand(x21, base_offset + 16));
3832   __ Stp(w6, w7, MemOperand(x19, -24 - base_offset));
3833   __ Stp(x8, x9, MemOperand(x19, -16 - base_offset));
3834   END();
3835 
3836   if (CAN_RUN()) {
3837     RUN();
3838 
3839     ASSERT_EQUAL_64(0x44556677, x0);
3840     ASSERT_EQUAL_64(0x00112233, x1);
3841     ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3842     ASSERT_EQUAL_64(0x00112233, x2);
3843     ASSERT_EQUAL_64(0xccddeeff, x3);
3844     ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3845     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3846     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3847     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3848     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3849     ASSERT_EQUAL_64(0x8899aabb, x6);
3850     ASSERT_EQUAL_64(0xbbaa9988, x7);
3851     ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3852     ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3853     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3854     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3855     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3856     ASSERT_EQUAL_64(src_base - base_offset, x20);
3857     ASSERT_EQUAL_64(dst_base - base_offset, x21);
3858     ASSERT_EQUAL_64(src_base + base_offset + 24, x18);
3859     ASSERT_EQUAL_64(dst_base + base_offset + 56, x19);
3860   }
3861 }
3862 
3863 
TEST(ldnp_stnp_offset)3864 TEST(ldnp_stnp_offset) {
3865   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3866 
3867   uint64_t src[4] = {0x0011223344556677,
3868                      0x8899aabbccddeeff,
3869                      0xffeeddccbbaa9988,
3870                      0x7766554433221100};
3871   uint64_t dst[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3872   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3873   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3874 
3875   START();
3876   __ Mov(x16, src_base);
3877   __ Mov(x17, dst_base);
3878   __ Mov(x18, src_base + 24);
3879   __ Mov(x19, dst_base + 64);
3880   __ Mov(x20, src_base + 32);
3881 
3882   // Ensure address set up has happened before executing non-temporal ops.
3883   __ Dmb(InnerShareable, BarrierAll);
3884 
3885   __ Ldnp(w0, w1, MemOperand(x16));
3886   __ Ldnp(w2, w3, MemOperand(x16, 4));
3887   __ Ldnp(x4, x5, MemOperand(x16, 8));
3888   __ Ldnp(w6, w7, MemOperand(x18, -12));
3889   __ Ldnp(x8, x9, MemOperand(x18, -16));
3890   __ Ldnp(q16, q17, MemOperand(x16));
3891   __ Ldnp(q19, q18, MemOperand(x20, -32));
3892   __ Stnp(w0, w1, MemOperand(x17));
3893   __ Stnp(w2, w3, MemOperand(x17, 8));
3894   __ Stnp(x4, x5, MemOperand(x17, 16));
3895   __ Stnp(w6, w7, MemOperand(x19, -32));
3896   __ Stnp(x8, x9, MemOperand(x19, -24));
3897   __ Stnp(q17, q16, MemOperand(x19));
3898   __ Stnp(q18, q19, MemOperand(x19, 32));
3899   END();
3900 
3901   if (CAN_RUN()) {
3902     RUN();
3903 
3904     ASSERT_EQUAL_64(0x44556677, x0);
3905     ASSERT_EQUAL_64(0x00112233, x1);
3906     ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3907     ASSERT_EQUAL_64(0x00112233, x2);
3908     ASSERT_EQUAL_64(0xccddeeff, x3);
3909     ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3910     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3911     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3912     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3913     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3914     ASSERT_EQUAL_64(0x8899aabb, x6);
3915     ASSERT_EQUAL_64(0xbbaa9988, x7);
3916     ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3917     ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3918     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3919     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3920     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3921     ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q16);
3922     ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q17);
3923     ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q18);
3924     ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q19);
3925     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[8]);
3926     ASSERT_EQUAL_64(0x7766554433221100, dst[9]);
3927     ASSERT_EQUAL_64(0x0011223344556677, dst[10]);
3928     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[11]);
3929     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[12]);
3930     ASSERT_EQUAL_64(0x7766554433221100, dst[13]);
3931     ASSERT_EQUAL_64(0x0011223344556677, dst[14]);
3932     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[15]);
3933     ASSERT_EQUAL_64(src_base, x16);
3934     ASSERT_EQUAL_64(dst_base, x17);
3935     ASSERT_EQUAL_64(src_base + 24, x18);
3936     ASSERT_EQUAL_64(dst_base + 64, x19);
3937     ASSERT_EQUAL_64(src_base + 32, x20);
3938   }
3939 }
3940 
TEST(ldp_stp_preindex)3941 TEST(ldp_stp_preindex) {
3942   SETUP();
3943 
3944   uint64_t src[3] = {0x0011223344556677,
3945                      0x8899aabbccddeeff,
3946                      0xffeeddccbbaa9988};
3947   uint64_t dst[5] = {0, 0, 0, 0, 0};
3948   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3949   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3950 
3951   START();
3952   __ Mov(x16, src_base);
3953   __ Mov(x17, dst_base);
3954   __ Mov(x18, dst_base + 16);
3955   __ Ldp(w0, w1, MemOperand(x16, 4, PreIndex));
3956   __ Mov(x19, x16);
3957   __ Ldp(w2, w3, MemOperand(x16, -4, PreIndex));
3958   __ Stp(w2, w3, MemOperand(x17, 4, PreIndex));
3959   __ Mov(x20, x17);
3960   __ Stp(w0, w1, MemOperand(x17, -4, PreIndex));
3961   __ Ldp(x4, x5, MemOperand(x16, 8, PreIndex));
3962   __ Mov(x21, x16);
3963   __ Ldp(x6, x7, MemOperand(x16, -8, PreIndex));
3964   __ Stp(x7, x6, MemOperand(x18, 8, PreIndex));
3965   __ Mov(x22, x18);
3966   __ Stp(x5, x4, MemOperand(x18, -8, PreIndex));
3967   END();
3968 
3969   if (CAN_RUN()) {
3970     RUN();
3971 
3972     ASSERT_EQUAL_64(0x00112233, x0);
3973     ASSERT_EQUAL_64(0xccddeeff, x1);
3974     ASSERT_EQUAL_64(0x44556677, x2);
3975     ASSERT_EQUAL_64(0x00112233, x3);
3976     ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
3977     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3978     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3979     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3980     ASSERT_EQUAL_64(0x0011223344556677, x6);
3981     ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
3982     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3983     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3984     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3985     ASSERT_EQUAL_64(src_base, x16);
3986     ASSERT_EQUAL_64(dst_base, x17);
3987     ASSERT_EQUAL_64(dst_base + 16, x18);
3988     ASSERT_EQUAL_64(src_base + 4, x19);
3989     ASSERT_EQUAL_64(dst_base + 4, x20);
3990     ASSERT_EQUAL_64(src_base + 8, x21);
3991     ASSERT_EQUAL_64(dst_base + 24, x22);
3992   }
3993 }
3994 
3995 
TEST(ldp_stp_preindex_wide)3996 TEST(ldp_stp_preindex_wide) {
3997   SETUP();
3998 
3999   uint64_t src[3] = {0x0011223344556677,
4000                      0x8899aabbccddeeff,
4001                      0xffeeddccbbaa9988};
4002   uint64_t dst[5] = {0, 0, 0, 0, 0};
4003   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4004   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4005   // Move base too far from the array to force multiple instructions
4006   // to be emitted.
4007   const int64_t base_offset = 1024;
4008 
4009   START();
4010   __ Mov(x24, src_base - base_offset);
4011   __ Mov(x25, dst_base + base_offset);
4012   __ Mov(x18, dst_base + base_offset + 16);
4013   __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PreIndex));
4014   __ Mov(x19, x24);
4015   __ Mov(x24, src_base - base_offset + 4);
4016   __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PreIndex));
4017   __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PreIndex));
4018   __ Mov(x20, x25);
4019   __ Mov(x25, dst_base + base_offset + 4);
4020   __ Mov(x24, src_base - base_offset);
4021   __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PreIndex));
4022   __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PreIndex));
4023   __ Mov(x21, x24);
4024   __ Mov(x24, src_base - base_offset + 8);
4025   __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PreIndex));
4026   __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PreIndex));
4027   __ Mov(x22, x18);
4028   __ Mov(x18, dst_base + base_offset + 16 + 8);
4029   __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PreIndex));
4030   END();
4031 
4032   if (CAN_RUN()) {
4033     RUN();
4034 
4035     ASSERT_EQUAL_64(0x00112233, x0);
4036     ASSERT_EQUAL_64(0xccddeeff, x1);
4037     ASSERT_EQUAL_64(0x44556677, x2);
4038     ASSERT_EQUAL_64(0x00112233, x3);
4039     ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
4040     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
4041     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
4042     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
4043     ASSERT_EQUAL_64(0x0011223344556677, x6);
4044     ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
4045     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
4046     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
4047     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
4048     ASSERT_EQUAL_64(src_base, x24);
4049     ASSERT_EQUAL_64(dst_base, x25);
4050     ASSERT_EQUAL_64(dst_base + 16, x18);
4051     ASSERT_EQUAL_64(src_base + 4, x19);
4052     ASSERT_EQUAL_64(dst_base + 4, x20);
4053     ASSERT_EQUAL_64(src_base + 8, x21);
4054     ASSERT_EQUAL_64(dst_base + 24, x22);
4055   }
4056 }
4057 
4058 
TEST(ldp_stp_postindex)4059 TEST(ldp_stp_postindex) {
4060   SETUP();
4061 
4062   uint64_t src[4] = {0x0011223344556677,
4063                      0x8899aabbccddeeff,
4064                      0xffeeddccbbaa9988,
4065                      0x7766554433221100};
4066   uint64_t dst[5] = {0, 0, 0, 0, 0};
4067   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4068   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4069 
4070   START();
4071   __ Mov(x16, src_base);
4072   __ Mov(x17, dst_base);
4073   __ Mov(x18, dst_base + 16);
4074   __ Ldp(w0, w1, MemOperand(x16, 4, PostIndex));
4075   __ Mov(x19, x16);
4076   __ Ldp(w2, w3, MemOperand(x16, -4, PostIndex));
4077   __ Stp(w2, w3, MemOperand(x17, 4, PostIndex));
4078   __ Mov(x20, x17);
4079   __ Stp(w0, w1, MemOperand(x17, -4, PostIndex));
4080   __ Ldp(x4, x5, MemOperand(x16, 8, PostIndex));
4081   __ Mov(x21, x16);
4082   __ Ldp(x6, x7, MemOperand(x16, -8, PostIndex));
4083   __ Stp(x7, x6, MemOperand(x18, 8, PostIndex));
4084   __ Mov(x22, x18);
4085   __ Stp(x5, x4, MemOperand(x18, -8, PostIndex));
4086   END();
4087 
4088   if (CAN_RUN()) {
4089     RUN();
4090 
4091     ASSERT_EQUAL_64(0x44556677, x0);
4092     ASSERT_EQUAL_64(0x00112233, x1);
4093     ASSERT_EQUAL_64(0x00112233, x2);
4094     ASSERT_EQUAL_64(0xccddeeff, x3);
4095     ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
4096     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
4097     ASSERT_EQUAL_64(0x0011223344556677, x4);
4098     ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
4099     ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
4100     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
4101     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
4102     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
4103     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
4104     ASSERT_EQUAL_64(src_base, x16);
4105     ASSERT_EQUAL_64(dst_base, x17);
4106     ASSERT_EQUAL_64(dst_base + 16, x18);
4107     ASSERT_EQUAL_64(src_base + 4, x19);
4108     ASSERT_EQUAL_64(dst_base + 4, x20);
4109     ASSERT_EQUAL_64(src_base + 8, x21);
4110     ASSERT_EQUAL_64(dst_base + 24, x22);
4111   }
4112 }
4113 
4114 
TEST(ldp_stp_postindex_wide)4115 TEST(ldp_stp_postindex_wide) {
4116   SETUP();
4117 
4118   uint64_t src[4] = {0x0011223344556677,
4119                      0x8899aabbccddeeff,
4120                      0xffeeddccbbaa9988,
4121                      0x7766554433221100};
4122   uint64_t dst[5] = {0, 0, 0, 0, 0};
4123   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4124   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4125   // Move base too far from the array to force multiple instructions
4126   // to be emitted.
4127   const int64_t base_offset = 1024;
4128 
4129   START();
4130   __ Mov(x24, src_base);
4131   __ Mov(x25, dst_base);
4132   __ Mov(x18, dst_base + 16);
4133   __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PostIndex));
4134   __ Mov(x19, x24);
4135   __ Sub(x24, x24, base_offset);
4136   __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PostIndex));
4137   __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PostIndex));
4138   __ Mov(x20, x25);
4139   __ Sub(x24, x24, base_offset);
4140   __ Add(x25, x25, base_offset);
4141   __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PostIndex));
4142   __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PostIndex));
4143   __ Mov(x21, x24);
4144   __ Sub(x24, x24, base_offset);
4145   __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PostIndex));
4146   __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PostIndex));
4147   __ Mov(x22, x18);
4148   __ Add(x18, x18, base_offset);
4149   __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PostIndex));
4150   END();
4151 
4152   if (CAN_RUN()) {
4153     RUN();
4154 
4155     ASSERT_EQUAL_64(0x44556677, x0);
4156     ASSERT_EQUAL_64(0x00112233, x1);
4157     ASSERT_EQUAL_64(0x00112233, x2);
4158     ASSERT_EQUAL_64(0xccddeeff, x3);
4159     ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
4160     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
4161     ASSERT_EQUAL_64(0x0011223344556677, x4);
4162     ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
4163     ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
4164     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
4165     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
4166     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
4167     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
4168     ASSERT_EQUAL_64(src_base + base_offset, x24);
4169     ASSERT_EQUAL_64(dst_base - base_offset, x25);
4170     ASSERT_EQUAL_64(dst_base - base_offset + 16, x18);
4171     ASSERT_EQUAL_64(src_base + base_offset + 4, x19);
4172     ASSERT_EQUAL_64(dst_base - base_offset + 4, x20);
4173     ASSERT_EQUAL_64(src_base + base_offset + 8, x21);
4174     ASSERT_EQUAL_64(dst_base - base_offset + 24, x22);
4175   }
4176 }
4177 
4178 
TEST(ldp_sign_extend)4179 TEST(ldp_sign_extend) {
4180   SETUP();
4181 
4182   uint32_t src[2] = {0x80000000, 0x7fffffff};
4183   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4184 
4185   START();
4186   __ Mov(x24, src_base);
4187   __ Ldpsw(x0, x1, MemOperand(x24));
4188   END();
4189 
4190   if (CAN_RUN()) {
4191     RUN();
4192 
4193     ASSERT_EQUAL_64(0xffffffff80000000, x0);
4194     ASSERT_EQUAL_64(0x000000007fffffff, x1);
4195   }
4196 }
4197 
4198 
TEST(ldur_stur)4199 TEST(ldur_stur) {
4200   SETUP();
4201 
4202   int64_t src[2] = {0x0123456789abcdef, 0x0123456789abcdef};
4203   int64_t dst[5] = {0, 0, 0, 0, 0};
4204   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4205   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4206 
4207   START();
4208   __ Mov(x17, src_base);
4209   __ Mov(x18, dst_base);
4210   __ Mov(x19, src_base + 16);
4211   __ Mov(x20, dst_base + 32);
4212   __ Mov(x21, dst_base + 40);
4213   __ Ldr(w0, MemOperand(x17, 1));
4214   __ Str(w0, MemOperand(x18, 2));
4215   __ Ldr(x1, MemOperand(x17, 3));
4216   __ Str(x1, MemOperand(x18, 9));
4217   __ Ldr(w2, MemOperand(x19, -9));
4218   __ Str(w2, MemOperand(x20, -5));
4219   __ Ldrb(w3, MemOperand(x19, -1));
4220   __ Strb(w3, MemOperand(x21, -1));
4221   END();
4222 
4223   if (CAN_RUN()) {
4224     RUN();
4225 
4226     ASSERT_EQUAL_64(0x6789abcd, x0);
4227     ASSERT_EQUAL_64(0x00006789abcd0000, dst[0]);
4228     ASSERT_EQUAL_64(0xabcdef0123456789, x1);
4229     ASSERT_EQUAL_64(0xcdef012345678900, dst[1]);
4230     ASSERT_EQUAL_64(0x000000ab, dst[2]);
4231     ASSERT_EQUAL_64(0xabcdef01, x2);
4232     ASSERT_EQUAL_64(0x00abcdef01000000, dst[3]);
4233     ASSERT_EQUAL_64(0x00000001, x3);
4234     ASSERT_EQUAL_64(0x0100000000000000, dst[4]);
4235     ASSERT_EQUAL_64(src_base, x17);
4236     ASSERT_EQUAL_64(dst_base, x18);
4237     ASSERT_EQUAL_64(src_base + 16, x19);
4238     ASSERT_EQUAL_64(dst_base + 32, x20);
4239   }
4240 }
4241 
4242 
TEST(ldur_stur_neon)4243 TEST(ldur_stur_neon) {
4244   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4245 
4246   int64_t src[3] = {0x0123456789abcdef, 0x0123456789abcdef, 0x0123456789abcdef};
4247   int64_t dst[5] = {0, 0, 0, 0, 0};
4248   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
4249   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
4250 
4251   START();
4252   __ Mov(x17, src_base);
4253   __ Mov(x18, dst_base);
4254   __ Ldr(b0, MemOperand(x17));
4255   __ Str(b0, MemOperand(x18));
4256   __ Ldr(h1, MemOperand(x17, 1));
4257   __ Str(h1, MemOperand(x18, 1));
4258   __ Ldr(s2, MemOperand(x17, 2));
4259   __ Str(s2, MemOperand(x18, 3));
4260   __ Ldr(d3, MemOperand(x17, 3));
4261   __ Str(d3, MemOperand(x18, 7));
4262   __ Ldr(q4, MemOperand(x17, 4));
4263   __ Str(q4, MemOperand(x18, 15));
4264   END();
4265 
4266   if (CAN_RUN()) {
4267     RUN();
4268 
4269     ASSERT_EQUAL_128(0, 0xef, q0);
4270     ASSERT_EQUAL_128(0, 0xabcd, q1);
4271     ASSERT_EQUAL_128(0, 0x456789ab, q2);
4272     ASSERT_EQUAL_128(0, 0xabcdef0123456789, q3);
4273     ASSERT_EQUAL_128(0x89abcdef01234567, 0x89abcdef01234567, q4);
4274     ASSERT_EQUAL_64(0x89456789ababcdef, dst[0]);
4275     ASSERT_EQUAL_64(0x67abcdef01234567, dst[1]);
4276     ASSERT_EQUAL_64(0x6789abcdef012345, dst[2]);
4277     ASSERT_EQUAL_64(0x0089abcdef012345, dst[3]);
4278   }
4279 }
4280 
4281 
TEST(ldr_literal)4282 TEST(ldr_literal) {
4283   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4284 
4285   START();
4286   __ Ldr(x2, 0x1234567890abcdef);
4287   __ Ldr(w3, 0xfedcba09);
4288   __ Ldrsw(x4, 0x7fffffff);
4289   __ Ldrsw(x5, 0x80000000);
4290   __ Ldr(q11, 0x1234000056780000, 0xabcd0000ef000000);
4291   __ Ldr(d13, 1.234);
4292   __ Ldr(s25, 2.5);
4293   END();
4294 
4295   if (CAN_RUN()) {
4296     RUN();
4297 
4298     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4299     ASSERT_EQUAL_64(0xfedcba09, x3);
4300     ASSERT_EQUAL_64(0x7fffffff, x4);
4301     ASSERT_EQUAL_64(0xffffffff80000000, x5);
4302     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4303     ASSERT_EQUAL_FP64(1.234, d13);
4304     ASSERT_EQUAL_FP32(2.5, s25);
4305   }
4306 }
4307 
4308 
TEST(ldr_literal_range)4309 TEST(ldr_literal_range) {
4310   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4311 
4312   START();
4313   // Make sure the pool is empty;
4314   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
4315   ASSERT_LITERAL_POOL_SIZE(0);
4316 
4317   // Create some literal pool entries.
4318   __ Ldr(x0, 0x1234567890abcdef);
4319   __ Ldr(w1, 0xfedcba09);
4320   __ Ldrsw(x2, 0x7fffffff);
4321   __ Ldrsw(x3, 0x80000000);
4322   __ Ldr(q2, 0x1234000056780000, 0xabcd0000ef000000);
4323   __ Ldr(d0, 1.234);
4324   __ Ldr(s1, 2.5);
4325   ASSERT_LITERAL_POOL_SIZE(48);
4326 
4327   // Emit more code than the maximum literal load range to ensure the pool
4328   // should be emitted.
4329   const ptrdiff_t end = masm.GetCursorOffset() + 2 * kMaxLoadLiteralRange;
4330   while (masm.GetCursorOffset() < end) {
4331     __ Nop();
4332   }
4333 
4334   // The pool should have been emitted.
4335   ASSERT_LITERAL_POOL_SIZE(0);
4336 
4337   // These loads should be after the pool (and will require a new one).
4338   __ Ldr(x4, 0x34567890abcdef12);
4339   __ Ldr(w5, 0xdcba09fe);
4340   __ Ldrsw(x6, 0x7fffffff);
4341   __ Ldrsw(x7, 0x80000000);
4342   __ Ldr(q6, 0x1234000056780000, 0xabcd0000ef000000);
4343   __ Ldr(d4, 123.4);
4344   __ Ldr(s5, 250.0);
4345   ASSERT_LITERAL_POOL_SIZE(48);
4346   END();
4347 
4348   if (CAN_RUN()) {
4349     RUN();
4350 
4351     // Check that the literals loaded correctly.
4352     ASSERT_EQUAL_64(0x1234567890abcdef, x0);
4353     ASSERT_EQUAL_64(0xfedcba09, x1);
4354     ASSERT_EQUAL_64(0x7fffffff, x2);
4355     ASSERT_EQUAL_64(0xffffffff80000000, x3);
4356     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q2);
4357     ASSERT_EQUAL_FP64(1.234, d0);
4358     ASSERT_EQUAL_FP32(2.5, s1);
4359     ASSERT_EQUAL_64(0x34567890abcdef12, x4);
4360     ASSERT_EQUAL_64(0xdcba09fe, x5);
4361     ASSERT_EQUAL_64(0x7fffffff, x6);
4362     ASSERT_EQUAL_64(0xffffffff80000000, x7);
4363     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q6);
4364     ASSERT_EQUAL_FP64(123.4, d4);
4365     ASSERT_EQUAL_FP32(250.0, s5);
4366   }
4367 }
4368 
4369 
4370 template <typename T>
LoadIntValueHelper(T values[],int card)4371 void LoadIntValueHelper(T values[], int card) {
4372   SETUP();
4373 
4374   const bool is_32bit = (sizeof(T) == 4);
4375   Register tgt1 = is_32bit ? Register(w1) : Register(x1);
4376   Register tgt2 = is_32bit ? Register(w2) : Register(x2);
4377 
4378   START();
4379   __ Mov(x0, 0);
4380 
4381   // If one of the values differ then x0 will be one.
4382   for (int i = 0; i < card; ++i) {
4383     __ Mov(tgt1, values[i]);
4384     __ Ldr(tgt2, values[i]);
4385     __ Cmp(tgt1, tgt2);
4386     __ Cset(x0, ne);
4387   }
4388   END();
4389 
4390   if (CAN_RUN()) {
4391     RUN();
4392 
4393     // If one of the values differs, the trace can be used to identify which
4394     // one.
4395     ASSERT_EQUAL_64(0, x0);
4396   }
4397 }
4398 
4399 
TEST(ldr_literal_values_x)4400 TEST(ldr_literal_values_x) {
4401   static const uint64_t kValues[] = {0x8000000000000000,
4402                                      0x7fffffffffffffff,
4403                                      0x0000000000000000,
4404                                      0xffffffffffffffff,
4405                                      0x00ff00ff00ff00ff,
4406                                      0x1234567890abcdef};
4407 
4408   LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
4409 }
4410 
4411 
TEST(ldr_literal_values_w)4412 TEST(ldr_literal_values_w) {
4413   static const uint32_t kValues[] = {0x80000000,
4414                                      0x7fffffff,
4415                                      0x00000000,
4416                                      0xffffffff,
4417                                      0x00ff00ff,
4418                                      0x12345678,
4419                                      0x90abcdef};
4420 
4421   LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
4422 }
4423 
TEST(ldr_literal_custom)4424 TEST(ldr_literal_custom) {
4425   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4426 
4427   Label end_of_pool_before;
4428   Label end_of_pool_after;
4429 
4430   const size_t kSizeOfPoolInBytes = 44;
4431 
4432   Literal<uint64_t> before_x(0x1234567890abcdef);
4433   Literal<uint32_t> before_w(0xfedcba09);
4434   Literal<uint32_t> before_sx(0x80000000);
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<uint32_t> after_sx(0x80000000);
4442   Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000);
4443   Literal<double> after_d(1.234);
4444   Literal<float> after_s(2.5);
4445 
4446   START();
4447 
4448   // Manually generate a pool.
4449   __ B(&end_of_pool_before);
4450   {
4451     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4452     __ place(&before_x);
4453     __ place(&before_w);
4454     __ place(&before_sx);
4455     __ place(&before_q);
4456     __ place(&before_d);
4457     __ place(&before_s);
4458   }
4459   __ Bind(&end_of_pool_before);
4460 
4461   {
4462     ExactAssemblyScope scope(&masm, 12 * kInstructionSize);
4463     __ ldr(x2, &before_x);
4464     __ ldr(w3, &before_w);
4465     __ ldrsw(x5, &before_sx);
4466     __ ldr(q11, &before_q);
4467     __ ldr(d13, &before_d);
4468     __ ldr(s25, &before_s);
4469 
4470     __ ldr(x6, &after_x);
4471     __ ldr(w7, &after_w);
4472     __ ldrsw(x8, &after_sx);
4473     __ ldr(q18, &after_q);
4474     __ ldr(d14, &after_d);
4475     __ ldr(s26, &after_s);
4476   }
4477 
4478   // Manually generate a pool.
4479   __ B(&end_of_pool_after);
4480   {
4481     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4482     __ place(&after_x);
4483     __ place(&after_w);
4484     __ place(&after_sx);
4485     __ place(&after_q);
4486     __ place(&after_d);
4487     __ place(&after_s);
4488   }
4489   __ Bind(&end_of_pool_after);
4490 
4491   END();
4492 
4493   if (CAN_RUN()) {
4494     RUN();
4495 
4496     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4497     ASSERT_EQUAL_64(0xfedcba09, x3);
4498     ASSERT_EQUAL_64(0xffffffff80000000, x5);
4499     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4500     ASSERT_EQUAL_FP64(1.234, d13);
4501     ASSERT_EQUAL_FP32(2.5, s25);
4502 
4503     ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4504     ASSERT_EQUAL_64(0xfedcba09, x7);
4505     ASSERT_EQUAL_64(0xffffffff80000000, x8);
4506     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18);
4507     ASSERT_EQUAL_FP64(1.234, d14);
4508     ASSERT_EQUAL_FP32(2.5, s26);
4509   }
4510 }
4511 
4512 
TEST(ldr_literal_custom_shared)4513 TEST(ldr_literal_custom_shared) {
4514   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4515 
4516   Label end_of_pool_before;
4517   Label end_of_pool_after;
4518 
4519   const size_t kSizeOfPoolInBytes = 40;
4520 
4521   Literal<uint64_t> before_x(0x1234567890abcdef);
4522   Literal<uint32_t> before_w(0xfedcba09);
4523   Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000);
4524   Literal<double> before_d(1.234);
4525   Literal<float> before_s(2.5);
4526 
4527   Literal<uint64_t> after_x(0x1234567890abcdef);
4528   Literal<uint32_t> after_w(0xfedcba09);
4529   Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000);
4530   Literal<double> after_d(1.234);
4531   Literal<float> after_s(2.5);
4532 
4533   START();
4534 
4535   // Manually generate a pool.
4536   __ B(&end_of_pool_before);
4537   {
4538     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4539     __ place(&before_x);
4540     __ place(&before_w);
4541     __ place(&before_q);
4542     __ place(&before_d);
4543     __ place(&before_s);
4544   }
4545   __ Bind(&end_of_pool_before);
4546 
4547   // Load the entries several times to test that literals can be shared.
4548   for (int i = 0; i < 50; i++) {
4549     ExactAssemblyScope scope(&masm, 12 * kInstructionSize);
4550     __ ldr(x2, &before_x);
4551     __ ldr(w3, &before_w);
4552     __ ldrsw(x5, &before_w);  // Re-use before_w.
4553     __ ldr(q11, &before_q);
4554     __ ldr(d13, &before_d);
4555     __ ldr(s25, &before_s);
4556 
4557     __ ldr(x6, &after_x);
4558     __ ldr(w7, &after_w);
4559     __ ldrsw(x8, &after_w);  // Re-use after_w.
4560     __ ldr(q18, &after_q);
4561     __ ldr(d14, &after_d);
4562     __ ldr(s26, &after_s);
4563   }
4564 
4565   // Manually generate a pool.
4566   __ B(&end_of_pool_after);
4567   {
4568     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4569     __ place(&after_x);
4570     __ place(&after_w);
4571     __ place(&after_q);
4572     __ place(&after_d);
4573     __ place(&after_s);
4574   }
4575   __ Bind(&end_of_pool_after);
4576 
4577   END();
4578 
4579   if (CAN_RUN()) {
4580     RUN();
4581 
4582     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4583     ASSERT_EQUAL_64(0xfedcba09, x3);
4584     ASSERT_EQUAL_64(0xfffffffffedcba09, x5);
4585     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4586     ASSERT_EQUAL_FP64(1.234, d13);
4587     ASSERT_EQUAL_FP32(2.5, s25);
4588 
4589     ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4590     ASSERT_EQUAL_64(0xfedcba09, x7);
4591     ASSERT_EQUAL_64(0xfffffffffedcba09, x8);
4592     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18);
4593     ASSERT_EQUAL_FP64(1.234, d14);
4594     ASSERT_EQUAL_FP32(2.5, s26);
4595   }
4596 }
4597 
4598 static const PrefetchOperation kPrfmOperations[] = {PLDL1KEEP,
4599                                                     PLDL1STRM,
4600                                                     PLDL2KEEP,
4601                                                     PLDL2STRM,
4602                                                     PLDL3KEEP,
4603                                                     PLDL3STRM,
4604 
4605                                                     PLIL1KEEP,
4606                                                     PLIL1STRM,
4607                                                     PLIL2KEEP,
4608                                                     PLIL2STRM,
4609                                                     PLIL3KEEP,
4610                                                     PLIL3STRM,
4611 
4612                                                     PSTL1KEEP,
4613                                                     PSTL1STRM,
4614                                                     PSTL2KEEP,
4615                                                     PSTL2STRM,
4616                                                     PSTL3KEEP,
4617                                                     PSTL3STRM};
4618 
TEST(prfm_offset)4619 TEST(prfm_offset) {
4620   SETUP();
4621 
4622   START();
4623   // The address used in prfm doesn't have to be valid.
4624   __ Mov(x0, 0x0123456789abcdef);
4625 
4626   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4627     // Unallocated prefetch operations are ignored, so test all of them.
4628     // We have to use the Assembler directly for this.
4629     ExactAssemblyScope guard(&masm, 3 * kInstructionSize);
4630     __ prfm(op, MemOperand(x0));
4631     __ prfm(op, MemOperand(x0, 8));
4632     __ prfm(op, MemOperand(x0, 32760));
4633   }
4634 
4635   for (PrefetchOperation op : kPrfmOperations) {
4636     // Also test named operations.
4637     __ Prfm(op, MemOperand(x0, 32768));
4638     __ Prfm(op, MemOperand(x0, 1));
4639     __ Prfm(op, MemOperand(x0, 9));
4640     __ Prfm(op, MemOperand(x0, 255));
4641     __ Prfm(op, MemOperand(x0, 257));
4642     __ Prfm(op, MemOperand(x0, -1));
4643     __ Prfm(op, MemOperand(x0, -9));
4644     __ Prfm(op, MemOperand(x0, -255));
4645     __ Prfm(op, MemOperand(x0, -257));
4646 
4647     __ Prfm(op, MemOperand(x0, 0xfedcba9876543210));
4648   }
4649 
4650   END();
4651   if (CAN_RUN()) {
4652     RUN();
4653   }
4654 }
4655 
4656 
TEST(prfm_regoffset)4657 TEST(prfm_regoffset) {
4658   SETUP();
4659 
4660   START();
4661   // The address used in prfm doesn't have to be valid.
4662   __ Mov(x0, 0x0123456789abcdef);
4663 
4664   CPURegList inputs(CPURegister::kRegister, kXRegSize, 10, 18);
4665   __ Mov(x10, 0);
4666   __ Mov(x11, 1);
4667   __ Mov(x12, 8);
4668   __ Mov(x13, 255);
4669   __ Mov(x14, -0);
4670   __ Mov(x15, -1);
4671   __ Mov(x16, -8);
4672   __ Mov(x17, -255);
4673   __ Mov(x18, 0xfedcba9876543210);
4674 
4675   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4676     // Unallocated prefetch operations are ignored, so test all of them.
4677     // We have to use the Assembler directly for this.
4678 
4679     // Prefetch operations of the form 0b11xxx are allocated to another
4680     // instruction.
4681     if (op >= 0b11000) continue;
4682 
4683     ExactAssemblyScope guard(&masm, inputs.GetCount() * kInstructionSize);
4684     CPURegList loop = inputs;
4685     while (!loop.IsEmpty()) {
4686       __ prfm(op, MemOperand(x0, Register(loop.PopLowestIndex())));
4687     }
4688   }
4689 
4690   for (PrefetchOperation op : kPrfmOperations) {
4691     // Also test named operations.
4692     CPURegList loop = inputs;
4693     while (!loop.IsEmpty()) {
4694       Register input(loop.PopLowestIndex());
4695       __ Prfm(op, MemOperand(x0, input, UXTW));
4696       __ Prfm(op, MemOperand(x0, input, UXTW, 3));
4697       __ Prfm(op, MemOperand(x0, input, LSL));
4698       __ Prfm(op, MemOperand(x0, input, LSL, 3));
4699       __ Prfm(op, MemOperand(x0, input, SXTW));
4700       __ Prfm(op, MemOperand(x0, input, SXTW, 3));
4701       __ Prfm(op, MemOperand(x0, input, SXTX));
4702       __ Prfm(op, MemOperand(x0, input, SXTX, 3));
4703     }
4704   }
4705 
4706   END();
4707   if (CAN_RUN()) {
4708     RUN();
4709   }
4710 }
4711 
4712 
TEST(prfm_literal_imm19)4713 TEST(prfm_literal_imm19) {
4714   SETUP();
4715   START();
4716 
4717   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4718     // Unallocated prefetch operations are ignored, so test all of them.
4719     // We have to use the Assembler directly for this.
4720     ExactAssemblyScope guard(&masm, 3 * kInstructionSize);
4721     __ prfm(op, INT64_C(0));
4722     __ prfm(op, 1);
4723     __ prfm(op, -1);
4724   }
4725 
4726   for (PrefetchOperation op : kPrfmOperations) {
4727     // Also test named operations.
4728     ExactAssemblyScope guard(&masm, 4 * kInstructionSize);
4729     // The address used in prfm doesn't have to be valid.
4730     __ prfm(op, 1000);
4731     __ prfm(op, -1000);
4732     __ prfm(op, 0x3ffff);
4733     __ prfm(op, -0x40000);
4734   }
4735 
4736   END();
4737   if (CAN_RUN()) {
4738     RUN();
4739   }
4740 }
4741 
4742 
TEST(prfm_literal)4743 TEST(prfm_literal) {
4744   SETUP();
4745 
4746   Label end_of_pool_before;
4747   Label end_of_pool_after;
4748   Literal<uint64_t> before(0);
4749   Literal<uint64_t> after(0);
4750 
4751   START();
4752 
4753   // Manually generate a pool.
4754   __ B(&end_of_pool_before);
4755   {
4756     ExactAssemblyScope scope(&masm, before.GetSize());
4757     __ place(&before);
4758   }
4759   __ Bind(&end_of_pool_before);
4760 
4761   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4762     // Unallocated prefetch operations are ignored, so test all of them.
4763     // We have to use the Assembler directly for this.
4764     ExactAssemblyScope guard(&masm, 2 * kInstructionSize);
4765     __ prfm(op, &before);
4766     __ prfm(op, &after);
4767   }
4768 
4769   for (PrefetchOperation op : kPrfmOperations) {
4770     // Also test named operations.
4771     ExactAssemblyScope guard(&masm, 2 * kInstructionSize);
4772     __ prfm(op, &before);
4773     __ prfm(op, &after);
4774   }
4775 
4776   // Manually generate a pool.
4777   __ B(&end_of_pool_after);
4778   {
4779     ExactAssemblyScope scope(&masm, after.GetSize());
4780     __ place(&after);
4781   }
4782   __ Bind(&end_of_pool_after);
4783 
4784   END();
4785   if (CAN_RUN()) {
4786     RUN();
4787   }
4788 }
4789 
4790 
TEST(prfm_wide)4791 TEST(prfm_wide) {
4792   SETUP();
4793 
4794   START();
4795   // The address used in prfm doesn't have to be valid.
4796   __ Mov(x0, 0x0123456789abcdef);
4797 
4798   for (PrefetchOperation op : kPrfmOperations) {
4799     __ Prfm(op, MemOperand(x0, 0x40000));
4800     __ Prfm(op, MemOperand(x0, -0x40001));
4801     __ Prfm(op, MemOperand(x0, UINT64_C(0x5555555555555555)));
4802     __ Prfm(op, MemOperand(x0, UINT64_C(0xfedcba9876543210)));
4803   }
4804 
4805   END();
4806   if (CAN_RUN()) {
4807     RUN();
4808   }
4809 }
4810 
4811 
TEST(load_prfm_literal)4812 TEST(load_prfm_literal) {
4813   // Test literals shared between both prfm and ldr.
4814   SETUP_WITH_FEATURES(CPUFeatures::kFP);
4815 
4816   Label end_of_pool_before;
4817   Label end_of_pool_after;
4818 
4819   const size_t kSizeOfPoolInBytes = 28;
4820 
4821   Literal<uint64_t> before_x(0x1234567890abcdef);
4822   Literal<uint32_t> before_w(0xfedcba09);
4823   Literal<uint32_t> before_sx(0x80000000);
4824   Literal<double> before_d(1.234);
4825   Literal<float> before_s(2.5);
4826   Literal<uint64_t> after_x(0x1234567890abcdef);
4827   Literal<uint32_t> after_w(0xfedcba09);
4828   Literal<uint32_t> after_sx(0x80000000);
4829   Literal<double> after_d(1.234);
4830   Literal<float> after_s(2.5);
4831 
4832   START();
4833 
4834   // Manually generate a pool.
4835   __ B(&end_of_pool_before);
4836   {
4837     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4838     __ place(&before_x);
4839     __ place(&before_w);
4840     __ place(&before_sx);
4841     __ place(&before_d);
4842     __ place(&before_s);
4843   }
4844   __ Bind(&end_of_pool_before);
4845 
4846   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4847     // Unallocated prefetch operations are ignored, so test all of them.
4848     ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4849 
4850     __ prfm(op, &before_x);
4851     __ prfm(op, &before_w);
4852     __ prfm(op, &before_sx);
4853     __ prfm(op, &before_d);
4854     __ prfm(op, &before_s);
4855 
4856     __ prfm(op, &after_x);
4857     __ prfm(op, &after_w);
4858     __ prfm(op, &after_sx);
4859     __ prfm(op, &after_d);
4860     __ prfm(op, &after_s);
4861   }
4862 
4863   for (PrefetchOperation op : kPrfmOperations) {
4864     // Also test named operations.
4865     ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4866 
4867     __ prfm(op, &before_x);
4868     __ prfm(op, &before_w);
4869     __ prfm(op, &before_sx);
4870     __ prfm(op, &before_d);
4871     __ prfm(op, &before_s);
4872 
4873     __ prfm(op, &after_x);
4874     __ prfm(op, &after_w);
4875     __ prfm(op, &after_sx);
4876     __ prfm(op, &after_d);
4877     __ prfm(op, &after_s);
4878   }
4879 
4880   {
4881     ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4882     __ ldr(x2, &before_x);
4883     __ ldr(w3, &before_w);
4884     __ ldrsw(x5, &before_sx);
4885     __ ldr(d13, &before_d);
4886     __ ldr(s25, &before_s);
4887 
4888     __ ldr(x6, &after_x);
4889     __ ldr(w7, &after_w);
4890     __ ldrsw(x8, &after_sx);
4891     __ ldr(d14, &after_d);
4892     __ ldr(s26, &after_s);
4893   }
4894 
4895   // Manually generate a pool.
4896   __ B(&end_of_pool_after);
4897   {
4898     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4899     __ place(&after_x);
4900     __ place(&after_w);
4901     __ place(&after_sx);
4902     __ place(&after_d);
4903     __ place(&after_s);
4904   }
4905   __ Bind(&end_of_pool_after);
4906 
4907   END();
4908 
4909   if (CAN_RUN()) {
4910     RUN();
4911 
4912     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4913     ASSERT_EQUAL_64(0xfedcba09, x3);
4914     ASSERT_EQUAL_64(0xffffffff80000000, x5);
4915     ASSERT_EQUAL_FP64(1.234, d13);
4916     ASSERT_EQUAL_FP32(2.5, s25);
4917 
4918     ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4919     ASSERT_EQUAL_64(0xfedcba09, x7);
4920     ASSERT_EQUAL_64(0xffffffff80000000, x8);
4921     ASSERT_EQUAL_FP64(1.234, d14);
4922     ASSERT_EQUAL_FP32(2.5, s26);
4923   }
4924 }
4925 
4926 
TEST(add_sub_imm)4927 TEST(add_sub_imm) {
4928   SETUP();
4929 
4930   START();
4931   __ Mov(x0, 0x0);
4932   __ Mov(x1, 0x1111);
4933   __ Mov(x2, 0xffffffffffffffff);
4934   __ Mov(x3, 0x8000000000000000);
4935 
4936   __ Add(x10, x0, Operand(0x123));
4937   __ Add(x11, x1, Operand(0x122000));
4938   __ Add(x12, x0, Operand(0xabc << 12));
4939   __ Add(x13, x2, Operand(1));
4940 
4941   __ Add(w14, w0, Operand(0x123));
4942   __ Add(w15, w1, Operand(0x122000));
4943   __ Add(w16, w0, Operand(0xabc << 12));
4944   __ Add(w17, w2, Operand(1));
4945 
4946   __ Sub(x20, x0, Operand(0x1));
4947   __ Sub(x21, x1, Operand(0x111));
4948   __ Sub(x22, x1, Operand(0x1 << 12));
4949   __ Sub(x23, x3, Operand(1));
4950 
4951   __ Sub(w24, w0, Operand(0x1));
4952   __ Sub(w25, w1, Operand(0x111));
4953   __ Sub(w26, w1, Operand(0x1 << 12));
4954   __ Sub(w27, w3, Operand(1));
4955   END();
4956 
4957   if (CAN_RUN()) {
4958     RUN();
4959 
4960     ASSERT_EQUAL_64(0x123, x10);
4961     ASSERT_EQUAL_64(0x123111, x11);
4962     ASSERT_EQUAL_64(0xabc000, x12);
4963     ASSERT_EQUAL_64(0x0, x13);
4964 
4965     ASSERT_EQUAL_32(0x123, w14);
4966     ASSERT_EQUAL_32(0x123111, w15);
4967     ASSERT_EQUAL_32(0xabc000, w16);
4968     ASSERT_EQUAL_32(0x0, w17);
4969 
4970     ASSERT_EQUAL_64(0xffffffffffffffff, x20);
4971     ASSERT_EQUAL_64(0x1000, x21);
4972     ASSERT_EQUAL_64(0x111, x22);
4973     ASSERT_EQUAL_64(0x7fffffffffffffff, x23);
4974 
4975     ASSERT_EQUAL_32(0xffffffff, w24);
4976     ASSERT_EQUAL_32(0x1000, w25);
4977     ASSERT_EQUAL_32(0x111, w26);
4978     ASSERT_EQUAL_32(0xffffffff, w27);
4979   }
4980 }
4981 
4982 
TEST(add_sub_wide_imm)4983 TEST(add_sub_wide_imm) {
4984   SETUP();
4985 
4986   START();
4987   __ Mov(x0, 0x0);
4988   __ Mov(x1, 0x1);
4989 
4990   __ Add(x10, x0, Operand(0x1234567890abcdef));
4991   __ Add(x11, x1, Operand(0xffffffff));
4992 
4993   __ Add(w12, w0, Operand(0x12345678));
4994   __ Add(w13, w1, Operand(0xffffffff));
4995 
4996   __ Add(w18, w0, Operand(kWMinInt));
4997   __ Sub(w19, w0, Operand(kWMinInt));
4998 
4999   __ Sub(x20, x0, Operand(0x1234567890abcdef));
5000   __ Sub(w21, w0, Operand(0x12345678));
5001 
5002   END();
5003 
5004   if (CAN_RUN()) {
5005     RUN();
5006 
5007     ASSERT_EQUAL_64(0x1234567890abcdef, x10);
5008     ASSERT_EQUAL_64(0x100000000, x11);
5009 
5010     ASSERT_EQUAL_32(0x12345678, w12);
5011     ASSERT_EQUAL_64(0x0, x13);
5012 
5013     ASSERT_EQUAL_32(kWMinInt, w18);
5014     ASSERT_EQUAL_32(kWMinInt, w19);
5015 
5016     ASSERT_EQUAL_64(-0x1234567890abcdef, x20);
5017     ASSERT_EQUAL_32(-0x12345678, w21);
5018   }
5019 }
5020 
5021 
TEST(add_sub_shifted)5022 TEST(add_sub_shifted) {
5023   SETUP();
5024 
5025   START();
5026   __ Mov(x0, 0);
5027   __ Mov(x1, 0x0123456789abcdef);
5028   __ Mov(x2, 0xfedcba9876543210);
5029   __ Mov(x3, 0xffffffffffffffff);
5030 
5031   __ Add(x10, x1, Operand(x2));
5032   __ Add(x11, x0, Operand(x1, LSL, 8));
5033   __ Add(x12, x0, Operand(x1, LSR, 8));
5034   __ Add(x13, x0, Operand(x1, ASR, 8));
5035   __ Add(x14, x0, Operand(x2, ASR, 8));
5036   __ Add(w15, w0, Operand(w1, ASR, 8));
5037   __ Add(w18, w3, Operand(w1, ROR, 8));
5038   __ Add(x19, x3, Operand(x1, ROR, 8));
5039 
5040   __ Sub(x20, x3, Operand(x2));
5041   __ Sub(x21, x3, Operand(x1, LSL, 8));
5042   __ Sub(x22, x3, Operand(x1, LSR, 8));
5043   __ Sub(x23, x3, Operand(x1, ASR, 8));
5044   __ Sub(x24, x3, Operand(x2, ASR, 8));
5045   __ Sub(w25, w3, Operand(w1, ASR, 8));
5046   __ Sub(w26, w3, Operand(w1, ROR, 8));
5047   __ Sub(x27, x3, Operand(x1, ROR, 8));
5048   END();
5049 
5050   if (CAN_RUN()) {
5051     RUN();
5052 
5053     ASSERT_EQUAL_64(0xffffffffffffffff, x10);
5054     ASSERT_EQUAL_64(0x23456789abcdef00, x11);
5055     ASSERT_EQUAL_64(0x000123456789abcd, x12);
5056     ASSERT_EQUAL_64(0x000123456789abcd, x13);
5057     ASSERT_EQUAL_64(0xfffedcba98765432, x14);
5058     ASSERT_EQUAL_64(0xff89abcd, x15);
5059     ASSERT_EQUAL_64(0xef89abcc, x18);
5060     ASSERT_EQUAL_64(0xef0123456789abcc, x19);
5061 
5062     ASSERT_EQUAL_64(0x0123456789abcdef, x20);
5063     ASSERT_EQUAL_64(0xdcba9876543210ff, x21);
5064     ASSERT_EQUAL_64(0xfffedcba98765432, x22);
5065     ASSERT_EQUAL_64(0xfffedcba98765432, x23);
5066     ASSERT_EQUAL_64(0x000123456789abcd, x24);
5067     ASSERT_EQUAL_64(0x00765432, x25);
5068     ASSERT_EQUAL_64(0x10765432, x26);
5069     ASSERT_EQUAL_64(0x10fedcba98765432, x27);
5070   }
5071 }
5072 
5073 
TEST(add_sub_extended)5074 TEST(add_sub_extended) {
5075   SETUP();
5076 
5077   START();
5078   __ Mov(x0, 0);
5079   __ Mov(x1, 0x0123456789abcdef);
5080   __ Mov(x2, 0xfedcba9876543210);
5081   __ Mov(w3, 0x80);
5082 
5083   __ Add(x10, x0, Operand(x1, UXTB, 0));
5084   __ Add(x11, x0, Operand(x1, UXTB, 1));
5085   __ Add(x12, x0, Operand(x1, UXTH, 2));
5086   __ Add(x13, x0, Operand(x1, UXTW, 4));
5087 
5088   __ Add(x14, x0, Operand(x1, SXTB, 0));
5089   __ Add(x15, x0, Operand(x1, SXTB, 1));
5090   __ Add(x16, x0, Operand(x1, SXTH, 2));
5091   __ Add(x17, x0, Operand(x1, SXTW, 3));
5092   __ Add(x18, x0, Operand(x2, SXTB, 0));
5093   __ Add(x19, x0, Operand(x2, SXTB, 1));
5094   __ Add(x20, x0, Operand(x2, SXTH, 2));
5095   __ Add(x21, x0, Operand(x2, SXTW, 3));
5096 
5097   __ Add(x22, x1, Operand(x2, SXTB, 1));
5098   __ Sub(x23, x1, Operand(x2, SXTB, 1));
5099 
5100   __ Add(w24, w1, Operand(w2, UXTB, 2));
5101   __ Add(w25, w0, Operand(w1, SXTB, 0));
5102   __ Add(w26, w0, Operand(w1, SXTB, 1));
5103   __ Add(w27, w2, Operand(w1, SXTW, 3));
5104 
5105   __ Add(w28, w0, Operand(w1, SXTW, 3));
5106   __ Add(x29, x0, Operand(w1, SXTW, 3));
5107 
5108   __ Sub(x30, x0, Operand(w3, SXTB, 1));
5109   END();
5110 
5111   if (CAN_RUN()) {
5112     RUN();
5113 
5114     ASSERT_EQUAL_64(0xef, x10);
5115     ASSERT_EQUAL_64(0x1de, x11);
5116     ASSERT_EQUAL_64(0x337bc, x12);
5117     ASSERT_EQUAL_64(0x89abcdef0, x13);
5118 
5119     ASSERT_EQUAL_64(0xffffffffffffffef, x14);
5120     ASSERT_EQUAL_64(0xffffffffffffffde, x15);
5121     ASSERT_EQUAL_64(0xffffffffffff37bc, x16);
5122     ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x17);
5123     ASSERT_EQUAL_64(0x10, x18);
5124     ASSERT_EQUAL_64(0x20, x19);
5125     ASSERT_EQUAL_64(0xc840, x20);
5126     ASSERT_EQUAL_64(0x3b2a19080, x21);
5127 
5128     ASSERT_EQUAL_64(0x0123456789abce0f, x22);
5129     ASSERT_EQUAL_64(0x0123456789abcdcf, x23);
5130 
5131     ASSERT_EQUAL_32(0x89abce2f, w24);
5132     ASSERT_EQUAL_32(0xffffffef, w25);
5133     ASSERT_EQUAL_32(0xffffffde, w26);
5134     ASSERT_EQUAL_32(0xc3b2a188, w27);
5135 
5136     ASSERT_EQUAL_32(0x4d5e6f78, w28);
5137     ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x29);
5138 
5139     ASSERT_EQUAL_64(256, x30);
5140   }
5141 }
5142 
5143 
TEST(add_sub_negative)5144 TEST(add_sub_negative) {
5145   SETUP();
5146 
5147   START();
5148   __ Mov(x0, 0);
5149   __ Mov(x1, 4687);
5150   __ Mov(x2, 0x1122334455667788);
5151   __ Mov(w3, 0x11223344);
5152   __ Mov(w4, 400000);
5153 
5154   __ Add(x10, x0, -42);
5155   __ Add(x11, x1, -687);
5156   __ Add(x12, x2, -0x88);
5157 
5158   __ Sub(x13, x0, -600);
5159   __ Sub(x14, x1, -313);
5160   __ Sub(x15, x2, -0x555);
5161 
5162   __ Add(w19, w3, -0x344);
5163   __ Add(w20, w4, -2000);
5164 
5165   __ Sub(w21, w3, -0xbc);
5166   __ Sub(w22, w4, -2000);
5167   END();
5168 
5169   if (CAN_RUN()) {
5170     RUN();
5171 
5172     ASSERT_EQUAL_64(-42, x10);
5173     ASSERT_EQUAL_64(4000, x11);
5174     ASSERT_EQUAL_64(0x1122334455667700, x12);
5175 
5176     ASSERT_EQUAL_64(600, x13);
5177     ASSERT_EQUAL_64(5000, x14);
5178     ASSERT_EQUAL_64(0x1122334455667cdd, x15);
5179 
5180     ASSERT_EQUAL_32(0x11223000, w19);
5181     ASSERT_EQUAL_32(398000, w20);
5182 
5183     ASSERT_EQUAL_32(0x11223400, w21);
5184     ASSERT_EQUAL_32(402000, w22);
5185   }
5186 }
5187 
5188 
TEST(add_sub_zero)5189 TEST(add_sub_zero) {
5190   SETUP();
5191 
5192   START();
5193   __ Mov(x0, 0);
5194   __ Mov(x1, 0);
5195   __ Mov(x2, 0);
5196 
5197   Label blob1;
5198   __ Bind(&blob1);
5199   __ Add(x0, x0, 0);
5200   __ Sub(x1, x1, 0);
5201   __ Sub(x2, x2, xzr);
5202   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob1) == 0);
5203 
5204   Label blob2;
5205   __ Bind(&blob2);
5206   __ Add(w3, w3, 0);
5207   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob2) != 0);
5208 
5209   Label blob3;
5210   __ Bind(&blob3);
5211   __ Sub(w3, w3, wzr);
5212   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob3) != 0);
5213 
5214   END();
5215 
5216   if (CAN_RUN()) {
5217     RUN();
5218 
5219     ASSERT_EQUAL_64(0, x0);
5220     ASSERT_EQUAL_64(0, x1);
5221     ASSERT_EQUAL_64(0, x2);
5222   }
5223 }
5224 
5225 
TEST(claim_drop_zero)5226 TEST(claim_drop_zero) {
5227   SETUP();
5228 
5229   START();
5230 
5231   Label start;
5232   __ Bind(&start);
5233   __ Claim(Operand(0));
5234   __ Drop(Operand(0));
5235   __ Claim(Operand(xzr));
5236   __ Drop(Operand(xzr));
5237   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
5238 
5239   END();
5240 
5241   if (CAN_RUN()) {
5242     RUN();
5243   }
5244 }
5245 
5246 
TEST(neg)5247 TEST(neg) {
5248   SETUP();
5249 
5250   START();
5251   __ Mov(x0, 0xf123456789abcdef);
5252 
5253   // Immediate.
5254   __ Neg(x1, 0x123);
5255   __ Neg(w2, 0x123);
5256 
5257   // Shifted.
5258   __ Neg(x3, Operand(x0, LSL, 1));
5259   __ Neg(w4, Operand(w0, LSL, 2));
5260   __ Neg(x5, Operand(x0, LSR, 3));
5261   __ Neg(w6, Operand(w0, LSR, 4));
5262   __ Neg(x7, Operand(x0, ASR, 5));
5263   __ Neg(w8, Operand(w0, ASR, 6));
5264 
5265   // Extended.
5266   __ Neg(w9, Operand(w0, UXTB));
5267   __ Neg(x10, Operand(x0, SXTB, 1));
5268   __ Neg(w11, Operand(w0, UXTH, 2));
5269   __ Neg(x12, Operand(x0, SXTH, 3));
5270   __ Neg(w13, Operand(w0, UXTW, 4));
5271   __ Neg(x14, Operand(x0, SXTW, 4));
5272   END();
5273 
5274   if (CAN_RUN()) {
5275     RUN();
5276 
5277     ASSERT_EQUAL_64(0xfffffffffffffedd, x1);
5278     ASSERT_EQUAL_64(0xfffffedd, x2);
5279     ASSERT_EQUAL_64(0x1db97530eca86422, x3);
5280     ASSERT_EQUAL_64(0xd950c844, x4);
5281     ASSERT_EQUAL_64(0xe1db97530eca8643, x5);
5282     ASSERT_EQUAL_64(0xf7654322, x6);
5283     ASSERT_EQUAL_64(0x0076e5d4c3b2a191, x7);
5284     ASSERT_EQUAL_64(0x01d950c9, x8);
5285     ASSERT_EQUAL_64(0xffffff11, x9);
5286     ASSERT_EQUAL_64(0x0000000000000022, x10);
5287     ASSERT_EQUAL_64(0xfffcc844, x11);
5288     ASSERT_EQUAL_64(0x0000000000019088, x12);
5289     ASSERT_EQUAL_64(0x65432110, x13);
5290     ASSERT_EQUAL_64(0x0000000765432110, x14);
5291   }
5292 }
5293 
5294 
5295 template <typename T, typename Op>
AdcsSbcsHelper(Op op,T left,T right,int carry,T expected,StatusFlags expected_flags)5296 static void AdcsSbcsHelper(
5297     Op op, T left, T right, int carry, T expected, StatusFlags expected_flags) {
5298   int reg_size = sizeof(T) * 8;
5299   Register left_reg(0, reg_size);
5300   Register right_reg(1, reg_size);
5301   Register result_reg(2, reg_size);
5302 
5303   SETUP();
5304   START();
5305 
5306   __ Mov(left_reg, left);
5307   __ Mov(right_reg, right);
5308   __ Mov(x10, (carry ? CFlag : NoFlag));
5309 
5310   __ Msr(NZCV, x10);
5311   (masm.*op)(result_reg, left_reg, right_reg);
5312 
5313   END();
5314   if (CAN_RUN()) {
5315     RUN();
5316 
5317     ASSERT_EQUAL_64(left, left_reg.X());
5318     ASSERT_EQUAL_64(right, right_reg.X());
5319     ASSERT_EQUAL_64(expected, result_reg.X());
5320     ASSERT_EQUAL_NZCV(expected_flags);
5321   }
5322 }
5323 
5324 
TEST(adcs_sbcs_x)5325 TEST(adcs_sbcs_x) {
5326   uint64_t inputs[] = {
5327       0x0000000000000000,
5328       0x0000000000000001,
5329       0x7ffffffffffffffe,
5330       0x7fffffffffffffff,
5331       0x8000000000000000,
5332       0x8000000000000001,
5333       0xfffffffffffffffe,
5334       0xffffffffffffffff,
5335   };
5336   static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]);
5337 
5338   struct Expected {
5339     uint64_t carry0_result;
5340     StatusFlags carry0_flags;
5341     uint64_t carry1_result;
5342     StatusFlags carry1_flags;
5343   };
5344 
5345   static const Expected expected_adcs_x[input_count][input_count] =
5346       {{{0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag},
5347         {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
5348         {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
5349         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5350         {0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
5351         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5352         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5353         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}},
5354        {{0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
5355         {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag},
5356         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5357         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5358         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5359         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5360         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5361         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}},
5362        {{0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
5363         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5364         {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag},
5365         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5366         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5367         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5368         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5369         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}},
5370        {{0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5371         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5372         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5373         {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag},
5374         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5375         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5376         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5377         {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}},
5378        {{0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
5379         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5380         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5381         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5382         {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag},
5383         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5384         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5385         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}},
5386        {{0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5387         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5388         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5389         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5390         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5391         {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag},
5392         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5393         {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}},
5394        {{0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5395         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5396         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5397         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5398         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5399         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5400         {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag},
5401         {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}},
5402        {{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5403         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5404         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5405         {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
5406         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5407         {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
5408         {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
5409         {0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}}};
5410 
5411   static const Expected expected_sbcs_x[input_count][input_count] =
5412       {{{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5413         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5414         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5415         {0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
5416         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5417         {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
5418         {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
5419         {0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}},
5420        {{0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5421         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5422         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5423         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5424         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5425         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5426         {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag},
5427         {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}},
5428        {{0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5429         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5430         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5431         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5432         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5433         {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag},
5434         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
5435         {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}},
5436        {{0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
5437         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5438         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5439         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5440         {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag},
5441         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
5442         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
5443         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}},
5444        {{0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5445         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5446         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5447         {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag},
5448         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5449         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
5450         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
5451         {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}},
5452        {{0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
5453         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5454         {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag},
5455         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
5456         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5457         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5458         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
5459         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}},
5460        {{0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
5461         {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag},
5462         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5463         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
5464         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5465         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
5466         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
5467         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}},
5468        {{0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag},
5469         {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
5470         {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
5471         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
5472         {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
5473         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
5474         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
5475         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}}};
5476 
5477   for (size_t left = 0; left < input_count; left++) {
5478     for (size_t right = 0; right < input_count; right++) {
5479       const Expected& expected = expected_adcs_x[left][right];
5480       AdcsSbcsHelper(&MacroAssembler::Adcs,
5481                      inputs[left],
5482                      inputs[right],
5483                      0,
5484                      expected.carry0_result,
5485                      expected.carry0_flags);
5486       AdcsSbcsHelper(&MacroAssembler::Adcs,
5487                      inputs[left],
5488                      inputs[right],
5489                      1,
5490                      expected.carry1_result,
5491                      expected.carry1_flags);
5492     }
5493   }
5494 
5495   for (size_t left = 0; left < input_count; left++) {
5496     for (size_t right = 0; right < input_count; right++) {
5497       const Expected& expected = expected_sbcs_x[left][right];
5498       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5499                      inputs[left],
5500                      inputs[right],
5501                      0,
5502                      expected.carry0_result,
5503                      expected.carry0_flags);
5504       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5505                      inputs[left],
5506                      inputs[right],
5507                      1,
5508                      expected.carry1_result,
5509                      expected.carry1_flags);
5510     }
5511   }
5512 }
5513 
5514 
TEST(adcs_sbcs_w)5515 TEST(adcs_sbcs_w) {
5516   uint32_t inputs[] = {
5517       0x00000000,
5518       0x00000001,
5519       0x7ffffffe,
5520       0x7fffffff,
5521       0x80000000,
5522       0x80000001,
5523       0xfffffffe,
5524       0xffffffff,
5525   };
5526   static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]);
5527 
5528   struct Expected {
5529     uint32_t carry0_result;
5530     StatusFlags carry0_flags;
5531     uint32_t carry1_result;
5532     StatusFlags carry1_flags;
5533   };
5534 
5535   static const Expected expected_adcs_w[input_count][input_count] =
5536       {{{0x00000000, ZFlag, 0x00000001, NoFlag},
5537         {0x00000001, NoFlag, 0x00000002, NoFlag},
5538         {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5539         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5540         {0x80000000, NFlag, 0x80000001, NFlag},
5541         {0x80000001, NFlag, 0x80000002, NFlag},
5542         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5543         {0xffffffff, NFlag, 0x00000000, ZCFlag}},
5544        {{0x00000001, NoFlag, 0x00000002, NoFlag},
5545         {0x00000002, NoFlag, 0x00000003, NoFlag},
5546         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5547         {0x80000000, NVFlag, 0x80000001, NVFlag},
5548         {0x80000001, NFlag, 0x80000002, NFlag},
5549         {0x80000002, NFlag, 0x80000003, NFlag},
5550         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5551         {0x00000000, ZCFlag, 0x00000001, CFlag}},
5552        {{0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5553         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5554         {0xfffffffc, NVFlag, 0xfffffffd, NVFlag},
5555         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5556         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5557         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5558         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5559         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}},
5560        {{0x7fffffff, NoFlag, 0x80000000, NVFlag},
5561         {0x80000000, NVFlag, 0x80000001, NVFlag},
5562         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5563         {0xfffffffe, NVFlag, 0xffffffff, NVFlag},
5564         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5565         {0x00000000, ZCFlag, 0x00000001, CFlag},
5566         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5567         {0x7ffffffe, CFlag, 0x7fffffff, CFlag}},
5568        {{0x80000000, NFlag, 0x80000001, NFlag},
5569         {0x80000001, NFlag, 0x80000002, NFlag},
5570         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5571         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5572         {0x00000000, ZCVFlag, 0x00000001, CVFlag},
5573         {0x00000001, CVFlag, 0x00000002, CVFlag},
5574         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5575         {0x7fffffff, CVFlag, 0x80000000, NCFlag}},
5576        {{0x80000001, NFlag, 0x80000002, NFlag},
5577         {0x80000002, NFlag, 0x80000003, NFlag},
5578         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5579         {0x00000000, ZCFlag, 0x00000001, CFlag},
5580         {0x00000001, CVFlag, 0x00000002, CVFlag},
5581         {0x00000002, CVFlag, 0x00000003, CVFlag},
5582         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5583         {0x80000000, NCFlag, 0x80000001, NCFlag}},
5584        {{0xfffffffe, NFlag, 0xffffffff, NFlag},
5585         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5586         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5587         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5588         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5589         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5590         {0xfffffffc, NCFlag, 0xfffffffd, NCFlag},
5591         {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}},
5592        {{0xffffffff, NFlag, 0x00000000, ZCFlag},
5593         {0x00000000, ZCFlag, 0x00000001, CFlag},
5594         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5595         {0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5596         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5597         {0x80000000, NCFlag, 0x80000001, NCFlag},
5598         {0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5599         {0xfffffffe, NCFlag, 0xffffffff, NCFlag}}};
5600 
5601   static const Expected expected_sbcs_w[input_count][input_count] =
5602       {{{0xffffffff, NFlag, 0x00000000, ZCFlag},
5603         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5604         {0x80000001, NFlag, 0x80000002, NFlag},
5605         {0x80000000, NFlag, 0x80000001, NFlag},
5606         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5607         {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5608         {0x00000001, NoFlag, 0x00000002, NoFlag},
5609         {0x00000000, ZFlag, 0x00000001, NoFlag}},
5610        {{0x00000000, ZCFlag, 0x00000001, CFlag},
5611         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5612         {0x80000002, NFlag, 0x80000003, NFlag},
5613         {0x80000001, NFlag, 0x80000002, NFlag},
5614         {0x80000000, NVFlag, 0x80000001, NVFlag},
5615         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5616         {0x00000002, NoFlag, 0x00000003, NoFlag},
5617         {0x00000001, NoFlag, 0x00000002, NoFlag}},
5618        {{0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5619         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5620         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5621         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5622         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5623         {0xfffffffc, NVFlag, 0xfffffffd, NVFlag},
5624         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5625         {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}},
5626        {{0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5627         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5628         {0x00000000, ZCFlag, 0x00000001, CFlag},
5629         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5630         {0xfffffffe, NVFlag, 0xffffffff, NVFlag},
5631         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5632         {0x80000000, NVFlag, 0x80000001, NVFlag},
5633         {0x7fffffff, NoFlag, 0x80000000, NVFlag}},
5634        {{0x7fffffff, CVFlag, 0x80000000, NCFlag},
5635         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5636         {0x00000001, CVFlag, 0x00000002, CVFlag},
5637         {0x00000000, ZCVFlag, 0x00000001, CVFlag},
5638         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5639         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5640         {0x80000001, NFlag, 0x80000002, NFlag},
5641         {0x80000000, NFlag, 0x80000001, NFlag}},
5642        {{0x80000000, NCFlag, 0x80000001, NCFlag},
5643         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5644         {0x00000002, CVFlag, 0x00000003, CVFlag},
5645         {0x00000001, CVFlag, 0x00000002, CVFlag},
5646         {0x00000000, ZCFlag, 0x00000001, CFlag},
5647         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5648         {0x80000002, NFlag, 0x80000003, NFlag},
5649         {0x80000001, NFlag, 0x80000002, NFlag}},
5650        {{0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5651         {0xfffffffc, NCFlag, 0xfffffffd, NCFlag},
5652         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5653         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5654         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5655         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5656         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5657         {0xfffffffe, NFlag, 0xffffffff, NFlag}},
5658        {{0xfffffffe, NCFlag, 0xffffffff, NCFlag},
5659         {0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5660         {0x80000000, NCFlag, 0x80000001, NCFlag},
5661         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5662         {0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5663         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5664         {0x00000000, ZCFlag, 0x00000001, CFlag},
5665         {0xffffffff, NFlag, 0x00000000, ZCFlag}}};
5666 
5667   for (size_t left = 0; left < input_count; left++) {
5668     for (size_t right = 0; right < input_count; right++) {
5669       const Expected& expected = expected_adcs_w[left][right];
5670       AdcsSbcsHelper(&MacroAssembler::Adcs,
5671                      inputs[left],
5672                      inputs[right],
5673                      0,
5674                      expected.carry0_result,
5675                      expected.carry0_flags);
5676       AdcsSbcsHelper(&MacroAssembler::Adcs,
5677                      inputs[left],
5678                      inputs[right],
5679                      1,
5680                      expected.carry1_result,
5681                      expected.carry1_flags);
5682     }
5683   }
5684 
5685   for (size_t left = 0; left < input_count; left++) {
5686     for (size_t right = 0; right < input_count; right++) {
5687       const Expected& expected = expected_sbcs_w[left][right];
5688       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5689                      inputs[left],
5690                      inputs[right],
5691                      0,
5692                      expected.carry0_result,
5693                      expected.carry0_flags);
5694       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5695                      inputs[left],
5696                      inputs[right],
5697                      1,
5698                      expected.carry1_result,
5699                      expected.carry1_flags);
5700     }
5701   }
5702 }
5703 
5704 
TEST(adc_sbc_shift)5705 TEST(adc_sbc_shift) {
5706   SETUP();
5707 
5708   START();
5709   __ Mov(x0, 0);
5710   __ Mov(x1, 1);
5711   __ Mov(x2, 0x0123456789abcdef);
5712   __ Mov(x3, 0xfedcba9876543210);
5713   __ Mov(x4, 0xffffffffffffffff);
5714 
5715   // Clear the C flag.
5716   __ Adds(x0, x0, Operand(0));
5717 
5718   __ Adc(x5, x2, Operand(x3));
5719   __ Adc(x6, x0, Operand(x1, LSL, 60));
5720   __ Sbc(x7, x4, Operand(x3, LSR, 4));
5721   __ Adc(x8, x2, Operand(x3, ASR, 4));
5722   __ Adc(x9, x2, Operand(x3, ROR, 8));
5723 
5724   __ Adc(w10, w2, Operand(w3));
5725   __ Adc(w11, w0, Operand(w1, LSL, 30));
5726   __ Sbc(w12, w4, Operand(w3, LSR, 4));
5727   __ Adc(w13, w2, Operand(w3, ASR, 4));
5728   __ Adc(w14, w2, Operand(w3, ROR, 8));
5729 
5730   // Set the C flag.
5731   __ Cmp(w0, Operand(w0));
5732 
5733   __ Adc(x18, x2, Operand(x3));
5734   __ Adc(x19, x0, Operand(x1, LSL, 60));
5735   __ Sbc(x20, x4, Operand(x3, LSR, 4));
5736   __ Adc(x21, x2, Operand(x3, ASR, 4));
5737   __ Adc(x22, x2, Operand(x3, ROR, 8));
5738 
5739   __ Adc(w23, w2, Operand(w3));
5740   __ Adc(w24, w0, Operand(w1, LSL, 30));
5741   __ Sbc(w25, w4, Operand(w3, LSR, 4));
5742   __ Adc(w26, w2, Operand(w3, ASR, 4));
5743   __ Adc(w27, w2, Operand(w3, ROR, 8));
5744   END();
5745 
5746   if (CAN_RUN()) {
5747     RUN();
5748 
5749     ASSERT_EQUAL_64(0xffffffffffffffff, x5);
5750     ASSERT_EQUAL_64(INT64_C(1) << 60, x6);
5751     ASSERT_EQUAL_64(0xf0123456789abcdd, x7);
5752     ASSERT_EQUAL_64(0x0111111111111110, x8);
5753     ASSERT_EQUAL_64(0x1222222222222221, x9);
5754 
5755     ASSERT_EQUAL_32(0xffffffff, w10);
5756     ASSERT_EQUAL_32(INT32_C(1) << 30, w11);
5757     ASSERT_EQUAL_32(0xf89abcdd, w12);
5758     ASSERT_EQUAL_32(0x91111110, w13);
5759     ASSERT_EQUAL_32(0x9a222221, w14);
5760 
5761     ASSERT_EQUAL_64(0xffffffffffffffff + 1, x18);
5762     ASSERT_EQUAL_64((INT64_C(1) << 60) + 1, x19);
5763     ASSERT_EQUAL_64(0xf0123456789abcdd + 1, x20);
5764     ASSERT_EQUAL_64(0x0111111111111110 + 1, x21);
5765     ASSERT_EQUAL_64(0x1222222222222221 + 1, x22);
5766 
5767     ASSERT_EQUAL_32(0xffffffff + 1, w23);
5768     ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, w24);
5769     ASSERT_EQUAL_32(0xf89abcdd + 1, w25);
5770     ASSERT_EQUAL_32(0x91111110 + 1, w26);
5771     ASSERT_EQUAL_32(0x9a222221 + 1, w27);
5772   }
5773 }
5774 
5775 
TEST(adc_sbc_extend)5776 TEST(adc_sbc_extend) {
5777   SETUP();
5778 
5779   START();
5780   // Clear the C flag.
5781   __ Adds(x0, x0, Operand(0));
5782 
5783   __ Mov(x0, 0);
5784   __ Mov(x1, 1);
5785   __ Mov(x2, 0x0123456789abcdef);
5786 
5787   __ Adc(x10, x1, Operand(w2, UXTB, 1));
5788   __ Adc(x11, x1, Operand(x2, SXTH, 2));
5789   __ Sbc(x12, x1, Operand(w2, UXTW, 4));
5790   __ Adc(x13, x1, Operand(x2, UXTX, 4));
5791 
5792   __ Adc(w14, w1, Operand(w2, UXTB, 1));
5793   __ Adc(w15, w1, Operand(w2, SXTH, 2));
5794   __ Adc(w9, w1, Operand(w2, UXTW, 4));
5795 
5796   // Set the C flag.
5797   __ Cmp(w0, Operand(w0));
5798 
5799   __ Adc(x20, x1, Operand(w2, UXTB, 1));
5800   __ Adc(x21, x1, Operand(x2, SXTH, 2));
5801   __ Sbc(x22, x1, Operand(w2, UXTW, 4));
5802   __ Adc(x23, x1, Operand(x2, UXTX, 4));
5803 
5804   __ Adc(w24, w1, Operand(w2, UXTB, 1));
5805   __ Adc(w25, w1, Operand(w2, SXTH, 2));
5806   __ Adc(w26, w1, Operand(w2, UXTW, 4));
5807   END();
5808 
5809   if (CAN_RUN()) {
5810     RUN();
5811 
5812     ASSERT_EQUAL_64(0x1df, x10);
5813     ASSERT_EQUAL_64(0xffffffffffff37bd, x11);
5814     ASSERT_EQUAL_64(0xfffffff765432110, x12);
5815     ASSERT_EQUAL_64(0x123456789abcdef1, x13);
5816 
5817     ASSERT_EQUAL_32(0x1df, w14);
5818     ASSERT_EQUAL_32(0xffff37bd, w15);
5819     ASSERT_EQUAL_32(0x9abcdef1, w9);
5820 
5821     ASSERT_EQUAL_64(0x1df + 1, x20);
5822     ASSERT_EQUAL_64(0xffffffffffff37bd + 1, x21);
5823     ASSERT_EQUAL_64(0xfffffff765432110 + 1, x22);
5824     ASSERT_EQUAL_64(0x123456789abcdef1 + 1, x23);
5825 
5826     ASSERT_EQUAL_32(0x1df + 1, w24);
5827     ASSERT_EQUAL_32(0xffff37bd + 1, w25);
5828     ASSERT_EQUAL_32(0x9abcdef1 + 1, w26);
5829   }
5830 
5831   // Check that adc correctly sets the condition flags.
5832   START();
5833   __ Mov(x0, 0xff);
5834   __ Mov(x1, 0xffffffffffffffff);
5835   // Clear the C flag.
5836   __ Adds(x0, x0, Operand(0));
5837   __ Adcs(x10, x0, Operand(x1, SXTX, 1));
5838   END();
5839 
5840   if (CAN_RUN()) {
5841     RUN();
5842 
5843     ASSERT_EQUAL_NZCV(CFlag);
5844   }
5845 
5846   START();
5847   __ Mov(x0, 0x7fffffffffffffff);
5848   __ Mov(x1, 1);
5849   // Clear the C flag.
5850   __ Adds(x0, x0, Operand(0));
5851   __ Adcs(x10, x0, Operand(x1, UXTB, 2));
5852   END();
5853 
5854   if (CAN_RUN()) {
5855     RUN();
5856 
5857     ASSERT_EQUAL_NZCV(NVFlag);
5858   }
5859 
5860   START();
5861   __ Mov(x0, 0x7fffffffffffffff);
5862   // Clear the C flag.
5863   __ Adds(x0, x0, Operand(0));
5864   __ Adcs(x10, x0, Operand(1));
5865   END();
5866 
5867   if (CAN_RUN()) {
5868     RUN();
5869 
5870     ASSERT_EQUAL_NZCV(NVFlag);
5871   }
5872 }
5873 
5874 
TEST(adc_sbc_wide_imm)5875 TEST(adc_sbc_wide_imm) {
5876   SETUP();
5877 
5878   START();
5879   __ Mov(x0, 0);
5880 
5881   // Clear the C flag.
5882   __ Adds(x0, x0, Operand(0));
5883 
5884   __ Adc(x7, x0, Operand(0x1234567890abcdef));
5885   __ Adc(w8, w0, Operand(0xffffffff));
5886   __ Sbc(x9, x0, Operand(0x1234567890abcdef));
5887   __ Sbc(w10, w0, Operand(0xffffffff));
5888   __ Ngc(x11, Operand(0xffffffff00000000));
5889   __ Ngc(w12, Operand(0xffff0000));
5890 
5891   // Set the C flag.
5892   __ Cmp(w0, Operand(w0));
5893 
5894   __ Adc(x18, x0, Operand(0x1234567890abcdef));
5895   __ Adc(w19, w0, Operand(0xffffffff));
5896   __ Sbc(x20, x0, Operand(0x1234567890abcdef));
5897   __ Sbc(w21, w0, Operand(0xffffffff));
5898   __ Ngc(x22, Operand(0xffffffff00000000));
5899   __ Ngc(w23, Operand(0xffff0000));
5900   END();
5901 
5902   if (CAN_RUN()) {
5903     RUN();
5904 
5905     ASSERT_EQUAL_64(0x1234567890abcdef, x7);
5906     ASSERT_EQUAL_64(0xffffffff, x8);
5907     ASSERT_EQUAL_64(0xedcba9876f543210, x9);
5908     ASSERT_EQUAL_64(0, x10);
5909     ASSERT_EQUAL_64(0xffffffff, x11);
5910     ASSERT_EQUAL_64(0xffff, x12);
5911 
5912     ASSERT_EQUAL_64(0x1234567890abcdef + 1, x18);
5913     ASSERT_EQUAL_64(0, x19);
5914     ASSERT_EQUAL_64(0xedcba9876f543211, x20);
5915     ASSERT_EQUAL_64(1, x21);
5916     ASSERT_EQUAL_64(0x0000000100000000, x22);
5917     ASSERT_EQUAL_64(0x0000000000010000, x23);
5918   }
5919 }
5920 
5921 
TEST(rmif)5922 TEST(rmif) {
5923   SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
5924 
5925   START();
5926   __ Mov(x0, 0x0123456789abcdef);
5927 
5928   // Clear bits of `rmif` masks leave NZCV unmodified, so we need to initialise
5929   // it to a known state to make the test reproducible.
5930   __ Msr(NZCV, x0);
5931 
5932   // Set NZCV to 0b1011 (0xb)
5933   __ Rmif(x0, 0, NCVFlag);
5934   __ Mrs(x1, NZCV);
5935 
5936   // Set NZCV to 0b0111 (0x7)
5937   __ Rmif(x0, 6, NZCVFlag);
5938   __ Mrs(x2, NZCV);
5939 
5940   // Set Z to 0, NZCV = 0b0011 (0x3)
5941   __ Rmif(x0, 60, ZFlag);
5942   __ Mrs(x3, NZCV);
5943 
5944   // Set N to 1 and C to 0, NZCV = 0b1001 (0x9)
5945   __ Rmif(x0, 62, NCFlag);
5946   __ Mrs(x4, NZCV);
5947 
5948   // No change to NZCV
5949   __ Rmif(x0, 0, NoFlag);
5950   __ Mrs(x5, NZCV);
5951   END();
5952 
5953   if (CAN_RUN()) {
5954     RUN();
5955     ASSERT_EQUAL_32(NCVFlag, w1);
5956     ASSERT_EQUAL_32(ZCVFlag, w2);
5957     ASSERT_EQUAL_32(CVFlag, w3);
5958     ASSERT_EQUAL_32(NVFlag, w4);
5959     ASSERT_EQUAL_32(NVFlag, w5);
5960   }
5961 }
5962 
5963 
TEST(setf8_setf16)5964 TEST(setf8_setf16) {
5965   SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
5966 
5967   START();
5968   __ Mov(x0, 0x0);
5969   __ Mov(x1, 0x1);
5970   __ Mov(x2, 0xff);
5971   __ Mov(x3, 0x100);
5972   __ Mov(x4, 0x101);
5973   __ Mov(x5, 0xffff);
5974   __ Mov(x6, 0x10000);
5975   __ Mov(x7, 0x10001);
5976   __ Mov(x8, 0xfffffffff);
5977 
5978   // These instruction don't modify 'C', so give it a consistent value.
5979   __ Ands(xzr, xzr, 0);
5980 
5981   __ Setf8(w0);
5982   __ Mrs(x9, NZCV);
5983   __ Setf8(w1);
5984   __ Mrs(x10, NZCV);
5985   __ Setf8(w2);
5986   __ Mrs(x11, NZCV);
5987   __ Setf8(w3);
5988   __ Mrs(x12, NZCV);
5989   __ Setf8(w4);
5990   __ Mrs(x13, NZCV);
5991   __ Setf8(w8);
5992   __ Mrs(x14, NZCV);
5993 
5994   __ Setf16(w0);
5995   __ Mrs(x15, NZCV);
5996   __ Setf16(w1);
5997   __ Mrs(x16, NZCV);
5998   __ Setf16(w5);
5999   __ Mrs(x17, NZCV);
6000   __ Setf16(w6);
6001   __ Mrs(x18, NZCV);
6002   __ Setf16(w7);
6003   __ Mrs(x19, NZCV);
6004   __ Setf16(w8);
6005   __ Mrs(x20, NZCV);
6006   END();
6007 
6008   if (CAN_RUN()) {
6009     RUN();
6010 
6011     ASSERT_EQUAL_32(ZFlag, w9);    // Zero
6012     ASSERT_EQUAL_32(NoFlag, w10);  // Regular int8
6013     ASSERT_EQUAL_32(NVFlag, w11);  // Negative but not sign-extended (overflow)
6014     ASSERT_EQUAL_32(ZVFlag, w12);  // Overflow with zero remainder
6015     ASSERT_EQUAL_32(VFlag, w13);   // Overflow with non-zero remainder
6016     ASSERT_EQUAL_32(NFlag, w14);   // Negative and sign-extended
6017 
6018     ASSERT_EQUAL_32(ZFlag, w15);   // Zero
6019     ASSERT_EQUAL_32(NoFlag, w16);  // Regular int16
6020     ASSERT_EQUAL_32(NVFlag, w17);  // Negative but not sign-extended (overflow)
6021     ASSERT_EQUAL_32(ZVFlag, w18);  // Overflow with zero remainder
6022     ASSERT_EQUAL_32(VFlag, w19);   // Overflow with non-zero remainder
6023     ASSERT_EQUAL_32(NFlag, w20);   // Negative and sign-extended
6024   }
6025 }
6026 
6027 
TEST(flags)6028 TEST(flags) {
6029   SETUP();
6030 
6031   START();
6032   __ Mov(x0, 0);
6033   __ Mov(x1, 0x1111111111111111);
6034   __ Neg(x10, Operand(x0));
6035   __ Neg(x11, Operand(x1));
6036   __ Neg(w12, Operand(w1));
6037   // Clear the C flag.
6038   __ Adds(x0, x0, Operand(0));
6039   __ Ngc(x13, Operand(x0));
6040   // Set the C flag.
6041   __ Cmp(x0, Operand(x0));
6042   __ Ngc(w14, Operand(w0));
6043   END();
6044 
6045   if (CAN_RUN()) {
6046     RUN();
6047 
6048     ASSERT_EQUAL_64(0, x10);
6049     ASSERT_EQUAL_64(-0x1111111111111111, x11);
6050     ASSERT_EQUAL_32(-0x11111111, w12);
6051     ASSERT_EQUAL_64(-1, x13);
6052     ASSERT_EQUAL_32(0, w14);
6053   }
6054 
6055   START();
6056   __ Mov(x0, 0);
6057   __ Cmp(x0, Operand(x0));
6058   END();
6059 
6060   if (CAN_RUN()) {
6061     RUN();
6062 
6063     ASSERT_EQUAL_NZCV(ZCFlag);
6064   }
6065 
6066   START();
6067   __ Mov(w0, 0);
6068   __ Cmp(w0, Operand(w0));
6069   END();
6070 
6071   if (CAN_RUN()) {
6072     RUN();
6073 
6074     ASSERT_EQUAL_NZCV(ZCFlag);
6075   }
6076 
6077   START();
6078   __ Mov(x0, 0);
6079   __ Mov(x1, 0x1111111111111111);
6080   __ Cmp(x0, Operand(x1));
6081   END();
6082 
6083   if (CAN_RUN()) {
6084     RUN();
6085 
6086     ASSERT_EQUAL_NZCV(NFlag);
6087   }
6088 
6089   START();
6090   __ Mov(w0, 0);
6091   __ Mov(w1, 0x11111111);
6092   __ Cmp(w0, Operand(w1));
6093   END();
6094 
6095   if (CAN_RUN()) {
6096     RUN();
6097 
6098     ASSERT_EQUAL_NZCV(NFlag);
6099   }
6100 
6101   START();
6102   __ Mov(x1, 0x1111111111111111);
6103   __ Cmp(x1, Operand(0));
6104   END();
6105 
6106   if (CAN_RUN()) {
6107     RUN();
6108 
6109     ASSERT_EQUAL_NZCV(CFlag);
6110   }
6111 
6112   START();
6113   __ Mov(w1, 0x11111111);
6114   __ Cmp(w1, Operand(0));
6115   END();
6116 
6117   if (CAN_RUN()) {
6118     RUN();
6119 
6120     ASSERT_EQUAL_NZCV(CFlag);
6121   }
6122 
6123   START();
6124   __ Mov(x0, 1);
6125   __ Mov(x1, 0x7fffffffffffffff);
6126   __ Cmn(x1, Operand(x0));
6127   END();
6128 
6129   if (CAN_RUN()) {
6130     RUN();
6131 
6132     ASSERT_EQUAL_NZCV(NVFlag);
6133   }
6134 
6135   START();
6136   __ Mov(w0, 1);
6137   __ Mov(w1, 0x7fffffff);
6138   __ Cmn(w1, Operand(w0));
6139   END();
6140 
6141   if (CAN_RUN()) {
6142     RUN();
6143 
6144     ASSERT_EQUAL_NZCV(NVFlag);
6145   }
6146 
6147   START();
6148   __ Mov(x0, 1);
6149   __ Mov(x1, 0xffffffffffffffff);
6150   __ Cmn(x1, Operand(x0));
6151   END();
6152 
6153   if (CAN_RUN()) {
6154     RUN();
6155 
6156     ASSERT_EQUAL_NZCV(ZCFlag);
6157   }
6158 
6159   START();
6160   __ Mov(w0, 1);
6161   __ Mov(w1, 0xffffffff);
6162   __ Cmn(w1, Operand(w0));
6163   END();
6164 
6165   if (CAN_RUN()) {
6166     RUN();
6167 
6168     ASSERT_EQUAL_NZCV(ZCFlag);
6169   }
6170 
6171   START();
6172   __ Mov(w0, 0);
6173   __ Mov(w1, 1);
6174   // Clear the C flag.
6175   __ Adds(w0, w0, Operand(0));
6176   __ Ngcs(w0, Operand(w1));
6177   END();
6178 
6179   if (CAN_RUN()) {
6180     RUN();
6181 
6182     ASSERT_EQUAL_NZCV(NFlag);
6183   }
6184 
6185   START();
6186   __ Mov(w0, 0);
6187   __ Mov(w1, 0);
6188   // Set the C flag.
6189   __ Cmp(w0, Operand(w0));
6190   __ Ngcs(w0, Operand(w1));
6191   END();
6192 
6193   if (CAN_RUN()) {
6194     RUN();
6195 
6196     ASSERT_EQUAL_NZCV(ZCFlag);
6197   }
6198 }
6199 
6200 
TEST(cmp_shift)6201 TEST(cmp_shift) {
6202   SETUP();
6203 
6204   START();
6205   __ Mov(x18, 0xf0000000);
6206   __ Mov(x19, 0xf000000010000000);
6207   __ Mov(x20, 0xf0000000f0000000);
6208   __ Mov(x21, 0x7800000078000000);
6209   __ Mov(x22, 0x3c0000003c000000);
6210   __ Mov(x23, 0x8000000780000000);
6211   __ Mov(x24, 0x0000000f00000000);
6212   __ Mov(x25, 0x00000003c0000000);
6213   __ Mov(x26, 0x8000000780000000);
6214   __ Mov(x27, 0xc0000003);
6215 
6216   __ Cmp(w20, Operand(w21, LSL, 1));
6217   __ Mrs(x0, NZCV);
6218 
6219   __ Cmp(x20, Operand(x22, LSL, 2));
6220   __ Mrs(x1, NZCV);
6221 
6222   __ Cmp(w19, Operand(w23, LSR, 3));
6223   __ Mrs(x2, NZCV);
6224 
6225   __ Cmp(x18, Operand(x24, LSR, 4));
6226   __ Mrs(x3, NZCV);
6227 
6228   __ Cmp(w20, Operand(w25, ASR, 2));
6229   __ Mrs(x4, NZCV);
6230 
6231   __ Cmp(x20, Operand(x26, ASR, 3));
6232   __ Mrs(x5, NZCV);
6233 
6234   __ Cmp(w27, Operand(w22, ROR, 28));
6235   __ Mrs(x6, NZCV);
6236 
6237   __ Cmp(x20, Operand(x21, ROR, 31));
6238   __ Mrs(x7, NZCV);
6239   END();
6240 
6241   if (CAN_RUN()) {
6242     RUN();
6243 
6244     ASSERT_EQUAL_32(ZCFlag, w0);
6245     ASSERT_EQUAL_32(ZCFlag, w1);
6246     ASSERT_EQUAL_32(ZCFlag, w2);
6247     ASSERT_EQUAL_32(ZCFlag, w3);
6248     ASSERT_EQUAL_32(ZCFlag, w4);
6249     ASSERT_EQUAL_32(ZCFlag, w5);
6250     ASSERT_EQUAL_32(ZCFlag, w6);
6251     ASSERT_EQUAL_32(ZCFlag, w7);
6252   }
6253 }
6254 
6255 
TEST(cmp_extend)6256 TEST(cmp_extend) {
6257   SETUP();
6258 
6259   START();
6260   __ Mov(w20, 0x2);
6261   __ Mov(w21, 0x1);
6262   __ Mov(x22, 0xffffffffffffffff);
6263   __ Mov(x23, 0xff);
6264   __ Mov(x24, 0xfffffffffffffffe);
6265   __ Mov(x25, 0xffff);
6266   __ Mov(x26, 0xffffffff);
6267 
6268   __ Cmp(w20, Operand(w21, LSL, 1));
6269   __ Mrs(x0, NZCV);
6270 
6271   __ Cmp(x22, Operand(x23, SXTB, 0));
6272   __ Mrs(x1, NZCV);
6273 
6274   __ Cmp(x24, Operand(x23, SXTB, 1));
6275   __ Mrs(x2, NZCV);
6276 
6277   __ Cmp(x24, Operand(x23, UXTB, 1));
6278   __ Mrs(x3, NZCV);
6279 
6280   __ Cmp(w22, Operand(w25, UXTH));
6281   __ Mrs(x4, NZCV);
6282 
6283   __ Cmp(x22, Operand(x25, SXTH));
6284   __ Mrs(x5, NZCV);
6285 
6286   __ Cmp(x22, Operand(x26, UXTW));
6287   __ Mrs(x6, NZCV);
6288 
6289   __ Cmp(x24, Operand(x26, SXTW, 1));
6290   __ Mrs(x7, NZCV);
6291   END();
6292 
6293   if (CAN_RUN()) {
6294     RUN();
6295 
6296     ASSERT_EQUAL_32(ZCFlag, w0);
6297     ASSERT_EQUAL_32(ZCFlag, w1);
6298     ASSERT_EQUAL_32(ZCFlag, w2);
6299     ASSERT_EQUAL_32(NCFlag, w3);
6300     ASSERT_EQUAL_32(NCFlag, w4);
6301     ASSERT_EQUAL_32(ZCFlag, w5);
6302     ASSERT_EQUAL_32(NCFlag, w6);
6303     ASSERT_EQUAL_32(ZCFlag, w7);
6304   }
6305 }
6306 
6307 
TEST(ccmp)6308 TEST(ccmp) {
6309   SETUP();
6310 
6311   START();
6312   __ Mov(w16, 0);
6313   __ Mov(w17, 1);
6314   __ Cmp(w16, w16);
6315   __ Ccmp(w16, w17, NCFlag, eq);
6316   __ Mrs(x0, NZCV);
6317 
6318   __ Cmp(w16, w16);
6319   __ Ccmp(w16, w17, NCFlag, ne);
6320   __ Mrs(x1, NZCV);
6321 
6322   __ Cmp(x16, x16);
6323   __ Ccmn(x16, 2, NZCVFlag, eq);
6324   __ Mrs(x2, NZCV);
6325 
6326   __ Cmp(x16, x16);
6327   __ Ccmn(x16, 2, NZCVFlag, ne);
6328   __ Mrs(x3, NZCV);
6329 
6330   // The MacroAssembler does not allow al as a condition.
6331   {
6332     ExactAssemblyScope scope(&masm, kInstructionSize);
6333     __ ccmp(x16, x16, NZCVFlag, al);
6334   }
6335   __ Mrs(x4, NZCV);
6336 
6337   // The MacroAssembler does not allow nv as a condition.
6338   {
6339     ExactAssemblyScope scope(&masm, kInstructionSize);
6340     __ ccmp(x16, x16, NZCVFlag, nv);
6341   }
6342   __ Mrs(x5, NZCV);
6343 
6344   END();
6345 
6346   if (CAN_RUN()) {
6347     RUN();
6348 
6349     ASSERT_EQUAL_32(NFlag, w0);
6350     ASSERT_EQUAL_32(NCFlag, w1);
6351     ASSERT_EQUAL_32(NoFlag, w2);
6352     ASSERT_EQUAL_32(NZCVFlag, w3);
6353     ASSERT_EQUAL_32(ZCFlag, w4);
6354     ASSERT_EQUAL_32(ZCFlag, w5);
6355   }
6356 }
6357 
6358 
TEST(ccmp_wide_imm)6359 TEST(ccmp_wide_imm) {
6360   SETUP();
6361 
6362   START();
6363   __ Mov(w20, 0);
6364 
6365   __ Cmp(w20, Operand(w20));
6366   __ Ccmp(w20, Operand(0x12345678), NZCVFlag, eq);
6367   __ Mrs(x0, NZCV);
6368 
6369   __ Cmp(w20, Operand(w20));
6370   __ Ccmp(x20, Operand(0xffffffffffffffff), NZCVFlag, eq);
6371   __ Mrs(x1, NZCV);
6372   END();
6373 
6374   if (CAN_RUN()) {
6375     RUN();
6376 
6377     ASSERT_EQUAL_32(NFlag, w0);
6378     ASSERT_EQUAL_32(NoFlag, w1);
6379   }
6380 }
6381 
6382 
TEST(ccmp_shift_extend)6383 TEST(ccmp_shift_extend) {
6384   SETUP();
6385 
6386   START();
6387   __ Mov(w20, 0x2);
6388   __ Mov(w21, 0x1);
6389   __ Mov(x22, 0xffffffffffffffff);
6390   __ Mov(x23, 0xff);
6391   __ Mov(x24, 0xfffffffffffffffe);
6392 
6393   __ Cmp(w20, Operand(w20));
6394   __ Ccmp(w20, Operand(w21, LSL, 1), NZCVFlag, eq);
6395   __ Mrs(x0, NZCV);
6396 
6397   __ Cmp(w20, Operand(w20));
6398   __ Ccmp(x22, Operand(x23, SXTB, 0), NZCVFlag, eq);
6399   __ Mrs(x1, NZCV);
6400 
6401   __ Cmp(w20, Operand(w20));
6402   __ Ccmp(x24, Operand(x23, SXTB, 1), NZCVFlag, eq);
6403   __ Mrs(x2, NZCV);
6404 
6405   __ Cmp(w20, Operand(w20));
6406   __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, eq);
6407   __ Mrs(x3, NZCV);
6408 
6409   __ Cmp(w20, Operand(w20));
6410   __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, ne);
6411   __ Mrs(x4, NZCV);
6412   END();
6413 
6414   if (CAN_RUN()) {
6415     RUN();
6416 
6417     ASSERT_EQUAL_32(ZCFlag, w0);
6418     ASSERT_EQUAL_32(ZCFlag, w1);
6419     ASSERT_EQUAL_32(ZCFlag, w2);
6420     ASSERT_EQUAL_32(NCFlag, w3);
6421     ASSERT_EQUAL_32(NZCVFlag, w4);
6422   }
6423 }
6424 
6425 
TEST(csel_reg)6426 TEST(csel_reg) {
6427   SETUP();
6428 
6429   START();
6430   __ Mov(x16, 0);
6431   __ Mov(x24, 0x0000000f0000000f);
6432   __ Mov(x25, 0x0000001f0000001f);
6433 
6434   __ Cmp(w16, Operand(0));
6435   __ Csel(w0, w24, w25, eq);
6436   __ Csel(w1, w24, w25, ne);
6437   __ Csinc(w2, w24, w25, mi);
6438   __ Csinc(w3, w24, w25, pl);
6439 
6440   // The MacroAssembler does not allow al or nv as a condition.
6441   {
6442     ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
6443     __ csel(w13, w24, w25, al);
6444     __ csel(x14, x24, x25, nv);
6445   }
6446 
6447   __ Cmp(x16, Operand(1));
6448   __ Csinv(x4, x24, x25, gt);
6449   __ Csinv(x5, x24, x25, le);
6450   __ Csneg(x6, x24, x25, hs);
6451   __ Csneg(x7, x24, x25, lo);
6452 
6453   __ Cset(w8, ne);
6454   __ Csetm(w9, ne);
6455   __ Cinc(x10, x25, ne);
6456   __ Cinv(x11, x24, ne);
6457   __ Cneg(x12, x24, ne);
6458 
6459   // The MacroAssembler does not allow al or nv as a condition.
6460   {
6461     ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
6462     __ csel(w15, w24, w25, al);
6463     __ csel(x17, x24, x25, nv);
6464   }
6465 
6466   END();
6467 
6468   if (CAN_RUN()) {
6469     RUN();
6470 
6471     ASSERT_EQUAL_64(0x0000000f, x0);
6472     ASSERT_EQUAL_64(0x0000001f, x1);
6473     ASSERT_EQUAL_64(0x00000020, x2);
6474     ASSERT_EQUAL_64(0x0000000f, x3);
6475     ASSERT_EQUAL_64(0xffffffe0ffffffe0, x4);
6476     ASSERT_EQUAL_64(0x0000000f0000000f, x5);
6477     ASSERT_EQUAL_64(0xffffffe0ffffffe1, x6);
6478     ASSERT_EQUAL_64(0x0000000f0000000f, x7);
6479     ASSERT_EQUAL_64(0x00000001, x8);
6480     ASSERT_EQUAL_64(0xffffffff, x9);
6481     ASSERT_EQUAL_64(0x0000001f00000020, x10);
6482     ASSERT_EQUAL_64(0xfffffff0fffffff0, x11);
6483     ASSERT_EQUAL_64(0xfffffff0fffffff1, x12);
6484     ASSERT_EQUAL_64(0x0000000f, x13);
6485     ASSERT_EQUAL_64(0x0000000f0000000f, x14);
6486     ASSERT_EQUAL_64(0x0000000f, x15);
6487     ASSERT_EQUAL_64(0x0000000f0000000f, x17);
6488   }
6489 }
6490 
TEST(csel_zero)6491 TEST(csel_zero) {
6492   SETUP();
6493 
6494   START();
6495 
6496   __ Mov(x15, 0x0);
6497   __ Mov(x16, 0x0000001f0000002f);
6498 
6499   // Check results when zero registers are used as inputs
6500   // for Csinc, Csinv and Csneg for both true and false conditions.
6501   __ Cmp(x15, 0);
6502   __ Csinc(x0, x16, xzr, eq);
6503   __ Csinc(x1, xzr, x16, eq);
6504   __ Cmp(x15, 1);
6505   __ Csinc(w2, w16, wzr, eq);
6506   __ Csinc(w3, wzr, w16, eq);
6507 
6508   __ Csinc(x4, xzr, xzr, eq);
6509 
6510   __ Cmp(x15, 0);
6511   __ Csinv(x5, x16, xzr, eq);
6512   __ Csinv(x6, xzr, x16, eq);
6513   __ Cmp(x15, 1);
6514   __ Csinv(w7, w16, wzr, eq);
6515   __ Csinv(w8, wzr, w16, eq);
6516 
6517   __ Csinv(x9, xzr, xzr, eq);
6518 
6519   __ Cmp(x15, 0);
6520   __ Csneg(x10, x16, xzr, eq);
6521   __ Csneg(x11, xzr, x16, eq);
6522   __ Cmp(x15, 1);
6523   __ Csneg(w12, w16, wzr, eq);
6524   __ Csneg(w13, wzr, w16, eq);
6525 
6526   __ Csneg(x14, xzr, xzr, eq);
6527 
6528   END();
6529 
6530   if (CAN_RUN()) {
6531     RUN();
6532 
6533     ASSERT_EQUAL_64(0x0000001f0000002f, x0);
6534     ASSERT_EQUAL_64(0x0, x1);
6535     ASSERT_EQUAL_32(0x1, w2);
6536     ASSERT_EQUAL_32(0x30, w3);
6537     ASSERT_EQUAL_64(0x1, x4);
6538     ASSERT_EQUAL_64(0x0000001f0000002f, x5);
6539     ASSERT_EQUAL_64(0x0, x6);
6540     ASSERT_EQUAL_32(0xffffffff, w7);
6541     ASSERT_EQUAL_32(0xffffffd0, w8);
6542     ASSERT_EQUAL_64(0xffffffffffffffff, x9);
6543     ASSERT_EQUAL_64(0x0000001f0000002f, x10);
6544     ASSERT_EQUAL_64(0x0, x11);
6545     ASSERT_EQUAL_32(0x0, w12);
6546     ASSERT_EQUAL_32(0xffffffd1, w13);
6547     ASSERT_EQUAL_64(0x0, x14);
6548   }
6549 }
6550 
6551 
TEST(csel_imm)6552 TEST(csel_imm) {
6553   SETUP();
6554 
6555   int values[] = {-123, -2, -1, 0, 1, 2, 123};
6556   int n_values = sizeof(values) / sizeof(values[0]);
6557 
6558   for (int i = 0; i < n_values; i++) {
6559     for (int j = 0; j < n_values; j++) {
6560       int left = values[i];
6561       int right = values[j];
6562 
6563       START();
6564       __ Mov(x10, 0);
6565       __ Cmp(x10, 0);
6566       __ Csel(w0, left, right, eq);
6567       __ Csel(w1, left, right, ne);
6568       __ Csel(x2, left, right, eq);
6569       __ Csel(x3, left, right, ne);
6570 
6571       END();
6572 
6573       if (CAN_RUN()) {
6574         RUN();
6575 
6576         ASSERT_EQUAL_32(left, w0);
6577         ASSERT_EQUAL_32(right, w1);
6578         ASSERT_EQUAL_64(left, x2);
6579         ASSERT_EQUAL_64(right, x3);
6580       }
6581     }
6582   }
6583 }
6584 
6585 
TEST(csel_mixed)6586 TEST(csel_mixed) {
6587   SETUP();
6588 
6589   START();
6590   __ Mov(x18, 0);
6591   __ Mov(x19, 0x80000000);
6592   __ Mov(x20, 0x8000000000000000);
6593 
6594   __ Cmp(x18, Operand(0));
6595   __ Csel(w0, w19, -2, ne);
6596   __ Csel(w1, w19, -1, ne);
6597   __ Csel(w2, w19, 0, ne);
6598   __ Csel(w3, w19, 1, ne);
6599   __ Csel(w4, w19, 2, ne);
6600   __ Csel(w5, w19, Operand(w19, ASR, 31), ne);
6601   __ Csel(w6, w19, Operand(w19, ROR, 1), ne);
6602   __ Csel(w7, w19, 3, eq);
6603 
6604   __ Csel(x8, x20, -2, ne);
6605   __ Csel(x9, x20, -1, ne);
6606   __ Csel(x10, x20, 0, ne);
6607   __ Csel(x11, x20, 1, ne);
6608   __ Csel(x12, x20, 2, ne);
6609   __ Csel(x13, x20, Operand(x20, ASR, 63), ne);
6610   __ Csel(x14, x20, Operand(x20, ROR, 1), ne);
6611   __ Csel(x15, x20, 3, eq);
6612 
6613   END();
6614 
6615   if (CAN_RUN()) {
6616     RUN();
6617 
6618     ASSERT_EQUAL_32(-2, w0);
6619     ASSERT_EQUAL_32(-1, w1);
6620     ASSERT_EQUAL_32(0, w2);
6621     ASSERT_EQUAL_32(1, w3);
6622     ASSERT_EQUAL_32(2, w4);
6623     ASSERT_EQUAL_32(-1, w5);
6624     ASSERT_EQUAL_32(0x40000000, w6);
6625     ASSERT_EQUAL_32(0x80000000, w7);
6626 
6627     ASSERT_EQUAL_64(-2, x8);
6628     ASSERT_EQUAL_64(-1, x9);
6629     ASSERT_EQUAL_64(0, x10);
6630     ASSERT_EQUAL_64(1, x11);
6631     ASSERT_EQUAL_64(2, x12);
6632     ASSERT_EQUAL_64(-1, x13);
6633     ASSERT_EQUAL_64(0x4000000000000000, x14);
6634     ASSERT_EQUAL_64(0x8000000000000000, x15);
6635   }
6636 }
6637 
6638 
TEST(lslv)6639 TEST(lslv) {
6640   SETUP();
6641 
6642   uint64_t value = 0x0123456789abcdef;
6643   int shift[] = {1, 3, 5, 9, 17, 33};
6644 
6645   START();
6646   __ Mov(x0, value);
6647   __ Mov(w1, shift[0]);
6648   __ Mov(w2, shift[1]);
6649   __ Mov(w3, shift[2]);
6650   __ Mov(w4, shift[3]);
6651   __ Mov(w5, shift[4]);
6652   __ Mov(w6, shift[5]);
6653 
6654   // The MacroAssembler does not allow zr as an argument.
6655   {
6656     ExactAssemblyScope scope(&masm, kInstructionSize);
6657     __ lslv(x0, x0, xzr);
6658   }
6659 
6660   __ Lsl(x16, x0, x1);
6661   __ Lsl(x17, x0, x2);
6662   __ Lsl(x18, x0, x3);
6663   __ Lsl(x19, x0, x4);
6664   __ Lsl(x20, x0, x5);
6665   __ Lsl(x21, x0, x6);
6666 
6667   __ Lsl(w22, w0, w1);
6668   __ Lsl(w23, w0, w2);
6669   __ Lsl(w24, w0, w3);
6670   __ Lsl(w25, w0, w4);
6671   __ Lsl(w26, w0, w5);
6672   __ Lsl(w27, w0, w6);
6673   END();
6674 
6675   if (CAN_RUN()) {
6676     RUN();
6677 
6678     ASSERT_EQUAL_64(value, x0);
6679     ASSERT_EQUAL_64(value << (shift[0] & 63), x16);
6680     ASSERT_EQUAL_64(value << (shift[1] & 63), x17);
6681     ASSERT_EQUAL_64(value << (shift[2] & 63), x18);
6682     ASSERT_EQUAL_64(value << (shift[3] & 63), x19);
6683     ASSERT_EQUAL_64(value << (shift[4] & 63), x20);
6684     ASSERT_EQUAL_64(value << (shift[5] & 63), x21);
6685     ASSERT_EQUAL_32(value << (shift[0] & 31), w22);
6686     ASSERT_EQUAL_32(value << (shift[1] & 31), w23);
6687     ASSERT_EQUAL_32(value << (shift[2] & 31), w24);
6688     ASSERT_EQUAL_32(value << (shift[3] & 31), w25);
6689     ASSERT_EQUAL_32(value << (shift[4] & 31), w26);
6690     ASSERT_EQUAL_32(value << (shift[5] & 31), w27);
6691   }
6692 }
6693 
6694 
TEST(lsrv)6695 TEST(lsrv) {
6696   SETUP();
6697 
6698   uint64_t value = 0x0123456789abcdef;
6699   int shift[] = {1, 3, 5, 9, 17, 33};
6700 
6701   START();
6702   __ Mov(x0, value);
6703   __ Mov(w1, shift[0]);
6704   __ Mov(w2, shift[1]);
6705   __ Mov(w3, shift[2]);
6706   __ Mov(w4, shift[3]);
6707   __ Mov(w5, shift[4]);
6708   __ Mov(w6, shift[5]);
6709 
6710   // The MacroAssembler does not allow zr as an argument.
6711   {
6712     ExactAssemblyScope scope(&masm, kInstructionSize);
6713     __ lsrv(x0, x0, xzr);
6714   }
6715 
6716   __ Lsr(x16, x0, x1);
6717   __ Lsr(x17, x0, x2);
6718   __ Lsr(x18, x0, x3);
6719   __ Lsr(x19, x0, x4);
6720   __ Lsr(x20, x0, x5);
6721   __ Lsr(x21, x0, x6);
6722 
6723   __ Lsr(w22, w0, w1);
6724   __ Lsr(w23, w0, w2);
6725   __ Lsr(w24, w0, w3);
6726   __ Lsr(w25, w0, w4);
6727   __ Lsr(w26, w0, w5);
6728   __ Lsr(w27, w0, w6);
6729   END();
6730 
6731   if (CAN_RUN()) {
6732     RUN();
6733 
6734     ASSERT_EQUAL_64(value, x0);
6735     ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
6736     ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
6737     ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
6738     ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
6739     ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
6740     ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
6741 
6742     value &= 0xffffffff;
6743     ASSERT_EQUAL_32(value >> (shift[0] & 31), w22);
6744     ASSERT_EQUAL_32(value >> (shift[1] & 31), w23);
6745     ASSERT_EQUAL_32(value >> (shift[2] & 31), w24);
6746     ASSERT_EQUAL_32(value >> (shift[3] & 31), w25);
6747     ASSERT_EQUAL_32(value >> (shift[4] & 31), w26);
6748     ASSERT_EQUAL_32(value >> (shift[5] & 31), w27);
6749   }
6750 }
6751 
6752 
TEST(asrv)6753 TEST(asrv) {
6754   SETUP();
6755 
6756   int64_t value = 0xfedcba98fedcba98;
6757   int shift[] = {1, 3, 5, 9, 17, 33};
6758 
6759   START();
6760   __ Mov(x0, value);
6761   __ Mov(w1, shift[0]);
6762   __ Mov(w2, shift[1]);
6763   __ Mov(w3, shift[2]);
6764   __ Mov(w4, shift[3]);
6765   __ Mov(w5, shift[4]);
6766   __ Mov(w6, shift[5]);
6767 
6768   // The MacroAssembler does not allow zr as an argument.
6769   {
6770     ExactAssemblyScope scope(&masm, kInstructionSize);
6771     __ asrv(x0, x0, xzr);
6772   }
6773 
6774   __ Asr(x16, x0, x1);
6775   __ Asr(x17, x0, x2);
6776   __ Asr(x18, x0, x3);
6777   __ Asr(x19, x0, x4);
6778   __ Asr(x20, x0, x5);
6779   __ Asr(x21, x0, x6);
6780 
6781   __ Asr(w22, w0, w1);
6782   __ Asr(w23, w0, w2);
6783   __ Asr(w24, w0, w3);
6784   __ Asr(w25, w0, w4);
6785   __ Asr(w26, w0, w5);
6786   __ Asr(w27, w0, w6);
6787   END();
6788 
6789   if (CAN_RUN()) {
6790     RUN();
6791 
6792     ASSERT_EQUAL_64(value, x0);
6793     ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
6794     ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
6795     ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
6796     ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
6797     ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
6798     ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
6799 
6800     int32_t value32 = static_cast<int32_t>(value & 0xffffffff);
6801     ASSERT_EQUAL_32(value32 >> (shift[0] & 31), w22);
6802     ASSERT_EQUAL_32(value32 >> (shift[1] & 31), w23);
6803     ASSERT_EQUAL_32(value32 >> (shift[2] & 31), w24);
6804     ASSERT_EQUAL_32(value32 >> (shift[3] & 31), w25);
6805     ASSERT_EQUAL_32(value32 >> (shift[4] & 31), w26);
6806     ASSERT_EQUAL_32(value32 >> (shift[5] & 31), w27);
6807   }
6808 }
6809 
6810 
TEST(rorv)6811 TEST(rorv) {
6812   SETUP();
6813 
6814   uint64_t value = 0x0123456789abcdef;
6815   int shift[] = {4, 8, 12, 16, 24, 36};
6816 
6817   START();
6818   __ Mov(x0, value);
6819   __ Mov(w1, shift[0]);
6820   __ Mov(w2, shift[1]);
6821   __ Mov(w3, shift[2]);
6822   __ Mov(w4, shift[3]);
6823   __ Mov(w5, shift[4]);
6824   __ Mov(w6, shift[5]);
6825 
6826   // The MacroAssembler does not allow zr as an argument.
6827   {
6828     ExactAssemblyScope scope(&masm, kInstructionSize);
6829     __ rorv(x0, x0, xzr);
6830   }
6831 
6832   __ Ror(x16, x0, x1);
6833   __ Ror(x17, x0, x2);
6834   __ Ror(x18, x0, x3);
6835   __ Ror(x19, x0, x4);
6836   __ Ror(x20, x0, x5);
6837   __ Ror(x21, x0, x6);
6838 
6839   __ Ror(w22, w0, w1);
6840   __ Ror(w23, w0, w2);
6841   __ Ror(w24, w0, w3);
6842   __ Ror(w25, w0, w4);
6843   __ Ror(w26, w0, w5);
6844   __ Ror(w27, w0, w6);
6845   END();
6846 
6847   if (CAN_RUN()) {
6848     RUN();
6849 
6850     ASSERT_EQUAL_64(value, x0);
6851     ASSERT_EQUAL_64(0xf0123456789abcde, x16);
6852     ASSERT_EQUAL_64(0xef0123456789abcd, x17);
6853     ASSERT_EQUAL_64(0xdef0123456789abc, x18);
6854     ASSERT_EQUAL_64(0xcdef0123456789ab, x19);
6855     ASSERT_EQUAL_64(0xabcdef0123456789, x20);
6856     ASSERT_EQUAL_64(0x789abcdef0123456, x21);
6857     ASSERT_EQUAL_32(0xf89abcde, w22);
6858     ASSERT_EQUAL_32(0xef89abcd, w23);
6859     ASSERT_EQUAL_32(0xdef89abc, w24);
6860     ASSERT_EQUAL_32(0xcdef89ab, w25);
6861     ASSERT_EQUAL_32(0xabcdef89, w26);
6862     ASSERT_EQUAL_32(0xf89abcde, w27);
6863   }
6864 }
6865 
6866 
TEST(bfm)6867 TEST(bfm) {
6868   SETUP();
6869 
6870   START();
6871   __ Mov(x1, 0x0123456789abcdef);
6872 
6873   __ Mov(x10, 0x8888888888888888);
6874   __ Mov(x11, 0x8888888888888888);
6875   __ Mov(x12, 0x8888888888888888);
6876   __ Mov(x13, 0x8888888888888888);
6877   __ Mov(x14, 0xffffffffffffffff);
6878   __ Mov(w20, 0x88888888);
6879   __ Mov(w21, 0x88888888);
6880 
6881   __ Bfm(x10, x1, 16, 31);
6882   __ Bfm(x11, x1, 32, 15);
6883 
6884   __ Bfm(w20, w1, 16, 23);
6885   __ Bfm(w21, w1, 24, 15);
6886 
6887   // Aliases.
6888   __ Bfi(x12, x1, 16, 8);
6889   __ Bfxil(x13, x1, 16, 8);
6890   __ Bfc(x14, 16, 8);
6891   END();
6892 
6893   if (CAN_RUN()) {
6894     RUN();
6895 
6896 
6897     ASSERT_EQUAL_64(0x88888888888889ab, x10);
6898     ASSERT_EQUAL_64(0x8888cdef88888888, x11);
6899 
6900     ASSERT_EQUAL_32(0x888888ab, w20);
6901     ASSERT_EQUAL_32(0x88cdef88, w21);
6902 
6903     ASSERT_EQUAL_64(0x8888888888ef8888, x12);
6904     ASSERT_EQUAL_64(0x88888888888888ab, x13);
6905     ASSERT_EQUAL_64(0xffffffffff00ffff, x14);
6906   }
6907 }
6908 
6909 
TEST(sbfm)6910 TEST(sbfm) {
6911   SETUP();
6912 
6913   START();
6914   __ Mov(x1, 0x0123456789abcdef);
6915   __ Mov(x2, 0xfedcba9876543210);
6916 
6917   __ Sbfm(x10, x1, 16, 31);
6918   __ Sbfm(x11, x1, 32, 15);
6919   __ Sbfm(x12, x1, 32, 47);
6920   __ Sbfm(x13, x1, 48, 35);
6921 
6922   __ Sbfm(w14, w1, 16, 23);
6923   __ Sbfm(w15, w1, 24, 15);
6924   __ Sbfm(w16, w2, 16, 23);
6925   __ Sbfm(w17, w2, 24, 15);
6926 
6927   // Aliases.
6928   __ Asr(x18, x1, 32);
6929   __ Asr(x19, x2, 32);
6930   __ Sbfiz(x20, x1, 8, 16);
6931   __ Sbfiz(x21, x2, 8, 16);
6932   __ Sbfx(x22, x1, 8, 16);
6933   __ Sbfx(x23, x2, 8, 16);
6934   __ Sxtb(x24, w1);
6935   __ Sxtb(x25, x2);
6936   __ Sxth(x26, w1);
6937   __ Sxth(x27, x2);
6938   __ Sxtw(x28, w1);
6939   __ Sxtw(x29, x2);
6940   END();
6941 
6942   if (CAN_RUN()) {
6943     RUN();
6944 
6945 
6946     ASSERT_EQUAL_64(0xffffffffffff89ab, x10);
6947     ASSERT_EQUAL_64(0xffffcdef00000000, x11);
6948     ASSERT_EQUAL_64(0x0000000000004567, x12);
6949     ASSERT_EQUAL_64(0x000789abcdef0000, x13);
6950 
6951     ASSERT_EQUAL_32(0xffffffab, w14);
6952     ASSERT_EQUAL_32(0xffcdef00, w15);
6953     ASSERT_EQUAL_32(0x00000054, w16);
6954     ASSERT_EQUAL_32(0x00321000, w17);
6955 
6956     ASSERT_EQUAL_64(0x0000000001234567, x18);
6957     ASSERT_EQUAL_64(0xfffffffffedcba98, x19);
6958     ASSERT_EQUAL_64(0xffffffffffcdef00, x20);
6959     ASSERT_EQUAL_64(0x0000000000321000, x21);
6960     ASSERT_EQUAL_64(0xffffffffffffabcd, x22);
6961     ASSERT_EQUAL_64(0x0000000000005432, x23);
6962     ASSERT_EQUAL_64(0xffffffffffffffef, x24);
6963     ASSERT_EQUAL_64(0x0000000000000010, x25);
6964     ASSERT_EQUAL_64(0xffffffffffffcdef, x26);
6965     ASSERT_EQUAL_64(0x0000000000003210, x27);
6966     ASSERT_EQUAL_64(0xffffffff89abcdef, x28);
6967     ASSERT_EQUAL_64(0x0000000076543210, x29);
6968   }
6969 }
6970 
6971 
TEST(ubfm)6972 TEST(ubfm) {
6973   SETUP();
6974 
6975   START();
6976   __ Mov(x1, 0x0123456789abcdef);
6977   __ Mov(x2, 0xfedcba9876543210);
6978 
6979   __ Mov(x10, 0x8888888888888888);
6980   __ Mov(x11, 0x8888888888888888);
6981 
6982   __ Ubfm(x10, x1, 16, 31);
6983   __ Ubfm(x11, x1, 32, 15);
6984   __ Ubfm(x12, x1, 32, 47);
6985   __ Ubfm(x13, x1, 48, 35);
6986 
6987   __ Ubfm(w25, w1, 16, 23);
6988   __ Ubfm(w26, w1, 24, 15);
6989   __ Ubfm(w27, w2, 16, 23);
6990   __ Ubfm(w28, w2, 24, 15);
6991 
6992   // Aliases
6993   __ Lsl(x15, x1, 63);
6994   __ Lsl(x16, x1, 0);
6995   __ Lsr(x17, x1, 32);
6996   __ Ubfiz(x18, x1, 8, 16);
6997   __ Ubfx(x19, x1, 8, 16);
6998   __ Uxtb(x20, x1);
6999   __ Uxth(x21, x1);
7000   __ Uxtw(x22, x1);
7001   END();
7002 
7003   if (CAN_RUN()) {
7004     RUN();
7005 
7006     ASSERT_EQUAL_64(0x00000000000089ab, x10);
7007     ASSERT_EQUAL_64(0x0000cdef00000000, x11);
7008     ASSERT_EQUAL_64(0x0000000000004567, x12);
7009     ASSERT_EQUAL_64(0x000789abcdef0000, x13);
7010 
7011     ASSERT_EQUAL_32(0x000000ab, w25);
7012     ASSERT_EQUAL_32(0x00cdef00, w26);
7013     ASSERT_EQUAL_32(0x00000054, w27);
7014     ASSERT_EQUAL_32(0x00321000, w28);
7015 
7016     ASSERT_EQUAL_64(0x8000000000000000, x15);
7017     ASSERT_EQUAL_64(0x0123456789abcdef, x16);
7018     ASSERT_EQUAL_64(0x0000000001234567, x17);
7019     ASSERT_EQUAL_64(0x0000000000cdef00, x18);
7020     ASSERT_EQUAL_64(0x000000000000abcd, x19);
7021     ASSERT_EQUAL_64(0x00000000000000ef, x20);
7022     ASSERT_EQUAL_64(0x000000000000cdef, x21);
7023     ASSERT_EQUAL_64(0x0000000089abcdef, x22);
7024   }
7025 }
7026 
7027 
TEST(extr)7028 TEST(extr) {
7029   SETUP();
7030 
7031   START();
7032   __ Mov(x1, 0x0123456789abcdef);
7033   __ Mov(x2, 0xfedcba9876543210);
7034 
7035   __ Extr(w10, w1, w2, 0);
7036   __ Extr(w11, w1, w2, 1);
7037   __ Extr(x12, x2, x1, 2);
7038 
7039   __ Ror(w13, w1, 0);
7040   __ Ror(w14, w2, 17);
7041   __ Ror(w15, w1, 31);
7042   __ Ror(x18, x2, 0);
7043   __ Ror(x19, x2, 1);
7044   __ Ror(x20, x1, 63);
7045   END();
7046 
7047   if (CAN_RUN()) {
7048     RUN();
7049 
7050     ASSERT_EQUAL_64(0x76543210, x10);
7051     ASSERT_EQUAL_64(0xbb2a1908, x11);
7052     ASSERT_EQUAL_64(0x0048d159e26af37b, x12);
7053     ASSERT_EQUAL_64(0x89abcdef, x13);
7054     ASSERT_EQUAL_64(0x19083b2a, x14);
7055     ASSERT_EQUAL_64(0x13579bdf, x15);
7056     ASSERT_EQUAL_64(0xfedcba9876543210, x18);
7057     ASSERT_EQUAL_64(0x7f6e5d4c3b2a1908, x19);
7058     ASSERT_EQUAL_64(0x02468acf13579bde, x20);
7059   }
7060 }
7061 
7062 
TEST(system_mrs)7063 TEST(system_mrs) {
7064   SETUP();
7065 
7066   START();
7067   __ Mov(w0, 0);
7068   __ Mov(w1, 1);
7069   __ Mov(w2, 0x80000000);
7070 
7071   // Set the Z and C flags.
7072   __ Cmp(w0, w0);
7073   __ Mrs(x3, NZCV);
7074 
7075   // Set the N flag.
7076   __ Cmp(w0, w1);
7077   __ Mrs(x4, NZCV);
7078 
7079   // Set the Z, C and V flags.
7080   __ Adds(w0, w2, w2);
7081   __ Mrs(x5, NZCV);
7082 
7083   // Read the default FPCR.
7084   __ Mrs(x6, FPCR);
7085   END();
7086 
7087   if (CAN_RUN()) {
7088     RUN();
7089 
7090     // NZCV
7091     ASSERT_EQUAL_32(ZCFlag, w3);
7092     ASSERT_EQUAL_32(NFlag, w4);
7093     ASSERT_EQUAL_32(ZCVFlag, w5);
7094 
7095     // FPCR
7096     // The default FPCR on Linux-based platforms is 0.
7097     ASSERT_EQUAL_32(0, w6);
7098   }
7099 }
7100 
TEST(system_rng)7101 TEST(system_rng) {
7102   SETUP_WITH_FEATURES(CPUFeatures::kRNG);
7103 
7104   START();
7105   // Random number.
7106   __ Mrs(x1, RNDR);
7107   // Assume that each generation is successful now.
7108   // TODO: Return failure occasionally.
7109   __ Mrs(x2, NZCV);
7110   __ Mrs(x3, RNDR);
7111   __ Mrs(x4, NZCV);
7112 
7113   // Reseeded random number.
7114   __ Mrs(x5, RNDRRS);
7115   // Assume that each generation is successful now.
7116   // TODO: Return failure occasionally.
7117   __ Mrs(x6, NZCV);
7118   __ Mrs(x7, RNDRRS);
7119   __ Mrs(x8, NZCV);
7120   END();
7121 
7122   if (CAN_RUN()) {
7123     RUN();
7124     // Random number generation series.
7125     // Check random numbers have been generated and aren't equal when reseed has
7126     // happened.
7127     // NOTE: With a different architectural implementation, there may be a
7128     // collison.
7129     // TODO: Return failure occasionally. Set ZFlag and return UNKNOWN value.
7130     ASSERT_NOT_EQUAL_64(x1, x3);
7131     ASSERT_EQUAL_64(NoFlag, x2);
7132     ASSERT_EQUAL_64(NoFlag, x4);
7133     ASSERT_NOT_EQUAL_64(x5, x7);
7134     ASSERT_EQUAL_64(NoFlag, x6);
7135     ASSERT_EQUAL_64(NoFlag, x8);
7136   }
7137 }
7138 
TEST(cfinv)7139 TEST(cfinv) {
7140   SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
7141 
7142   START();
7143   __ Mov(w0, 1);
7144 
7145   // Set the C flag.
7146   __ Cmp(w0, 0);
7147   __ Mrs(x1, NZCV);
7148 
7149   // Invert the C flag.
7150   __ Cfinv();
7151   __ Mrs(x2, NZCV);
7152 
7153   // Invert the C flag again.
7154   __ Cfinv();
7155   __ Mrs(x3, NZCV);
7156   END();
7157 
7158   if (CAN_RUN()) {
7159     RUN();
7160 
7161     ASSERT_EQUAL_32(CFlag, w1);
7162     ASSERT_EQUAL_32(NoFlag, w2);
7163     ASSERT_EQUAL_32(CFlag, w3);
7164   }
7165 }
7166 
7167 
TEST(axflag_xaflag)7168 TEST(axflag_xaflag) {
7169   // The AXFLAG and XAFLAG instructions are designed for converting the FP
7170   // conditional flags from Arm format to an alternate format efficiently.
7171   // There are only 4 cases which are relevant for this conversion but we test
7172   // the behaviour for all 16 cases anyway. The 4 important cases are labelled
7173   // below.
7174   StatusFlags expected_x[16] = {NoFlag,
7175                                 ZFlag,
7176                                 CFlag,  // Greater than
7177                                 ZFlag,  // Unordered
7178                                 ZFlag,
7179                                 ZFlag,
7180                                 ZCFlag,  // Equal to
7181                                 ZFlag,
7182                                 NoFlag,  // Less than
7183                                 ZFlag,
7184                                 CFlag,
7185                                 ZFlag,
7186                                 ZFlag,
7187                                 ZFlag,
7188                                 ZCFlag,
7189                                 ZFlag};
7190   StatusFlags expected_a[16] = {NFlag,  // Less than
7191                                 NFlag,
7192                                 CFlag,  // Greater than
7193                                 CFlag,
7194                                 CVFlag,  // Unordered
7195                                 CVFlag,
7196                                 ZCFlag,  // Equal to
7197                                 ZCFlag,
7198                                 NFlag,
7199                                 NFlag,
7200                                 CFlag,
7201                                 CFlag,
7202                                 CVFlag,
7203                                 CVFlag,
7204                                 ZCFlag,
7205                                 ZCFlag};
7206 
7207   for (unsigned i = 0; i < 16; i++) {
7208     SETUP_WITH_FEATURES(CPUFeatures::kAXFlag);
7209 
7210     START();
7211     __ Mov(x0, i << Flags_offset);
7212     __ Msr(NZCV, x0);
7213     __ Axflag();
7214     __ Mrs(x1, NZCV);
7215     __ Msr(NZCV, x0);
7216     __ Xaflag();
7217     __ Mrs(x2, NZCV);
7218     END();
7219 
7220     if (CAN_RUN()) {
7221       RUN();
7222       ASSERT_EQUAL_32(expected_x[i], w1);
7223       ASSERT_EQUAL_32(expected_a[i], w2);
7224     }
7225   }
7226 }
7227 
7228 
TEST(system_msr)7229 TEST(system_msr) {
7230   // All FPCR fields that must be implemented: AHP, DN, FZ, RMode
7231   const uint64_t fpcr_core = (0b1 << 26) |  // AHP
7232                              (0b1 << 25) |  // DN
7233                              (0b1 << 24) |  // FZ
7234                              (0b11 << 22);  // RMode
7235 
7236   SETUP();
7237 
7238   START();
7239   __ Mov(w0, 0);
7240   __ Mov(w1, 0x7fffffff);
7241 
7242   __ Mov(x7, 0);
7243 
7244   __ Mov(x10, NVFlag);
7245   __ Cmp(w0, w0);     // Set Z and C.
7246   __ Msr(NZCV, x10);  // Set N and V.
7247   // The Msr should have overwritten every flag set by the Cmp.
7248   __ Cinc(x7, x7, mi);  // N
7249   __ Cinc(x7, x7, ne);  // !Z
7250   __ Cinc(x7, x7, lo);  // !C
7251   __ Cinc(x7, x7, vs);  // V
7252 
7253   __ Mov(x10, ZCFlag);
7254   __ Cmn(w1, w1);     // Set N and V.
7255   __ Msr(NZCV, x10);  // Set Z and C.
7256   // The Msr should have overwritten every flag set by the Cmn.
7257   __ Cinc(x7, x7, pl);  // !N
7258   __ Cinc(x7, x7, eq);  // Z
7259   __ Cinc(x7, x7, hs);  // C
7260   __ Cinc(x7, x7, vc);  // !V
7261 
7262   Register old_fpcr = x15;
7263   __ Mrs(old_fpcr, FPCR);
7264 
7265   // All core FPCR fields must be writable.
7266   __ Mov(x8, fpcr_core);
7267   __ Msr(FPCR, x8);
7268   __ Mrs(x8, FPCR);
7269 
7270 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7271   // All FPCR fields that aren't `RES0`:
7272   const uint64_t fpcr_all = fpcr_core | (0b11 << 20) |  // Stride
7273                             (0b1 << 19) |               // FZ16
7274                             (0b111 << 16) |             // Len
7275                             (0b1 << 15) |               // IDE
7276                             (0b1 << 12) |               // IXE
7277                             (0b1 << 11) |               // UFE
7278                             (0b1 << 10) |               // OFE
7279                             (0b1 << 9) |                // DZE
7280                             (0b1 << 8);                 // IOE
7281 
7282   // All FPCR fields, including optional ones. This part of the test doesn't
7283   // achieve much other than ensuring that supported fields can be cleared by
7284   // the next test.
7285   __ Mov(x9, fpcr_all);
7286   __ Msr(FPCR, x9);
7287   __ Mrs(x9, FPCR);
7288   __ And(x9, x9, fpcr_core);
7289 
7290   // The undefined bits must ignore writes.
7291   // It's conceivable that a future version of the architecture could use these
7292   // fields (making this test fail), but in the meantime this is a useful test
7293   // for the simulator.
7294   __ Mov(x10, ~fpcr_all);
7295   __ Msr(FPCR, x10);
7296   __ Mrs(x10, FPCR);
7297 #endif
7298 
7299   __ Msr(FPCR, old_fpcr);
7300 
7301   END();
7302 
7303   if (CAN_RUN()) {
7304     RUN();
7305 
7306     // We should have incremented x7 (from 0) exactly 8 times.
7307     ASSERT_EQUAL_64(8, x7);
7308 
7309     ASSERT_EQUAL_64(fpcr_core, x8);
7310 
7311 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7312     ASSERT_EQUAL_64(fpcr_core, x9);
7313     ASSERT_EQUAL_64(0, x10);
7314 #endif
7315   }
7316 }
7317 
7318 
TEST(system_pauth_a)7319 TEST(system_pauth_a) {
7320   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7321   START();
7322 
7323   // Exclude x16 and x17 from the scratch register list so we can use
7324   // Pac/Autia1716 safely.
7325   UseScratchRegisterScope temps(&masm);
7326   temps.Exclude(x16, x17);
7327   temps.Include(x10, x11);
7328 
7329   Register pointer = x21;
7330   Register retry_limit = x22;
7331   Label retry;
7332 
7333   __ Mov(pointer, 0x0000000012345678);
7334   __ Mov(retry_limit, 0x0000000012345678 + 32);
7335 
7336   // Back up stack pointer.
7337   __ Mov(x20, sp);
7338 
7339   // Modifiers
7340   __ Mov(x16, 0x477d469dec0b8760);
7341   __ Mov(sp, 0x477d469dec0b8760);
7342 
7343   __ Bind(&retry);
7344 
7345   // Generate PACs using the 3 system instructions.
7346   __ Mov(x17, pointer);
7347   __ Pacia1716();
7348   __ Mov(x0, x17);
7349 
7350   __ Mov(lr, pointer);
7351   __ Paciaz();
7352   __ Mov(x1, lr);
7353 
7354   __ Mov(lr, pointer);
7355   __ Paciasp();
7356   __ Mov(x2, lr);
7357 
7358   // Authenticate the pointers above.
7359   __ Mov(x17, x0);
7360   __ Autia1716();
7361   __ Mov(x3, x17);
7362 
7363   __ Mov(lr, x1);
7364   __ Autiaz();
7365   __ Mov(x4, lr);
7366 
7367   __ Mov(lr, x2);
7368   __ Autiasp();
7369   __ Mov(x5, lr);
7370 
7371   // Attempt to authenticate incorrect pointers.
7372   __ Mov(x17, x1);
7373   __ Autia1716();
7374   __ Mov(x6, x17);
7375 
7376   __ Mov(lr, x0);
7377   __ Autiaz();
7378   __ Mov(x7, lr);
7379 
7380   __ Mov(lr, x1);
7381   __ Autiasp();
7382   __ Mov(x8, lr);
7383 
7384   // Strip the pac code from the pointer in x0.
7385   __ Mov(lr, x0);
7386   __ Xpaclri();
7387   __ Mov(x9, lr);
7388 
7389   // Retry on collisions.
7390   __ Cmp(x0, x1);
7391   __ Ccmp(pointer, x0, ZFlag, ne);
7392   __ Ccmp(pointer, x1, ZFlag, ne);
7393   __ Ccmp(pointer, x2, ZFlag, ne);
7394   __ Ccmp(pointer, x6, ZFlag, ne);
7395   __ Ccmp(pointer, x7, ZFlag, ne);
7396   __ Ccmp(pointer, x8, ZFlag, ne);
7397   __ Ccmp(pointer, retry_limit, ZFlag, eq);
7398   __ Cinc(pointer, pointer, ne);
7399   __ B(ne, &retry);
7400 
7401   // Restore stack pointer.
7402   __ Mov(sp, x20);
7403 
7404   END();
7405 
7406   if (CAN_RUN()) {
7407     RUN();
7408 
7409     // Check PAC codes have been generated.
7410     ASSERT_NOT_EQUAL_64(pointer, x0);
7411     ASSERT_NOT_EQUAL_64(pointer, x1);
7412     ASSERT_NOT_EQUAL_64(pointer, x2);
7413     ASSERT_NOT_EQUAL_64(x0, x1);
7414     ASSERT_EQUAL_64(x0, x2);
7415 
7416     // Pointers correctly authenticated.
7417     ASSERT_EQUAL_64(pointer, x3);
7418     ASSERT_EQUAL_64(pointer, x4);
7419     ASSERT_EQUAL_64(pointer, x5);
7420 
7421     // Pointers corrupted after failing to authenticate.
7422 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7423     ASSERT_EQUAL_64(0x0020000012345678, x6);
7424     ASSERT_EQUAL_64(0x0020000012345678, x7);
7425     ASSERT_EQUAL_64(0x0020000012345678, x8);
7426 #else
7427     ASSERT_NOT_EQUAL_64(pointer, x6);
7428     ASSERT_NOT_EQUAL_64(pointer, x7);
7429     ASSERT_NOT_EQUAL_64(pointer, x8);
7430 #endif
7431 
7432     // Pointer with code stripped.
7433     ASSERT_EQUAL_64(pointer, x9);
7434   }
7435 }
7436 
7437 
TEST(system_pauth_b)7438 TEST(system_pauth_b) {
7439   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7440   START();
7441 
7442   // Exclude x16 and x17 from the scratch register list so we can use
7443   // Pac/Autia1716 safely.
7444   UseScratchRegisterScope temps(&masm);
7445   temps.Exclude(x16, x17);
7446   temps.Include(x10, x11);
7447 
7448   Register pointer = x21;
7449   Register retry_limit = x22;
7450   Label retry;
7451 
7452   __ Mov(pointer, 0x0000000012345678);
7453   __ Mov(retry_limit, 0x0000000012345678 + 32);
7454 
7455   // Back up stack pointer.
7456   __ Mov(x20, sp);
7457 
7458   // Modifiers
7459   __ Mov(x16, 0x477d469dec0b8760);
7460   __ Mov(sp, 0x477d469dec0b8760);
7461 
7462   __ Bind(&retry);
7463 
7464   // Generate PACs using the 3 system instructions.
7465   __ Mov(x17, 0x0000000012345678);
7466   __ Pacib1716();
7467   __ Mov(x0, x17);
7468 
7469   __ Mov(lr, 0x0000000012345678);
7470   __ Pacibz();
7471   __ Mov(x1, lr);
7472 
7473   __ Mov(lr, 0x0000000012345678);
7474   __ Pacibsp();
7475   __ Mov(x2, lr);
7476 
7477   // Authenticate the pointers above.
7478   __ Mov(x17, x0);
7479   __ Autib1716();
7480   __ Mov(x3, x17);
7481 
7482   __ Mov(lr, x1);
7483   __ Autibz();
7484   __ Mov(x4, lr);
7485 
7486   __ Mov(lr, x2);
7487   __ Autibsp();
7488   __ Mov(x5, lr);
7489 
7490   // Attempt to authenticate incorrect pointers.
7491   __ Mov(x17, x1);
7492   __ Autib1716();
7493   __ Mov(x6, x17);
7494 
7495   __ Mov(lr, x0);
7496   __ Autibz();
7497   __ Mov(x7, lr);
7498 
7499   __ Mov(lr, x1);
7500   __ Autibsp();
7501   __ Mov(x8, lr);
7502 
7503   // Strip the pac code from the pointer in x0.
7504   __ Mov(lr, x0);
7505   __ Xpaclri();
7506   __ Mov(x9, lr);
7507 
7508   // Retry on collisions.
7509   __ Cmp(x0, x1);
7510   __ Ccmp(pointer, x0, ZFlag, ne);
7511   __ Ccmp(pointer, x1, ZFlag, ne);
7512   __ Ccmp(pointer, x2, ZFlag, ne);
7513   __ Ccmp(pointer, x6, ZFlag, ne);
7514   __ Ccmp(pointer, x7, ZFlag, ne);
7515   __ Ccmp(pointer, x8, ZFlag, ne);
7516   __ Ccmp(pointer, retry_limit, ZFlag, eq);
7517   __ Cinc(pointer, pointer, ne);
7518   __ B(ne, &retry);
7519 
7520   // Restore stack pointer.
7521   __ Mov(sp, x20);
7522 
7523   END();
7524 
7525   if (CAN_RUN()) {
7526     RUN();
7527 
7528     // Check PAC codes have been generated and aren't equal.
7529     // NOTE: with a different ComputePAC implementation, there may be a
7530     // collision.
7531     ASSERT_NOT_EQUAL_64(pointer, x0);
7532     ASSERT_NOT_EQUAL_64(pointer, x1);
7533     ASSERT_NOT_EQUAL_64(pointer, x2);
7534     ASSERT_NOT_EQUAL_64(x0, x1);
7535     ASSERT_EQUAL_64(x0, x2);
7536 
7537     // Pointers correctly authenticated.
7538     ASSERT_EQUAL_64(pointer, x3);
7539     ASSERT_EQUAL_64(pointer, x4);
7540     ASSERT_EQUAL_64(pointer, x5);
7541 
7542     // Pointers corrupted after failing to authenticate.
7543 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7544     ASSERT_EQUAL_64(0x0040000012345678, x6);
7545     ASSERT_EQUAL_64(0x0040000012345678, x7);
7546     ASSERT_EQUAL_64(0x0040000012345678, x8);
7547 #else
7548     ASSERT_NOT_EQUAL_64(pointer, x6);
7549     ASSERT_NOT_EQUAL_64(pointer, x7);
7550     ASSERT_NOT_EQUAL_64(pointer, x8);
7551 #endif
7552 
7553     // Pointer with code stripped.
7554     ASSERT_EQUAL_64(pointer, x9);
7555   }
7556 }
7557 
7558 #ifdef VIXL_NEGATIVE_TESTING
TEST(system_pauth_negative_test)7559 TEST(system_pauth_negative_test) {
7560   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7561   START();
7562 
7563   // Test for an assert (independent of order).
7564   MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7565                          "Assertion failed "
7566                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7567 
7568   // Test for x16 assert.
7569   {
7570     UseScratchRegisterScope temps(&masm);
7571     temps.Exclude(x17);
7572     temps.Include(x16);
7573     MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7574                            "Assertion failed "
7575                            "(!GetScratchRegisterList()->IncludesAliasOf(x16))");
7576   }
7577 
7578   // Test for x17 assert.
7579   {
7580     UseScratchRegisterScope temps(&masm);
7581     temps.Exclude(x16);
7582     temps.Include(x17);
7583     MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7584                            "Assertion failed "
7585                            "(!GetScratchRegisterList()->IncludesAliasOf(x17))");
7586   }
7587 
7588   // Repeat first test for other 1716 instructions.
7589   MUST_FAIL_WITH_MESSAGE(__ Pacib1716(),
7590                          "Assertion failed "
7591                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7592   MUST_FAIL_WITH_MESSAGE(__ Autia1716(),
7593                          "Assertion failed "
7594                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7595   MUST_FAIL_WITH_MESSAGE(__ Autib1716(),
7596                          "Assertion failed "
7597                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7598 
7599   END();
7600 }
7601 #endif  // VIXL_NEGATIVE_TESTING
7602 
7603 
TEST(system)7604 TEST(system) {
7605   // RegisterDump::Dump uses NEON.
7606   SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRAS);
7607   RegisterDump before;
7608 
7609   START();
7610   before.Dump(&masm);
7611   __ Nop();
7612   __ Esb();
7613   __ Csdb();
7614   END();
7615 
7616   if (CAN_RUN()) {
7617     RUN();
7618 
7619     ASSERT_EQUAL_REGISTERS(before);
7620     ASSERT_EQUAL_NZCV(before.flags_nzcv());
7621   }
7622 }
7623 
BtiHelper(Register ipreg)7624 static void BtiHelper(Register ipreg) {
7625   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7626 
7627   Label jump_target, jump_call_target, call_target, done;
7628   START();
7629   UseScratchRegisterScope temps(&masm);
7630   temps.Exclude(ipreg);
7631   __ Adr(x0, &jump_target);
7632   __ Br(x0);
7633   __ Nop();
7634   __ Bind(&jump_target, EmitBTI_j);
7635   __ Adr(x0, &call_target);
7636   __ Blr(x0);
7637   __ Adr(ipreg, &jump_call_target);
7638   __ Blr(ipreg);
7639   __ Mov(lr, 0);  // Zero lr so we branch to done.
7640   __ Br(ipreg);
7641   __ Bind(&call_target, EmitBTI_c);
7642   __ Ret();
7643   __ Bind(&jump_call_target, EmitBTI_jc);
7644   __ Cbz(lr, &done);
7645   __ Ret();
7646   __ Bind(&done);
7647   END();
7648 
7649   if (CAN_RUN()) {
7650 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7651     simulator.SetGuardedPages(true);
7652 #endif
7653     // On hardware, we'll run the test anyway, but mark it as SKIPPED until
7654     // we've implemented a mechanism for marking Guarded pages.
7655 
7656     RUN();
7657 
7658 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
7659     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7660 #endif
7661   }
7662 }
7663 
TEST(bti)7664 TEST(bti) {
7665   BtiHelper(x16);
7666   BtiHelper(x17);
7667 }
7668 
TEST(unguarded_bti_is_nop)7669 TEST(unguarded_bti_is_nop) {
7670   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7671 
7672   Label start, none, c, j, jc;
7673   Label jump_to_c, call_to_j;
7674   START();
7675   __ B(&start);
7676   __ Bind(&none, EmitBTI);
7677   __ Bind(&c, EmitBTI_c);
7678   __ Bind(&j, EmitBTI_j);
7679   __ Bind(&jc, EmitBTI_jc);
7680   __ Hint(BTI);
7681   __ Hint(BTI_c);
7682   __ Hint(BTI_j);
7683   __ Hint(BTI_jc);
7684   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&none) == 8 * kInstructionSize);
7685   __ Cmp(x1, 1);
7686   __ B(lt, &jump_to_c);
7687   __ B(eq, &call_to_j);
7688   __ Ret();
7689 
7690   __ Bind(&start);
7691   __ Adr(x0, &none);
7692   __ Mov(x1, 0);
7693   __ Br(x0);
7694 
7695   __ Bind(&jump_to_c);
7696   __ Adr(x0, &c);
7697   __ Mov(x1, 1);
7698   __ Br(x0);
7699 
7700   __ Bind(&call_to_j);
7701   __ Adr(x0, &j);
7702   __ Mov(x1, 2);
7703   __ Blr(x0);
7704   END();
7705 
7706   if (CAN_RUN()) {
7707 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7708     simulator.SetGuardedPages(false);
7709 #endif
7710     RUN();
7711   }
7712 }
7713 
7714 #ifdef VIXL_NEGATIVE_TESTING
TEST(bti_jump_to_ip_unidentified)7715 TEST(bti_jump_to_ip_unidentified) {
7716   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7717 
7718   START();
7719   UseScratchRegisterScope temps(&masm);
7720   temps.Exclude(x17);
7721   Label l;
7722   __ Adr(x17, &l);
7723   __ Br(x17);
7724   __ Nop();
7725   __ Bind(&l);
7726   __ Nop();
7727   END();
7728 
7729   if (CAN_RUN()) {
7730 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7731     simulator.SetGuardedPages(true);
7732     MUST_FAIL_WITH_MESSAGE(RUN(),
7733                            "Executing non-BTI instruction with wrong "
7734                            "BType.");
7735 #else
7736     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7737 #endif
7738   }
7739 }
7740 
TEST(bti_jump_to_unidentified)7741 TEST(bti_jump_to_unidentified) {
7742   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7743 
7744   START();
7745   Label l;
7746   __ Adr(x0, &l);
7747   __ Br(x0);
7748   __ Nop();
7749   __ Bind(&l);
7750   __ Nop();
7751   END();
7752 
7753   if (CAN_RUN()) {
7754 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7755     simulator.SetGuardedPages(true);
7756     MUST_FAIL_WITH_MESSAGE(RUN(),
7757                            "Executing non-BTI instruction with wrong "
7758                            "BType.");
7759 #else
7760     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7761 #endif
7762   }
7763 }
7764 
TEST(bti_call_to_unidentified)7765 TEST(bti_call_to_unidentified) {
7766   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7767 
7768   START();
7769   Label l;
7770   __ Adr(x0, &l);
7771   __ Blr(x0);
7772   __ Nop();
7773   __ Bind(&l);
7774   __ Nop();
7775   END();
7776 
7777   if (CAN_RUN()) {
7778 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7779     simulator.SetGuardedPages(true);
7780     MUST_FAIL_WITH_MESSAGE(RUN(),
7781                            "Executing non-BTI instruction with wrong "
7782                            "BType.");
7783 #else
7784     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7785 #endif
7786   }
7787 }
7788 
TEST(bti_jump_to_c)7789 TEST(bti_jump_to_c) {
7790   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7791 
7792   START();
7793   // Jumping to a "BTI c" target must fail.
7794   Label jump_target;
7795   __ Adr(x0, &jump_target);
7796   __ Br(x0);
7797   __ Nop();
7798   __ Bind(&jump_target, EmitBTI_c);
7799   __ Nop();
7800   END();
7801 
7802   if (CAN_RUN()) {
7803 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7804     simulator.SetGuardedPages(true);
7805     MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI c with wrong BType.");
7806 #else
7807     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7808 #endif
7809   }
7810 }
7811 
TEST(bti_call_to_j)7812 TEST(bti_call_to_j) {
7813   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7814 
7815   START();
7816   // Calling a "BTI j" target must fail.
7817   Label call_target;
7818   __ Adr(x0, &call_target);
7819   __ Blr(x0);
7820   __ Nop();
7821   __ Bind(&call_target, EmitBTI_j);
7822   __ Nop();
7823   END();
7824 
7825   if (CAN_RUN()) {
7826 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7827     simulator.SetGuardedPages(true);
7828     MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI j with wrong BType.");
7829 #else
7830     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7831 #endif
7832   }
7833 }
7834 #endif  // VIXL_NEGATIVE_TESTING
7835 
TEST(fall_through_bti)7836 TEST(fall_through_bti) {
7837   SETUP_WITH_FEATURES(CPUFeatures::kBTI, CPUFeatures::kPAuth);
7838 
7839   START();
7840   Label target, target_j, target_c, target_jc;
7841   __ Mov(x0, 0);  // 'Normal' instruction sets BTYPE to zero.
7842   __ Bind(&target, EmitBTI);
7843   __ Add(x0, x0, 1);
7844   __ Bind(&target_j, EmitBTI_j);
7845   __ Add(x0, x0, 1);
7846   __ Bind(&target_c, EmitBTI_c);
7847   __ Add(x0, x0, 1);
7848   __ Bind(&target_jc, EmitBTI_jc);
7849   __ Add(x0, x0, 1);
7850   __ Paciasp();
7851   END();
7852 
7853   if (CAN_RUN()) {
7854 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7855     simulator.SetGuardedPages(true);
7856 #endif
7857     // On hardware, we'll run the test anyway, but mark it as SKIPPED until
7858     // we've implemented a mechanism for marking Guarded pages.
7859 
7860     RUN();
7861 
7862     ASSERT_EQUAL_64(4, x0);
7863 
7864 #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
7865     printf("SKIPPED: marking guarded pages is unimplemented on hardware");
7866 #endif
7867   }
7868 }
7869 
TEST(zero_dest)7870 TEST(zero_dest) {
7871   // RegisterDump::Dump uses NEON.
7872   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
7873   RegisterDump before;
7874 
7875   START();
7876   // Preserve the stack pointer, in case we clobber it.
7877   __ Mov(x30, sp);
7878   // Initialize the other registers used in this test.
7879   uint64_t literal_base = 0x0100001000100101;
7880   __ Mov(x0, 0);
7881   __ Mov(x1, literal_base);
7882   for (unsigned i = 2; i < x30.GetCode(); i++) {
7883     __ Add(XRegister(i), XRegister(i - 1), x1);
7884   }
7885   before.Dump(&masm);
7886 
7887   // All of these instructions should be NOPs in these forms, but have
7888   // alternate forms which can write into the stack pointer.
7889   {
7890     ExactAssemblyScope scope(&masm, 3 * 7 * kInstructionSize);
7891     __ add(xzr, x0, x1);
7892     __ add(xzr, x1, xzr);
7893     __ add(xzr, xzr, x1);
7894 
7895     __ and_(xzr, x0, x2);
7896     __ and_(xzr, x2, xzr);
7897     __ and_(xzr, xzr, x2);
7898 
7899     __ bic(xzr, x0, x3);
7900     __ bic(xzr, x3, xzr);
7901     __ bic(xzr, xzr, x3);
7902 
7903     __ eon(xzr, x0, x4);
7904     __ eon(xzr, x4, xzr);
7905     __ eon(xzr, xzr, x4);
7906 
7907     __ eor(xzr, x0, x5);
7908     __ eor(xzr, x5, xzr);
7909     __ eor(xzr, xzr, x5);
7910 
7911     __ orr(xzr, x0, x6);
7912     __ orr(xzr, x6, xzr);
7913     __ orr(xzr, xzr, x6);
7914 
7915     __ sub(xzr, x0, x7);
7916     __ sub(xzr, x7, xzr);
7917     __ sub(xzr, xzr, x7);
7918   }
7919 
7920   // Swap the saved stack pointer with the real one. If sp was written
7921   // during the test, it will show up in x30. This is done because the test
7922   // framework assumes that sp will be valid at the end of the test.
7923   __ Mov(x29, x30);
7924   __ Mov(x30, sp);
7925   __ Mov(sp, x29);
7926   // We used x29 as a scratch register, so reset it to make sure it doesn't
7927   // trigger a test failure.
7928   __ Add(x29, x28, x1);
7929   END();
7930 
7931   if (CAN_RUN()) {
7932     RUN();
7933 
7934     ASSERT_EQUAL_REGISTERS(before);
7935     ASSERT_EQUAL_NZCV(before.flags_nzcv());
7936   }
7937 }
7938 
7939 
TEST(zero_dest_setflags)7940 TEST(zero_dest_setflags) {
7941   // RegisterDump::Dump uses NEON.
7942   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
7943   RegisterDump before;
7944 
7945   START();
7946   // Preserve the stack pointer, in case we clobber it.
7947   __ Mov(x30, sp);
7948   // Initialize the other registers used in this test.
7949   uint64_t literal_base = 0x0100001000100101;
7950   __ Mov(x0, 0);
7951   __ Mov(x1, literal_base);
7952   for (int i = 2; i < 30; i++) {
7953     __ Add(XRegister(i), XRegister(i - 1), x1);
7954   }
7955   before.Dump(&masm);
7956 
7957   // All of these instructions should only write to the flags in these forms,
7958   // but have alternate forms which can write into the stack pointer.
7959   {
7960     ExactAssemblyScope scope(&masm, 6 * kInstructionSize);
7961     __ adds(xzr, x0, Operand(x1, UXTX));
7962     __ adds(xzr, x1, Operand(xzr, UXTX));
7963     __ adds(xzr, x1, 1234);
7964     __ adds(xzr, x0, x1);
7965     __ adds(xzr, x1, xzr);
7966     __ adds(xzr, xzr, x1);
7967   }
7968 
7969   {
7970     ExactAssemblyScope scope(&masm, 5 * kInstructionSize);
7971     __ ands(xzr, x2, ~0xf);
7972     __ ands(xzr, xzr, ~0xf);
7973     __ ands(xzr, x0, x2);
7974     __ ands(xzr, x2, xzr);
7975     __ ands(xzr, xzr, x2);
7976   }
7977 
7978   {
7979     ExactAssemblyScope scope(&masm, 5 * kInstructionSize);
7980     __ bics(xzr, x3, ~0xf);
7981     __ bics(xzr, xzr, ~0xf);
7982     __ bics(xzr, x0, x3);
7983     __ bics(xzr, x3, xzr);
7984     __ bics(xzr, xzr, x3);
7985   }
7986 
7987   {
7988     ExactAssemblyScope scope(&masm, 6 * kInstructionSize);
7989     __ subs(xzr, x0, Operand(x3, UXTX));
7990     __ subs(xzr, x3, Operand(xzr, UXTX));
7991     __ subs(xzr, x3, 1234);
7992     __ subs(xzr, x0, x3);
7993     __ subs(xzr, x3, xzr);
7994     __ subs(xzr, xzr, x3);
7995   }
7996 
7997   // Swap the saved stack pointer with the real one. If sp was written
7998   // during the test, it will show up in x30. This is done because the test
7999   // framework assumes that sp will be valid at the end of the test.
8000   __ Mov(x29, x30);
8001   __ Mov(x30, sp);
8002   __ Mov(sp, x29);
8003   // We used x29 as a scratch register, so reset it to make sure it doesn't
8004   // trigger a test failure.
8005   __ Add(x29, x28, x1);
8006   END();
8007 
8008   if (CAN_RUN()) {
8009     RUN();
8010 
8011     ASSERT_EQUAL_REGISTERS(before);
8012   }
8013 }
8014 
8015 
TEST(stack_pointer_override)8016 TEST(stack_pointer_override) {
8017   // This test generates some stack maintenance code, but the test only checks
8018   // the reported state.
8019   SETUP();
8020   START();
8021 
8022   // The default stack pointer in VIXL is sp.
8023   VIXL_CHECK(sp.Is(__ StackPointer()));
8024   __ SetStackPointer(x0);
8025   VIXL_CHECK(x0.Is(__ StackPointer()));
8026   __ SetStackPointer(x28);
8027   VIXL_CHECK(x28.Is(__ StackPointer()));
8028   __ SetStackPointer(sp);
8029   VIXL_CHECK(sp.Is(__ StackPointer()));
8030 
8031   END();
8032   if (CAN_RUN()) {
8033     RUN();
8034   }
8035 }
8036 
8037 
TEST(peek_poke_simple)8038 TEST(peek_poke_simple) {
8039   SETUP();
8040   START();
8041 
8042   static const RegList x0_to_x3 =
8043       x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit();
8044   static const RegList x10_to_x13 =
8045       x10.GetBit() | x11.GetBit() | x12.GetBit() | x13.GetBit();
8046 
8047   // The literal base is chosen to have two useful properties:
8048   //  * When multiplied by small values (such as a register index), this value
8049   //    is clearly readable in the result.
8050   //  * The value is not formed from repeating fixed-size smaller values, so it
8051   //    can be used to detect endianness-related errors.
8052   uint64_t literal_base = 0x0100001000100101;
8053 
8054   // Initialize the registers.
8055   __ Mov(x0, literal_base);
8056   __ Add(x1, x0, x0);
8057   __ Add(x2, x1, x0);
8058   __ Add(x3, x2, x0);
8059 
8060   __ Claim(32);
8061 
8062   // Simple exchange.
8063   //  After this test:
8064   //    x0-x3 should be unchanged.
8065   //    w10-w13 should contain the lower words of x0-x3.
8066   __ Poke(x0, 0);
8067   __ Poke(x1, 8);
8068   __ Poke(x2, 16);
8069   __ Poke(x3, 24);
8070   Clobber(&masm, x0_to_x3);
8071   __ Peek(x0, 0);
8072   __ Peek(x1, 8);
8073   __ Peek(x2, 16);
8074   __ Peek(x3, 24);
8075 
8076   __ Poke(w0, 0);
8077   __ Poke(w1, 4);
8078   __ Poke(w2, 8);
8079   __ Poke(w3, 12);
8080   Clobber(&masm, x10_to_x13);
8081   __ Peek(w10, 0);
8082   __ Peek(w11, 4);
8083   __ Peek(w12, 8);
8084   __ Peek(w13, 12);
8085 
8086   __ Drop(32);
8087 
8088   END();
8089   if (CAN_RUN()) {
8090     RUN();
8091 
8092     ASSERT_EQUAL_64(literal_base * 1, x0);
8093     ASSERT_EQUAL_64(literal_base * 2, x1);
8094     ASSERT_EQUAL_64(literal_base * 3, x2);
8095     ASSERT_EQUAL_64(literal_base * 4, x3);
8096 
8097     ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
8098     ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
8099     ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
8100     ASSERT_EQUAL_64((literal_base * 4) & 0xffffffff, x13);
8101   }
8102 }
8103 
8104 
TEST(peek_poke_unaligned)8105 TEST(peek_poke_unaligned) {
8106   SETUP();
8107   START();
8108 
8109   // The literal base is chosen to have two useful properties:
8110   //  * When multiplied by small values (such as a register index), this value
8111   //    is clearly readable in the result.
8112   //  * The value is not formed from repeating fixed-size smaller values, so it
8113   //    can be used to detect endianness-related errors.
8114   uint64_t literal_base = 0x0100001000100101;
8115 
8116   // Initialize the registers.
8117   __ Mov(x0, literal_base);
8118   __ Add(x1, x0, x0);
8119   __ Add(x2, x1, x0);
8120   __ Add(x3, x2, x0);
8121   __ Add(x4, x3, x0);
8122   __ Add(x5, x4, x0);
8123   __ Add(x6, x5, x0);
8124 
8125   __ Claim(32);
8126 
8127   // Unaligned exchanges.
8128   //  After this test:
8129   //    x0-x6 should be unchanged.
8130   //    w10-w12 should contain the lower words of x0-x2.
8131   __ Poke(x0, 1);
8132   Clobber(&masm, x0.GetBit());
8133   __ Peek(x0, 1);
8134   __ Poke(x1, 2);
8135   Clobber(&masm, x1.GetBit());
8136   __ Peek(x1, 2);
8137   __ Poke(x2, 3);
8138   Clobber(&masm, x2.GetBit());
8139   __ Peek(x2, 3);
8140   __ Poke(x3, 4);
8141   Clobber(&masm, x3.GetBit());
8142   __ Peek(x3, 4);
8143   __ Poke(x4, 5);
8144   Clobber(&masm, x4.GetBit());
8145   __ Peek(x4, 5);
8146   __ Poke(x5, 6);
8147   Clobber(&masm, x5.GetBit());
8148   __ Peek(x5, 6);
8149   __ Poke(x6, 7);
8150   Clobber(&masm, x6.GetBit());
8151   __ Peek(x6, 7);
8152 
8153   __ Poke(w0, 1);
8154   Clobber(&masm, w10.GetBit());
8155   __ Peek(w10, 1);
8156   __ Poke(w1, 2);
8157   Clobber(&masm, w11.GetBit());
8158   __ Peek(w11, 2);
8159   __ Poke(w2, 3);
8160   Clobber(&masm, w12.GetBit());
8161   __ Peek(w12, 3);
8162 
8163   __ Drop(32);
8164 
8165   END();
8166   if (CAN_RUN()) {
8167     RUN();
8168 
8169     ASSERT_EQUAL_64(literal_base * 1, x0);
8170     ASSERT_EQUAL_64(literal_base * 2, x1);
8171     ASSERT_EQUAL_64(literal_base * 3, x2);
8172     ASSERT_EQUAL_64(literal_base * 4, x3);
8173     ASSERT_EQUAL_64(literal_base * 5, x4);
8174     ASSERT_EQUAL_64(literal_base * 6, x5);
8175     ASSERT_EQUAL_64(literal_base * 7, x6);
8176 
8177     ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
8178     ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
8179     ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
8180   }
8181 }
8182 
8183 
TEST(peek_poke_endianness)8184 TEST(peek_poke_endianness) {
8185   SETUP();
8186   START();
8187 
8188   // The literal base is chosen to have two useful properties:
8189   //  * When multiplied by small values (such as a register index), this value
8190   //    is clearly readable in the result.
8191   //  * The value is not formed from repeating fixed-size smaller values, so it
8192   //    can be used to detect endianness-related errors.
8193   uint64_t literal_base = 0x0100001000100101;
8194 
8195   // Initialize the registers.
8196   __ Mov(x0, literal_base);
8197   __ Add(x1, x0, x0);
8198 
8199   __ Claim(32);
8200 
8201   // Endianness tests.
8202   //  After this section:
8203   //    x4 should match x0[31:0]:x0[63:32]
8204   //    w5 should match w1[15:0]:w1[31:16]
8205   __ Poke(x0, 0);
8206   __ Poke(x0, 8);
8207   __ Peek(x4, 4);
8208 
8209   __ Poke(w1, 0);
8210   __ Poke(w1, 4);
8211   __ Peek(w5, 2);
8212 
8213   __ Drop(32);
8214 
8215   END();
8216   if (CAN_RUN()) {
8217     RUN();
8218 
8219     uint64_t x0_expected = literal_base * 1;
8220     uint64_t x1_expected = literal_base * 2;
8221     uint64_t x4_expected = (x0_expected << 32) | (x0_expected >> 32);
8222     uint64_t x5_expected =
8223         ((x1_expected << 16) & 0xffff0000) | ((x1_expected >> 16) & 0x0000ffff);
8224 
8225     ASSERT_EQUAL_64(x0_expected, x0);
8226     ASSERT_EQUAL_64(x1_expected, x1);
8227     ASSERT_EQUAL_64(x4_expected, x4);
8228     ASSERT_EQUAL_64(x5_expected, x5);
8229   }
8230 }
8231 
8232 
TEST(peek_poke_mixed)8233 TEST(peek_poke_mixed) {
8234   SETUP();
8235   START();
8236 
8237   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8238   UseScratchRegisterScope temps(&masm);
8239   temps.ExcludeAll();
8240 
8241   // The literal base is chosen to have two useful properties:
8242   //  * When multiplied by small values (such as a register index), this value
8243   //    is clearly readable in the result.
8244   //  * The value is not formed from repeating fixed-size smaller values, so it
8245   //    can be used to detect endianness-related errors.
8246   uint64_t literal_base = 0x0100001000100101;
8247 
8248   // Initialize the registers.
8249   __ Mov(x0, literal_base);
8250   __ Add(x1, x0, x0);
8251   __ Add(x2, x1, x0);
8252   __ Add(x3, x2, x0);
8253 
8254   __ Claim(32);
8255 
8256   // Mix with other stack operations.
8257   //  After this section:
8258   //    x0-x3 should be unchanged.
8259   //    x6 should match x1[31:0]:x0[63:32]
8260   //    w7 should match x1[15:0]:x0[63:48]
8261   __ Poke(x1, 8);
8262   __ Poke(x0, 0);
8263   {
8264     VIXL_ASSERT(__ StackPointer().Is(sp));
8265     __ Mov(x4, __ StackPointer());
8266     __ SetStackPointer(x4);
8267 
8268     __ Poke(wzr, 0);  // Clobber the space we're about to drop.
8269     __ Drop(4);
8270     __ Peek(x6, 0);
8271     __ Claim(8);
8272     __ Peek(w7, 10);
8273     __ Poke(x3, 28);
8274     __ Poke(xzr, 0);  // Clobber the space we're about to drop.
8275     __ Drop(8);
8276     __ Poke(x2, 12);
8277     __ Push(w0);
8278 
8279     __ Mov(sp, __ StackPointer());
8280     __ SetStackPointer(sp);
8281   }
8282 
8283   __ Pop(x0, x1, x2, x3);
8284 
8285   END();
8286   if (CAN_RUN()) {
8287     RUN();
8288 
8289     uint64_t x0_expected = literal_base * 1;
8290     uint64_t x1_expected = literal_base * 2;
8291     uint64_t x2_expected = literal_base * 3;
8292     uint64_t x3_expected = literal_base * 4;
8293     uint64_t x6_expected = (x1_expected << 32) | (x0_expected >> 32);
8294     uint64_t x7_expected =
8295         ((x1_expected << 16) & 0xffff0000) | ((x0_expected >> 48) & 0x0000ffff);
8296 
8297     ASSERT_EQUAL_64(x0_expected, x0);
8298     ASSERT_EQUAL_64(x1_expected, x1);
8299     ASSERT_EQUAL_64(x2_expected, x2);
8300     ASSERT_EQUAL_64(x3_expected, x3);
8301     ASSERT_EQUAL_64(x6_expected, x6);
8302     ASSERT_EQUAL_64(x7_expected, x7);
8303   }
8304 }
8305 
8306 
TEST(peek_poke_reglist)8307 TEST(peek_poke_reglist) {
8308   SETUP_WITH_FEATURES(CPUFeatures::kFP);
8309 
8310   START();
8311 
8312   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8313   UseScratchRegisterScope temps(&masm);
8314   temps.ExcludeAll();
8315 
8316   // The literal base is chosen to have two useful properties:
8317   //  * When multiplied by small values (such as a register index), this value
8318   //    is clearly readable in the result.
8319   //  * The value is not formed from repeating fixed-size smaller values, so it
8320   //    can be used to detect endianness-related errors.
8321   uint64_t base = 0x0100001000100101;
8322 
8323   // Initialize the registers.
8324   __ Mov(x1, base);
8325   __ Add(x2, x1, x1);
8326   __ Add(x3, x2, x1);
8327   __ Add(x4, x3, x1);
8328 
8329   CPURegList list_1(x1, x2, x3, x4);
8330   CPURegList list_2(x11, x12, x13, x14);
8331   int list_1_size = list_1.GetTotalSizeInBytes();
8332 
8333   __ Claim(2 * list_1_size);
8334 
8335   __ PokeCPURegList(list_1, 0);
8336   __ PokeXRegList(list_1.GetList(), list_1_size);
8337   __ PeekCPURegList(list_2, 2 * kXRegSizeInBytes);
8338   __ PeekXRegList(x15.GetBit(), kWRegSizeInBytes);
8339   __ PeekWRegList(w16.GetBit() | w17.GetBit(), 3 * kXRegSizeInBytes);
8340 
8341   __ Drop(2 * list_1_size);
8342 
8343 
8344   uint64_t base_d = 0x1010010001000010;
8345 
8346   // Initialize the registers.
8347   __ Mov(x1, base_d);
8348   __ Add(x2, x1, x1);
8349   __ Add(x3, x2, x1);
8350   __ Add(x4, x3, x1);
8351   __ Fmov(d1, x1);
8352   __ Fmov(d2, x2);
8353   __ Fmov(d3, x3);
8354   __ Fmov(d4, x4);
8355 
8356   CPURegList list_d_1(d1, d2, d3, d4);
8357   CPURegList list_d_2(d11, d12, d13, d14);
8358   int list_d_1_size = list_d_1.GetTotalSizeInBytes();
8359 
8360   __ Claim(2 * list_d_1_size);
8361 
8362   __ PokeCPURegList(list_d_1, 0);
8363   __ PokeDRegList(list_d_1.GetList(), list_d_1_size);
8364   __ PeekCPURegList(list_d_2, 2 * kDRegSizeInBytes);
8365   __ PeekDRegList(d15.GetBit(), kSRegSizeInBytes);
8366   __ PeekSRegList(s16.GetBit() | s17.GetBit(), 3 * kDRegSizeInBytes);
8367 
8368   __ Drop(2 * list_d_1_size);
8369 
8370 
8371   END();
8372   if (CAN_RUN()) {
8373     RUN();
8374 
8375     ASSERT_EQUAL_64(3 * base, x11);
8376     ASSERT_EQUAL_64(4 * base, x12);
8377     ASSERT_EQUAL_64(1 * base, x13);
8378     ASSERT_EQUAL_64(2 * base, x14);
8379     ASSERT_EQUAL_64(((1 * base) >> kWRegSize) | ((2 * base) << kWRegSize), x15);
8380     ASSERT_EQUAL_64(2 * base, x14);
8381     ASSERT_EQUAL_32((4 * base) & kWRegMask, w16);
8382     ASSERT_EQUAL_32((4 * base) >> kWRegSize, w17);
8383 
8384     ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base_d), d11);
8385     ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base_d), d12);
8386     ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base_d), d13);
8387     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14);
8388     ASSERT_EQUAL_FP64(RawbitsToDouble((base_d >> kSRegSize) |
8389                                       ((2 * base_d) << kSRegSize)),
8390                       d15);
8391     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14);
8392     ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) & kSRegMask), s16);
8393     ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) >> kSRegSize), s17);
8394   }
8395 }
8396 
8397 
TEST(load_store_reglist)8398 TEST(load_store_reglist) {
8399   SETUP_WITH_FEATURES(CPUFeatures::kFP);
8400 
8401   START();
8402 
8403   // The literal base is chosen to have two useful properties:
8404   //  * When multiplied by small values (such as a register index), this value
8405   //    is clearly readable in the result.
8406   //  * The value is not formed from repeating fixed-size smaller values, so it
8407   //    can be used to detect endianness-related errors.
8408   uint64_t high_base = UINT32_C(0x01000010);
8409   uint64_t low_base = UINT32_C(0x00100101);
8410   uint64_t base = (high_base << 32) | low_base;
8411   uint64_t array[21];
8412   memset(array, 0, sizeof(array));
8413 
8414   // Initialize the registers.
8415   __ Mov(x1, base);
8416   __ Add(x2, x1, x1);
8417   __ Add(x3, x2, x1);
8418   __ Add(x4, x3, x1);
8419   __ Fmov(d1, x1);
8420   __ Fmov(d2, x2);
8421   __ Fmov(d3, x3);
8422   __ Fmov(d4, x4);
8423   __ Fmov(d5, x1);
8424   __ Fmov(d6, x2);
8425   __ Fmov(d7, x3);
8426   __ Fmov(d8, x4);
8427 
8428   Register reg_base = x20;
8429   Register reg_index = x21;
8430   int size_stored = 0;
8431 
8432   __ Mov(reg_base, reinterpret_cast<uintptr_t>(&array));
8433 
8434   // Test aligned accesses.
8435   CPURegList list_src(w1, w2, w3, w4);
8436   CPURegList list_dst(w11, w12, w13, w14);
8437   CPURegList list_fp_src_1(d1, d2, d3, d4);
8438   CPURegList list_fp_dst_1(d11, d12, d13, d14);
8439 
8440   __ StoreCPURegList(list_src, MemOperand(reg_base, 0 * sizeof(uint64_t)));
8441   __ LoadCPURegList(list_dst, MemOperand(reg_base, 0 * sizeof(uint64_t)));
8442   size_stored += 4 * kWRegSizeInBytes;
8443 
8444   __ Mov(reg_index, size_stored);
8445   __ StoreCPURegList(list_src, MemOperand(reg_base, reg_index));
8446   __ LoadCPURegList(list_dst, MemOperand(reg_base, reg_index));
8447   size_stored += 4 * kWRegSizeInBytes;
8448 
8449   __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, size_stored));
8450   __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, size_stored));
8451   size_stored += 4 * kDRegSizeInBytes;
8452 
8453   __ Mov(reg_index, size_stored);
8454   __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, reg_index));
8455   __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, reg_index));
8456   size_stored += 4 * kDRegSizeInBytes;
8457 
8458   // Test unaligned accesses.
8459   CPURegList list_fp_src_2(d5, d6, d7, d8);
8460   CPURegList list_fp_dst_2(d15, d16, d17, d18);
8461 
8462   __ Str(wzr, MemOperand(reg_base, size_stored));
8463   size_stored += 1 * kWRegSizeInBytes;
8464   __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, size_stored));
8465   __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, size_stored));
8466   size_stored += 4 * kDRegSizeInBytes;
8467 
8468   __ Mov(reg_index, size_stored);
8469   __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, reg_index));
8470   __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, reg_index));
8471 
8472   END();
8473   if (CAN_RUN()) {
8474     RUN();
8475 
8476     VIXL_CHECK(array[0] == (1 * low_base) + (2 * low_base << kWRegSize));
8477     VIXL_CHECK(array[1] == (3 * low_base) + (4 * low_base << kWRegSize));
8478     VIXL_CHECK(array[2] == (1 * low_base) + (2 * low_base << kWRegSize));
8479     VIXL_CHECK(array[3] == (3 * low_base) + (4 * low_base << kWRegSize));
8480     VIXL_CHECK(array[4] == 1 * base);
8481     VIXL_CHECK(array[5] == 2 * base);
8482     VIXL_CHECK(array[6] == 3 * base);
8483     VIXL_CHECK(array[7] == 4 * base);
8484     VIXL_CHECK(array[8] == 1 * base);
8485     VIXL_CHECK(array[9] == 2 * base);
8486     VIXL_CHECK(array[10] == 3 * base);
8487     VIXL_CHECK(array[11] == 4 * base);
8488     VIXL_CHECK(array[12] == ((1 * low_base) << kSRegSize));
8489     VIXL_CHECK(array[13] == (((2 * low_base) << kSRegSize) | (1 * high_base)));
8490     VIXL_CHECK(array[14] == (((3 * low_base) << kSRegSize) | (2 * high_base)));
8491     VIXL_CHECK(array[15] == (((4 * low_base) << kSRegSize) | (3 * high_base)));
8492     VIXL_CHECK(array[16] == (((1 * low_base) << kSRegSize) | (4 * high_base)));
8493     VIXL_CHECK(array[17] == (((2 * low_base) << kSRegSize) | (1 * high_base)));
8494     VIXL_CHECK(array[18] == (((3 * low_base) << kSRegSize) | (2 * high_base)));
8495     VIXL_CHECK(array[19] == (((4 * low_base) << kSRegSize) | (3 * high_base)));
8496     VIXL_CHECK(array[20] == (4 * high_base));
8497 
8498     ASSERT_EQUAL_64(1 * low_base, x11);
8499     ASSERT_EQUAL_64(2 * low_base, x12);
8500     ASSERT_EQUAL_64(3 * low_base, x13);
8501     ASSERT_EQUAL_64(4 * low_base, x14);
8502     ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d11);
8503     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d12);
8504     ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d13);
8505     ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d14);
8506     ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d15);
8507     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d16);
8508     ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d17);
8509     ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d18);
8510   }
8511 }
8512 
8513 
8514 // This enum is used only as an argument to the push-pop test helpers.
8515 enum PushPopMethod {
8516   // Push or Pop using the Push and Pop methods, with blocks of up to four
8517   // registers. (Smaller blocks will be used if necessary.)
8518   PushPopByFour,
8519 
8520   // Use Push<Size>RegList and Pop<Size>RegList to transfer the registers.
8521   PushPopRegList
8522 };
8523 
8524 
8525 // For the PushPop* tests, use the maximum number of registers that the test
8526 // supports (where a reg_count argument would otherwise be provided).
8527 static int const kPushPopUseMaxRegCount = -1;
8528 
8529 // Test a simple push-pop pattern:
8530 //  * Claim <claim> bytes to set the stack alignment.
8531 //  * Push <reg_count> registers with size <reg_size>.
8532 //  * Clobber the register contents.
8533 //  * Pop <reg_count> registers to restore the original contents.
8534 //  * Drop <claim> bytes to restore the original stack pointer.
8535 //
8536 // Different push and pop methods can be specified independently to test for
8537 // proper word-endian behaviour.
PushPopSimpleHelper(int reg_count,int claim,int reg_size,PushPopMethod push_method,PushPopMethod pop_method)8538 static void PushPopSimpleHelper(int reg_count,
8539                                 int claim,
8540                                 int reg_size,
8541                                 PushPopMethod push_method,
8542                                 PushPopMethod pop_method) {
8543   SETUP();
8544 
8545   START();
8546 
8547   // Arbitrarily pick a register to use as a stack pointer.
8548   const Register& stack_pointer = x20;
8549   const RegList allowed = ~stack_pointer.GetBit();
8550   if (reg_count == kPushPopUseMaxRegCount) {
8551     reg_count = CountSetBits(allowed, kNumberOfRegisters);
8552   }
8553   // Work out which registers to use, based on reg_size.
8554   Register r[kNumberOfRegisters];
8555   Register x[kNumberOfRegisters];
8556   RegList list =
8557       PopulateRegisterArray(NULL, x, r, reg_size, reg_count, allowed);
8558 
8559   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8560   UseScratchRegisterScope temps(&masm);
8561   temps.ExcludeAll();
8562 
8563   // The literal base is chosen to have two useful properties:
8564   //  * When multiplied by small values (such as a register index), this value
8565   //    is clearly readable in the result.
8566   //  * The value is not formed from repeating fixed-size smaller values, so it
8567   //    can be used to detect endianness-related errors.
8568   uint64_t literal_base = 0x0100001000100101;
8569 
8570   {
8571     VIXL_ASSERT(__ StackPointer().Is(sp));
8572     __ Mov(stack_pointer, __ StackPointer());
8573     __ SetStackPointer(stack_pointer);
8574 
8575     int i;
8576 
8577     // Initialize the registers.
8578     for (i = 0; i < reg_count; i++) {
8579       // Always write into the X register, to ensure that the upper word is
8580       // properly ignored by Push when testing W registers.
8581       __ Mov(x[i], literal_base * i);
8582     }
8583 
8584     // Claim memory first, as requested.
8585     __ Claim(claim);
8586 
8587     switch (push_method) {
8588       case PushPopByFour:
8589         // Push high-numbered registers first (to the highest addresses).
8590         for (i = reg_count; i >= 4; i -= 4) {
8591           __ Push(r[i - 1], r[i - 2], r[i - 3], r[i - 4]);
8592         }
8593         // Finish off the leftovers.
8594         switch (i) {
8595           case 3:
8596             __ Push(r[2], r[1], r[0]);
8597             break;
8598           case 2:
8599             __ Push(r[1], r[0]);
8600             break;
8601           case 1:
8602             __ Push(r[0]);
8603             break;
8604           default:
8605             VIXL_ASSERT(i == 0);
8606             break;
8607         }
8608         break;
8609       case PushPopRegList:
8610         __ PushSizeRegList(list, reg_size);
8611         break;
8612     }
8613 
8614     // Clobber all the registers, to ensure that they get repopulated by Pop.
8615     Clobber(&masm, list);
8616 
8617     switch (pop_method) {
8618       case PushPopByFour:
8619         // Pop low-numbered registers first (from the lowest addresses).
8620         for (i = 0; i <= (reg_count - 4); i += 4) {
8621           __ Pop(r[i], r[i + 1], r[i + 2], r[i + 3]);
8622         }
8623         // Finish off the leftovers.
8624         switch (reg_count - i) {
8625           case 3:
8626             __ Pop(r[i], r[i + 1], r[i + 2]);
8627             break;
8628           case 2:
8629             __ Pop(r[i], r[i + 1]);
8630             break;
8631           case 1:
8632             __ Pop(r[i]);
8633             break;
8634           default:
8635             VIXL_ASSERT(i == reg_count);
8636             break;
8637         }
8638         break;
8639       case PushPopRegList:
8640         __ PopSizeRegList(list, reg_size);
8641         break;
8642     }
8643 
8644     // Drop memory to restore stack_pointer.
8645     __ Drop(claim);
8646 
8647     __ Mov(sp, __ StackPointer());
8648     __ SetStackPointer(sp);
8649   }
8650 
8651   END();
8652 
8653   if (CAN_RUN()) {
8654     RUN();
8655 
8656     // Check that the register contents were preserved.
8657     // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
8658     // that the upper word was properly cleared by Pop.
8659     literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8660     for (int i = 0; i < reg_count; i++) {
8661       if (x[i].Is(xzr)) {
8662         ASSERT_EQUAL_64(0, x[i]);
8663       } else {
8664         ASSERT_EQUAL_64(literal_base * i, x[i]);
8665       }
8666     }
8667   }
8668 }
8669 
8670 
TEST(push_pop_xreg_simple_32)8671 TEST(push_pop_xreg_simple_32) {
8672   for (int claim = 0; claim <= 8; claim++) {
8673     for (int count = 0; count <= 8; count++) {
8674       PushPopSimpleHelper(count,
8675                           claim,
8676                           kWRegSize,
8677                           PushPopByFour,
8678                           PushPopByFour);
8679       PushPopSimpleHelper(count,
8680                           claim,
8681                           kWRegSize,
8682                           PushPopByFour,
8683                           PushPopRegList);
8684       PushPopSimpleHelper(count,
8685                           claim,
8686                           kWRegSize,
8687                           PushPopRegList,
8688                           PushPopByFour);
8689       PushPopSimpleHelper(count,
8690                           claim,
8691                           kWRegSize,
8692                           PushPopRegList,
8693                           PushPopRegList);
8694     }
8695     // Test with the maximum number of registers.
8696     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8697                         claim,
8698                         kWRegSize,
8699                         PushPopByFour,
8700                         PushPopByFour);
8701     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8702                         claim,
8703                         kWRegSize,
8704                         PushPopByFour,
8705                         PushPopRegList);
8706     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8707                         claim,
8708                         kWRegSize,
8709                         PushPopRegList,
8710                         PushPopByFour);
8711     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8712                         claim,
8713                         kWRegSize,
8714                         PushPopRegList,
8715                         PushPopRegList);
8716   }
8717 }
8718 
8719 
TEST(push_pop_xreg_simple_64)8720 TEST(push_pop_xreg_simple_64) {
8721   for (int claim = 0; claim <= 8; claim++) {
8722     for (int count = 0; count <= 8; count++) {
8723       PushPopSimpleHelper(count,
8724                           claim,
8725                           kXRegSize,
8726                           PushPopByFour,
8727                           PushPopByFour);
8728       PushPopSimpleHelper(count,
8729                           claim,
8730                           kXRegSize,
8731                           PushPopByFour,
8732                           PushPopRegList);
8733       PushPopSimpleHelper(count,
8734                           claim,
8735                           kXRegSize,
8736                           PushPopRegList,
8737                           PushPopByFour);
8738       PushPopSimpleHelper(count,
8739                           claim,
8740                           kXRegSize,
8741                           PushPopRegList,
8742                           PushPopRegList);
8743     }
8744     // Test with the maximum number of registers.
8745     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8746                         claim,
8747                         kXRegSize,
8748                         PushPopByFour,
8749                         PushPopByFour);
8750     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8751                         claim,
8752                         kXRegSize,
8753                         PushPopByFour,
8754                         PushPopRegList);
8755     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8756                         claim,
8757                         kXRegSize,
8758                         PushPopRegList,
8759                         PushPopByFour);
8760     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8761                         claim,
8762                         kXRegSize,
8763                         PushPopRegList,
8764                         PushPopRegList);
8765   }
8766 }
8767 
8768 // For the PushPopFP* tests, use the maximum number of registers that the test
8769 // supports (where a reg_count argument would otherwise be provided).
8770 static int const kPushPopFPUseMaxRegCount = -1;
8771 
8772 // Test a simple push-pop pattern:
8773 //  * Claim <claim> bytes to set the stack alignment.
8774 //  * Push <reg_count> FP registers with size <reg_size>.
8775 //  * Clobber the register contents.
8776 //  * Pop <reg_count> FP registers to restore the original contents.
8777 //  * Drop <claim> bytes to restore the original stack pointer.
8778 //
8779 // Different push and pop methods can be specified independently to test for
8780 // proper word-endian behaviour.
PushPopFPSimpleHelper(int reg_count,int claim,int reg_size,PushPopMethod push_method,PushPopMethod pop_method)8781 static void PushPopFPSimpleHelper(int reg_count,
8782                                   int claim,
8783                                   int reg_size,
8784                                   PushPopMethod push_method,
8785                                   PushPopMethod pop_method) {
8786   SETUP_WITH_FEATURES((reg_count == 0) ? CPUFeatures::kNone : CPUFeatures::kFP);
8787 
8788   START();
8789 
8790   // We can use any floating-point register. None of them are reserved for
8791   // debug code, for example.
8792   static RegList const allowed = ~0;
8793   if (reg_count == kPushPopFPUseMaxRegCount) {
8794     reg_count = CountSetBits(allowed, kNumberOfVRegisters);
8795   }
8796   // Work out which registers to use, based on reg_size.
8797   VRegister v[kNumberOfRegisters];
8798   VRegister d[kNumberOfRegisters];
8799   RegList list =
8800       PopulateVRegisterArray(NULL, d, v, reg_size, reg_count, allowed);
8801 
8802   // Arbitrarily pick a register to use as a stack pointer.
8803   const Register& stack_pointer = x10;
8804 
8805   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8806   UseScratchRegisterScope temps(&masm);
8807   temps.ExcludeAll();
8808 
8809   // The literal base is chosen to have two useful properties:
8810   //  * When multiplied (using an integer) by small values (such as a register
8811   //    index), this value is clearly readable in the result.
8812   //  * The value is not formed from repeating fixed-size smaller values, so it
8813   //    can be used to detect endianness-related errors.
8814   //  * It is never a floating-point NaN, and will therefore always compare
8815   //    equal to itself.
8816   uint64_t literal_base = 0x0100001000100101;
8817 
8818   {
8819     VIXL_ASSERT(__ StackPointer().Is(sp));
8820     __ Mov(stack_pointer, __ StackPointer());
8821     __ SetStackPointer(stack_pointer);
8822 
8823     int i;
8824 
8825     // Initialize the registers, using X registers to load the literal.
8826     __ Mov(x0, 0);
8827     __ Mov(x1, literal_base);
8828     for (i = 0; i < reg_count; i++) {
8829       // Always write into the D register, to ensure that the upper word is
8830       // properly ignored by Push when testing S registers.
8831       __ Fmov(d[i], x0);
8832       // Calculate the next literal.
8833       __ Add(x0, x0, x1);
8834     }
8835 
8836     // Claim memory first, as requested.
8837     __ Claim(claim);
8838 
8839     switch (push_method) {
8840       case PushPopByFour:
8841         // Push high-numbered registers first (to the highest addresses).
8842         for (i = reg_count; i >= 4; i -= 4) {
8843           __ Push(v[i - 1], v[i - 2], v[i - 3], v[i - 4]);
8844         }
8845         // Finish off the leftovers.
8846         switch (i) {
8847           case 3:
8848             __ Push(v[2], v[1], v[0]);
8849             break;
8850           case 2:
8851             __ Push(v[1], v[0]);
8852             break;
8853           case 1:
8854             __ Push(v[0]);
8855             break;
8856           default:
8857             VIXL_ASSERT(i == 0);
8858             break;
8859         }
8860         break;
8861       case PushPopRegList:
8862         __ PushSizeRegList(list, reg_size, CPURegister::kVRegister);
8863         break;
8864     }
8865 
8866     // Clobber all the registers, to ensure that they get repopulated by Pop.
8867     ClobberFP(&masm, list);
8868 
8869     switch (pop_method) {
8870       case PushPopByFour:
8871         // Pop low-numbered registers first (from the lowest addresses).
8872         for (i = 0; i <= (reg_count - 4); i += 4) {
8873           __ Pop(v[i], v[i + 1], v[i + 2], v[i + 3]);
8874         }
8875         // Finish off the leftovers.
8876         switch (reg_count - i) {
8877           case 3:
8878             __ Pop(v[i], v[i + 1], v[i + 2]);
8879             break;
8880           case 2:
8881             __ Pop(v[i], v[i + 1]);
8882             break;
8883           case 1:
8884             __ Pop(v[i]);
8885             break;
8886           default:
8887             VIXL_ASSERT(i == reg_count);
8888             break;
8889         }
8890         break;
8891       case PushPopRegList:
8892         __ PopSizeRegList(list, reg_size, CPURegister::kVRegister);
8893         break;
8894     }
8895 
8896     // Drop memory to restore the stack pointer.
8897     __ Drop(claim);
8898 
8899     __ Mov(sp, __ StackPointer());
8900     __ SetStackPointer(sp);
8901   }
8902 
8903   END();
8904 
8905   if (CAN_RUN()) {
8906     RUN();
8907 
8908     // Check that the register contents were preserved.
8909     // Always use ASSERT_EQUAL_FP64, even when testing S registers, so we can
8910     // test that the upper word was properly cleared by Pop.
8911     literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8912     for (int i = 0; i < reg_count; i++) {
8913       uint64_t literal = literal_base * i;
8914       double expected;
8915       memcpy(&expected, &literal, sizeof(expected));
8916       ASSERT_EQUAL_FP64(expected, d[i]);
8917     }
8918   }
8919 }
8920 
8921 
TEST(push_pop_fp_xreg_simple_32)8922 TEST(push_pop_fp_xreg_simple_32) {
8923   for (int claim = 0; claim <= 8; claim++) {
8924     for (int count = 0; count <= 8; count++) {
8925       PushPopFPSimpleHelper(count,
8926                             claim,
8927                             kSRegSize,
8928                             PushPopByFour,
8929                             PushPopByFour);
8930       PushPopFPSimpleHelper(count,
8931                             claim,
8932                             kSRegSize,
8933                             PushPopByFour,
8934                             PushPopRegList);
8935       PushPopFPSimpleHelper(count,
8936                             claim,
8937                             kSRegSize,
8938                             PushPopRegList,
8939                             PushPopByFour);
8940       PushPopFPSimpleHelper(count,
8941                             claim,
8942                             kSRegSize,
8943                             PushPopRegList,
8944                             PushPopRegList);
8945     }
8946     // Test with the maximum number of registers.
8947     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8948                           claim,
8949                           kSRegSize,
8950                           PushPopByFour,
8951                           PushPopByFour);
8952     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8953                           claim,
8954                           kSRegSize,
8955                           PushPopByFour,
8956                           PushPopRegList);
8957     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8958                           claim,
8959                           kSRegSize,
8960                           PushPopRegList,
8961                           PushPopByFour);
8962     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8963                           claim,
8964                           kSRegSize,
8965                           PushPopRegList,
8966                           PushPopRegList);
8967   }
8968 }
8969 
8970 
TEST(push_pop_fp_xreg_simple_64)8971 TEST(push_pop_fp_xreg_simple_64) {
8972   for (int claim = 0; claim <= 8; claim++) {
8973     for (int count = 0; count <= 8; count++) {
8974       PushPopFPSimpleHelper(count,
8975                             claim,
8976                             kDRegSize,
8977                             PushPopByFour,
8978                             PushPopByFour);
8979       PushPopFPSimpleHelper(count,
8980                             claim,
8981                             kDRegSize,
8982                             PushPopByFour,
8983                             PushPopRegList);
8984       PushPopFPSimpleHelper(count,
8985                             claim,
8986                             kDRegSize,
8987                             PushPopRegList,
8988                             PushPopByFour);
8989       PushPopFPSimpleHelper(count,
8990                             claim,
8991                             kDRegSize,
8992                             PushPopRegList,
8993                             PushPopRegList);
8994     }
8995     // Test with the maximum number of registers.
8996     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8997                           claim,
8998                           kDRegSize,
8999                           PushPopByFour,
9000                           PushPopByFour);
9001     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
9002                           claim,
9003                           kDRegSize,
9004                           PushPopByFour,
9005                           PushPopRegList);
9006     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
9007                           claim,
9008                           kDRegSize,
9009                           PushPopRegList,
9010                           PushPopByFour);
9011     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
9012                           claim,
9013                           kDRegSize,
9014                           PushPopRegList,
9015                           PushPopRegList);
9016   }
9017 }
9018 
9019 
9020 // Push and pop data using an overlapping combination of Push/Pop and
9021 // RegList-based methods.
PushPopMixedMethodsHelper(int claim,int reg_size)9022 static void PushPopMixedMethodsHelper(int claim, int reg_size) {
9023   SETUP();
9024 
9025   // Arbitrarily pick a register to use as a stack pointer.
9026   const Register& stack_pointer = x5;
9027   const RegList allowed = ~stack_pointer.GetBit();
9028   // Work out which registers to use, based on reg_size.
9029   Register r[10];
9030   Register x[10];
9031   PopulateRegisterArray(NULL, x, r, reg_size, 10, allowed);
9032 
9033   // Calculate some handy register lists.
9034   RegList r0_to_r3 = 0;
9035   for (int i = 0; i <= 3; i++) {
9036     r0_to_r3 |= x[i].GetBit();
9037   }
9038   RegList r4_to_r5 = 0;
9039   for (int i = 4; i <= 5; i++) {
9040     r4_to_r5 |= x[i].GetBit();
9041   }
9042   RegList r6_to_r9 = 0;
9043   for (int i = 6; i <= 9; i++) {
9044     r6_to_r9 |= x[i].GetBit();
9045   }
9046 
9047   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
9048   UseScratchRegisterScope temps(&masm);
9049   temps.ExcludeAll();
9050 
9051   // The literal base is chosen to have two useful properties:
9052   //  * When multiplied by small values (such as a register index), this value
9053   //    is clearly readable in the result.
9054   //  * The value is not formed from repeating fixed-size smaller values, so it
9055   //    can be used to detect endianness-related errors.
9056   uint64_t literal_base = 0x0100001000100101;
9057 
9058   START();
9059   {
9060     VIXL_ASSERT(__ StackPointer().Is(sp));
9061     __ Mov(stack_pointer, __ StackPointer());
9062     __ SetStackPointer(stack_pointer);
9063 
9064     // Claim memory first, as requested.
9065     __ Claim(claim);
9066 
9067     __ Mov(x[3], literal_base * 3);
9068     __ Mov(x[2], literal_base * 2);
9069     __ Mov(x[1], literal_base * 1);
9070     __ Mov(x[0], literal_base * 0);
9071 
9072     __ PushSizeRegList(r0_to_r3, reg_size);
9073     __ Push(r[3], r[2]);
9074 
9075     Clobber(&masm, r0_to_r3);
9076     __ PopSizeRegList(r0_to_r3, reg_size);
9077 
9078     __ Push(r[2], r[1], r[3], r[0]);
9079 
9080     Clobber(&masm, r4_to_r5);
9081     __ Pop(r[4], r[5]);
9082     Clobber(&masm, r6_to_r9);
9083     __ Pop(r[6], r[7], r[8], r[9]);
9084 
9085     // Drop memory to restore stack_pointer.
9086     __ Drop(claim);
9087 
9088     __ Mov(sp, __ StackPointer());
9089     __ SetStackPointer(sp);
9090   }
9091 
9092   END();
9093 
9094   if (CAN_RUN()) {
9095     RUN();
9096 
9097     // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
9098     // that the upper word was properly cleared by Pop.
9099     literal_base &= (0xffffffffffffffff >> (64 - reg_size));
9100 
9101     ASSERT_EQUAL_64(literal_base * 3, x[9]);
9102     ASSERT_EQUAL_64(literal_base * 2, x[8]);
9103     ASSERT_EQUAL_64(literal_base * 0, x[7]);
9104     ASSERT_EQUAL_64(literal_base * 3, x[6]);
9105     ASSERT_EQUAL_64(literal_base * 1, x[5]);
9106     ASSERT_EQUAL_64(literal_base * 2, x[4]);
9107   }
9108 }
9109 
9110 
TEST(push_pop_xreg_mixed_methods_64)9111 TEST(push_pop_xreg_mixed_methods_64) {
9112   for (int claim = 0; claim <= 8; claim++) {
9113     PushPopMixedMethodsHelper(claim, kXRegSize);
9114   }
9115 }
9116 
9117 
TEST(push_pop_xreg_mixed_methods_32)9118 TEST(push_pop_xreg_mixed_methods_32) {
9119   for (int claim = 0; claim <= 8; claim++) {
9120     PushPopMixedMethodsHelper(claim, kWRegSize);
9121   }
9122 }
9123 
9124 
9125 // Push and pop data using overlapping X- and W-sized quantities.
PushPopWXOverlapHelper(int reg_count,int claim)9126 static void PushPopWXOverlapHelper(int reg_count, int claim) {
9127   SETUP();
9128 
9129   // Arbitrarily pick a register to use as a stack pointer.
9130   const Register& stack_pointer = x10;
9131   const RegList allowed = ~stack_pointer.GetBit();
9132   if (reg_count == kPushPopUseMaxRegCount) {
9133     reg_count = CountSetBits(allowed, kNumberOfRegisters);
9134   }
9135   // Work out which registers to use, based on reg_size.
9136   Register w[kNumberOfRegisters];
9137   Register x[kNumberOfRegisters];
9138   RegList list = PopulateRegisterArray(w, x, NULL, 0, reg_count, allowed);
9139 
9140   // The number of W-sized slots we expect to pop. When we pop, we alternate
9141   // between W and X registers, so we need reg_count*1.5 W-sized slots.
9142   int const requested_w_slots = reg_count + reg_count / 2;
9143 
9144   // Track what _should_ be on the stack, using W-sized slots.
9145   static int const kMaxWSlots = kNumberOfRegisters + kNumberOfRegisters / 2;
9146   uint32_t stack[kMaxWSlots];
9147   for (int i = 0; i < kMaxWSlots; i++) {
9148     stack[i] = 0xdeadbeef;
9149   }
9150 
9151   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
9152   UseScratchRegisterScope temps(&masm);
9153   temps.ExcludeAll();
9154 
9155   // The literal base is chosen to have two useful properties:
9156   //  * When multiplied by small values (such as a register index), this value
9157   //    is clearly readable in the result.
9158   //  * The value is not formed from repeating fixed-size smaller values, so it
9159   //    can be used to detect endianness-related errors.
9160   static uint64_t const literal_base = 0x0100001000100101;
9161   static uint64_t const literal_base_hi = literal_base >> 32;
9162   static uint64_t const literal_base_lo = literal_base & 0xffffffff;
9163   static uint64_t const literal_base_w = literal_base & 0xffffffff;
9164 
9165   START();
9166   {
9167     VIXL_ASSERT(__ StackPointer().Is(sp));
9168     __ Mov(stack_pointer, __ StackPointer());
9169     __ SetStackPointer(stack_pointer);
9170 
9171     // Initialize the registers.
9172     for (int i = 0; i < reg_count; i++) {
9173       // Always write into the X register, to ensure that the upper word is
9174       // properly ignored by Push when testing W registers.
9175       __ Mov(x[i], literal_base * i);
9176     }
9177 
9178     // Claim memory first, as requested.
9179     __ Claim(claim);
9180 
9181     // The push-pop pattern is as follows:
9182     // Push:           Pop:
9183     //  x[0](hi)   ->   w[0]
9184     //  x[0](lo)   ->   x[1](hi)
9185     //  w[1]       ->   x[1](lo)
9186     //  w[1]       ->   w[2]
9187     //  x[2](hi)   ->   x[2](hi)
9188     //  x[2](lo)   ->   x[2](lo)
9189     //  x[2](hi)   ->   w[3]
9190     //  x[2](lo)   ->   x[4](hi)
9191     //  x[2](hi)   ->   x[4](lo)
9192     //  x[2](lo)   ->   w[5]
9193     //  w[3]       ->   x[5](hi)
9194     //  w[3]       ->   x[6](lo)
9195     //  w[3]       ->   w[7]
9196     //  w[3]       ->   x[8](hi)
9197     //  x[4](hi)   ->   x[8](lo)
9198     //  x[4](lo)   ->   w[9]
9199     // ... pattern continues ...
9200     //
9201     // That is, registers are pushed starting with the lower numbers,
9202     // alternating between x and w registers, and pushing i%4+1 copies of each,
9203     // where i is the register number.
9204     // Registers are popped starting with the higher numbers one-by-one,
9205     // alternating between x and w registers, but only popping one at a time.
9206     //
9207     // This pattern provides a wide variety of alignment effects and overlaps.
9208 
9209     // ---- Push ----
9210 
9211     int active_w_slots = 0;
9212     for (int i = 0; active_w_slots < requested_w_slots; i++) {
9213       VIXL_ASSERT(i < reg_count);
9214       // In order to test various arguments to PushMultipleTimes, and to try to
9215       // exercise different alignment and overlap effects, we push each
9216       // register a different number of times.
9217       int times = i % 4 + 1;
9218       if (i & 1) {
9219         // Push odd-numbered registers as W registers.
9220         __ PushMultipleTimes(times, w[i]);
9221         // Fill in the expected stack slots.
9222         for (int j = 0; j < times; j++) {
9223           if (w[i].Is(wzr)) {
9224             // The zero register always writes zeroes.
9225             stack[active_w_slots++] = 0;
9226           } else {
9227             stack[active_w_slots++] = literal_base_w * i;
9228           }
9229         }
9230       } else {
9231         // Push even-numbered registers as X registers.
9232         __ PushMultipleTimes(times, x[i]);
9233         // Fill in the expected stack slots.
9234         for (int j = 0; j < times; j++) {
9235           if (x[i].Is(xzr)) {
9236             // The zero register always writes zeroes.
9237             stack[active_w_slots++] = 0;
9238             stack[active_w_slots++] = 0;
9239           } else {
9240             stack[active_w_slots++] = literal_base_hi * i;
9241             stack[active_w_slots++] = literal_base_lo * i;
9242           }
9243         }
9244       }
9245     }
9246     // Because we were pushing several registers at a time, we probably pushed
9247     // more than we needed to.
9248     if (active_w_slots > requested_w_slots) {
9249       __ Drop((active_w_slots - requested_w_slots) * kWRegSizeInBytes);
9250       // Bump the number of active W-sized slots back to where it should be,
9251       // and fill the empty space with a placeholder value.
9252       do {
9253         stack[active_w_slots--] = 0xdeadbeef;
9254       } while (active_w_slots > requested_w_slots);
9255     }
9256 
9257     // ---- Pop ----
9258 
9259     Clobber(&masm, list);
9260 
9261     // If popping an even number of registers, the first one will be X-sized.
9262     // Otherwise, the first one will be W-sized.
9263     bool next_is_64 = !(reg_count & 1);
9264     for (int i = reg_count - 1; i >= 0; i--) {
9265       if (next_is_64) {
9266         __ Pop(x[i]);
9267         active_w_slots -= 2;
9268       } else {
9269         __ Pop(w[i]);
9270         active_w_slots -= 1;
9271       }
9272       next_is_64 = !next_is_64;
9273     }
9274     VIXL_ASSERT(active_w_slots == 0);
9275 
9276     // Drop memory to restore stack_pointer.
9277     __ Drop(claim);
9278 
9279     __ Mov(sp, __ StackPointer());
9280     __ SetStackPointer(sp);
9281   }
9282 
9283   END();
9284 
9285   if (CAN_RUN()) {
9286     RUN();
9287 
9288     int slot = 0;
9289     for (int i = 0; i < reg_count; i++) {
9290       // Even-numbered registers were written as W registers.
9291       // Odd-numbered registers were written as X registers.
9292       bool expect_64 = (i & 1);
9293       uint64_t expected;
9294 
9295       if (expect_64) {
9296         uint64_t hi = stack[slot++];
9297         uint64_t lo = stack[slot++];
9298         expected = (hi << 32) | lo;
9299       } else {
9300         expected = stack[slot++];
9301       }
9302 
9303       // Always use ASSERT_EQUAL_64, even when testing W registers, so we can
9304       // test that the upper word was properly cleared by Pop.
9305       if (x[i].Is(xzr)) {
9306         ASSERT_EQUAL_64(0, x[i]);
9307       } else {
9308         ASSERT_EQUAL_64(expected, x[i]);
9309       }
9310     }
9311     VIXL_ASSERT(slot == requested_w_slots);
9312   }
9313 }
9314 
9315 
TEST(push_pop_xreg_wx_overlap)9316 TEST(push_pop_xreg_wx_overlap) {
9317   for (int claim = 0; claim <= 8; claim++) {
9318     for (int count = 1; count <= 8; count++) {
9319       PushPopWXOverlapHelper(count, claim);
9320     }
9321     // Test with the maximum number of registers.
9322     PushPopWXOverlapHelper(kPushPopUseMaxRegCount, claim);
9323   }
9324 }
9325 
9326 
TEST(push_pop_sp)9327 TEST(push_pop_sp) {
9328   SETUP();
9329 
9330   START();
9331 
9332   VIXL_ASSERT(sp.Is(__ StackPointer()));
9333 
9334   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
9335   UseScratchRegisterScope temps(&masm);
9336   temps.ExcludeAll();
9337 
9338   __ Mov(x3, 0x3333333333333333);
9339   __ Mov(x2, 0x2222222222222222);
9340   __ Mov(x1, 0x1111111111111111);
9341   __ Mov(x0, 0x0000000000000000);
9342   __ Claim(2 * kXRegSizeInBytes);
9343   __ PushXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit());
9344   __ Push(x3, x2);
9345   __ PopXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit());
9346   __ Push(x2, x1, x3, x0);
9347   __ Pop(x4, x5);
9348   __ Pop(x6, x7, x8, x9);
9349 
9350   __ Claim(2 * kXRegSizeInBytes);
9351   __ PushWRegList(w0.GetBit() | w1.GetBit() | w2.GetBit() | w3.GetBit());
9352   __ Push(w3, w1, w2, w0);
9353   __ PopWRegList(w10.GetBit() | w11.GetBit() | w12.GetBit() | w13.GetBit());
9354   __ Pop(w14, w15, w16, w17);
9355 
9356   __ Claim(2 * kXRegSizeInBytes);
9357   __ Push(w2, w2, w1, w1);
9358   __ Push(x3, x3);
9359   __ Pop(w18, w19, w20, w21);
9360   __ Pop(x22, x23);
9361 
9362   __ Claim(2 * kXRegSizeInBytes);
9363   __ PushXRegList(x1.GetBit() | x22.GetBit());
9364   __ PopXRegList(x24.GetBit() | x26.GetBit());
9365 
9366   __ Claim(2 * kXRegSizeInBytes);
9367   __ PushWRegList(w1.GetBit() | w2.GetBit() | w4.GetBit() | w22.GetBit());
9368   __ PopWRegList(w25.GetBit() | w27.GetBit() | w28.GetBit() | w29.GetBit());
9369 
9370   __ Claim(2 * kXRegSizeInBytes);
9371   __ PushXRegList(0);
9372   __ PopXRegList(0);
9373   __ PushXRegList(0xffffffff);
9374   __ PopXRegList(0xffffffff);
9375   __ Drop(12 * kXRegSizeInBytes);
9376   END();
9377 
9378   if (CAN_RUN()) {
9379     RUN();
9380 
9381     ASSERT_EQUAL_64(0x1111111111111111, x3);
9382     ASSERT_EQUAL_64(0x0000000000000000, x2);
9383     ASSERT_EQUAL_64(0x3333333333333333, x1);
9384     ASSERT_EQUAL_64(0x2222222222222222, x0);
9385     ASSERT_EQUAL_64(0x3333333333333333, x9);
9386     ASSERT_EQUAL_64(0x2222222222222222, x8);
9387     ASSERT_EQUAL_64(0x0000000000000000, x7);
9388     ASSERT_EQUAL_64(0x3333333333333333, x6);
9389     ASSERT_EQUAL_64(0x1111111111111111, x5);
9390     ASSERT_EQUAL_64(0x2222222222222222, x4);
9391 
9392     ASSERT_EQUAL_32(0x11111111U, w13);
9393     ASSERT_EQUAL_32(0x33333333U, w12);
9394     ASSERT_EQUAL_32(0x00000000U, w11);
9395     ASSERT_EQUAL_32(0x22222222U, w10);
9396     ASSERT_EQUAL_32(0x11111111U, w17);
9397     ASSERT_EQUAL_32(0x00000000U, w16);
9398     ASSERT_EQUAL_32(0x33333333U, w15);
9399     ASSERT_EQUAL_32(0x22222222U, w14);
9400 
9401     ASSERT_EQUAL_32(0x11111111U, w18);
9402     ASSERT_EQUAL_32(0x11111111U, w19);
9403     ASSERT_EQUAL_32(0x11111111U, w20);
9404     ASSERT_EQUAL_32(0x11111111U, w21);
9405     ASSERT_EQUAL_64(0x3333333333333333, x22);
9406     ASSERT_EQUAL_64(0x0000000000000000, x23);
9407 
9408     ASSERT_EQUAL_64(0x3333333333333333, x24);
9409     ASSERT_EQUAL_64(0x3333333333333333, x26);
9410 
9411     ASSERT_EQUAL_32(0x33333333U, w25);
9412     ASSERT_EQUAL_32(0x00000000U, w27);
9413     ASSERT_EQUAL_32(0x22222222U, w28);
9414     ASSERT_EQUAL_32(0x33333333U, w29);
9415   }
9416 }
9417 
9418 
TEST(printf)9419 TEST(printf) {
9420   // RegisterDump::Dump uses NEON.
9421   // Printf uses FP to cast FP arguments to doubles.
9422   SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
9423 
9424   START();
9425 
9426   char const* test_plain_string = "Printf with no arguments.\n";
9427   char const* test_substring = "'This is a substring.'";
9428   RegisterDump before;
9429 
9430   // Initialize x29 to the value of the stack pointer. We will use x29 as a
9431   // temporary stack pointer later, and initializing it in this way allows the
9432   // RegisterDump check to pass.
9433   __ Mov(x29, __ StackPointer());
9434 
9435   // Test simple integer arguments.
9436   __ Mov(x0, 1234);
9437   __ Mov(x1, 0x1234);
9438 
9439   // Test simple floating-point arguments.
9440   __ Fmov(d0, 1.234);
9441 
9442   // Test pointer (string) arguments.
9443   __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9444 
9445   // Test the maximum number of arguments, and sign extension.
9446   __ Mov(w3, 0xffffffff);
9447   __ Mov(w4, 0xffffffff);
9448   __ Mov(x5, 0xffffffffffffffff);
9449   __ Mov(x6, 0xffffffffffffffff);
9450   __ Fmov(s1, 1.234);
9451   __ Fmov(s2, 2.345);
9452   __ Fmov(d3, 3.456);
9453   __ Fmov(d4, 4.567);
9454 
9455   // Test printing callee-saved registers.
9456   __ Mov(x28, 0x123456789abcdef);
9457   __ Fmov(d10, 42.0);
9458 
9459   // Test with three arguments.
9460   __ Mov(x10, 3);
9461   __ Mov(x11, 40);
9462   __ Mov(x12, 500);
9463 
9464   // A single character.
9465   __ Mov(w13, 'x');
9466 
9467   // Check that we don't clobber any registers.
9468   before.Dump(&masm);
9469 
9470   __ Printf(test_plain_string);  // NOLINT(runtime/printf)
9471   __ Printf("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
9472   __ Printf("w5: %" PRId32 ", x5: %" PRId64 "\n", w5, x5);
9473   __ Printf("d0: %f\n", d0);
9474   __ Printf("Test %%s: %s\n", x2);
9475   __ Printf("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32
9476             "\n"
9477             "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9478             w3,
9479             w4,
9480             x5,
9481             x6);
9482   __ Printf("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
9483   __ Printf("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
9484   __ Printf("%g\n", d10);
9485   __ Printf("%%%%%s%%%c%%\n", x2, w13);
9486 
9487   // Print the stack pointer (sp).
9488   __ Printf("StackPointer(sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
9489             __ StackPointer(),
9490             __ StackPointer().W());
9491 
9492   // Test with a different stack pointer.
9493   const Register old_stack_pointer = __ StackPointer();
9494   __ Mov(x29, old_stack_pointer);
9495   __ SetStackPointer(x29);
9496   // Print the stack pointer (not sp).
9497   __ Printf("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
9498             __ StackPointer(),
9499             __ StackPointer().W());
9500   __ Mov(old_stack_pointer, __ StackPointer());
9501   __ SetStackPointer(old_stack_pointer);
9502 
9503   // Test with three arguments.
9504   __ Printf("3=%u, 4=%u, 5=%u\n", x10, x11, x12);
9505 
9506   // Mixed argument types.
9507   __ Printf("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
9508             w3,
9509             s1,
9510             x5,
9511             d3);
9512   __ Printf("s1: %f, d3: %f, w3: %" PRId32 ", x5: %" PRId64 "\n",
9513             s1,
9514             d3,
9515             w3,
9516             x5);
9517 
9518   END();
9519   if (CAN_RUN()) {
9520     RUN();
9521 
9522     // We cannot easily test the output of the Printf sequences, and because
9523     // Printf preserves all registers by default, we can't look at the number of
9524     // bytes that were printed. However, the printf_no_preserve test should
9525     // check
9526     // that, and here we just test that we didn't clobber any registers.
9527     ASSERT_EQUAL_REGISTERS(before);
9528   }
9529 }
9530 
9531 
TEST(printf_no_preserve)9532 TEST(printf_no_preserve) {
9533   // PrintfNoPreserve uses FP to cast FP arguments to doubles.
9534   SETUP_WITH_FEATURES(CPUFeatures::kFP);
9535 
9536   START();
9537 
9538   char const* test_plain_string = "Printf with no arguments.\n";
9539   char const* test_substring = "'This is a substring.'";
9540 
9541   __ PrintfNoPreserve(test_plain_string);
9542   __ Mov(x19, x0);
9543 
9544   // Test simple integer arguments.
9545   __ Mov(x0, 1234);
9546   __ Mov(x1, 0x1234);
9547   __ PrintfNoPreserve("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
9548   __ Mov(x20, x0);
9549 
9550   // Test simple floating-point arguments.
9551   __ Fmov(d0, 1.234);
9552   __ PrintfNoPreserve("d0: %f\n", d0);
9553   __ Mov(x21, x0);
9554 
9555   // Test pointer (string) arguments.
9556   __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9557   __ PrintfNoPreserve("Test %%s: %s\n", x2);
9558   __ Mov(x22, x0);
9559 
9560   // Test the maximum number of arguments, and sign extension.
9561   __ Mov(w3, 0xffffffff);
9562   __ Mov(w4, 0xffffffff);
9563   __ Mov(x5, 0xffffffffffffffff);
9564   __ Mov(x6, 0xffffffffffffffff);
9565   __ PrintfNoPreserve("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32
9566                       "\n"
9567                       "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9568                       w3,
9569                       w4,
9570                       x5,
9571                       x6);
9572   __ Mov(x23, x0);
9573 
9574   __ Fmov(s1, 1.234);
9575   __ Fmov(s2, 2.345);
9576   __ Fmov(d3, 3.456);
9577   __ Fmov(d4, 4.567);
9578   __ PrintfNoPreserve("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
9579   __ Mov(x24, x0);
9580 
9581   // Test printing callee-saved registers.
9582   __ Mov(x28, 0x123456789abcdef);
9583   __ PrintfNoPreserve("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
9584   __ Mov(x25, x0);
9585 
9586   __ Fmov(d10, 42.0);
9587   __ PrintfNoPreserve("%g\n", d10);
9588   __ Mov(x26, x0);
9589 
9590   // Test with a different stack pointer.
9591   const Register old_stack_pointer = __ StackPointer();
9592   __ Mov(x29, old_stack_pointer);
9593   __ SetStackPointer(x29);
9594   // Print the stack pointer (not sp).
9595   __ PrintfNoPreserve("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32
9596                       "\n",
9597                       __ StackPointer(),
9598                       __ StackPointer().W());
9599   __ Mov(x27, x0);
9600   __ Mov(old_stack_pointer, __ StackPointer());
9601   __ SetStackPointer(old_stack_pointer);
9602 
9603   // Test with three arguments.
9604   __ Mov(x3, 3);
9605   __ Mov(x4, 40);
9606   __ Mov(x5, 500);
9607   __ PrintfNoPreserve("3=%u, 4=%u, 5=%u\n", x3, x4, x5);
9608   __ Mov(x28, x0);
9609 
9610   // Mixed argument types.
9611   __ Mov(w3, 0xffffffff);
9612   __ Fmov(s1, 1.234);
9613   __ Mov(x5, 0xffffffffffffffff);
9614   __ Fmov(d3, 3.456);
9615   __ PrintfNoPreserve("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
9616                       w3,
9617                       s1,
9618                       x5,
9619                       d3);
9620   __ Mov(x29, x0);
9621 
9622   END();
9623   if (CAN_RUN()) {
9624     RUN();
9625 
9626     // We cannot easily test the exact output of the Printf sequences, but we
9627     // can
9628     // use the return code to check that the string length was correct.
9629 
9630     // Printf with no arguments.
9631     ASSERT_EQUAL_64(strlen(test_plain_string), x19);
9632     // x0: 1234, x1: 0x00001234
9633     ASSERT_EQUAL_64(25, x20);
9634     // d0: 1.234000
9635     ASSERT_EQUAL_64(13, x21);
9636     // Test %s: 'This is a substring.'
9637     ASSERT_EQUAL_64(32, x22);
9638     // w3(uint32): 4294967295
9639     // w4(int32): -1
9640     // x5(uint64): 18446744073709551615
9641     // x6(int64): -1
9642     ASSERT_EQUAL_64(23 + 14 + 33 + 14, x23);
9643     // %f: 1.234000
9644     // %g: 2.345
9645     // %e: 3.456000e+00
9646     // %E: 4.567000E+00
9647     ASSERT_EQUAL_64(13 + 10 + 17 + 17, x24);
9648     // 0x89abcdef, 0x123456789abcdef
9649     ASSERT_EQUAL_64(30, x25);
9650     // 42
9651     ASSERT_EQUAL_64(3, x26);
9652     // StackPointer(not sp): 0x00007fb037ae2370, 0x37ae2370
9653     // Note: This is an example value, but the field width is fixed here so the
9654     // string length is still predictable.
9655     ASSERT_EQUAL_64(53, x27);
9656     // 3=3, 4=40, 5=500
9657     ASSERT_EQUAL_64(17, x28);
9658     // w3: 4294967295, s1: 1.234000, x5: 18446744073709551615, d3: 3.456000
9659     ASSERT_EQUAL_64(69, x29);
9660   }
9661 }
9662 
9663 
TEST(trace)9664 TEST(trace) {
9665   // The Trace helper should not generate any code unless the simulator is being
9666   // used.
9667   SETUP();
9668   START();
9669 
9670   Label start;
9671   __ Bind(&start);
9672   __ Trace(LOG_ALL, TRACE_ENABLE);
9673   __ Trace(LOG_ALL, TRACE_DISABLE);
9674   if (masm.GenerateSimulatorCode()) {
9675     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0);
9676   } else {
9677     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
9678   }
9679 
9680   END();
9681 }
9682 
9683 
TEST(log)9684 TEST(log) {
9685   // The Log helper should not generate any code unless the simulator is being
9686   // used.
9687   SETUP();
9688   START();
9689 
9690   Label start;
9691   __ Bind(&start);
9692   __ Log(LOG_ALL);
9693   if (masm.GenerateSimulatorCode()) {
9694     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0);
9695   } else {
9696     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
9697   }
9698 
9699   END();
9700 }
9701 
9702 
TEST(blr_lr)9703 TEST(blr_lr) {
9704   // A simple test to check that the simulator correctly handle "blr lr".
9705   SETUP();
9706 
9707   START();
9708   Label target;
9709   Label end;
9710 
9711   __ Mov(x0, 0x0);
9712   __ Adr(lr, &target);
9713 
9714   __ Blr(lr);
9715   __ Mov(x0, 0xdeadbeef);
9716   __ B(&end);
9717 
9718   __ Bind(&target);
9719   __ Mov(x0, 0xc001c0de);
9720 
9721   __ Bind(&end);
9722   END();
9723 
9724   if (CAN_RUN()) {
9725     RUN();
9726 
9727     ASSERT_EQUAL_64(0xc001c0de, x0);
9728   }
9729 }
9730 
9731 
TEST(barriers)9732 TEST(barriers) {
9733   // Generate all supported barriers, this is just a smoke test
9734   SETUP();
9735 
9736   START();
9737 
9738   // DMB
9739   __ Dmb(FullSystem, BarrierAll);
9740   __ Dmb(FullSystem, BarrierReads);
9741   __ Dmb(FullSystem, BarrierWrites);
9742   __ Dmb(FullSystem, BarrierOther);
9743 
9744   __ Dmb(InnerShareable, BarrierAll);
9745   __ Dmb(InnerShareable, BarrierReads);
9746   __ Dmb(InnerShareable, BarrierWrites);
9747   __ Dmb(InnerShareable, BarrierOther);
9748 
9749   __ Dmb(NonShareable, BarrierAll);
9750   __ Dmb(NonShareable, BarrierReads);
9751   __ Dmb(NonShareable, BarrierWrites);
9752   __ Dmb(NonShareable, BarrierOther);
9753 
9754   __ Dmb(OuterShareable, BarrierAll);
9755   __ Dmb(OuterShareable, BarrierReads);
9756   __ Dmb(OuterShareable, BarrierWrites);
9757   __ Dmb(OuterShareable, BarrierOther);
9758 
9759   // DSB
9760   __ Dsb(FullSystem, BarrierAll);
9761   __ Dsb(FullSystem, BarrierReads);
9762   __ Dsb(FullSystem, BarrierWrites);
9763   __ Dsb(FullSystem, BarrierOther);
9764 
9765   __ Dsb(InnerShareable, BarrierAll);
9766   __ Dsb(InnerShareable, BarrierReads);
9767   __ Dsb(InnerShareable, BarrierWrites);
9768   __ Dsb(InnerShareable, BarrierOther);
9769 
9770   __ Dsb(NonShareable, BarrierAll);
9771   __ Dsb(NonShareable, BarrierReads);
9772   __ Dsb(NonShareable, BarrierWrites);
9773   __ Dsb(NonShareable, BarrierOther);
9774 
9775   __ Dsb(OuterShareable, BarrierAll);
9776   __ Dsb(OuterShareable, BarrierReads);
9777   __ Dsb(OuterShareable, BarrierWrites);
9778   __ Dsb(OuterShareable, BarrierOther);
9779 
9780   // ISB
9781   __ Isb();
9782 
9783   END();
9784 
9785   if (CAN_RUN()) {
9786     RUN();
9787   }
9788 }
9789 
9790 
TEST(ldar_stlr)9791 TEST(ldar_stlr) {
9792   // The middle value is read, modified, and written. The padding exists only to
9793   // check for over-write.
9794   uint8_t b[] = {0, 0x12, 0};
9795   uint16_t h[] = {0, 0x1234, 0};
9796   uint32_t w[] = {0, 0x12345678, 0};
9797   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9798 
9799   SETUP();
9800   START();
9801 
9802   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9803   __ Ldarb(w0, MemOperand(x10));
9804   __ Add(w0, w0, 1);
9805   __ Stlrb(w0, MemOperand(x10));
9806 
9807   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9808   __ Ldarh(w0, MemOperand(x10));
9809   __ Add(w0, w0, 1);
9810   __ Stlrh(w0, MemOperand(x10));
9811 
9812   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9813   __ Ldar(w0, MemOperand(x10));
9814   __ Add(w0, w0, 1);
9815   __ Stlr(w0, MemOperand(x10));
9816 
9817   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9818   __ Ldar(x0, MemOperand(x10));
9819   __ Add(x0, x0, 1);
9820   __ Stlr(x0, MemOperand(x10));
9821 
9822   END();
9823   if (CAN_RUN()) {
9824     RUN();
9825 
9826     ASSERT_EQUAL_32(0x13, b[1]);
9827     ASSERT_EQUAL_32(0x1235, h[1]);
9828     ASSERT_EQUAL_32(0x12345679, w[1]);
9829     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
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   }
9841 }
9842 
9843 
TEST(ldlar_stllr)9844 TEST(ldlar_stllr) {
9845   // The middle value is read, modified, and written. The padding exists only to
9846   // check for over-write.
9847   uint8_t b[] = {0, 0x12, 0};
9848   uint16_t h[] = {0, 0x1234, 0};
9849   uint32_t w[] = {0, 0x12345678, 0};
9850   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9851 
9852   SETUP_WITH_FEATURES(CPUFeatures::kLORegions);
9853 
9854   START();
9855 
9856   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9857   __ Ldlarb(w0, MemOperand(x10));
9858   __ Add(w0, w0, 1);
9859   __ Stllrb(w0, MemOperand(x10));
9860 
9861   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9862   __ Ldlarh(w0, MemOperand(x10));
9863   __ Add(w0, w0, 1);
9864   __ Stllrh(w0, MemOperand(x10));
9865 
9866   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9867   __ Ldlar(w0, MemOperand(x10));
9868   __ Add(w0, w0, 1);
9869   __ Stllr(w0, MemOperand(x10));
9870 
9871   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9872   __ Ldlar(x0, MemOperand(x10));
9873   __ Add(x0, x0, 1);
9874   __ Stllr(x0, MemOperand(x10));
9875 
9876   END();
9877 
9878   if (CAN_RUN()) {
9879     RUN();
9880 
9881     ASSERT_EQUAL_32(0x13, b[1]);
9882     ASSERT_EQUAL_32(0x1235, h[1]);
9883     ASSERT_EQUAL_32(0x12345679, w[1]);
9884     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9885 
9886     // Check for over-write.
9887     ASSERT_EQUAL_32(0, b[0]);
9888     ASSERT_EQUAL_32(0, b[2]);
9889     ASSERT_EQUAL_32(0, h[0]);
9890     ASSERT_EQUAL_32(0, h[2]);
9891     ASSERT_EQUAL_32(0, w[0]);
9892     ASSERT_EQUAL_32(0, w[2]);
9893     ASSERT_EQUAL_64(0, x[0]);
9894     ASSERT_EQUAL_64(0, x[2]);
9895   }
9896 }
9897 
9898 
TEST(ldxr_stxr)9899 TEST(ldxr_stxr) {
9900   // The middle value is read, modified, and written. The padding exists only to
9901   // check for over-write.
9902   uint8_t b[] = {0, 0x12, 0};
9903   uint16_t h[] = {0, 0x1234, 0};
9904   uint32_t w[] = {0, 0x12345678, 0};
9905   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9906 
9907   // As above, but get suitably-aligned values for ldxp and stxp.
9908   uint32_t wp_data[] = {0, 0, 0, 0, 0};
9909   uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
9910   wp[1] = 0x12345678;  // wp[1] is 64-bit-aligned.
9911   wp[2] = 0x87654321;
9912   uint64_t xp_data[] = {0, 0, 0, 0, 0};
9913   uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
9914   xp[1] = 0x123456789abcdef0;  // xp[1] is 128-bit-aligned.
9915   xp[2] = 0x0fedcba987654321;
9916 
9917   SETUP();
9918   START();
9919 
9920   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9921   Label try_b;
9922   __ Bind(&try_b);
9923   __ Ldxrb(w0, MemOperand(x10));
9924   __ Add(w0, w0, 1);
9925   __ Stxrb(w5, w0, MemOperand(x10));
9926   __ Cbnz(w5, &try_b);
9927 
9928   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9929   Label try_h;
9930   __ Bind(&try_h);
9931   __ Ldxrh(w0, MemOperand(x10));
9932   __ Add(w0, w0, 1);
9933   __ Stxrh(w5, w0, MemOperand(x10));
9934   __ Cbnz(w5, &try_h);
9935 
9936   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9937   Label try_w;
9938   __ Bind(&try_w);
9939   __ Ldxr(w0, MemOperand(x10));
9940   __ Add(w0, w0, 1);
9941   __ Stxr(w5, w0, MemOperand(x10));
9942   __ Cbnz(w5, &try_w);
9943 
9944   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9945   Label try_x;
9946   __ Bind(&try_x);
9947   __ Ldxr(x0, MemOperand(x10));
9948   __ Add(x0, x0, 1);
9949   __ Stxr(w5, x0, MemOperand(x10));
9950   __ Cbnz(w5, &try_x);
9951 
9952   __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
9953   Label try_wp;
9954   __ Bind(&try_wp);
9955   __ Ldxp(w0, w1, MemOperand(x10));
9956   __ Add(w0, w0, 1);
9957   __ Add(w1, w1, 1);
9958   __ Stxp(w5, w0, w1, MemOperand(x10));
9959   __ Cbnz(w5, &try_wp);
9960 
9961   __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
9962   Label try_xp;
9963   __ Bind(&try_xp);
9964   __ Ldxp(x0, x1, MemOperand(x10));
9965   __ Add(x0, x0, 1);
9966   __ Add(x1, x1, 1);
9967   __ Stxp(w5, x0, x1, MemOperand(x10));
9968   __ Cbnz(w5, &try_xp);
9969 
9970   END();
9971   if (CAN_RUN()) {
9972     RUN();
9973 
9974     ASSERT_EQUAL_32(0x13, b[1]);
9975     ASSERT_EQUAL_32(0x1235, h[1]);
9976     ASSERT_EQUAL_32(0x12345679, w[1]);
9977     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9978     ASSERT_EQUAL_32(0x12345679, wp[1]);
9979     ASSERT_EQUAL_32(0x87654322, wp[2]);
9980     ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
9981     ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
9982 
9983     // Check for over-write.
9984     ASSERT_EQUAL_32(0, b[0]);
9985     ASSERT_EQUAL_32(0, b[2]);
9986     ASSERT_EQUAL_32(0, h[0]);
9987     ASSERT_EQUAL_32(0, h[2]);
9988     ASSERT_EQUAL_32(0, w[0]);
9989     ASSERT_EQUAL_32(0, w[2]);
9990     ASSERT_EQUAL_64(0, x[0]);
9991     ASSERT_EQUAL_64(0, x[2]);
9992     ASSERT_EQUAL_32(0, wp[0]);
9993     ASSERT_EQUAL_32(0, wp[3]);
9994     ASSERT_EQUAL_64(0, xp[0]);
9995     ASSERT_EQUAL_64(0, xp[3]);
9996   }
9997 }
9998 
9999 
TEST(ldaxr_stlxr)10000 TEST(ldaxr_stlxr) {
10001   // The middle value is read, modified, and written. The padding exists only to
10002   // check for over-write.
10003   uint8_t b[] = {0, 0x12, 0};
10004   uint16_t h[] = {0, 0x1234, 0};
10005   uint32_t w[] = {0, 0x12345678, 0};
10006   uint64_t x[] = {0, 0x123456789abcdef0, 0};
10007 
10008   // As above, but get suitably-aligned values for ldxp and stxp.
10009   uint32_t wp_data[] = {0, 0, 0, 0, 0};
10010   uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
10011   wp[1] = 0x12345678;  // wp[1] is 64-bit-aligned.
10012   wp[2] = 0x87654321;
10013   uint64_t xp_data[] = {0, 0, 0, 0, 0};
10014   uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
10015   xp[1] = 0x123456789abcdef0;  // xp[1] is 128-bit-aligned.
10016   xp[2] = 0x0fedcba987654321;
10017 
10018   SETUP();
10019   START();
10020 
10021   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
10022   Label try_b;
10023   __ Bind(&try_b);
10024   __ Ldaxrb(w0, MemOperand(x10));
10025   __ Add(w0, w0, 1);
10026   __ Stlxrb(w5, w0, MemOperand(x10));
10027   __ Cbnz(w5, &try_b);
10028 
10029   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
10030   Label try_h;
10031   __ Bind(&try_h);
10032   __ Ldaxrh(w0, MemOperand(x10));
10033   __ Add(w0, w0, 1);
10034   __ Stlxrh(w5, w0, MemOperand(x10));
10035   __ Cbnz(w5, &try_h);
10036 
10037   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
10038   Label try_w;
10039   __ Bind(&try_w);
10040   __ Ldaxr(w0, MemOperand(x10));
10041   __ Add(w0, w0, 1);
10042   __ Stlxr(w5, w0, MemOperand(x10));
10043   __ Cbnz(w5, &try_w);
10044 
10045   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
10046   Label try_x;
10047   __ Bind(&try_x);
10048   __ Ldaxr(x0, MemOperand(x10));
10049   __ Add(x0, x0, 1);
10050   __ Stlxr(w5, x0, MemOperand(x10));
10051   __ Cbnz(w5, &try_x);
10052 
10053   __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
10054   Label try_wp;
10055   __ Bind(&try_wp);
10056   __ Ldaxp(w0, w1, MemOperand(x10));
10057   __ Add(w0, w0, 1);
10058   __ Add(w1, w1, 1);
10059   __ Stlxp(w5, w0, w1, MemOperand(x10));
10060   __ Cbnz(w5, &try_wp);
10061 
10062   __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
10063   Label try_xp;
10064   __ Bind(&try_xp);
10065   __ Ldaxp(x0, x1, MemOperand(x10));
10066   __ Add(x0, x0, 1);
10067   __ Add(x1, x1, 1);
10068   __ Stlxp(w5, x0, x1, MemOperand(x10));
10069   __ Cbnz(w5, &try_xp);
10070 
10071   END();
10072   if (CAN_RUN()) {
10073     RUN();
10074 
10075     ASSERT_EQUAL_32(0x13, b[1]);
10076     ASSERT_EQUAL_32(0x1235, h[1]);
10077     ASSERT_EQUAL_32(0x12345679, w[1]);
10078     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
10079     ASSERT_EQUAL_32(0x12345679, wp[1]);
10080     ASSERT_EQUAL_32(0x87654322, wp[2]);
10081     ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
10082     ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
10083 
10084     // Check for over-write.
10085     ASSERT_EQUAL_32(0, b[0]);
10086     ASSERT_EQUAL_32(0, b[2]);
10087     ASSERT_EQUAL_32(0, h[0]);
10088     ASSERT_EQUAL_32(0, h[2]);
10089     ASSERT_EQUAL_32(0, w[0]);
10090     ASSERT_EQUAL_32(0, w[2]);
10091     ASSERT_EQUAL_64(0, x[0]);
10092     ASSERT_EQUAL_64(0, x[2]);
10093     ASSERT_EQUAL_32(0, wp[0]);
10094     ASSERT_EQUAL_32(0, wp[3]);
10095     ASSERT_EQUAL_64(0, xp[0]);
10096     ASSERT_EQUAL_64(0, xp[3]);
10097   }
10098 }
10099 
10100 
TEST(clrex)10101 TEST(clrex) {
10102   // This data should never be written.
10103   uint64_t data[] = {0, 0, 0};
10104   uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
10105 
10106   SETUP();
10107   START();
10108 
10109   __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
10110   __ Mov(w6, 0);
10111 
10112   __ Ldxrb(w0, MemOperand(x10));
10113   __ Clrex();
10114   __ Add(w0, w0, 1);
10115   __ Stxrb(w5, w0, MemOperand(x10));
10116   __ Add(w6, w6, w5);
10117 
10118   __ Ldxrh(w0, MemOperand(x10));
10119   __ Clrex();
10120   __ Add(w0, w0, 1);
10121   __ Stxrh(w5, w0, MemOperand(x10));
10122   __ Add(w6, w6, w5);
10123 
10124   __ Ldxr(w0, MemOperand(x10));
10125   __ Clrex();
10126   __ Add(w0, w0, 1);
10127   __ Stxr(w5, w0, MemOperand(x10));
10128   __ Add(w6, w6, w5);
10129 
10130   __ Ldxr(x0, MemOperand(x10));
10131   __ Clrex();
10132   __ Add(x0, x0, 1);
10133   __ Stxr(w5, x0, MemOperand(x10));
10134   __ Add(w6, w6, w5);
10135 
10136   __ Ldxp(w0, w1, MemOperand(x10));
10137   __ Clrex();
10138   __ Add(w0, w0, 1);
10139   __ Add(w1, w1, 1);
10140   __ Stxp(w5, w0, w1, MemOperand(x10));
10141   __ Add(w6, w6, w5);
10142 
10143   __ Ldxp(x0, x1, MemOperand(x10));
10144   __ Clrex();
10145   __ Add(x0, x0, 1);
10146   __ Add(x1, x1, 1);
10147   __ Stxp(w5, x0, x1, MemOperand(x10));
10148   __ Add(w6, w6, w5);
10149 
10150   // Acquire-release variants.
10151 
10152   __ Ldaxrb(w0, MemOperand(x10));
10153   __ Clrex();
10154   __ Add(w0, w0, 1);
10155   __ Stlxrb(w5, w0, MemOperand(x10));
10156   __ Add(w6, w6, w5);
10157 
10158   __ Ldaxrh(w0, MemOperand(x10));
10159   __ Clrex();
10160   __ Add(w0, w0, 1);
10161   __ Stlxrh(w5, w0, MemOperand(x10));
10162   __ Add(w6, w6, w5);
10163 
10164   __ Ldaxr(w0, MemOperand(x10));
10165   __ Clrex();
10166   __ Add(w0, w0, 1);
10167   __ Stlxr(w5, w0, MemOperand(x10));
10168   __ Add(w6, w6, w5);
10169 
10170   __ Ldaxr(x0, MemOperand(x10));
10171   __ Clrex();
10172   __ Add(x0, x0, 1);
10173   __ Stlxr(w5, x0, MemOperand(x10));
10174   __ Add(w6, w6, w5);
10175 
10176   __ Ldaxp(w0, w1, MemOperand(x10));
10177   __ Clrex();
10178   __ Add(w0, w0, 1);
10179   __ Add(w1, w1, 1);
10180   __ Stlxp(w5, w0, w1, MemOperand(x10));
10181   __ Add(w6, w6, w5);
10182 
10183   __ Ldaxp(x0, x1, MemOperand(x10));
10184   __ Clrex();
10185   __ Add(x0, x0, 1);
10186   __ Add(x1, x1, 1);
10187   __ Stlxp(w5, x0, x1, MemOperand(x10));
10188   __ Add(w6, w6, w5);
10189 
10190   END();
10191   if (CAN_RUN()) {
10192     RUN();
10193 
10194     // None of the 12 store-exclusives should have succeeded.
10195     ASSERT_EQUAL_32(12, w6);
10196 
10197     ASSERT_EQUAL_64(0, data[0]);
10198     ASSERT_EQUAL_64(0, data[1]);
10199     ASSERT_EQUAL_64(0, data[2]);
10200   }
10201 }
10202 
10203 
10204 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
10205 // Check that the simulator occasionally makes store-exclusive fail.
TEST(ldxr_stxr_fail)10206 TEST(ldxr_stxr_fail) {
10207   uint64_t data[] = {0, 0, 0};
10208   uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
10209 
10210   // Impose a hard limit on the number of attempts, so the test cannot hang.
10211   static const uint64_t kWatchdog = 10000;
10212   Label done;
10213 
10214   SETUP();
10215   START();
10216 
10217   __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
10218   __ Mov(x11, kWatchdog);
10219 
10220   // This loop is the opposite of what we normally do with ldxr and stxr; we
10221   // keep trying until we fail (or the watchdog counter runs out).
10222   Label try_b;
10223   __ Bind(&try_b);
10224   __ Ldxrb(w0, MemOperand(x10));
10225   __ Stxrb(w5, w0, MemOperand(x10));
10226   // Check the watchdog counter.
10227   __ Sub(x11, x11, 1);
10228   __ Cbz(x11, &done);
10229   // Check the exclusive-store result.
10230   __ Cbz(w5, &try_b);
10231 
10232   Label try_h;
10233   __ Bind(&try_h);
10234   __ Ldxrh(w0, MemOperand(x10));
10235   __ Stxrh(w5, w0, MemOperand(x10));
10236   __ Sub(x11, x11, 1);
10237   __ Cbz(x11, &done);
10238   __ Cbz(w5, &try_h);
10239 
10240   Label try_w;
10241   __ Bind(&try_w);
10242   __ Ldxr(w0, MemOperand(x10));
10243   __ Stxr(w5, w0, MemOperand(x10));
10244   __ Sub(x11, x11, 1);
10245   __ Cbz(x11, &done);
10246   __ Cbz(w5, &try_w);
10247 
10248   Label try_x;
10249   __ Bind(&try_x);
10250   __ Ldxr(x0, MemOperand(x10));
10251   __ Stxr(w5, x0, MemOperand(x10));
10252   __ Sub(x11, x11, 1);
10253   __ Cbz(x11, &done);
10254   __ Cbz(w5, &try_x);
10255 
10256   Label try_wp;
10257   __ Bind(&try_wp);
10258   __ Ldxp(w0, w1, MemOperand(x10));
10259   __ Stxp(w5, w0, w1, MemOperand(x10));
10260   __ Sub(x11, x11, 1);
10261   __ Cbz(x11, &done);
10262   __ Cbz(w5, &try_wp);
10263 
10264   Label try_xp;
10265   __ Bind(&try_xp);
10266   __ Ldxp(x0, x1, MemOperand(x10));
10267   __ Stxp(w5, x0, x1, MemOperand(x10));
10268   __ Sub(x11, x11, 1);
10269   __ Cbz(x11, &done);
10270   __ Cbz(w5, &try_xp);
10271 
10272   __ Bind(&done);
10273   // Trigger an error if x11 (watchdog) is zero.
10274   __ Cmp(x11, 0);
10275   __ Cset(x12, eq);
10276 
10277   END();
10278   if (CAN_RUN()) {
10279     RUN();
10280 
10281     // Check that the watchdog counter didn't run out.
10282     ASSERT_EQUAL_64(0, x12);
10283   }
10284 }
10285 #endif
10286 
10287 
10288 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
10289 // Check that the simulator occasionally makes store-exclusive fail.
TEST(ldaxr_stlxr_fail)10290 TEST(ldaxr_stlxr_fail) {
10291   uint64_t data[] = {0, 0, 0};
10292   uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
10293 
10294   // Impose a hard limit on the number of attempts, so the test cannot hang.
10295   static const uint64_t kWatchdog = 10000;
10296   Label done;
10297 
10298   SETUP();
10299   START();
10300 
10301   __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
10302   __ Mov(x11, kWatchdog);
10303 
10304   // This loop is the opposite of what we normally do with ldxr and stxr; we
10305   // keep trying until we fail (or the watchdog counter runs out).
10306   Label try_b;
10307   __ Bind(&try_b);
10308   __ Ldxrb(w0, MemOperand(x10));
10309   __ Stxrb(w5, w0, MemOperand(x10));
10310   // Check the watchdog counter.
10311   __ Sub(x11, x11, 1);
10312   __ Cbz(x11, &done);
10313   // Check the exclusive-store result.
10314   __ Cbz(w5, &try_b);
10315 
10316   Label try_h;
10317   __ Bind(&try_h);
10318   __ Ldaxrh(w0, MemOperand(x10));
10319   __ Stlxrh(w5, w0, MemOperand(x10));
10320   __ Sub(x11, x11, 1);
10321   __ Cbz(x11, &done);
10322   __ Cbz(w5, &try_h);
10323 
10324   Label try_w;
10325   __ Bind(&try_w);
10326   __ Ldaxr(w0, MemOperand(x10));
10327   __ Stlxr(w5, w0, MemOperand(x10));
10328   __ Sub(x11, x11, 1);
10329   __ Cbz(x11, &done);
10330   __ Cbz(w5, &try_w);
10331 
10332   Label try_x;
10333   __ Bind(&try_x);
10334   __ Ldaxr(x0, MemOperand(x10));
10335   __ Stlxr(w5, x0, MemOperand(x10));
10336   __ Sub(x11, x11, 1);
10337   __ Cbz(x11, &done);
10338   __ Cbz(w5, &try_x);
10339 
10340   Label try_wp;
10341   __ Bind(&try_wp);
10342   __ Ldaxp(w0, w1, MemOperand(x10));
10343   __ Stlxp(w5, w0, w1, MemOperand(x10));
10344   __ Sub(x11, x11, 1);
10345   __ Cbz(x11, &done);
10346   __ Cbz(w5, &try_wp);
10347 
10348   Label try_xp;
10349   __ Bind(&try_xp);
10350   __ Ldaxp(x0, x1, MemOperand(x10));
10351   __ Stlxp(w5, x0, x1, MemOperand(x10));
10352   __ Sub(x11, x11, 1);
10353   __ Cbz(x11, &done);
10354   __ Cbz(w5, &try_xp);
10355 
10356   __ Bind(&done);
10357   // Trigger an error if x11 (watchdog) is zero.
10358   __ Cmp(x11, 0);
10359   __ Cset(x12, eq);
10360 
10361   END();
10362   if (CAN_RUN()) {
10363     RUN();
10364 
10365     // Check that the watchdog counter didn't run out.
10366     ASSERT_EQUAL_64(0, x12);
10367   }
10368 }
10369 #endif
10370 
TEST(cas_casa_casl_casal_w)10371 TEST(cas_casa_casl_casal_w) {
10372   uint64_t data1 = 0x0123456789abcdef;
10373   uint64_t data2 = 0x0123456789abcdef;
10374   uint64_t data3 = 0x0123456789abcdef;
10375   uint64_t data4 = 0x0123456789abcdef;
10376   uint64_t data5 = 0x0123456789abcdef;
10377   uint64_t data6 = 0x0123456789abcdef;
10378   uint64_t data7 = 0x0123456789abcdef;
10379   uint64_t data8 = 0x0123456789abcdef;
10380 
10381   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10382 
10383   START();
10384 
10385   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10386   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10387   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 4);
10388   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 4);
10389   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 0);
10390   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 0);
10391   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 4);
10392   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 4);
10393 
10394   __ Mov(x0, 0xffffffff);
10395 
10396   __ Mov(x1, 0xfedcba9876543210);
10397   __ Mov(x2, 0x0123456789abcdef);
10398   __ Mov(x3, 0xfedcba9876543210);
10399   __ Mov(x4, 0x89abcdef01234567);
10400   __ Mov(x5, 0xfedcba9876543210);
10401   __ Mov(x6, 0x0123456789abcdef);
10402   __ Mov(x7, 0xfedcba9876543210);
10403   __ Mov(x8, 0x89abcdef01234567);
10404 
10405   __ Cas(w1, w0, MemOperand(x21));
10406   __ Cas(w2, w0, MemOperand(x22));
10407   __ Casa(w3, w0, MemOperand(x23));
10408   __ Casa(w4, w0, MemOperand(x24));
10409   __ Casl(w5, w0, MemOperand(x25));
10410   __ Casl(w6, w0, MemOperand(x26));
10411   __ Casal(w7, w0, MemOperand(x27));
10412   __ Casal(w8, w0, MemOperand(x28));
10413 
10414   END();
10415 
10416   if (CAN_RUN()) {
10417     RUN();
10418 
10419     ASSERT_EQUAL_64(0x89abcdef, x1);
10420     ASSERT_EQUAL_64(0x89abcdef, x2);
10421     ASSERT_EQUAL_64(0x01234567, x3);
10422     ASSERT_EQUAL_64(0x01234567, x4);
10423     ASSERT_EQUAL_64(0x89abcdef, x5);
10424     ASSERT_EQUAL_64(0x89abcdef, x6);
10425     ASSERT_EQUAL_64(0x01234567, x7);
10426     ASSERT_EQUAL_64(0x01234567, x8);
10427 
10428     ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10429     ASSERT_EQUAL_64(0x01234567ffffffff, data2);
10430     ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10431     ASSERT_EQUAL_64(0xffffffff89abcdef, data4);
10432     ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10433     ASSERT_EQUAL_64(0x01234567ffffffff, data6);
10434     ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10435     ASSERT_EQUAL_64(0xffffffff89abcdef, data8);
10436   }
10437 }
10438 
TEST(cas_casa_casl_casal_x)10439 TEST(cas_casa_casl_casal_x) {
10440   uint64_t data1 = 0x0123456789abcdef;
10441   uint64_t data2 = 0x0123456789abcdef;
10442   uint64_t data3 = 0x0123456789abcdef;
10443   uint64_t data4 = 0x0123456789abcdef;
10444   uint64_t data5 = 0x0123456789abcdef;
10445   uint64_t data6 = 0x0123456789abcdef;
10446   uint64_t data7 = 0x0123456789abcdef;
10447   uint64_t data8 = 0x0123456789abcdef;
10448 
10449   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10450 
10451   START();
10452 
10453   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1));
10454   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2));
10455   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3));
10456   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4));
10457   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5));
10458   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6));
10459   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7));
10460   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8));
10461 
10462   __ Mov(x0, 0xffffffffffffffff);
10463 
10464   __ Mov(x1, 0xfedcba9876543210);
10465   __ Mov(x2, 0x0123456789abcdef);
10466   __ Mov(x3, 0xfedcba9876543210);
10467   __ Mov(x4, 0x0123456789abcdef);
10468   __ Mov(x5, 0xfedcba9876543210);
10469   __ Mov(x6, 0x0123456789abcdef);
10470   __ Mov(x7, 0xfedcba9876543210);
10471   __ Mov(x8, 0x0123456789abcdef);
10472 
10473   __ Cas(x1, x0, MemOperand(x21));
10474   __ Cas(x2, x0, MemOperand(x22));
10475   __ Casa(x3, x0, MemOperand(x23));
10476   __ Casa(x4, x0, MemOperand(x24));
10477   __ Casl(x5, x0, MemOperand(x25));
10478   __ Casl(x6, x0, MemOperand(x26));
10479   __ Casal(x7, x0, MemOperand(x27));
10480   __ Casal(x8, x0, MemOperand(x28));
10481 
10482   END();
10483 
10484   if (CAN_RUN()) {
10485     RUN();
10486 
10487     ASSERT_EQUAL_64(0x0123456789abcdef, x1);
10488     ASSERT_EQUAL_64(0x0123456789abcdef, x2);
10489     ASSERT_EQUAL_64(0x0123456789abcdef, x3);
10490     ASSERT_EQUAL_64(0x0123456789abcdef, x4);
10491     ASSERT_EQUAL_64(0x0123456789abcdef, x5);
10492     ASSERT_EQUAL_64(0x0123456789abcdef, x6);
10493     ASSERT_EQUAL_64(0x0123456789abcdef, x7);
10494     ASSERT_EQUAL_64(0x0123456789abcdef, x8);
10495 
10496     ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10497     ASSERT_EQUAL_64(0xffffffffffffffff, data2);
10498     ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10499     ASSERT_EQUAL_64(0xffffffffffffffff, data4);
10500     ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10501     ASSERT_EQUAL_64(0xffffffffffffffff, data6);
10502     ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10503     ASSERT_EQUAL_64(0xffffffffffffffff, data8);
10504   }
10505 }
10506 
TEST(casb_casab_caslb_casalb)10507 TEST(casb_casab_caslb_casalb) {
10508   uint32_t data1 = 0x01234567;
10509   uint32_t data2 = 0x01234567;
10510   uint32_t data3 = 0x01234567;
10511   uint32_t data4 = 0x01234567;
10512   uint32_t data5 = 0x01234567;
10513   uint32_t data6 = 0x01234567;
10514   uint32_t data7 = 0x01234567;
10515   uint32_t data8 = 0x01234567;
10516 
10517   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10518 
10519   START();
10520 
10521   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10522   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10523   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 1);
10524   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 1);
10525   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 2);
10526   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 2);
10527   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 3);
10528   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 3);
10529 
10530   __ Mov(x0, 0xff);
10531 
10532   __ Mov(x1, 0x76543210);
10533   __ Mov(x2, 0x01234567);
10534   __ Mov(x3, 0x76543210);
10535   __ Mov(x4, 0x67012345);
10536   __ Mov(x5, 0x76543210);
10537   __ Mov(x6, 0x45670123);
10538   __ Mov(x7, 0x76543210);
10539   __ Mov(x8, 0x23456701);
10540 
10541   __ Casb(w1, w0, MemOperand(x21));
10542   __ Casb(w2, w0, MemOperand(x22));
10543   __ Casab(w3, w0, MemOperand(x23));
10544   __ Casab(w4, w0, MemOperand(x24));
10545   __ Caslb(w5, w0, MemOperand(x25));
10546   __ Caslb(w6, w0, MemOperand(x26));
10547   __ Casalb(w7, w0, MemOperand(x27));
10548   __ Casalb(w8, w0, MemOperand(x28));
10549 
10550   END();
10551 
10552   if (CAN_RUN()) {
10553     RUN();
10554 
10555     ASSERT_EQUAL_64(0x00000067, x1);
10556     ASSERT_EQUAL_64(0x00000067, x2);
10557     ASSERT_EQUAL_64(0x00000045, x3);
10558     ASSERT_EQUAL_64(0x00000045, x4);
10559     ASSERT_EQUAL_64(0x00000023, x5);
10560     ASSERT_EQUAL_64(0x00000023, x6);
10561     ASSERT_EQUAL_64(0x00000001, x7);
10562     ASSERT_EQUAL_64(0x00000001, x8);
10563 
10564     ASSERT_EQUAL_64(0x01234567, data1);
10565     ASSERT_EQUAL_64(0x012345ff, data2);
10566     ASSERT_EQUAL_64(0x01234567, data3);
10567     ASSERT_EQUAL_64(0x0123ff67, data4);
10568     ASSERT_EQUAL_64(0x01234567, data5);
10569     ASSERT_EQUAL_64(0x01ff4567, data6);
10570     ASSERT_EQUAL_64(0x01234567, data7);
10571     ASSERT_EQUAL_64(0xff234567, data8);
10572   }
10573 }
10574 
TEST(cash_casah_caslh_casalh)10575 TEST(cash_casah_caslh_casalh) {
10576   uint64_t data1 = 0x0123456789abcdef;
10577   uint64_t data2 = 0x0123456789abcdef;
10578   uint64_t data3 = 0x0123456789abcdef;
10579   uint64_t data4 = 0x0123456789abcdef;
10580   uint64_t data5 = 0x0123456789abcdef;
10581   uint64_t data6 = 0x0123456789abcdef;
10582   uint64_t data7 = 0x0123456789abcdef;
10583   uint64_t data8 = 0x0123456789abcdef;
10584 
10585   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10586 
10587   START();
10588 
10589   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10590   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10591   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 2);
10592   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 2);
10593   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 4);
10594   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 4);
10595   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 6);
10596   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 6);
10597 
10598   __ Mov(x0, 0xffff);
10599 
10600   __ Mov(x1, 0xfedcba9876543210);
10601   __ Mov(x2, 0x0123456789abcdef);
10602   __ Mov(x3, 0xfedcba9876543210);
10603   __ Mov(x4, 0xcdef0123456789ab);
10604   __ Mov(x5, 0xfedcba9876543210);
10605   __ Mov(x6, 0x89abcdef01234567);
10606   __ Mov(x7, 0xfedcba9876543210);
10607   __ Mov(x8, 0x456789abcdef0123);
10608 
10609   __ Cash(w1, w0, MemOperand(x21));
10610   __ Cash(w2, w0, MemOperand(x22));
10611   __ Casah(w3, w0, MemOperand(x23));
10612   __ Casah(w4, w0, MemOperand(x24));
10613   __ Caslh(w5, w0, MemOperand(x25));
10614   __ Caslh(w6, w0, MemOperand(x26));
10615   __ Casalh(w7, w0, MemOperand(x27));
10616   __ Casalh(w8, w0, MemOperand(x28));
10617 
10618   END();
10619 
10620   if (CAN_RUN()) {
10621     RUN();
10622 
10623     ASSERT_EQUAL_64(0x0000cdef, x1);
10624     ASSERT_EQUAL_64(0x0000cdef, x2);
10625     ASSERT_EQUAL_64(0x000089ab, x3);
10626     ASSERT_EQUAL_64(0x000089ab, x4);
10627     ASSERT_EQUAL_64(0x00004567, x5);
10628     ASSERT_EQUAL_64(0x00004567, x6);
10629     ASSERT_EQUAL_64(0x00000123, x7);
10630     ASSERT_EQUAL_64(0x00000123, x8);
10631 
10632     ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10633     ASSERT_EQUAL_64(0x0123456789abffff, data2);
10634     ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10635     ASSERT_EQUAL_64(0x01234567ffffcdef, data4);
10636     ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10637     ASSERT_EQUAL_64(0x0123ffff89abcdef, data6);
10638     ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10639     ASSERT_EQUAL_64(0xffff456789abcdef, data8);
10640   }
10641 }
10642 
TEST(casp_caspa_caspl_caspal_w)10643 TEST(casp_caspa_caspl_caspal_w) {
10644   uint64_t data1[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10645   uint64_t data2[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10646   uint64_t data3[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10647   uint64_t data4[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10648   uint64_t data5[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10649   uint64_t data6[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10650   uint64_t data7[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10651   uint64_t data8[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10652 
10653   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10654 
10655   START();
10656 
10657   __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0);
10658   __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0);
10659   __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 8);
10660   __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 8);
10661   __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 8);
10662   __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 8);
10663   __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0);
10664   __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0);
10665 
10666   __ Mov(x0, 0xfff00fff);
10667   __ Mov(x1, 0xfff11fff);
10668 
10669   __ Mov(x2, 0x77665544);
10670   __ Mov(x3, 0x33221100);
10671   __ Mov(x4, 0x33221100);
10672   __ Mov(x5, 0x77665544);
10673 
10674   __ Mov(x6, 0xffeeddcc);
10675   __ Mov(x7, 0xbbaa9988);
10676   __ Mov(x8, 0xbbaa9988);
10677   __ Mov(x9, 0xffeeddcc);
10678 
10679   __ Mov(x10, 0xffeeddcc);
10680   __ Mov(x11, 0xbbaa9988);
10681   __ Mov(x12, 0xbbaa9988);
10682   __ Mov(x13, 0xffeeddcc);
10683 
10684   __ Mov(x14, 0x77665544);
10685   __ Mov(x15, 0x33221100);
10686   __ Mov(x16, 0x33221100);
10687   __ Mov(x17, 0x77665544);
10688 
10689   __ Casp(w2, w3, w0, w1, MemOperand(x21));
10690   __ Casp(w4, w5, w0, w1, MemOperand(x22));
10691   __ Caspa(w6, w7, w0, w1, MemOperand(x23));
10692   __ Caspa(w8, w9, w0, w1, MemOperand(x24));
10693   __ Caspl(w10, w11, w0, w1, MemOperand(x25));
10694   __ Caspl(w12, w13, w0, w1, MemOperand(x26));
10695   __ Caspal(w14, w15, w0, w1, MemOperand(x27));
10696   __ Caspal(w16, w17, w0, w1, MemOperand(x28));
10697 
10698   END();
10699 
10700   if (CAN_RUN()) {
10701     RUN();
10702 
10703     ASSERT_EQUAL_64(0x33221100, x2);
10704     ASSERT_EQUAL_64(0x77665544, x3);
10705     ASSERT_EQUAL_64(0x33221100, x4);
10706     ASSERT_EQUAL_64(0x77665544, x5);
10707     ASSERT_EQUAL_64(0xbbaa9988, x6);
10708     ASSERT_EQUAL_64(0xffeeddcc, x7);
10709     ASSERT_EQUAL_64(0xbbaa9988, x8);
10710     ASSERT_EQUAL_64(0xffeeddcc, x9);
10711     ASSERT_EQUAL_64(0xbbaa9988, x10);
10712     ASSERT_EQUAL_64(0xffeeddcc, x11);
10713     ASSERT_EQUAL_64(0xbbaa9988, x12);
10714     ASSERT_EQUAL_64(0xffeeddcc, x13);
10715     ASSERT_EQUAL_64(0x33221100, x14);
10716     ASSERT_EQUAL_64(0x77665544, x15);
10717     ASSERT_EQUAL_64(0x33221100, x16);
10718     ASSERT_EQUAL_64(0x77665544, x17);
10719 
10720     ASSERT_EQUAL_64(0x7766554433221100, data1[0]);
10721     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]);
10722     ASSERT_EQUAL_64(0xfff11ffffff00fff, data2[0]);
10723     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data2[1]);
10724     ASSERT_EQUAL_64(0x7766554433221100, data3[0]);
10725     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]);
10726     ASSERT_EQUAL_64(0x7766554433221100, data4[0]);
10727     ASSERT_EQUAL_64(0xfff11ffffff00fff, data4[1]);
10728     ASSERT_EQUAL_64(0x7766554433221100, data5[0]);
10729     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]);
10730     ASSERT_EQUAL_64(0x7766554433221100, data6[0]);
10731     ASSERT_EQUAL_64(0xfff11ffffff00fff, data6[1]);
10732     ASSERT_EQUAL_64(0x7766554433221100, data7[0]);
10733     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]);
10734     ASSERT_EQUAL_64(0xfff11ffffff00fff, data8[0]);
10735     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data8[1]);
10736   }
10737 }
10738 
TEST(casp_caspa_caspl_caspal_x)10739 TEST(casp_caspa_caspl_caspal_x) {
10740   alignas(kXRegSizeInBytes * 2) uint64_t data1[] = {0x7766554433221100,
10741                                                     0xffeeddccbbaa9988,
10742                                                     0xfedcba9876543210,
10743                                                     0x0123456789abcdef};
10744   alignas(kXRegSizeInBytes * 2) uint64_t data2[] = {0x7766554433221100,
10745                                                     0xffeeddccbbaa9988,
10746                                                     0xfedcba9876543210,
10747                                                     0x0123456789abcdef};
10748   alignas(kXRegSizeInBytes * 2) uint64_t data3[] = {0x7766554433221100,
10749                                                     0xffeeddccbbaa9988,
10750                                                     0xfedcba9876543210,
10751                                                     0x0123456789abcdef};
10752   alignas(kXRegSizeInBytes * 2) uint64_t data4[] = {0x7766554433221100,
10753                                                     0xffeeddccbbaa9988,
10754                                                     0xfedcba9876543210,
10755                                                     0x0123456789abcdef};
10756   alignas(kXRegSizeInBytes * 2) uint64_t data5[] = {0x7766554433221100,
10757                                                     0xffeeddccbbaa9988,
10758                                                     0xfedcba9876543210,
10759                                                     0x0123456789abcdef};
10760   alignas(kXRegSizeInBytes * 2) uint64_t data6[] = {0x7766554433221100,
10761                                                     0xffeeddccbbaa9988,
10762                                                     0xfedcba9876543210,
10763                                                     0x0123456789abcdef};
10764   alignas(kXRegSizeInBytes * 2) uint64_t data7[] = {0x7766554433221100,
10765                                                     0xffeeddccbbaa9988,
10766                                                     0xfedcba9876543210,
10767                                                     0x0123456789abcdef};
10768   alignas(kXRegSizeInBytes * 2) uint64_t data8[] = {0x7766554433221100,
10769                                                     0xffeeddccbbaa9988,
10770                                                     0xfedcba9876543210,
10771                                                     0x0123456789abcdef};
10772 
10773   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10774 
10775   START();
10776 
10777   __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0);
10778   __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0);
10779   __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 16);
10780   __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 16);
10781   __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 16);
10782   __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 16);
10783   __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0);
10784   __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0);
10785 
10786   __ Mov(x0, 0xfffffff00fffffff);
10787   __ Mov(x1, 0xfffffff11fffffff);
10788 
10789   __ Mov(x2, 0xffeeddccbbaa9988);
10790   __ Mov(x3, 0x7766554433221100);
10791   __ Mov(x4, 0x7766554433221100);
10792   __ Mov(x5, 0xffeeddccbbaa9988);
10793 
10794   __ Mov(x6, 0x0123456789abcdef);
10795   __ Mov(x7, 0xfedcba9876543210);
10796   __ Mov(x8, 0xfedcba9876543210);
10797   __ Mov(x9, 0x0123456789abcdef);
10798 
10799   __ Mov(x10, 0x0123456789abcdef);
10800   __ Mov(x11, 0xfedcba9876543210);
10801   __ Mov(x12, 0xfedcba9876543210);
10802   __ Mov(x13, 0x0123456789abcdef);
10803 
10804   __ Mov(x14, 0xffeeddccbbaa9988);
10805   __ Mov(x15, 0x7766554433221100);
10806   __ Mov(x16, 0x7766554433221100);
10807   __ Mov(x17, 0xffeeddccbbaa9988);
10808 
10809   __ Casp(x2, x3, x0, x1, MemOperand(x21));
10810   __ Casp(x4, x5, x0, x1, MemOperand(x22));
10811   __ Caspa(x6, x7, x0, x1, MemOperand(x23));
10812   __ Caspa(x8, x9, x0, x1, MemOperand(x24));
10813   __ Caspl(x10, x11, x0, x1, MemOperand(x25));
10814   __ Caspl(x12, x13, x0, x1, MemOperand(x26));
10815   __ Caspal(x14, x15, x0, x1, MemOperand(x27));
10816   __ Caspal(x16, x17, x0, x1, MemOperand(x28));
10817 
10818   END();
10819 
10820   if (CAN_RUN()) {
10821     RUN();
10822 
10823     ASSERT_EQUAL_64(0x7766554433221100, x2);
10824     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x3);
10825     ASSERT_EQUAL_64(0x7766554433221100, x4);
10826     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
10827 
10828     ASSERT_EQUAL_64(0xfedcba9876543210, x6);
10829     ASSERT_EQUAL_64(0x0123456789abcdef, x7);
10830     ASSERT_EQUAL_64(0xfedcba9876543210, x8);
10831     ASSERT_EQUAL_64(0x0123456789abcdef, x9);
10832 
10833     ASSERT_EQUAL_64(0xfedcba9876543210, x10);
10834     ASSERT_EQUAL_64(0x0123456789abcdef, x11);
10835     ASSERT_EQUAL_64(0xfedcba9876543210, x12);
10836     ASSERT_EQUAL_64(0x0123456789abcdef, x13);
10837 
10838     ASSERT_EQUAL_64(0x7766554433221100, x14);
10839     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x15);
10840     ASSERT_EQUAL_64(0x7766554433221100, x16);
10841     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x17);
10842 
10843     ASSERT_EQUAL_64(0x7766554433221100, data1[0]);
10844     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]);
10845     ASSERT_EQUAL_64(0xfedcba9876543210, data1[2]);
10846     ASSERT_EQUAL_64(0x0123456789abcdef, data1[3]);
10847 
10848     ASSERT_EQUAL_64(0xfffffff00fffffff, data2[0]);
10849     ASSERT_EQUAL_64(0xfffffff11fffffff, data2[1]);
10850     ASSERT_EQUAL_64(0xfedcba9876543210, data2[2]);
10851     ASSERT_EQUAL_64(0x0123456789abcdef, data2[3]);
10852 
10853     ASSERT_EQUAL_64(0x7766554433221100, data3[0]);
10854     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]);
10855     ASSERT_EQUAL_64(0xfedcba9876543210, data3[2]);
10856     ASSERT_EQUAL_64(0x0123456789abcdef, data3[3]);
10857 
10858     ASSERT_EQUAL_64(0x7766554433221100, data4[0]);
10859     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data4[1]);
10860     ASSERT_EQUAL_64(0xfffffff00fffffff, data4[2]);
10861     ASSERT_EQUAL_64(0xfffffff11fffffff, data4[3]);
10862 
10863     ASSERT_EQUAL_64(0x7766554433221100, data5[0]);
10864     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]);
10865     ASSERT_EQUAL_64(0xfedcba9876543210, data5[2]);
10866     ASSERT_EQUAL_64(0x0123456789abcdef, data5[3]);
10867 
10868     ASSERT_EQUAL_64(0x7766554433221100, data6[0]);
10869     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data6[1]);
10870     ASSERT_EQUAL_64(0xfffffff00fffffff, data6[2]);
10871     ASSERT_EQUAL_64(0xfffffff11fffffff, data6[3]);
10872 
10873     ASSERT_EQUAL_64(0x7766554433221100, data7[0]);
10874     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]);
10875     ASSERT_EQUAL_64(0xfedcba9876543210, data7[2]);
10876     ASSERT_EQUAL_64(0x0123456789abcdef, data7[3]);
10877 
10878     ASSERT_EQUAL_64(0xfffffff00fffffff, data8[0]);
10879     ASSERT_EQUAL_64(0xfffffff11fffffff, data8[1]);
10880     ASSERT_EQUAL_64(0xfedcba9876543210, data8[2]);
10881     ASSERT_EQUAL_64(0x0123456789abcdef, data8[3]);
10882   }
10883 }
10884 
10885 
10886 typedef void (MacroAssembler::*AtomicMemoryLoadSignature)(
10887     const Register& rs, const Register& rt, const MemOperand& src);
10888 typedef void (MacroAssembler::*AtomicMemoryStoreSignature)(
10889     const Register& rs, const MemOperand& src);
10890 
AtomicMemoryWHelper(AtomicMemoryLoadSignature * load_funcs,AtomicMemoryStoreSignature * store_funcs,uint64_t arg1,uint64_t arg2,uint64_t expected,uint64_t result_mask)10891 void AtomicMemoryWHelper(AtomicMemoryLoadSignature* load_funcs,
10892                          AtomicMemoryStoreSignature* store_funcs,
10893                          uint64_t arg1,
10894                          uint64_t arg2,
10895                          uint64_t expected,
10896                          uint64_t result_mask) {
10897   uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10898   uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10899   uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10900   uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10901   uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10902   uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10903 
10904   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10905   START();
10906 
10907   __ Mov(x20, reinterpret_cast<uintptr_t>(data0));
10908   __ Mov(x21, reinterpret_cast<uintptr_t>(data1));
10909   __ Mov(x22, reinterpret_cast<uintptr_t>(data2));
10910   __ Mov(x23, reinterpret_cast<uintptr_t>(data3));
10911 
10912   __ Mov(x0, arg1);
10913   __ Mov(x1, arg1);
10914   __ Mov(x2, arg1);
10915   __ Mov(x3, arg1);
10916 
10917   (masm.*(load_funcs[0]))(w0, w10, MemOperand(x20));
10918   (masm.*(load_funcs[1]))(w1, w11, MemOperand(x21));
10919   (masm.*(load_funcs[2]))(w2, w12, MemOperand(x22));
10920   (masm.*(load_funcs[3]))(w3, w13, MemOperand(x23));
10921 
10922   if (store_funcs != NULL) {
10923     __ Mov(x24, reinterpret_cast<uintptr_t>(data4));
10924     __ Mov(x25, reinterpret_cast<uintptr_t>(data5));
10925     __ Mov(x4, arg1);
10926     __ Mov(x5, arg1);
10927 
10928     (masm.*(store_funcs[0]))(w4, MemOperand(x24));
10929     (masm.*(store_funcs[1]))(w5, MemOperand(x25));
10930   }
10931 
10932   END();
10933 
10934   if (CAN_RUN()) {
10935     RUN();
10936 
10937     uint64_t stored_value = arg2 & result_mask;
10938     ASSERT_EQUAL_64(stored_value, x10);
10939     ASSERT_EQUAL_64(stored_value, x11);
10940     ASSERT_EQUAL_64(stored_value, x12);
10941     ASSERT_EQUAL_64(stored_value, x13);
10942 
10943     // The data fields contain arg2 already then only the bits masked by
10944     // result_mask are overwritten.
10945     uint64_t final_expected = (arg2 & ~result_mask) | (expected & result_mask);
10946     ASSERT_EQUAL_64(final_expected, data0[0]);
10947     ASSERT_EQUAL_64(final_expected, data1[0]);
10948     ASSERT_EQUAL_64(final_expected, data2[0]);
10949     ASSERT_EQUAL_64(final_expected, data3[0]);
10950 
10951     if (store_funcs != NULL) {
10952       ASSERT_EQUAL_64(final_expected, data4[0]);
10953       ASSERT_EQUAL_64(final_expected, data5[0]);
10954     }
10955   }
10956 }
10957 
AtomicMemoryXHelper(AtomicMemoryLoadSignature * load_funcs,AtomicMemoryStoreSignature * store_funcs,uint64_t arg1,uint64_t arg2,uint64_t expected)10958 void AtomicMemoryXHelper(AtomicMemoryLoadSignature* load_funcs,
10959                          AtomicMemoryStoreSignature* store_funcs,
10960                          uint64_t arg1,
10961                          uint64_t arg2,
10962                          uint64_t expected) {
10963   uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10964   uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10965   uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10966   uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10967   uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10968   uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10969 
10970   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10971   START();
10972 
10973   __ Mov(x20, reinterpret_cast<uintptr_t>(data0));
10974   __ Mov(x21, reinterpret_cast<uintptr_t>(data1));
10975   __ Mov(x22, reinterpret_cast<uintptr_t>(data2));
10976   __ Mov(x23, reinterpret_cast<uintptr_t>(data3));
10977 
10978   __ Mov(x0, arg1);
10979   __ Mov(x1, arg1);
10980   __ Mov(x2, arg1);
10981   __ Mov(x3, arg1);
10982 
10983   (masm.*(load_funcs[0]))(x0, x10, MemOperand(x20));
10984   (masm.*(load_funcs[1]))(x1, x11, MemOperand(x21));
10985   (masm.*(load_funcs[2]))(x2, x12, MemOperand(x22));
10986   (masm.*(load_funcs[3]))(x3, x13, MemOperand(x23));
10987 
10988   if (store_funcs != NULL) {
10989     __ Mov(x24, reinterpret_cast<uintptr_t>(data4));
10990     __ Mov(x25, reinterpret_cast<uintptr_t>(data5));
10991     __ Mov(x4, arg1);
10992     __ Mov(x5, arg1);
10993 
10994     (masm.*(store_funcs[0]))(x4, MemOperand(x24));
10995     (masm.*(store_funcs[1]))(x5, MemOperand(x25));
10996   }
10997 
10998   END();
10999 
11000   if (CAN_RUN()) {
11001     RUN();
11002 
11003     ASSERT_EQUAL_64(arg2, x10);
11004     ASSERT_EQUAL_64(arg2, x11);
11005     ASSERT_EQUAL_64(arg2, x12);
11006     ASSERT_EQUAL_64(arg2, x13);
11007 
11008     ASSERT_EQUAL_64(expected, data0[0]);
11009     ASSERT_EQUAL_64(expected, data1[0]);
11010     ASSERT_EQUAL_64(expected, data2[0]);
11011     ASSERT_EQUAL_64(expected, data3[0]);
11012 
11013     if (store_funcs != NULL) {
11014       ASSERT_EQUAL_64(expected, data4[0]);
11015       ASSERT_EQUAL_64(expected, data5[0]);
11016     }
11017   }
11018 }
11019 
11020 // clang-format off
11021 #define MAKE_LOADS(NAME)           \
11022     {&MacroAssembler::Ld##NAME,    \
11023      &MacroAssembler::Ld##NAME##a, \
11024      &MacroAssembler::Ld##NAME##l, \
11025      &MacroAssembler::Ld##NAME##al}
11026 #define MAKE_STORES(NAME) \
11027     {&MacroAssembler::St##NAME, &MacroAssembler::St##NAME##l}
11028 
11029 #define MAKE_B_LOADS(NAME)          \
11030     {&MacroAssembler::Ld##NAME##b,  \
11031      &MacroAssembler::Ld##NAME##ab, \
11032      &MacroAssembler::Ld##NAME##lb, \
11033      &MacroAssembler::Ld##NAME##alb}
11034 #define MAKE_B_STORES(NAME) \
11035     {&MacroAssembler::St##NAME##b, &MacroAssembler::St##NAME##lb}
11036 
11037 #define MAKE_H_LOADS(NAME)          \
11038     {&MacroAssembler::Ld##NAME##h,  \
11039      &MacroAssembler::Ld##NAME##ah, \
11040      &MacroAssembler::Ld##NAME##lh, \
11041      &MacroAssembler::Ld##NAME##alh}
11042 #define MAKE_H_STORES(NAME) \
11043     {&MacroAssembler::St##NAME##h, &MacroAssembler::St##NAME##lh}
11044 // clang-format on
11045 
TEST(atomic_memory_add)11046 TEST(atomic_memory_add) {
11047   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(add);
11048   AtomicMemoryStoreSignature stores[] = MAKE_STORES(add);
11049   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(add);
11050   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(add);
11051   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(add);
11052   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(add);
11053 
11054   // The arguments are chosen to have two useful properties:
11055   //  * When multiplied by small values (such as a register index), this value
11056   //    is clearly readable in the result.
11057   //  * The value is not formed from repeating fixed-size smaller values, so it
11058   //    can be used to detect endianness-related errors.
11059   uint64_t arg1 = 0x0100001000100101;
11060   uint64_t arg2 = 0x0200002000200202;
11061   uint64_t expected = arg1 + arg2;
11062 
11063   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11064   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11065   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11066   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11067 }
11068 
TEST(atomic_memory_clr)11069 TEST(atomic_memory_clr) {
11070   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(clr);
11071   AtomicMemoryStoreSignature stores[] = MAKE_STORES(clr);
11072   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(clr);
11073   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(clr);
11074   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(clr);
11075   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(clr);
11076 
11077   uint64_t arg1 = 0x0300003000300303;
11078   uint64_t arg2 = 0x0500005000500505;
11079   uint64_t expected = arg2 & ~arg1;
11080 
11081   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11082   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11083   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11084   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11085 }
11086 
TEST(atomic_memory_eor)11087 TEST(atomic_memory_eor) {
11088   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(eor);
11089   AtomicMemoryStoreSignature stores[] = MAKE_STORES(eor);
11090   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(eor);
11091   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(eor);
11092   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(eor);
11093   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(eor);
11094 
11095   uint64_t arg1 = 0x0300003000300303;
11096   uint64_t arg2 = 0x0500005000500505;
11097   uint64_t expected = arg1 ^ arg2;
11098 
11099   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11100   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11101   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11102   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11103 }
11104 
TEST(atomic_memory_set)11105 TEST(atomic_memory_set) {
11106   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(set);
11107   AtomicMemoryStoreSignature stores[] = MAKE_STORES(set);
11108   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(set);
11109   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(set);
11110   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(set);
11111   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(set);
11112 
11113   uint64_t arg1 = 0x0300003000300303;
11114   uint64_t arg2 = 0x0500005000500505;
11115   uint64_t expected = arg1 | arg2;
11116 
11117   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11118   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11119   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11120   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11121 }
11122 
TEST(atomic_memory_smax)11123 TEST(atomic_memory_smax) {
11124   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smax);
11125   AtomicMemoryStoreSignature stores[] = MAKE_STORES(smax);
11126   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smax);
11127   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smax);
11128   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smax);
11129   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smax);
11130 
11131   uint64_t arg1 = 0x8100000080108181;
11132   uint64_t arg2 = 0x0100001000100101;
11133   uint64_t expected = 0x0100001000100101;
11134 
11135   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11136   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11137   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11138   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11139 }
11140 
TEST(atomic_memory_smin)11141 TEST(atomic_memory_smin) {
11142   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smin);
11143   AtomicMemoryStoreSignature stores[] = MAKE_STORES(smin);
11144   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smin);
11145   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smin);
11146   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smin);
11147   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smin);
11148 
11149   uint64_t arg1 = 0x8100000080108181;
11150   uint64_t arg2 = 0x0100001000100101;
11151   uint64_t expected = 0x8100000080108181;
11152 
11153   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11154   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11155   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11156   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11157 }
11158 
TEST(atomic_memory_umax)11159 TEST(atomic_memory_umax) {
11160   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umax);
11161   AtomicMemoryStoreSignature stores[] = MAKE_STORES(umax);
11162   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umax);
11163   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umax);
11164   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umax);
11165   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umax);
11166 
11167   uint64_t arg1 = 0x8100000080108181;
11168   uint64_t arg2 = 0x0100001000100101;
11169   uint64_t expected = 0x8100000080108181;
11170 
11171   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11172   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11173   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11174   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11175 }
11176 
TEST(atomic_memory_umin)11177 TEST(atomic_memory_umin) {
11178   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umin);
11179   AtomicMemoryStoreSignature stores[] = MAKE_STORES(umin);
11180   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umin);
11181   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umin);
11182   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umin);
11183   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umin);
11184 
11185   uint64_t arg1 = 0x8100000080108181;
11186   uint64_t arg2 = 0x0100001000100101;
11187   uint64_t expected = 0x0100001000100101;
11188 
11189   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
11190   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
11191   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
11192   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
11193 }
11194 
TEST(atomic_memory_swp)11195 TEST(atomic_memory_swp) {
11196   AtomicMemoryLoadSignature loads[] = {&MacroAssembler::Swp,
11197                                        &MacroAssembler::Swpa,
11198                                        &MacroAssembler::Swpl,
11199                                        &MacroAssembler::Swpal};
11200   AtomicMemoryLoadSignature b_loads[] = {&MacroAssembler::Swpb,
11201                                          &MacroAssembler::Swpab,
11202                                          &MacroAssembler::Swplb,
11203                                          &MacroAssembler::Swpalb};
11204   AtomicMemoryLoadSignature h_loads[] = {&MacroAssembler::Swph,
11205                                          &MacroAssembler::Swpah,
11206                                          &MacroAssembler::Swplh,
11207                                          &MacroAssembler::Swpalh};
11208 
11209   uint64_t arg1 = 0x0100001000100101;
11210   uint64_t arg2 = 0x0200002000200202;
11211   uint64_t expected = 0x0100001000100101;
11212 
11213   // SWP functions have equivalent signatures to the Atomic Memory LD functions
11214   // so we can use the same helper but without the ST aliases.
11215   AtomicMemoryWHelper(b_loads, NULL, arg1, arg2, expected, kByteMask);
11216   AtomicMemoryWHelper(h_loads, NULL, arg1, arg2, expected, kHalfWordMask);
11217   AtomicMemoryWHelper(loads, NULL, arg1, arg2, expected, kWordMask);
11218   AtomicMemoryXHelper(loads, NULL, arg1, arg2, expected);
11219 }
11220 
11221 
TEST(ldaprb_ldaprh_ldapr)11222 TEST(ldaprb_ldaprh_ldapr) {
11223   uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11224   uint64_t data1[] = {0x1010101010101010, 0x1010101010101010};
11225   uint64_t data2[] = {0x1010101010101010, 0x1010101010101010};
11226   uint64_t data3[] = {0x1010101010101010, 0x1010101010101010};
11227 
11228   uint64_t* data0_aligned = AlignUp(data0, kXRegSizeInBytes * 2);
11229   uint64_t* data1_aligned = AlignUp(data1, kXRegSizeInBytes * 2);
11230   uint64_t* data2_aligned = AlignUp(data2, kXRegSizeInBytes * 2);
11231   uint64_t* data3_aligned = AlignUp(data3, kXRegSizeInBytes * 2);
11232 
11233   SETUP_WITH_FEATURES(CPUFeatures::kRCpc);
11234   START();
11235 
11236   __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned));
11237   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
11238   __ Mov(x22, reinterpret_cast<uintptr_t>(data2_aligned));
11239   __ Mov(x23, reinterpret_cast<uintptr_t>(data3_aligned));
11240 
11241   __ Ldaprb(w0, MemOperand(x20));
11242   __ Ldaprh(w1, MemOperand(x21));
11243   __ Ldapr(w2, MemOperand(x22));
11244   __ Ldapr(x3, MemOperand(x23));
11245 
11246   END();
11247 
11248   if (CAN_RUN()) {
11249     RUN();
11250     ASSERT_EQUAL_64(0x10, x0);
11251     ASSERT_EQUAL_64(0x1010, x1);
11252     ASSERT_EQUAL_64(0x10101010, x2);
11253     ASSERT_EQUAL_64(0x1010101010101010, x3);
11254   }
11255 }
11256 
11257 
TEST(ldapurb_ldapurh_ldapur)11258 TEST(ldapurb_ldapurh_ldapur) {
11259   uint64_t data[]
11260       __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef,
11261                                                         0xfedcba9876543210};
11262 
11263   uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
11264 
11265   SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
11266   START();
11267 
11268   __ Mov(x20, data_base);
11269   __ Mov(x21, data_base + 2 * sizeof(data[0]));
11270 
11271   __ Ldaprb(w0, MemOperand(x20));
11272   __ Ldaprh(w1, MemOperand(x20));
11273   __ Ldapr(w2, MemOperand(x20));
11274   __ Ldapr(x3, MemOperand(x20));
11275   __ Ldaprb(w4, MemOperand(x20, 12));
11276   __ Ldaprh(w5, MemOperand(x20, 8));
11277   __ Ldapr(w6, MemOperand(x20, 10));
11278   __ Ldapr(x7, MemOperand(x20, 7));
11279   __ Ldaprb(w8, MemOperand(x21, -1));
11280   __ Ldaprh(w9, MemOperand(x21, -3));
11281   __ Ldapr(w10, MemOperand(x21, -9));
11282   __ Ldapr(x11, MemOperand(x21, -12));
11283 
11284   END();
11285 
11286   if (CAN_RUN()) {
11287     RUN();
11288     ASSERT_EQUAL_64(0xef, x0);
11289     ASSERT_EQUAL_64(0xcdef, x1);
11290     ASSERT_EQUAL_64(0x89abcdef, x2);
11291     ASSERT_EQUAL_64(0x0123456789abcdef, x3);
11292     ASSERT_EQUAL_64(0x98, x4);
11293     ASSERT_EQUAL_64(0x3210, x5);
11294     ASSERT_EQUAL_64(0xba987654, x6);
11295     ASSERT_EQUAL_64(0xdcba987654321001, x7);
11296     ASSERT_EQUAL_64(0xfe, x8);
11297     ASSERT_EQUAL_64(0xdcba, x9);
11298     ASSERT_EQUAL_64(0x54321001, x10);
11299     ASSERT_EQUAL_64(0x7654321001234567, x11);
11300   }
11301 }
11302 
11303 
TEST(ldapursb_ldapursh_ldapursw)11304 TEST(ldapursb_ldapursh_ldapursw) {
11305   uint64_t data[]
11306       __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef,
11307                                                         0xfedcba9876543210};
11308 
11309   uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
11310 
11311   SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
11312   START();
11313 
11314   __ Mov(x20, data_base);
11315   __ Mov(x21, data_base + 2 * sizeof(data[0]));
11316 
11317   __ Ldapursb(w0, MemOperand(x20));
11318   __ Ldapursb(x1, MemOperand(x20));
11319   __ Ldapursh(w2, MemOperand(x20));
11320   __ Ldapursh(x3, MemOperand(x20));
11321   __ Ldapursw(x4, MemOperand(x20));
11322   __ Ldapursb(w5, MemOperand(x20, 12));
11323   __ Ldapursb(x6, MemOperand(x20, 12));
11324   __ Ldapursh(w7, MemOperand(x20, 13));
11325   __ Ldapursh(x8, MemOperand(x20, 13));
11326   __ Ldapursw(x9, MemOperand(x20, 10));
11327   __ Ldapursb(w10, MemOperand(x21, -1));
11328   __ Ldapursb(x11, MemOperand(x21, -1));
11329   __ Ldapursh(w12, MemOperand(x21, -4));
11330   __ Ldapursh(x13, MemOperand(x21, -4));
11331   __ Ldapursw(x14, MemOperand(x21, -5));
11332 
11333   __ Ldapursb(x15, MemOperand(x20, 8));
11334   __ Ldapursh(x16, MemOperand(x20, 8));
11335   __ Ldapursw(x17, MemOperand(x20, 8));
11336 
11337   END();
11338 
11339   if (CAN_RUN()) {
11340     RUN();
11341     ASSERT_EQUAL_64(0xffffffef, x0);
11342     ASSERT_EQUAL_64(0xffffffffffffffef, x1);
11343     ASSERT_EQUAL_64(0xffffcdef, x2);
11344     ASSERT_EQUAL_64(0xffffffffffffcdef, x3);
11345     ASSERT_EQUAL_64(0xffffffff89abcdef, x4);
11346     ASSERT_EQUAL_64(0xffffff98, x5);
11347     ASSERT_EQUAL_64(0xffffffffffffff98, x6);
11348     ASSERT_EQUAL_64(0xffffdcba, x7);
11349     ASSERT_EQUAL_64(0xffffffffffffdcba, x8);
11350     ASSERT_EQUAL_64(0xffffffffba987654, x9);
11351     ASSERT_EQUAL_64(0xfffffffe, x10);
11352     ASSERT_EQUAL_64(0xfffffffffffffffe, x11);
11353     ASSERT_EQUAL_64(0xffffba98, x12);
11354     ASSERT_EQUAL_64(0xffffffffffffba98, x13);
11355     ASSERT_EQUAL_64(0xffffffffdcba9876, x14);
11356 
11357     ASSERT_EQUAL_64(0x0000000000000010, x15);
11358     ASSERT_EQUAL_64(0x0000000000003210, x16);
11359     ASSERT_EQUAL_64(0x0000000076543210, x17);
11360   }
11361 }
11362 
11363 
TEST(stlurb_stlurh_strlur)11364 TEST(stlurb_stlurh_strlur) {
11365   uint64_t data[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0, 0x0};
11366 
11367   uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
11368 
11369   SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
11370   START();
11371 
11372   __ Mov(x0, 0x0011223344556677);
11373   __ Mov(x20, data_base);
11374   __ Mov(x21, data_base + 2 * sizeof(data[0]));
11375 
11376   __ Stlrb(w0, MemOperand(x20));
11377   __ Stlrh(w0, MemOperand(x20, 1));
11378   __ Stlr(w0, MemOperand(x20, 3));
11379   __ Stlr(x0, MemOperand(x21, -8));
11380 
11381   END();
11382 
11383   if (CAN_RUN()) {
11384     RUN();
11385     ASSERT_EQUAL_64(0x0044556677667777, data[0]);
11386     ASSERT_EQUAL_64(0x0011223344556677, data[1]);
11387   }
11388 }
11389 
11390 
11391 #define SIMPLE_ATOMIC_OPS(V, DEF) \
11392   V(DEF, add)                     \
11393   V(DEF, clr)                     \
11394   V(DEF, eor)                     \
11395   V(DEF, set)                     \
11396   V(DEF, smax)                    \
11397   V(DEF, smin)                    \
11398   V(DEF, umax)                    \
11399   V(DEF, umin)
11400 
11401 #define SIMPLE_ATOMIC_STORE_MODES(V, NAME) \
11402   V(NAME)                                  \
11403   V(NAME##l)
11404 
11405 #define SIMPLE_ATOMIC_LOAD_MODES(V, NAME) \
11406   SIMPLE_ATOMIC_STORE_MODES(V, NAME)      \
11407   V(NAME##a)                              \
11408   V(NAME##al)
11409 
11410 
TEST(unaligned_single_copy_atomicity)11411 TEST(unaligned_single_copy_atomicity) {
11412   uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11413   uint64_t dst[] = {0x0000000000000000, 0x0000000000000000};
11414 
11415   uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule);
11416   uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule);
11417 
11418   CPUFeatures features(CPUFeatures::kAtomics,
11419                        CPUFeatures::kLORegions,
11420                        CPUFeatures::kRCpc,
11421                        CPUFeatures::kRCpcImm);
11422   features.Combine(CPUFeatures::kUSCAT);
11423   SETUP_WITH_FEATURES(features);
11424   START();
11425 
11426   __ Mov(x0, 0x0123456789abcdef);
11427   __ Mov(x1, 0x456789abcdef0123);
11428   __ Mov(x2, 0x89abcdef01234567);
11429   __ Mov(x3, 0xcdef0123456789ab);
11430   __ Mov(x18, reinterpret_cast<uintptr_t>(data0_aligned));
11431   __ Mov(x19, reinterpret_cast<uintptr_t>(dst_aligned));
11432   __ Mov(x20, x18);
11433   __ Mov(x21, x19);
11434 
11435   for (unsigned i = 0; i < kAtomicAccessGranule; i++) {
11436     __ Stxrb(w0, w1, MemOperand(x20));
11437     __ Stlxrb(w0, w1, MemOperand(x20));
11438     __ Ldxrb(w0, MemOperand(x20));
11439     __ Ldaxrb(w0, MemOperand(x20));
11440     __ Stllrb(w0, MemOperand(x20));
11441     __ Stlrb(w0, MemOperand(x20));
11442     __ Casb(w0, w1, MemOperand(x20));
11443     __ Caslb(w0, w1, MemOperand(x20));
11444     __ Ldlarb(w0, MemOperand(x20));
11445     __ Ldarb(w0, MemOperand(x20));
11446     __ Casab(w0, w1, MemOperand(x20));
11447     __ Casalb(w0, w1, MemOperand(x20));
11448 
11449     __ Swpb(w0, w1, MemOperand(x20));
11450     __ Swplb(w0, w1, MemOperand(x20));
11451     __ Swpab(w0, w1, MemOperand(x20));
11452     __ Swpalb(w0, w1, MemOperand(x20));
11453     __ Ldaprb(w0, MemOperand(x20));
11454     // Use offset instead of Add to test Stlurb and Ldapurb.
11455     __ Stlrb(w0, MemOperand(x19, i));
11456     __ Ldaprb(w0, MemOperand(x19, i));
11457     __ Ldapursb(w0, MemOperand(x20));
11458     __ Ldapursb(x0, MemOperand(x20));
11459 
11460 #define ATOMIC_LOAD_B(NAME) __ Ld##NAME##b(w0, w1, MemOperand(x20));
11461 #define ATOMIC_STORE_B(NAME) __ St##NAME##b(w0, MemOperand(x20));
11462     SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_B)
11463     SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_B)
11464 #undef ATOMIC_LOAD_B
11465 #undef ATOMIC_STORE_B
11466 
11467     if (i <= (kAtomicAccessGranule - kHRegSizeInBytes)) {
11468       __ Stxrh(w0, w1, MemOperand(x20));
11469       __ Stlxrh(w0, w1, MemOperand(x20));
11470       __ Ldxrh(w0, MemOperand(x20));
11471       __ Ldaxrh(w0, MemOperand(x20));
11472       __ Stllrh(w0, MemOperand(x20));
11473       __ Stlrh(w0, MemOperand(x20));
11474       __ Cash(w0, w1, MemOperand(x20));
11475       __ Caslh(w0, w1, MemOperand(x20));
11476       __ Ldlarh(w0, MemOperand(x20));
11477       __ Ldarh(w0, MemOperand(x20));
11478       __ Casah(w0, w1, MemOperand(x20));
11479       __ Casalh(w0, w1, MemOperand(x20));
11480 
11481       __ Swph(w0, w1, MemOperand(x20));
11482       __ Swplh(w0, w1, MemOperand(x20));
11483       __ Swpah(w0, w1, MemOperand(x20));
11484       __ Swpalh(w0, w1, MemOperand(x20));
11485       __ Ldaprh(w0, MemOperand(x20));
11486       // Use offset instead of Add to test Stlurh and Ldapurh.
11487       __ Stlrh(w0, MemOperand(x19, i));
11488       __ Ldaprh(w0, MemOperand(x19, i));
11489       __ Ldapursh(w0, MemOperand(x20));
11490       __ Ldapursh(x0, MemOperand(x20));
11491 
11492 #define ATOMIC_LOAD_H(NAME) __ Ld##NAME##h(w0, w1, MemOperand(x20));
11493 #define ATOMIC_STORE_H(NAME) __ St##NAME##h(w0, MemOperand(x20));
11494       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H)
11495       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H)
11496 #undef ATOMIC_LOAD_H
11497 #undef ATOMIC_STORE_H
11498     }
11499 
11500     if (i <= (kAtomicAccessGranule - kWRegSizeInBytes)) {
11501       __ Stxr(w0, w1, MemOperand(x20));
11502       __ Stlxr(w0, w1, MemOperand(x20));
11503       __ Ldxr(w0, MemOperand(x20));
11504       __ Ldaxr(w0, MemOperand(x20));
11505       __ Stllr(w0, MemOperand(x20));
11506       __ Stlr(w0, MemOperand(x20));
11507       __ Cas(w0, w1, MemOperand(x20));
11508       __ Casl(w0, w1, MemOperand(x20));
11509       __ Ldlar(w0, MemOperand(x20));
11510       __ Ldar(w0, MemOperand(x20));
11511       __ Casa(w0, w1, MemOperand(x20));
11512       __ Casal(w0, w1, MemOperand(x20));
11513 
11514       __ Swp(w0, w1, MemOperand(x20));
11515       __ Swpl(w0, w1, MemOperand(x20));
11516       __ Swpa(w0, w1, MemOperand(x20));
11517       __ Swpal(w0, w1, MemOperand(x20));
11518       __ Ldapr(w0, MemOperand(x20));
11519       // Use offset instead of Add to test Stlur and Ldapur.
11520       __ Stlr(w0, MemOperand(x19, i));
11521       __ Ldapr(w0, MemOperand(x19, i));
11522       __ Ldapursw(x0, MemOperand(x20));
11523 
11524 #define ATOMIC_LOAD_W(NAME) __ Ld##NAME(w0, w1, MemOperand(x20));
11525 #define ATOMIC_STORE_W(NAME) __ St##NAME(w0, MemOperand(x20));
11526       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W)
11527       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W)
11528 #undef ATOMIC_LOAD_W
11529 #undef ATOMIC_STORE_W
11530     }
11531 
11532     if (i <= (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) {
11533       __ Casp(w0, w1, w2, w3, MemOperand(x20));
11534       __ Caspl(w0, w1, w2, w3, MemOperand(x20));
11535       __ Caspa(w0, w1, w2, w3, MemOperand(x20));
11536       __ Caspal(w0, w1, w2, w3, MemOperand(x20));
11537       __ Stxp(w0, w1, w2, MemOperand(x20));
11538       __ Stlxp(w0, w1, w2, MemOperand(x20));
11539       __ Ldxp(w0, w1, MemOperand(x20));
11540       __ Ldaxp(w0, w1, MemOperand(x20));
11541     }
11542 
11543     if (i <= (kAtomicAccessGranule - kXRegSizeInBytes)) {
11544       __ Stxr(x0, x1, MemOperand(x20));
11545       __ Stlxr(x0, x1, MemOperand(x20));
11546       __ Ldxr(x0, MemOperand(x20));
11547       __ Ldaxr(x0, MemOperand(x20));
11548       __ Stllr(x0, MemOperand(x20));
11549       __ Stlr(x0, MemOperand(x20));
11550       __ Cas(x0, x1, MemOperand(x20));
11551       __ Casl(x0, x1, MemOperand(x20));
11552       __ Ldlar(x0, MemOperand(x20));
11553       __ Ldar(x0, MemOperand(x20));
11554       __ Casa(x0, x1, MemOperand(x20));
11555       __ Casal(x0, x1, MemOperand(x20));
11556 
11557       __ Swp(x0, x1, MemOperand(x20));
11558       __ Swpl(x0, x1, MemOperand(x20));
11559       __ Swpa(x0, x1, MemOperand(x20));
11560       __ Swpal(x0, x1, MemOperand(x20));
11561       __ Ldapr(x0, MemOperand(x20));
11562       // Use offset instead of Add to test Stlur and Ldapur.
11563       __ Stlr(x0, MemOperand(x19, i));
11564       __ Ldapr(x0, MemOperand(x19, i));
11565 
11566 #define ATOMIC_LOAD_X(NAME) __ Ld##NAME(x0, x1, MemOperand(x20));
11567 #define ATOMIC_STORE_X(NAME) __ St##NAME(x0, MemOperand(x20));
11568       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X)
11569       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X)
11570 #undef ATOMIC_LOAD_X
11571 #undef ATOMIC_STORE_X
11572     }
11573 
11574     if (i <= (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) {
11575       __ Casp(x0, x1, x2, x3, MemOperand(x20));
11576       __ Caspl(x0, x1, x2, x3, MemOperand(x20));
11577       __ Caspa(x0, x1, x2, x3, MemOperand(x20));
11578       __ Caspal(x0, x1, x2, x3, MemOperand(x20));
11579       __ Stxp(x0, x1, x2, MemOperand(x20));
11580       __ Stlxp(x0, x1, x2, MemOperand(x20));
11581       __ Ldxp(x0, x1, MemOperand(x20));
11582       __ Ldaxp(x0, x1, MemOperand(x20));
11583     }
11584 
11585     __ Add(x20, x20, 1);
11586     __ Add(x21, x21, 1);
11587   }
11588   END();
11589 
11590   if (CAN_RUN()) {
11591     // We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the seen
11592     // check.
11593     RUN_WITHOUT_SEEN_FEATURE_CHECK();
11594   }
11595 }
11596 
11597 
11598 #if defined(VIXL_NEGATIVE_TESTING) && defined(VIXL_INCLUDE_SIMULATOR_AARCH64)
11599 
11600 #define CHECK_ALIGN_FAIL(i, expr)                                              \
11601   {                                                                            \
11602     CPUFeatures features(CPUFeatures::kAtomics,                                \
11603                          CPUFeatures::kLORegions,                              \
11604                          CPUFeatures::kRCpc,                                   \
11605                          CPUFeatures::kRCpcImm);                               \
11606     features.Combine(CPUFeatures::kUSCAT);                                     \
11607     SETUP_WITH_FEATURES(features);                                             \
11608     START();                                                                   \
11609     __ Mov(x0, 0x0123456789abcdef);                                            \
11610     __ Mov(x1, 0x456789abcdef0123);                                            \
11611     __ Mov(x2, 0x89abcdef01234567);                                            \
11612     __ Mov(x3, 0xcdef0123456789ab);                                            \
11613     __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned));                   \
11614     __ Mov(x21, reinterpret_cast<uintptr_t>(dst_aligned));                     \
11615     __ Add(x20, x20, i);                                                       \
11616     __ Add(x21, x21, i);                                                       \
11617     expr;                                                                      \
11618     END();                                                                     \
11619     if (CAN_RUN()) {                                                           \
11620       /* We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the */ \
11621       /* seen check. */                                                        \
11622       MUST_FAIL_WITH_MESSAGE(RUN_WITHOUT_SEEN_FEATURE_CHECK(),                 \
11623                              "ALIGNMENT EXCEPTION");                           \
11624     }                                                                          \
11625   }
11626 
TEST(unaligned_single_copy_atomicity_negative_test)11627 TEST(unaligned_single_copy_atomicity_negative_test) {
11628   uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11629   uint64_t dst[] = {0x0000000000000000, 0x0000000000000000};
11630 
11631   uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule);
11632   uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule);
11633 
11634   for (unsigned i = 0; i < kAtomicAccessGranule; i++) {
11635     if (i > (kAtomicAccessGranule - kHRegSizeInBytes)) {
11636       CHECK_ALIGN_FAIL(i, __ Stxrh(w0, w1, MemOperand(x20)));
11637       CHECK_ALIGN_FAIL(i, __ Stlxrh(w0, w1, MemOperand(x20)));
11638       CHECK_ALIGN_FAIL(i, __ Ldxrh(w0, MemOperand(x20)));
11639       CHECK_ALIGN_FAIL(i, __ Ldaxrh(w0, MemOperand(x20)));
11640       CHECK_ALIGN_FAIL(i, __ Stllrh(w0, MemOperand(x20)));
11641       CHECK_ALIGN_FAIL(i, __ Stlrh(w0, MemOperand(x20)));
11642       CHECK_ALIGN_FAIL(i, __ Cash(w0, w1, MemOperand(x20)));
11643       CHECK_ALIGN_FAIL(i, __ Caslh(w0, w1, MemOperand(x20)));
11644       CHECK_ALIGN_FAIL(i, __ Ldlarh(w0, MemOperand(x20)));
11645       CHECK_ALIGN_FAIL(i, __ Ldarh(w0, MemOperand(x20)));
11646       CHECK_ALIGN_FAIL(i, __ Casah(w0, w1, MemOperand(x20)));
11647       CHECK_ALIGN_FAIL(i, __ Casalh(w0, w1, MemOperand(x20)));
11648 
11649       CHECK_ALIGN_FAIL(i, __ Swph(w0, w1, MemOperand(x20)));
11650       CHECK_ALIGN_FAIL(i, __ Swplh(w0, w1, MemOperand(x20)));
11651       CHECK_ALIGN_FAIL(i, __ Swpah(w0, w1, MemOperand(x20)));
11652       CHECK_ALIGN_FAIL(i, __ Swpalh(w0, w1, MemOperand(x20)));
11653       CHECK_ALIGN_FAIL(i, __ Ldaprh(w0, MemOperand(x20)));
11654       // Use offset instead of Add to test Stlurh and Ldapurh.
11655       CHECK_ALIGN_FAIL(0, __ Stlrh(w0, MemOperand(x20, i)));
11656       CHECK_ALIGN_FAIL(0, __ Ldaprh(w0, MemOperand(x20, i)));
11657       CHECK_ALIGN_FAIL(i, __ Ldapursh(w0, MemOperand(x20)));
11658       CHECK_ALIGN_FAIL(i, __ Ldapursh(x0, MemOperand(x20)));
11659 
11660 #define ATOMIC_LOAD_H(NAME) \
11661   CHECK_ALIGN_FAIL(i, __ Ld##NAME##h(w0, w1, MemOperand(x20)));
11662 #define ATOMIC_STORE_H(NAME) \
11663   CHECK_ALIGN_FAIL(i, __ St##NAME##h(w0, MemOperand(x20)));
11664       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H)
11665       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H)
11666 #undef ATOMIC_LOAD_H
11667 #undef ATOMIC_STORE_H
11668     }
11669 
11670     if (i > (kAtomicAccessGranule - kWRegSizeInBytes)) {
11671       CHECK_ALIGN_FAIL(i, __ Stxr(w0, w1, MemOperand(x20)));
11672       CHECK_ALIGN_FAIL(i, __ Stlxr(w0, w1, MemOperand(x20)));
11673       CHECK_ALIGN_FAIL(i, __ Ldxr(w0, MemOperand(x20)));
11674       CHECK_ALIGN_FAIL(i, __ Ldaxr(w0, MemOperand(x20)));
11675       CHECK_ALIGN_FAIL(i, __ Stllr(w0, MemOperand(x20)));
11676       CHECK_ALIGN_FAIL(i, __ Stlr(w0, MemOperand(x20)));
11677       CHECK_ALIGN_FAIL(i, __ Cas(w0, w1, MemOperand(x20)));
11678       CHECK_ALIGN_FAIL(i, __ Casl(w0, w1, MemOperand(x20)));
11679       CHECK_ALIGN_FAIL(i, __ Ldlar(w0, MemOperand(x20)));
11680       CHECK_ALIGN_FAIL(i, __ Ldar(w0, MemOperand(x20)));
11681       CHECK_ALIGN_FAIL(i, __ Casa(w0, w1, MemOperand(x20)));
11682       CHECK_ALIGN_FAIL(i, __ Casal(w0, w1, MemOperand(x20)));
11683 
11684       CHECK_ALIGN_FAIL(i, __ Swp(w0, w1, MemOperand(x20)));
11685       CHECK_ALIGN_FAIL(i, __ Swpl(w0, w1, MemOperand(x20)));
11686       CHECK_ALIGN_FAIL(i, __ Swpa(w0, w1, MemOperand(x20)));
11687       CHECK_ALIGN_FAIL(i, __ Swpal(w0, w1, MemOperand(x20)));
11688       CHECK_ALIGN_FAIL(i, __ Ldapr(w0, MemOperand(x20)));
11689       // Use offset instead of add to test Stlur and Ldapur.
11690       CHECK_ALIGN_FAIL(0, __ Stlr(w0, MemOperand(x20, i)));
11691       CHECK_ALIGN_FAIL(0, __ Ldapr(w0, MemOperand(x20, i)));
11692       CHECK_ALIGN_FAIL(i, __ Ldapursw(x0, MemOperand(x20)));
11693 
11694 #define ATOMIC_LOAD_W(NAME) \
11695   CHECK_ALIGN_FAIL(i, __ Ld##NAME(w0, w1, MemOperand(x20)));
11696 #define ATOMIC_STORE_W(NAME) \
11697   CHECK_ALIGN_FAIL(i, __ St##NAME(w0, MemOperand(x20)));
11698       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W)
11699       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W)
11700 #undef ATOMIC_LOAD_W
11701 #undef ATOMIC_STORE_W
11702     }
11703 
11704     if (i > (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) {
11705       CHECK_ALIGN_FAIL(i, __ Casp(w0, w1, w2, w3, MemOperand(x20)));
11706       CHECK_ALIGN_FAIL(i, __ Caspl(w0, w1, w2, w3, MemOperand(x20)));
11707       CHECK_ALIGN_FAIL(i, __ Caspa(w0, w1, w2, w3, MemOperand(x20)));
11708       CHECK_ALIGN_FAIL(i, __ Caspal(w0, w1, w2, w3, MemOperand(x20)));
11709       CHECK_ALIGN_FAIL(i, __ Stxp(w0, w1, w2, MemOperand(x20)));
11710       CHECK_ALIGN_FAIL(i, __ Stlxp(w0, w1, w2, MemOperand(x20)));
11711       CHECK_ALIGN_FAIL(i, __ Ldxp(w0, w1, MemOperand(x20)));
11712       CHECK_ALIGN_FAIL(i, __ Ldaxp(w0, w1, MemOperand(x20)));
11713     }
11714 
11715     if (i > (kAtomicAccessGranule - kXRegSizeInBytes)) {
11716       CHECK_ALIGN_FAIL(i, __ Stxr(x0, x1, MemOperand(x20)));
11717       CHECK_ALIGN_FAIL(i, __ Stlxr(x0, x1, MemOperand(x20)));
11718       CHECK_ALIGN_FAIL(i, __ Ldxr(x0, MemOperand(x20)));
11719       CHECK_ALIGN_FAIL(i, __ Ldaxr(x0, MemOperand(x20)));
11720       CHECK_ALIGN_FAIL(i, __ Stllr(x0, MemOperand(x20)));
11721       CHECK_ALIGN_FAIL(i, __ Stlr(x0, MemOperand(x20)));
11722       CHECK_ALIGN_FAIL(i, __ Cas(x0, x1, MemOperand(x20)));
11723       CHECK_ALIGN_FAIL(i, __ Casl(x0, x1, MemOperand(x20)));
11724       CHECK_ALIGN_FAIL(i, __ Ldlar(x0, MemOperand(x20)));
11725       CHECK_ALIGN_FAIL(i, __ Ldar(x0, MemOperand(x20)));
11726       CHECK_ALIGN_FAIL(i, __ Casa(x0, x1, MemOperand(x20)));
11727       CHECK_ALIGN_FAIL(i, __ Casal(x0, x1, MemOperand(x20)));
11728 
11729       CHECK_ALIGN_FAIL(i, __ Swp(x0, x1, MemOperand(x20)));
11730       CHECK_ALIGN_FAIL(i, __ Swpl(x0, x1, MemOperand(x20)));
11731       CHECK_ALIGN_FAIL(i, __ Swpa(x0, x1, MemOperand(x20)));
11732       CHECK_ALIGN_FAIL(i, __ Swpal(x0, x1, MemOperand(x20)));
11733       CHECK_ALIGN_FAIL(i, __ Ldapr(x0, MemOperand(x20)));
11734       // Use offset instead of add to test Stlur and Ldapur.
11735       CHECK_ALIGN_FAIL(0, __ Stlr(x0, MemOperand(x20, i)));
11736       CHECK_ALIGN_FAIL(0, __ Ldapr(x0, MemOperand(x20, i)));
11737 
11738 #define ATOMIC_LOAD_X(NAME) \
11739   CHECK_ALIGN_FAIL(i, __ Ld##NAME(x0, x1, MemOperand(x20)));
11740 #define ATOMIC_STORE_X(NAME) \
11741   CHECK_ALIGN_FAIL(i, __ St##NAME(x0, MemOperand(x20)));
11742       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X)
11743       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X)
11744 #undef ATOMIC_LOAD_X
11745 #undef ATOMIC_STORE_X
11746     }
11747 
11748     if (i > (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) {
11749       CHECK_ALIGN_FAIL(i, __ Casp(x0, x1, x2, x3, MemOperand(x20)));
11750       CHECK_ALIGN_FAIL(i, __ Caspl(x0, x1, x2, x3, MemOperand(x20)));
11751       CHECK_ALIGN_FAIL(i, __ Caspa(x0, x1, x2, x3, MemOperand(x20)));
11752       CHECK_ALIGN_FAIL(i, __ Caspal(x0, x1, x2, x3, MemOperand(x20)));
11753       CHECK_ALIGN_FAIL(i, __ Stxp(x0, x1, x2, MemOperand(x20)));
11754       CHECK_ALIGN_FAIL(i, __ Stlxp(x0, x1, x2, MemOperand(x20)));
11755       CHECK_ALIGN_FAIL(i, __ Ldxp(x0, x1, MemOperand(x20)));
11756       CHECK_ALIGN_FAIL(i, __ Ldaxp(x0, x1, MemOperand(x20)));
11757     }
11758   }
11759 }
11760 
TEST(unaligned_single_copy_atomicity_negative_test_2)11761 TEST(unaligned_single_copy_atomicity_negative_test_2) {
11762   uint64_t data[] = {0x1010101010101010, 0x1010101010101010};
11763 
11764   uint64_t* data_aligned = AlignUp(data, kAtomicAccessGranule);
11765 
11766   // Check that the same code doesn't fail with USCAT enabled but does
11767   // fail when not enabled.
11768   {
11769     SETUP_WITH_FEATURES(CPUFeatures::kUSCAT);
11770     START();
11771     __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned));
11772     __ Add(x0, x0, 1);
11773     __ Ldxrh(w1, MemOperand(x0));
11774     END();
11775     if (CAN_RUN()) {
11776       RUN_WITHOUT_SEEN_FEATURE_CHECK();
11777     }
11778   }
11779   {
11780     SETUP();
11781     START();
11782     __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned));
11783     __ Add(x0, x0, 1);
11784     __ Ldxrh(w1, MemOperand(x0));
11785     END();
11786     if (CAN_RUN()) {
11787       MUST_FAIL_WITH_MESSAGE(RUN(), "ALIGNMENT EXCEPTION");
11788     }
11789   }
11790 }
11791 #endif  // VIXL_NEGATIVE_TESTING && VIXL_INCLUDE_SIMULATOR_AARCH64
11792 
11793 
TEST(load_store_tagged_immediate_offset)11794 TEST(load_store_tagged_immediate_offset) {
11795   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11796   int tag_count = sizeof(tags) / sizeof(tags[0]);
11797 
11798   const int kMaxDataLength = 160;
11799 
11800   for (int i = 0; i < tag_count; i++) {
11801     unsigned char src[kMaxDataLength];
11802     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11803     uint64_t src_tag = tags[i];
11804     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11805 
11806     for (int k = 0; k < kMaxDataLength; k++) {
11807       src[k] = k + 1;
11808     }
11809 
11810     for (int j = 0; j < tag_count; j++) {
11811       unsigned char dst[kMaxDataLength];
11812       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11813       uint64_t dst_tag = tags[j];
11814       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11815 
11816       memset(dst, 0, kMaxDataLength);
11817 
11818       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11819       START();
11820 
11821       __ Mov(x0, src_tagged);
11822       __ Mov(x1, dst_tagged);
11823 
11824       int offset = 0;
11825 
11826       // Scaled-immediate offsets.
11827       {
11828         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11829         __ ldp(q0, q1, MemOperand(x0, offset));
11830         __ stp(q0, q1, MemOperand(x1, offset));
11831       }
11832       offset += 2 * kQRegSizeInBytes;
11833 
11834       {
11835         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11836         __ ldp(x2, x3, MemOperand(x0, offset));
11837         __ stp(x2, x3, MemOperand(x1, offset));
11838       }
11839       offset += 2 * kXRegSizeInBytes;
11840 
11841       {
11842         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11843         __ ldpsw(x2, x3, MemOperand(x0, offset));
11844         __ stp(w2, w3, MemOperand(x1, offset));
11845       }
11846       offset += 2 * kWRegSizeInBytes;
11847 
11848       {
11849         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11850         __ ldp(d0, d1, MemOperand(x0, offset));
11851         __ stp(d0, d1, MemOperand(x1, offset));
11852       }
11853       offset += 2 * kDRegSizeInBytes;
11854 
11855       {
11856         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11857         __ ldp(w2, w3, MemOperand(x0, offset));
11858         __ stp(w2, w3, MemOperand(x1, offset));
11859       }
11860       offset += 2 * kWRegSizeInBytes;
11861 
11862       {
11863         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11864         __ ldp(s0, s1, MemOperand(x0, offset));
11865         __ stp(s0, s1, MemOperand(x1, offset));
11866       }
11867       offset += 2 * kSRegSizeInBytes;
11868 
11869       {
11870         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11871         __ ldr(x2, MemOperand(x0, offset), RequireScaledOffset);
11872         __ str(x2, MemOperand(x1, offset), RequireScaledOffset);
11873       }
11874       offset += kXRegSizeInBytes;
11875 
11876       {
11877         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11878         __ ldr(d0, MemOperand(x0, offset), RequireScaledOffset);
11879         __ str(d0, MemOperand(x1, offset), RequireScaledOffset);
11880       }
11881       offset += kDRegSizeInBytes;
11882 
11883       {
11884         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11885         __ ldr(w2, MemOperand(x0, offset), RequireScaledOffset);
11886         __ str(w2, MemOperand(x1, offset), RequireScaledOffset);
11887       }
11888       offset += kWRegSizeInBytes;
11889 
11890       {
11891         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11892         __ ldr(s0, MemOperand(x0, offset), RequireScaledOffset);
11893         __ str(s0, MemOperand(x1, offset), RequireScaledOffset);
11894       }
11895       offset += kSRegSizeInBytes;
11896 
11897       {
11898         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11899         __ ldrh(w2, MemOperand(x0, offset), RequireScaledOffset);
11900         __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11901       }
11902       offset += 2;
11903 
11904       {
11905         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11906         __ ldrsh(w2, MemOperand(x0, offset), RequireScaledOffset);
11907         __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11908       }
11909       offset += 2;
11910 
11911       {
11912         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11913         __ ldrb(w2, MemOperand(x0, offset), RequireScaledOffset);
11914         __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11915       }
11916       offset += 1;
11917 
11918       {
11919         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11920         __ ldrsb(w2, MemOperand(x0, offset), RequireScaledOffset);
11921         __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11922       }
11923       offset += 1;
11924 
11925       // Unscaled-immediate offsets.
11926 
11927       {
11928         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11929         __ ldur(x2, MemOperand(x0, offset), RequireUnscaledOffset);
11930         __ stur(x2, MemOperand(x1, offset), RequireUnscaledOffset);
11931       }
11932       offset += kXRegSizeInBytes;
11933 
11934       {
11935         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11936         __ ldur(d0, MemOperand(x0, offset), RequireUnscaledOffset);
11937         __ stur(d0, MemOperand(x1, offset), RequireUnscaledOffset);
11938       }
11939       offset += kDRegSizeInBytes;
11940 
11941       {
11942         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11943         __ ldur(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11944         __ stur(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11945       }
11946       offset += kWRegSizeInBytes;
11947 
11948       {
11949         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11950         __ ldur(s0, MemOperand(x0, offset), RequireUnscaledOffset);
11951         __ stur(s0, MemOperand(x1, offset), RequireUnscaledOffset);
11952       }
11953       offset += kSRegSizeInBytes;
11954 
11955       {
11956         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11957         __ ldurh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11958         __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11959       }
11960       offset += 2;
11961 
11962       {
11963         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11964         __ ldursh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11965         __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11966       }
11967       offset += 2;
11968 
11969       {
11970         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11971         __ ldurb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11972         __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11973       }
11974       offset += 1;
11975 
11976       {
11977         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11978         __ ldursb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11979         __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11980       }
11981       offset += 1;
11982 
11983       // Extract the tag (so we can test that it was preserved correctly).
11984       __ Ubfx(x0, x0, kAddressTagOffset, kAddressTagWidth);
11985       __ Ubfx(x1, x1, kAddressTagOffset, kAddressTagWidth);
11986 
11987       VIXL_ASSERT(kMaxDataLength >= offset);
11988 
11989       END();
11990       if (CAN_RUN()) {
11991         RUN();
11992 
11993         ASSERT_EQUAL_64(src_tag, x0);
11994         ASSERT_EQUAL_64(dst_tag, x1);
11995 
11996         for (int k = 0; k < offset; k++) {
11997           VIXL_CHECK(src[k] == dst[k]);
11998         }
11999       }
12000     }
12001   }
12002 }
12003 
12004 
TEST(load_store_tagged_immediate_preindex)12005 TEST(load_store_tagged_immediate_preindex) {
12006   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12007   int tag_count = sizeof(tags) / sizeof(tags[0]);
12008 
12009   const int kMaxDataLength = 128;
12010 
12011   for (int i = 0; i < tag_count; i++) {
12012     unsigned char src[kMaxDataLength];
12013     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
12014     uint64_t src_tag = tags[i];
12015     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
12016 
12017     for (int k = 0; k < kMaxDataLength; k++) {
12018       src[k] = k + 1;
12019     }
12020 
12021     for (int j = 0; j < tag_count; j++) {
12022       unsigned char dst[kMaxDataLength];
12023       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
12024       uint64_t dst_tag = tags[j];
12025       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
12026 
12027       for (int k = 0; k < kMaxDataLength; k++) {
12028         dst[k] = 0;
12029       }
12030 
12031       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12032       START();
12033 
12034       // Each MemOperand must apply a pre-index equal to the size of the
12035       // previous access.
12036 
12037       // Start with a non-zero preindex.
12038       int preindex = 62 * kXRegSizeInBytes;
12039       int data_length = 0;
12040 
12041       __ Mov(x0, src_tagged - preindex);
12042       __ Mov(x1, dst_tagged - preindex);
12043 
12044       {
12045         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12046         __ ldp(q0, q1, MemOperand(x0, preindex, PreIndex));
12047         __ stp(q0, q1, MemOperand(x1, preindex, PreIndex));
12048       }
12049       preindex = 2 * kQRegSizeInBytes;
12050       data_length = preindex;
12051 
12052       {
12053         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12054         __ ldp(x2, x3, MemOperand(x0, preindex, PreIndex));
12055         __ stp(x2, x3, MemOperand(x1, preindex, PreIndex));
12056       }
12057       preindex = 2 * kXRegSizeInBytes;
12058       data_length += preindex;
12059 
12060       {
12061         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12062         __ ldpsw(x2, x3, MemOperand(x0, preindex, PreIndex));
12063         __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
12064       }
12065       preindex = 2 * kWRegSizeInBytes;
12066       data_length += preindex;
12067 
12068       {
12069         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12070         __ ldp(d0, d1, MemOperand(x0, preindex, PreIndex));
12071         __ stp(d0, d1, MemOperand(x1, preindex, PreIndex));
12072       }
12073       preindex = 2 * kDRegSizeInBytes;
12074       data_length += preindex;
12075 
12076       {
12077         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12078         __ ldp(w2, w3, MemOperand(x0, preindex, PreIndex));
12079         __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
12080       }
12081       preindex = 2 * kWRegSizeInBytes;
12082       data_length += preindex;
12083 
12084       {
12085         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12086         __ ldp(s0, s1, MemOperand(x0, preindex, PreIndex));
12087         __ stp(s0, s1, MemOperand(x1, preindex, PreIndex));
12088       }
12089       preindex = 2 * kSRegSizeInBytes;
12090       data_length += preindex;
12091 
12092       {
12093         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12094         __ ldr(x2, MemOperand(x0, preindex, PreIndex));
12095         __ str(x2, MemOperand(x1, preindex, PreIndex));
12096       }
12097       preindex = kXRegSizeInBytes;
12098       data_length += preindex;
12099 
12100       {
12101         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12102         __ ldr(d0, MemOperand(x0, preindex, PreIndex));
12103         __ str(d0, MemOperand(x1, preindex, PreIndex));
12104       }
12105       preindex = kDRegSizeInBytes;
12106       data_length += preindex;
12107 
12108       {
12109         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12110         __ ldr(w2, MemOperand(x0, preindex, PreIndex));
12111         __ str(w2, MemOperand(x1, preindex, PreIndex));
12112       }
12113       preindex = kWRegSizeInBytes;
12114       data_length += preindex;
12115 
12116       {
12117         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12118         __ ldr(s0, MemOperand(x0, preindex, PreIndex));
12119         __ str(s0, MemOperand(x1, preindex, PreIndex));
12120       }
12121       preindex = kSRegSizeInBytes;
12122       data_length += preindex;
12123 
12124       {
12125         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12126         __ ldrh(w2, MemOperand(x0, preindex, PreIndex));
12127         __ strh(w2, MemOperand(x1, preindex, PreIndex));
12128       }
12129       preindex = 2;
12130       data_length += preindex;
12131 
12132       {
12133         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12134         __ ldrsh(w2, MemOperand(x0, preindex, PreIndex));
12135         __ strh(w2, MemOperand(x1, preindex, PreIndex));
12136       }
12137       preindex = 2;
12138       data_length += preindex;
12139 
12140       {
12141         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12142         __ ldrb(w2, MemOperand(x0, preindex, PreIndex));
12143         __ strb(w2, MemOperand(x1, preindex, PreIndex));
12144       }
12145       preindex = 1;
12146       data_length += preindex;
12147 
12148       {
12149         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12150         __ ldrsb(w2, MemOperand(x0, preindex, PreIndex));
12151         __ strb(w2, MemOperand(x1, preindex, PreIndex));
12152       }
12153       preindex = 1;
12154       data_length += preindex;
12155 
12156       VIXL_ASSERT(kMaxDataLength >= data_length);
12157 
12158       END();
12159       if (CAN_RUN()) {
12160         RUN();
12161 
12162         // Check that the preindex was correctly applied in each operation, and
12163         // that the tag was preserved.
12164         ASSERT_EQUAL_64(src_tagged + data_length - preindex, x0);
12165         ASSERT_EQUAL_64(dst_tagged + data_length - preindex, x1);
12166 
12167         for (int k = 0; k < data_length; k++) {
12168           VIXL_CHECK(src[k] == dst[k]);
12169         }
12170       }
12171     }
12172   }
12173 }
12174 
12175 
TEST(load_store_tagged_immediate_postindex)12176 TEST(load_store_tagged_immediate_postindex) {
12177   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12178   int tag_count = sizeof(tags) / sizeof(tags[0]);
12179 
12180   const int kMaxDataLength = 128;
12181 
12182   for (int i = 0; i < tag_count; i++) {
12183     unsigned char src[kMaxDataLength];
12184     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
12185     uint64_t src_tag = tags[i];
12186     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
12187 
12188     for (int k = 0; k < kMaxDataLength; k++) {
12189       src[k] = k + 1;
12190     }
12191 
12192     for (int j = 0; j < tag_count; j++) {
12193       unsigned char dst[kMaxDataLength];
12194       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
12195       uint64_t dst_tag = tags[j];
12196       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
12197 
12198       for (int k = 0; k < kMaxDataLength; k++) {
12199         dst[k] = 0;
12200       }
12201 
12202       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12203       START();
12204 
12205       int postindex = 2 * kXRegSizeInBytes;
12206       int data_length = 0;
12207 
12208       __ Mov(x0, src_tagged);
12209       __ Mov(x1, dst_tagged);
12210 
12211       {
12212         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12213         __ ldp(x2, x3, MemOperand(x0, postindex, PostIndex));
12214         __ stp(x2, x3, MemOperand(x1, postindex, PostIndex));
12215       }
12216       data_length = postindex;
12217 
12218       postindex = 2 * kQRegSizeInBytes;
12219       {
12220         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12221         __ ldp(q0, q1, MemOperand(x0, postindex, PostIndex));
12222         __ stp(q0, q1, MemOperand(x1, postindex, PostIndex));
12223       }
12224       data_length += postindex;
12225 
12226       postindex = 2 * kWRegSizeInBytes;
12227       {
12228         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12229         __ ldpsw(x2, x3, MemOperand(x0, postindex, PostIndex));
12230         __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
12231       }
12232       data_length += postindex;
12233 
12234       postindex = 2 * kDRegSizeInBytes;
12235       {
12236         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12237         __ ldp(d0, d1, MemOperand(x0, postindex, PostIndex));
12238         __ stp(d0, d1, MemOperand(x1, postindex, PostIndex));
12239       }
12240       data_length += postindex;
12241 
12242       postindex = 2 * kWRegSizeInBytes;
12243       {
12244         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12245         __ ldp(w2, w3, MemOperand(x0, postindex, PostIndex));
12246         __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
12247       }
12248       data_length += postindex;
12249 
12250       postindex = 2 * kSRegSizeInBytes;
12251       {
12252         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12253         __ ldp(s0, s1, MemOperand(x0, postindex, PostIndex));
12254         __ stp(s0, s1, MemOperand(x1, postindex, PostIndex));
12255       }
12256       data_length += postindex;
12257 
12258       postindex = kXRegSizeInBytes;
12259       {
12260         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12261         __ ldr(x2, MemOperand(x0, postindex, PostIndex));
12262         __ str(x2, MemOperand(x1, postindex, PostIndex));
12263       }
12264       data_length += postindex;
12265 
12266       postindex = kDRegSizeInBytes;
12267       {
12268         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12269         __ ldr(d0, MemOperand(x0, postindex, PostIndex));
12270         __ str(d0, MemOperand(x1, postindex, PostIndex));
12271       }
12272       data_length += postindex;
12273 
12274       postindex = kWRegSizeInBytes;
12275       {
12276         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12277         __ ldr(w2, MemOperand(x0, postindex, PostIndex));
12278         __ str(w2, MemOperand(x1, postindex, PostIndex));
12279       }
12280       data_length += postindex;
12281 
12282       postindex = kSRegSizeInBytes;
12283       {
12284         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12285         __ ldr(s0, MemOperand(x0, postindex, PostIndex));
12286         __ str(s0, MemOperand(x1, postindex, PostIndex));
12287       }
12288       data_length += postindex;
12289 
12290       postindex = 2;
12291       {
12292         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12293         __ ldrh(w2, MemOperand(x0, postindex, PostIndex));
12294         __ strh(w2, MemOperand(x1, postindex, PostIndex));
12295       }
12296       data_length += postindex;
12297 
12298       postindex = 2;
12299       {
12300         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12301         __ ldrsh(w2, MemOperand(x0, postindex, PostIndex));
12302         __ strh(w2, MemOperand(x1, postindex, PostIndex));
12303       }
12304       data_length += postindex;
12305 
12306       postindex = 1;
12307       {
12308         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12309         __ ldrb(w2, MemOperand(x0, postindex, PostIndex));
12310         __ strb(w2, MemOperand(x1, postindex, PostIndex));
12311       }
12312       data_length += postindex;
12313 
12314       postindex = 1;
12315       {
12316         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12317         __ ldrsb(w2, MemOperand(x0, postindex, PostIndex));
12318         __ strb(w2, MemOperand(x1, postindex, PostIndex));
12319       }
12320       data_length += postindex;
12321 
12322       VIXL_ASSERT(kMaxDataLength >= data_length);
12323 
12324       END();
12325       if (CAN_RUN()) {
12326         RUN();
12327 
12328         // Check that the postindex was correctly applied in each operation, and
12329         // that the tag was preserved.
12330         ASSERT_EQUAL_64(src_tagged + data_length, x0);
12331         ASSERT_EQUAL_64(dst_tagged + data_length, x1);
12332 
12333         for (int k = 0; k < data_length; k++) {
12334           VIXL_CHECK(src[k] == dst[k]);
12335         }
12336       }
12337     }
12338   }
12339 }
12340 
12341 
TEST(load_store_tagged_register_offset)12342 TEST(load_store_tagged_register_offset) {
12343   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12344   int tag_count = sizeof(tags) / sizeof(tags[0]);
12345 
12346   const int kMaxDataLength = 128;
12347 
12348   for (int i = 0; i < tag_count; i++) {
12349     unsigned char src[kMaxDataLength];
12350     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
12351     uint64_t src_tag = tags[i];
12352     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
12353 
12354     for (int k = 0; k < kMaxDataLength; k++) {
12355       src[k] = k + 1;
12356     }
12357 
12358     for (int j = 0; j < tag_count; j++) {
12359       unsigned char dst[kMaxDataLength];
12360       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
12361       uint64_t dst_tag = tags[j];
12362       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
12363 
12364       // Also tag the offset register; the operation should still succeed.
12365       for (int o = 0; o < tag_count; o++) {
12366         uint64_t offset_base = CPU::SetPointerTag(UINT64_C(0), tags[o]);
12367         int data_length = 0;
12368 
12369         for (int k = 0; k < kMaxDataLength; k++) {
12370           dst[k] = 0;
12371         }
12372 
12373         SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12374         START();
12375 
12376         __ Mov(x0, src_tagged);
12377         __ Mov(x1, dst_tagged);
12378 
12379         __ Mov(x10, offset_base + data_length);
12380         {
12381           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12382           __ ldr(x2, MemOperand(x0, x10));
12383           __ str(x2, MemOperand(x1, x10));
12384         }
12385         data_length += kXRegSizeInBytes;
12386 
12387         __ Mov(x10, offset_base + data_length);
12388         {
12389           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12390           __ ldr(d0, MemOperand(x0, x10));
12391           __ str(d0, MemOperand(x1, x10));
12392         }
12393         data_length += kDRegSizeInBytes;
12394 
12395         __ Mov(x10, offset_base + data_length);
12396         {
12397           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12398           __ ldr(w2, MemOperand(x0, x10));
12399           __ str(w2, MemOperand(x1, x10));
12400         }
12401         data_length += kWRegSizeInBytes;
12402 
12403         __ Mov(x10, offset_base + data_length);
12404         {
12405           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12406           __ ldr(s0, MemOperand(x0, x10));
12407           __ str(s0, MemOperand(x1, x10));
12408         }
12409         data_length += kSRegSizeInBytes;
12410 
12411         __ Mov(x10, offset_base + data_length);
12412         {
12413           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12414           __ ldrh(w2, MemOperand(x0, x10));
12415           __ strh(w2, MemOperand(x1, x10));
12416         }
12417         data_length += 2;
12418 
12419         __ Mov(x10, offset_base + data_length);
12420         {
12421           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12422           __ ldrsh(w2, MemOperand(x0, x10));
12423           __ strh(w2, MemOperand(x1, x10));
12424         }
12425         data_length += 2;
12426 
12427         __ Mov(x10, offset_base + data_length);
12428         {
12429           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12430           __ ldrb(w2, MemOperand(x0, x10));
12431           __ strb(w2, MemOperand(x1, x10));
12432         }
12433         data_length += 1;
12434 
12435         __ Mov(x10, offset_base + data_length);
12436         {
12437           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
12438           __ ldrsb(w2, MemOperand(x0, x10));
12439           __ strb(w2, MemOperand(x1, x10));
12440         }
12441         data_length += 1;
12442 
12443         VIXL_ASSERT(kMaxDataLength >= data_length);
12444 
12445         END();
12446         if (CAN_RUN()) {
12447           RUN();
12448 
12449           // Check that the postindex was correctly applied in each operation,
12450           // and that the tag was preserved.
12451           ASSERT_EQUAL_64(src_tagged, x0);
12452           ASSERT_EQUAL_64(dst_tagged, x1);
12453           ASSERT_EQUAL_64(offset_base + data_length - 1, x10);
12454 
12455           for (int k = 0; k < data_length; k++) {
12456             VIXL_CHECK(src[k] == dst[k]);
12457           }
12458         }
12459       }
12460     }
12461   }
12462 }
12463 
12464 
TEST(load_store_tagged_register_postindex)12465 TEST(load_store_tagged_register_postindex) {
12466   uint64_t src[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
12467   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
12468   int tag_count = sizeof(tags) / sizeof(tags[0]);
12469 
12470   for (int j = 0; j < tag_count; j++) {
12471     for (int i = 0; i < tag_count; i++) {
12472       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
12473 
12474       uint64_t src_base = reinterpret_cast<uint64_t>(src);
12475       uint64_t src_tagged = CPU::SetPointerTag(src_base, tags[i]);
12476       uint64_t offset_tagged = CPU::SetPointerTag(UINT64_C(0), tags[j]);
12477 
12478       START();
12479       __ Mov(x10, src_tagged);
12480       __ Mov(x11, offset_tagged);
12481       __ Ld1(v0.V16B(), MemOperand(x10, x11, PostIndex));
12482       // TODO: add other instructions (ld2-4, st1-4) as they become available.
12483       END();
12484 
12485       if (CAN_RUN()) {
12486         RUN();
12487 
12488         ASSERT_EQUAL_128(0x0f0e0d0c0b0a0908, 0x0706050403020100, q0);
12489         ASSERT_EQUAL_64(src_tagged + offset_tagged, x10);
12490       }
12491     }
12492   }
12493 }
12494 
12495 
TEST(branch_tagged)12496 TEST(branch_tagged) {
12497   SETUP();
12498   START();
12499 
12500   Label loop, loop_entry, done;
12501   __ Adr(x0, &loop);
12502   __ Mov(x1, 0);
12503   __ B(&loop_entry);
12504 
12505   __ Bind(&loop);
12506   __ Add(x1, x1, 1);  // Count successful jumps.
12507 
12508   // Advance to the next tag, then bail out if we've come back around to tag 0.
12509   __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12510   __ Tst(x0, kAddressTagMask);
12511   __ B(eq, &done);
12512 
12513   __ Bind(&loop_entry);
12514   __ Br(x0);
12515 
12516   __ Bind(&done);
12517 
12518   END();
12519   if (CAN_RUN()) {
12520     RUN();
12521 
12522     ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12523   }
12524 }
12525 
12526 
TEST(branch_and_link_tagged)12527 TEST(branch_and_link_tagged) {
12528   SETUP();
12529   START();
12530 
12531   Label loop, loop_entry, done;
12532   __ Adr(x0, &loop);
12533   __ Mov(x1, 0);
12534   __ B(&loop_entry);
12535 
12536   __ Bind(&loop);
12537 
12538   // Bail out (before counting a successful jump) if lr appears to be tagged.
12539   __ Tst(lr, kAddressTagMask);
12540   __ B(ne, &done);
12541 
12542   __ Add(x1, x1, 1);  // Count successful jumps.
12543 
12544   // Advance to the next tag, then bail out if we've come back around to tag 0.
12545   __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12546   __ Tst(x0, kAddressTagMask);
12547   __ B(eq, &done);
12548 
12549   __ Bind(&loop_entry);
12550   __ Blr(x0);
12551 
12552   __ Bind(&done);
12553 
12554   END();
12555   if (CAN_RUN()) {
12556     RUN();
12557 
12558     ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12559   }
12560 }
12561 
12562 
TEST(branch_tagged_and_adr_adrp)12563 TEST(branch_tagged_and_adr_adrp) {
12564   SETUP_CUSTOM(kPageSize, PageOffsetDependentCode);
12565   START();
12566 
12567   Label loop, loop_entry, done;
12568   __ Adr(x0, &loop);
12569   __ Mov(x1, 0);
12570   __ B(&loop_entry);
12571 
12572   __ Bind(&loop);
12573 
12574   // Bail out (before counting a successful jump) if `adr x10, ...` is tagged.
12575   __ Adr(x10, &done);
12576   __ Tst(x10, kAddressTagMask);
12577   __ B(ne, &done);
12578 
12579   // Bail out (before counting a successful jump) if `adrp x11, ...` is tagged.
12580   __ Adrp(x11, &done);
12581   __ Tst(x11, kAddressTagMask);
12582   __ B(ne, &done);
12583 
12584   __ Add(x1, x1, 1);  // Count successful iterations.
12585 
12586   // Advance to the next tag, then bail out if we've come back around to tag 0.
12587   __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12588   __ Tst(x0, kAddressTagMask);
12589   __ B(eq, &done);
12590 
12591   __ Bind(&loop_entry);
12592   __ Br(x0);
12593 
12594   __ Bind(&done);
12595 
12596   END();
12597   if (CAN_RUN()) {
12598     RUN();
12599 
12600     ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12601   }
12602 }
12603 
TEST(system_sys)12604 TEST(system_sys) {
12605   SETUP();
12606   const char* msg = "SYS test!";
12607   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12608 
12609   START();
12610   __ Mov(x4, msg_addr);
12611   __ Sys(3, 0x7, 0x5, 1, x4);
12612   __ Mov(x3, x4);
12613   __ Sys(3, 0x7, 0xa, 1, x3);
12614   __ Mov(x2, x3);
12615   __ Sys(3, 0x7, 0xb, 1, x2);
12616   __ Mov(x1, x2);
12617   __ Sys(3, 0x7, 0xe, 1, x1);
12618   // TODO: Add tests to check ZVA equivalent.
12619   END();
12620 
12621   if (CAN_RUN()) {
12622     RUN();
12623   }
12624 }
12625 
12626 
TEST(system_ic)12627 TEST(system_ic) {
12628   SETUP();
12629   const char* msg = "IC test!";
12630   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12631 
12632   START();
12633   __ Mov(x11, msg_addr);
12634   __ Ic(IVAU, x11);
12635   END();
12636 
12637   if (CAN_RUN()) {
12638     RUN();
12639   }
12640 }
12641 
12642 
TEST(system_dc)12643 TEST(system_dc) {
12644   SETUP();
12645   const char* msg = "DC test!";
12646   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12647 
12648   START();
12649   __ Mov(x20, msg_addr);
12650   __ Dc(CVAC, x20);
12651   __ Mov(x21, msg_addr);
12652   __ Dc(CVAU, x21);
12653   __ Mov(x22, msg_addr);
12654   __ Dc(CIVAC, x22);
12655   // TODO: Add tests to check ZVA.
12656   END();
12657 
12658   if (CAN_RUN()) {
12659     RUN();
12660     ASSERT_EQUAL_64(msg_addr, x20);
12661     ASSERT_EQUAL_64(msg_addr, x21);
12662     ASSERT_EQUAL_64(msg_addr, x22);
12663   }
12664 }
12665 
12666 
TEST(system_dcpop)12667 TEST(system_dcpop) {
12668   SETUP_WITH_FEATURES(CPUFeatures::kDCPoP);
12669   const char* msg = "DCPoP test!";
12670   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12671 
12672   START();
12673   __ Mov(x20, msg_addr);
12674   __ Dc(CVAP, x20);
12675   END();
12676 
12677   if (CAN_RUN()) {
12678     RUN();
12679     ASSERT_EQUAL_64(msg_addr, x20);
12680   }
12681 }
12682 
TEST(system_dccvadp)12683 TEST(system_dccvadp) {
12684   SETUP_WITH_FEATURES(CPUFeatures::kDCCVADP);
12685   const char* msg = "DCCVADP test!";
12686   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12687 
12688   START();
12689   __ Mov(x20, msg_addr);
12690   __ Dc(CVADP, x20);
12691   END();
12692 
12693   if (CAN_RUN()) {
12694     RUN();
12695     ASSERT_EQUAL_64(msg_addr, x20);
12696   }
12697 }
12698 
TEST(system_dc_mte)12699 TEST(system_dc_mte) {
12700   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
12701   const char* msg = "DC MTE test!";
12702   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12703 
12704   START();
12705   __ Mov(x20, msg_addr);
12706   __ Dc(CGVAC, x20);
12707   __ Dc(CGDVAC, x20);
12708   __ Dc(CGVAP, x20);
12709   __ Dc(CGDVAP, x20);
12710   __ Dc(CIGVAC, x20);
12711   __ Dc(CIGDVAC, x20);
12712   END();
12713 
12714   if (CAN_RUN()) {
12715     RUN();
12716     ASSERT_EQUAL_64(msg_addr, x20);
12717   }
12718 }
12719 
12720 // We currently disable tests for CRC32 instructions when running natively.
12721 // Support for this family of instruction is optional, and so native platforms
12722 // may simply fail to execute the test.
TEST(crc32b)12723 TEST(crc32b) {
12724   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12725 
12726   START();
12727 
12728   __ Mov(w0, 0);
12729   __ Mov(w1, 0);
12730   __ Crc32b(w10, w0, w1);
12731 
12732   __ Mov(w0, 0x1);
12733   __ Mov(w1, 0x138);
12734   __ Crc32b(w11, w0, w1);
12735 
12736   __ Mov(w0, 0x1);
12737   __ Mov(w1, 0x38);
12738   __ Crc32b(w12, w0, w1);
12739 
12740   __ Mov(w0, 0);
12741   __ Mov(w1, 128);
12742   __ Crc32b(w13, w0, w1);
12743 
12744   __ Mov(w0, UINT32_MAX);
12745   __ Mov(w1, 255);
12746   __ Crc32b(w14, w0, w1);
12747 
12748   __ Mov(w0, 0x00010001);
12749   __ Mov(w1, 0x10001000);
12750   __ Crc32b(w15, w0, w1);
12751 
12752   END();
12753 
12754   if (CAN_RUN()) {
12755     RUN();
12756 
12757     ASSERT_EQUAL_64(0x0, x10);
12758     ASSERT_EQUAL_64(0x5f058808, x11);
12759     ASSERT_EQUAL_64(0x5f058808, x12);
12760     ASSERT_EQUAL_64(0xedb88320, x13);
12761     ASSERT_EQUAL_64(0x00ffffff, x14);
12762     ASSERT_EQUAL_64(0x77073196, x15);
12763   }
12764 }
12765 
12766 
TEST(crc32h)12767 TEST(crc32h) {
12768   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12769 
12770   START();
12771 
12772   __ Mov(w0, 0);
12773   __ Mov(w1, 0);
12774   __ Crc32h(w10, w0, w1);
12775 
12776   __ Mov(w0, 0x1);
12777   __ Mov(w1, 0x10038);
12778   __ Crc32h(w11, w0, w1);
12779 
12780   __ Mov(w0, 0x1);
12781   __ Mov(w1, 0x38);
12782   __ Crc32h(w12, w0, w1);
12783 
12784   __ Mov(w0, 0);
12785   __ Mov(w1, 128);
12786   __ Crc32h(w13, w0, w1);
12787 
12788   __ Mov(w0, UINT32_MAX);
12789   __ Mov(w1, 255);
12790   __ Crc32h(w14, w0, w1);
12791 
12792   __ Mov(w0, 0x00010001);
12793   __ Mov(w1, 0x10001000);
12794   __ Crc32h(w15, w0, w1);
12795 
12796   END();
12797 
12798   if (CAN_RUN()) {
12799     RUN();
12800 
12801     ASSERT_EQUAL_64(0x0, x10);
12802     ASSERT_EQUAL_64(0x0e848dba, x11);
12803     ASSERT_EQUAL_64(0x0e848dba, x12);
12804     ASSERT_EQUAL_64(0x3b83984b, x13);
12805     ASSERT_EQUAL_64(0x2d021072, x14);
12806     ASSERT_EQUAL_64(0x04ac2124, x15);
12807   }
12808 }
12809 
12810 
TEST(crc32w)12811 TEST(crc32w) {
12812   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12813 
12814   START();
12815 
12816   __ Mov(w0, 0);
12817   __ Mov(w1, 0);
12818   __ Crc32w(w10, w0, w1);
12819 
12820   __ Mov(w0, 0x1);
12821   __ Mov(w1, 0x80000031);
12822   __ Crc32w(w11, w0, w1);
12823 
12824   __ Mov(w0, 0);
12825   __ Mov(w1, 128);
12826   __ Crc32w(w13, w0, w1);
12827 
12828   __ Mov(w0, UINT32_MAX);
12829   __ Mov(w1, 255);
12830   __ Crc32w(w14, w0, w1);
12831 
12832   __ Mov(w0, 0x00010001);
12833   __ Mov(w1, 0x10001000);
12834   __ Crc32w(w15, w0, w1);
12835 
12836   END();
12837 
12838   if (CAN_RUN()) {
12839     RUN();
12840 
12841     ASSERT_EQUAL_64(0x0, x10);
12842     ASSERT_EQUAL_64(0x1d937b81, x11);
12843     ASSERT_EQUAL_64(0xed59b63b, x13);
12844     ASSERT_EQUAL_64(0x00be2612, x14);
12845     ASSERT_EQUAL_64(0xa036e530, x15);
12846   }
12847 }
12848 
12849 
TEST(crc32x)12850 TEST(crc32x) {
12851   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12852 
12853   START();
12854 
12855   __ Mov(w0, 0);
12856   __ Mov(x1, 0);
12857   __ Crc32x(w10, w0, x1);
12858 
12859   __ Mov(w0, 0x1);
12860   __ Mov(x1, UINT64_C(0x0000000800000031));
12861   __ Crc32x(w11, w0, x1);
12862 
12863   __ Mov(w0, 0);
12864   __ Mov(x1, 128);
12865   __ Crc32x(w13, w0, x1);
12866 
12867   __ Mov(w0, UINT32_MAX);
12868   __ Mov(x1, 255);
12869   __ Crc32x(w14, w0, x1);
12870 
12871   __ Mov(w0, 0x00010001);
12872   __ Mov(x1, UINT64_C(0x1000100000000000));
12873   __ Crc32x(w15, w0, x1);
12874 
12875   END();
12876 
12877   if (CAN_RUN()) {
12878     RUN();
12879 
12880     ASSERT_EQUAL_64(0x0, x10);
12881     ASSERT_EQUAL_64(0x40797b92, x11);
12882     ASSERT_EQUAL_64(0x533b85da, x13);
12883     ASSERT_EQUAL_64(0xbc962670, x14);
12884     ASSERT_EQUAL_64(0x0667602f, x15);
12885   }
12886 }
12887 
12888 
TEST(crc32cb)12889 TEST(crc32cb) {
12890   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12891 
12892   START();
12893 
12894   __ Mov(w0, 0);
12895   __ Mov(w1, 0);
12896   __ Crc32cb(w10, w0, w1);
12897 
12898   __ Mov(w0, 0x1);
12899   __ Mov(w1, 0x138);
12900   __ Crc32cb(w11, w0, w1);
12901 
12902   __ Mov(w0, 0x1);
12903   __ Mov(w1, 0x38);
12904   __ Crc32cb(w12, w0, w1);
12905 
12906   __ Mov(w0, 0);
12907   __ Mov(w1, 128);
12908   __ Crc32cb(w13, w0, w1);
12909 
12910   __ Mov(w0, UINT32_MAX);
12911   __ Mov(w1, 255);
12912   __ Crc32cb(w14, w0, w1);
12913 
12914   __ Mov(w0, 0x00010001);
12915   __ Mov(w1, 0x10001000);
12916   __ Crc32cb(w15, w0, w1);
12917 
12918   END();
12919 
12920   if (CAN_RUN()) {
12921     RUN();
12922 
12923     ASSERT_EQUAL_64(0x0, x10);
12924     ASSERT_EQUAL_64(0x4851927d, x11);
12925     ASSERT_EQUAL_64(0x4851927d, x12);
12926     ASSERT_EQUAL_64(0x82f63b78, x13);
12927     ASSERT_EQUAL_64(0x00ffffff, x14);
12928     ASSERT_EQUAL_64(0xf26b8203, x15);
12929   }
12930 }
12931 
12932 
TEST(crc32ch)12933 TEST(crc32ch) {
12934   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12935 
12936   START();
12937 
12938   __ Mov(w0, 0);
12939   __ Mov(w1, 0);
12940   __ Crc32ch(w10, w0, w1);
12941 
12942   __ Mov(w0, 0x1);
12943   __ Mov(w1, 0x10038);
12944   __ Crc32ch(w11, w0, w1);
12945 
12946   __ Mov(w0, 0x1);
12947   __ Mov(w1, 0x38);
12948   __ Crc32ch(w12, w0, w1);
12949 
12950   __ Mov(w0, 0);
12951   __ Mov(w1, 128);
12952   __ Crc32ch(w13, w0, w1);
12953 
12954   __ Mov(w0, UINT32_MAX);
12955   __ Mov(w1, 255);
12956   __ Crc32ch(w14, w0, w1);
12957 
12958   __ Mov(w0, 0x00010001);
12959   __ Mov(w1, 0x10001000);
12960   __ Crc32ch(w15, w0, w1);
12961 
12962   END();
12963 
12964   if (CAN_RUN()) {
12965     RUN();
12966 
12967     ASSERT_EQUAL_64(0x0, x10);
12968     ASSERT_EQUAL_64(0xcef8494c, x11);
12969     ASSERT_EQUAL_64(0xcef8494c, x12);
12970     ASSERT_EQUAL_64(0xfbc3faf9, x13);
12971     ASSERT_EQUAL_64(0xad7dacae, x14);
12972     ASSERT_EQUAL_64(0x03fc5f19, x15);
12973   }
12974 }
12975 
12976 
TEST(crc32cw)12977 TEST(crc32cw) {
12978   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12979 
12980   START();
12981 
12982   __ Mov(w0, 0);
12983   __ Mov(w1, 0);
12984   __ Crc32cw(w10, w0, w1);
12985 
12986   __ Mov(w0, 0x1);
12987   __ Mov(w1, 0x80000031);
12988   __ Crc32cw(w11, w0, w1);
12989 
12990   __ Mov(w0, 0);
12991   __ Mov(w1, 128);
12992   __ Crc32cw(w13, w0, w1);
12993 
12994   __ Mov(w0, UINT32_MAX);
12995   __ Mov(w1, 255);
12996   __ Crc32cw(w14, w0, w1);
12997 
12998   __ Mov(w0, 0x00010001);
12999   __ Mov(w1, 0x10001000);
13000   __ Crc32cw(w15, w0, w1);
13001 
13002   END();
13003 
13004   if (CAN_RUN()) {
13005     RUN();
13006 
13007     ASSERT_EQUAL_64(0x0, x10);
13008     ASSERT_EQUAL_64(0xbcb79ece, x11);
13009     ASSERT_EQUAL_64(0x52a0c93f, x13);
13010     ASSERT_EQUAL_64(0x9f9b5c7a, x14);
13011     ASSERT_EQUAL_64(0xae1b882a, x15);
13012   }
13013 }
13014 
13015 
TEST(crc32cx)13016 TEST(crc32cx) {
13017   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
13018 
13019   START();
13020 
13021   __ Mov(w0, 0);
13022   __ Mov(x1, 0);
13023   __ Crc32cx(w10, w0, x1);
13024 
13025   __ Mov(w0, 0x1);
13026   __ Mov(x1, UINT64_C(0x0000000800000031));
13027   __ Crc32cx(w11, w0, x1);
13028 
13029   __ Mov(w0, 0);
13030   __ Mov(x1, 128);
13031   __ Crc32cx(w13, w0, x1);
13032 
13033   __ Mov(w0, UINT32_MAX);
13034   __ Mov(x1, 255);
13035   __ Crc32cx(w14, w0, x1);
13036 
13037   __ Mov(w0, 0x00010001);
13038   __ Mov(x1, UINT64_C(0x1000100000000000));
13039   __ Crc32cx(w15, w0, x1);
13040 
13041   END();
13042 
13043   if (CAN_RUN()) {
13044     RUN();
13045 
13046     ASSERT_EQUAL_64(0x0, x10);
13047     ASSERT_EQUAL_64(0x7f320fcb, x11);
13048     ASSERT_EQUAL_64(0x34019664, x13);
13049     ASSERT_EQUAL_64(0x6cc27dd0, x14);
13050     ASSERT_EQUAL_64(0xc6f0acdb, x15);
13051   }
13052 }
13053 
TEST(regress_cmp_shift_imm)13054 TEST(regress_cmp_shift_imm) {
13055   SETUP();
13056 
13057   START();
13058 
13059   __ Mov(x0, 0x3d720c8d);
13060   __ Cmp(x0, Operand(0x3d720c8d));
13061 
13062   END();
13063   if (CAN_RUN()) {
13064     RUN();
13065 
13066     ASSERT_EQUAL_NZCV(ZCFlag);
13067   }
13068 }
13069 
13070 
TEST(compute_address)13071 TEST(compute_address) {
13072   SETUP();
13073 
13074   START();
13075   int64_t base_address = INT64_C(0x123000000abc);
13076   int64_t reg_offset = INT64_C(0x1087654321);
13077   Register base = x0;
13078   Register offset = x1;
13079 
13080   __ Mov(base, base_address);
13081   __ Mov(offset, reg_offset);
13082 
13083 
13084   __ ComputeAddress(x2, MemOperand(base, 0));
13085   __ ComputeAddress(x3, MemOperand(base, 8));
13086   __ ComputeAddress(x4, MemOperand(base, -100));
13087 
13088   __ ComputeAddress(x5, MemOperand(base, offset));
13089   __ ComputeAddress(x6, MemOperand(base, offset, LSL, 2));
13090   __ ComputeAddress(x7, MemOperand(base, offset, LSL, 4));
13091   __ ComputeAddress(x8, MemOperand(base, offset, LSL, 8));
13092 
13093   __ ComputeAddress(x9, MemOperand(base, offset, SXTW));
13094   __ ComputeAddress(x10, MemOperand(base, offset, UXTW, 1));
13095   __ ComputeAddress(x11, MemOperand(base, offset, SXTW, 2));
13096   __ ComputeAddress(x12, MemOperand(base, offset, UXTW, 3));
13097 
13098   END();
13099 
13100   if (CAN_RUN()) {
13101     RUN();
13102 
13103     ASSERT_EQUAL_64(base_address, base);
13104 
13105     ASSERT_EQUAL_64(INT64_C(0x123000000abc), x2);
13106     ASSERT_EQUAL_64(INT64_C(0x123000000ac4), x3);
13107     ASSERT_EQUAL_64(INT64_C(0x123000000a58), x4);
13108 
13109     ASSERT_EQUAL_64(INT64_C(0x124087654ddd), x5);
13110     ASSERT_EQUAL_64(INT64_C(0x12721d951740), x6);
13111     ASSERT_EQUAL_64(INT64_C(0x133876543ccc), x7);
13112     ASSERT_EQUAL_64(INT64_C(0x22b765432bbc), x8);
13113 
13114     ASSERT_EQUAL_64(INT64_C(0x122f87654ddd), x9);
13115     ASSERT_EQUAL_64(INT64_C(0x12310eca90fe), x10);
13116     ASSERT_EQUAL_64(INT64_C(0x122e1d951740), x11);
13117     ASSERT_EQUAL_64(INT64_C(0x12343b2a23c4), x12);
13118   }
13119 }
13120 
13121 
TEST(far_branch_backward)13122 TEST(far_branch_backward) {
13123   // Test that the MacroAssembler correctly resolves backward branches to labels
13124   // that are outside the immediate range of branch instructions.
13125   // Take into account that backward branches can reach one instruction further
13126   // than forward branches.
13127   const int overflow_size =
13128       kInstructionSize +
13129       std::max(Instruction::GetImmBranchForwardRange(TestBranchType),
13130                std::max(Instruction::GetImmBranchForwardRange(
13131                             CompareBranchType),
13132                         Instruction::GetImmBranchForwardRange(CondBranchType)));
13133 
13134   SETUP();
13135   START();
13136 
13137   Label done, fail;
13138   Label test_tbz, test_cbz, test_bcond;
13139   Label success_tbz, success_cbz, success_bcond;
13140 
13141   __ Mov(x0, 0);
13142   __ Mov(x1, 1);
13143   __ Mov(x10, 0);
13144 
13145   __ B(&test_tbz);
13146   __ Bind(&success_tbz);
13147   __ Orr(x0, x0, 1 << 0);
13148   __ B(&test_cbz);
13149   __ Bind(&success_cbz);
13150   __ Orr(x0, x0, 1 << 1);
13151   __ B(&test_bcond);
13152   __ Bind(&success_bcond);
13153   __ Orr(x0, x0, 1 << 2);
13154 
13155   __ B(&done);
13156 
13157   // Generate enough code to overflow the immediate range of the three types of
13158   // branches below.
13159   for (unsigned i = 0; i < overflow_size / kInstructionSize; ++i) {
13160     if (i % 100 == 0) {
13161       // If we do land in this code, we do not want to execute so many nops
13162       // before reaching the end of test (especially if tracing is activated).
13163       __ B(&fail);
13164     } else {
13165       __ Nop();
13166     }
13167   }
13168   __ B(&fail);
13169 
13170   __ Bind(&test_tbz);
13171   __ Tbz(x10, 7, &success_tbz);
13172   __ Bind(&test_cbz);
13173   __ Cbz(x10, &success_cbz);
13174   __ Bind(&test_bcond);
13175   __ Cmp(x10, 0);
13176   __ B(eq, &success_bcond);
13177 
13178   // For each out-of-range branch instructions, at least two instructions should
13179   // have been generated.
13180   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&test_tbz) >=
13181              7 * kInstructionSize);
13182 
13183   __ Bind(&fail);
13184   __ Mov(x1, 0);
13185   __ Bind(&done);
13186 
13187   END();
13188   if (CAN_RUN()) {
13189     RUN();
13190 
13191     ASSERT_EQUAL_64(0x7, x0);
13192     ASSERT_EQUAL_64(0x1, x1);
13193   }
13194 }
13195 
13196 
TEST(single_veneer)13197 TEST(single_veneer) {
13198   SETUP();
13199   START();
13200 
13201   const int max_range = Instruction::GetImmBranchForwardRange(TestBranchType);
13202 
13203   Label success, fail, done;
13204 
13205   __ Mov(x0, 0);
13206   __ Mov(x1, 1);
13207   __ Mov(x10, 0);
13208 
13209   __ Tbz(x10, 7, &success);
13210 
13211   // Generate enough code to overflow the immediate range of the `tbz`.
13212   for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) {
13213     if (i % 100 == 0) {
13214       // If we do land in this code, we do not want to execute so many nops
13215       // before reaching the end of test (especially if tracing is activated).
13216       __ B(&fail);
13217     } else {
13218       __ Nop();
13219     }
13220   }
13221   __ B(&fail);
13222 
13223   __ Bind(&success);
13224   __ Mov(x0, 1);
13225 
13226   __ B(&done);
13227   __ Bind(&fail);
13228   __ Mov(x1, 0);
13229   __ Bind(&done);
13230 
13231   END();
13232   if (CAN_RUN()) {
13233     RUN();
13234 
13235     ASSERT_EQUAL_64(1, x0);
13236     ASSERT_EQUAL_64(1, x1);
13237   }
13238 }
13239 
13240 
TEST(simple_veneers)13241 TEST(simple_veneers) {
13242   // Test that the MacroAssembler correctly emits veneers for forward branches
13243   // to labels that are outside the immediate range of branch instructions.
13244   const int max_range =
13245       std::max(Instruction::GetImmBranchForwardRange(TestBranchType),
13246                std::max(Instruction::GetImmBranchForwardRange(
13247                             CompareBranchType),
13248                         Instruction::GetImmBranchForwardRange(CondBranchType)));
13249 
13250   SETUP();
13251   START();
13252 
13253   Label done, fail;
13254   Label test_tbz, test_cbz, test_bcond;
13255   Label success_tbz, success_cbz, success_bcond;
13256 
13257   __ Mov(x0, 0);
13258   __ Mov(x1, 1);
13259   __ Mov(x10, 0);
13260 
13261   __ Bind(&test_tbz);
13262   __ Tbz(x10, 7, &success_tbz);
13263   __ Bind(&test_cbz);
13264   __ Cbz(x10, &success_cbz);
13265   __ Bind(&test_bcond);
13266   __ Cmp(x10, 0);
13267   __ B(eq, &success_bcond);
13268 
13269   // Generate enough code to overflow the immediate range of the three types of
13270   // branches below.
13271   for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) {
13272     if (i % 100 == 0) {
13273       // If we do land in this code, we do not want to execute so many nops
13274       // before reaching the end of test (especially if tracing is activated).
13275       __ B(&fail);
13276     } else {
13277       __ Nop();
13278     }
13279   }
13280   __ B(&fail);
13281 
13282   __ Bind(&success_tbz);
13283   __ Orr(x0, x0, 1 << 0);
13284   __ B(&test_cbz);
13285   __ Bind(&success_cbz);
13286   __ Orr(x0, x0, 1 << 1);
13287   __ B(&test_bcond);
13288   __ Bind(&success_bcond);
13289   __ Orr(x0, x0, 1 << 2);
13290 
13291   __ B(&done);
13292   __ Bind(&fail);
13293   __ Mov(x1, 0);
13294   __ Bind(&done);
13295 
13296   END();
13297   if (CAN_RUN()) {
13298     RUN();
13299 
13300     ASSERT_EQUAL_64(0x7, x0);
13301     ASSERT_EQUAL_64(0x1, x1);
13302   }
13303 }
13304 
13305 
TEST(veneers_stress)13306 TEST(veneers_stress) {
13307   SETUP();
13308   START();
13309 
13310   // This is a code generation test stressing the emission of veneers. The code
13311   // generated is not executed.
13312 
13313   Label target;
13314   const unsigned max_range =
13315       Instruction::GetImmBranchForwardRange(CondBranchType);
13316   const unsigned iterations =
13317       (max_range + max_range / 4) / (4 * kInstructionSize);
13318   for (unsigned i = 0; i < iterations; i++) {
13319     __ B(&target);
13320     __ B(eq, &target);
13321     __ Cbz(x0, &target);
13322     __ Tbz(x0, 0, &target);
13323   }
13324   __ Bind(&target);
13325 
13326   END();
13327 }
13328 
13329 
TEST(veneers_two_out_of_range)13330 TEST(veneers_two_out_of_range) {
13331   SETUP();
13332   START();
13333 
13334   // This is a code generation test. The code generated is not executed.
13335   // Ensure that the MacroAssembler considers unresolved branches to chose when
13336   // a veneer pool should be emitted. We generate two branches that go out of
13337   // range at the same offset. When the MacroAssembler decides to emit the
13338   // veneer pool, the emission of a first veneer should not cause the other
13339   // branch to go out of range.
13340 
13341   int range_cbz = Instruction::GetImmBranchForwardRange(CompareBranchType);
13342   int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
13343   int max_target = static_cast<int>(masm.GetCursorOffset()) + range_cbz;
13344 
13345   Label done;
13346 
13347   // We use different labels to prevent the MacroAssembler from sharing veneers.
13348   Label target_cbz, target_tbz;
13349 
13350   __ Cbz(x0, &target_cbz);
13351   while (masm.GetCursorOffset() < max_target - range_tbz) {
13352     __ Nop();
13353   }
13354   __ Tbz(x0, 0, &target_tbz);
13355   while (masm.GetCursorOffset() < max_target) {
13356     __ Nop();
13357   }
13358 
13359   // This additional nop makes the branches go out of range.
13360   __ Nop();
13361 
13362   __ Bind(&target_cbz);
13363   __ Bind(&target_tbz);
13364 
13365   END();
13366 }
13367 
13368 
TEST(veneers_hanging)13369 TEST(veneers_hanging) {
13370   SETUP();
13371   START();
13372 
13373   // This is a code generation test. The code generated is not executed.
13374   // Ensure that the MacroAssembler considers unresolved branches to chose when
13375   // a veneer pool should be emitted. This is similar to the
13376   // 'veneers_two_out_of_range' test. We try to trigger the following situation:
13377   //   b.eq label
13378   //   b.eq label
13379   //   ...
13380   //   nop
13381   //   ...
13382   //   cbz x0, label
13383   //   cbz x0, label
13384   //   ...
13385   //   tbz x0, 0 label
13386   //   nop
13387   //   ...
13388   //   nop    <- From here the `b.eq` and `cbz` instructions run out of range,
13389   //             so a literal pool is required.
13390   //   veneer
13391   //   veneer
13392   //   veneer <- The `tbz` runs out of range somewhere in the middle of the
13393   //   veneer    veneer pool.
13394   //   veneer
13395 
13396   const int range_bcond = Instruction::GetImmBranchForwardRange(CondBranchType);
13397   const int range_cbz =
13398       Instruction::GetImmBranchForwardRange(CompareBranchType);
13399   const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
13400   const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_bcond;
13401 
13402   Label done;
13403   const int n_bcond = 100;
13404   const int n_cbz = 100;
13405   const int n_tbz = 1;
13406   const int kNTotalBranches = n_bcond + n_cbz + n_tbz;
13407 
13408   // We use different labels to prevent the MacroAssembler from sharing veneers.
13409   Label labels[kNTotalBranches];
13410   for (int i = 0; i < kNTotalBranches; i++) {
13411     new (&labels[i]) Label();
13412   }
13413 
13414   for (int i = 0; i < n_bcond; i++) {
13415     __ B(eq, &labels[i]);
13416   }
13417 
13418   while (masm.GetCursorOffset() < max_target - range_cbz) {
13419     __ Nop();
13420   }
13421 
13422   for (int i = 0; i < n_cbz; i++) {
13423     __ Cbz(x0, &labels[n_bcond + i]);
13424   }
13425 
13426   // Ensure the 'tbz' will go out of range after some of the previously
13427   // generated branches.
13428   int margin = (n_bcond / 2) * kInstructionSize;
13429   while (masm.GetCursorOffset() < max_target - range_tbz + margin) {
13430     __ Nop();
13431   }
13432 
13433   __ Tbz(x0, 0, &labels[n_bcond + n_cbz]);
13434 
13435   while (masm.GetCursorOffset() < max_target) {
13436     __ Nop();
13437   }
13438 
13439   // This additional nop makes the 'b.eq' and 'cbz' instructions go out of range
13440   // and forces the emission of a veneer pool. The 'tbz' is not yet out of
13441   // range, but will go out of range while veneers are emitted for the other
13442   // branches.
13443   // The MacroAssembler should ensure that veneers are correctly emitted for all
13444   // the branches, including the 'tbz'. Checks will fail if the target of a
13445   // branch is out of range.
13446   __ Nop();
13447 
13448   for (int i = 0; i < kNTotalBranches; i++) {
13449     __ Bind(&labels[i]);
13450   }
13451 
13452   END();
13453 }
13454 
13455 
TEST(collision_literal_veneer_pools)13456 TEST(collision_literal_veneer_pools) {
13457   SETUP_WITH_FEATURES(CPUFeatures::kFP);
13458   START();
13459 
13460   // This is a code generation test. The code generated is not executed.
13461 
13462   // Make sure the literal pool is empty;
13463   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13464   ASSERT_LITERAL_POOL_SIZE(0);
13465 
13466   // We chose the offsets below to (try to) trigger the following situation:
13467   // buffer offset
13468   //              0:   tbz x0, 0, target_tbz ----------------------------------.
13469   //              4:   nop                                                     |
13470   //                   ...                                                     |
13471   //                   nop                                                     |
13472   //    literal gen:   ldr s0, [pc + ...]   ; load from `pool start + 0`       |
13473   //                   ldr s0, [pc + ...]   ; load from `pool start + 4`       |
13474   //                   ...                                                     |
13475   //                   ldr s0, [pc + ...]                                      |
13476   //     pool start:   floating-point literal (0.1)                            |
13477   //                   floating-point literal (1.1)                            |
13478   //                   ...                                                     |
13479   //                   floating-point literal (<n>.1)     <-----tbz-max-range--'
13480   //                   floating-point literal (<n+1>.1)
13481   //                   ...
13482 
13483   const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
13484   const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_tbz;
13485 
13486   const size_t target_literal_pool_size = 100 * kInstructionSize;
13487   const int offset_start_literal_gen =
13488       target_literal_pool_size + target_literal_pool_size / 2;
13489 
13490 
13491   Label target_tbz;
13492 
13493   __ Tbz(x0, 0, &target_tbz);
13494   VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1);
13495   while (masm.GetCursorOffset() < max_target - offset_start_literal_gen) {
13496     __ Nop();
13497   }
13498   VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1);
13499 
13500   for (int i = 0; i < 100; i++) {
13501     // Use a different value to force one literal pool entry per iteration.
13502     __ Ldr(s0, i + 0.1);
13503   }
13504   VIXL_CHECK(masm.GetLiteralPoolSize() >= target_literal_pool_size);
13505 
13506   // Force emission of a literal pool.
13507   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13508   ASSERT_LITERAL_POOL_SIZE(0);
13509 
13510   // The branch should not have gone out of range during the emission of the
13511   // literal pool.
13512   __ Bind(&target_tbz);
13513 
13514   VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 0);
13515 
13516   END();
13517 }
13518 
VeneerBackwardBranchHelper(ImmBranchType type,int limit)13519 static void VeneerBackwardBranchHelper(ImmBranchType type, int limit) {
13520   SETUP();
13521   START();
13522 
13523   // This is a code generation test. The code generated is not executed.
13524 
13525   __ Mov(x0, 1);
13526 
13527   // Non-veneer case: generate 'limit' instructions, plus the branch itself.
13528   Label start0;
13529   __ Bind(&start0);
13530   for (int i = 0; i < limit; i++) {
13531     __ Nop();
13532   }
13533   switch (type) {
13534     case CompareBranchType:
13535       __ Cbz(x0, &start0);
13536       break;
13537     case TestBranchType:
13538       __ Tbz(x0, 0, &start0);
13539       break;
13540     default:
13541       VIXL_ASSERT(type == CondBranchType);
13542       __ B(eq, &start0);
13543   }
13544   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start0) ==
13545              ((limit + 1) * kInstructionSize));
13546 
13547   // Veneer case: As above, plus one extra nop and a branch for the veneer; we
13548   // expect a total of limit + 3 instructions.
13549   //
13550   //  start1:
13551   //    nop x (limit + 1)
13552   //    tbnz skip_veneer
13553   //    b start1
13554   //  skip_veneer:
13555   //
13556   Label start1;
13557   __ Bind(&start1);
13558   for (int i = 0; i < limit; i++) {
13559     __ Nop();
13560   }
13561   __ Nop();  // One extra instruction to exceed branch range.
13562   switch (type) {
13563     case CompareBranchType:
13564       __ Cbz(x0, &start0);
13565       break;
13566     case TestBranchType:
13567       __ Tbz(x0, 0, &start0);
13568       break;
13569     default:
13570       VIXL_ASSERT(type == CondBranchType);
13571       __ B(eq, &start0);
13572   }
13573   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start1) ==
13574              ((limit + 3) * kInstructionSize));
13575 
13576   END();
13577   DISASSEMBLE();
13578 }
13579 
TEST(veneer_backward_tbz)13580 TEST(veneer_backward_tbz) { VeneerBackwardBranchHelper(TestBranchType, 8192); }
13581 
TEST(veneer_backward_cbz)13582 TEST(veneer_backward_cbz) {
13583   VeneerBackwardBranchHelper(CompareBranchType, 262144);
13584 }
13585 
TEST(veneer_backward_bcond)13586 TEST(veneer_backward_bcond) {
13587   VeneerBackwardBranchHelper(CondBranchType, 262144);
13588 }
13589 
TEST(ldr_literal_explicit)13590 TEST(ldr_literal_explicit) {
13591   SETUP();
13592 
13593   START();
13594   Literal<int64_t> automatically_placed_literal(1, masm.GetLiteralPool());
13595   Literal<int64_t> manually_placed_literal(2);
13596   {
13597     ExactAssemblyScope scope(&masm, kInstructionSize + sizeof(int64_t));
13598     Label over_literal;
13599     __ b(&over_literal);
13600     __ place(&manually_placed_literal);
13601     __ bind(&over_literal);
13602   }
13603   __ Ldr(x1, &manually_placed_literal);
13604   __ Ldr(x2, &automatically_placed_literal);
13605   __ Add(x0, x1, x2);
13606   END();
13607 
13608   if (CAN_RUN()) {
13609     RUN();
13610 
13611     ASSERT_EQUAL_64(3, x0);
13612   }
13613 }
13614 
13615 
TEST(ldr_literal_automatically_placed)13616 TEST(ldr_literal_automatically_placed) {
13617   SETUP_WITH_FEATURES(CPUFeatures::kFP);
13618 
13619   START();
13620 
13621   // We start with an empty literal pool.
13622   ASSERT_LITERAL_POOL_SIZE(0);
13623 
13624   // Create a literal that should be placed by the literal pool.
13625   Literal<int64_t> explicit_literal(2, masm.GetLiteralPool());
13626   // It should not appear in the literal pool until its first use.
13627   ASSERT_LITERAL_POOL_SIZE(0);
13628 
13629   // Check that using standard literals does not break the use of explicitly
13630   // created literals.
13631   __ Ldr(d1, 1.1);
13632   ASSERT_LITERAL_POOL_SIZE(8);
13633   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13634   ASSERT_LITERAL_POOL_SIZE(0);
13635 
13636   __ Ldr(x2, &explicit_literal);
13637   ASSERT_LITERAL_POOL_SIZE(8);
13638   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13639   ASSERT_LITERAL_POOL_SIZE(0);
13640 
13641   __ Ldr(d3, 3.3);
13642   ASSERT_LITERAL_POOL_SIZE(8);
13643   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13644   ASSERT_LITERAL_POOL_SIZE(0);
13645 
13646   // Re-use our explicitly created literal. It has already been placed, so it
13647   // should not impact the literal pool.
13648   __ Ldr(x4, &explicit_literal);
13649   ASSERT_LITERAL_POOL_SIZE(0);
13650 
13651   END();
13652 
13653   if (CAN_RUN()) {
13654     RUN();
13655 
13656     ASSERT_EQUAL_FP64(1.1, d1);
13657     ASSERT_EQUAL_64(2, x2);
13658     ASSERT_EQUAL_FP64(3.3, d3);
13659     ASSERT_EQUAL_64(2, x4);
13660   }
13661 }
13662 
13663 
TEST(literal_update_overwrite)13664 TEST(literal_update_overwrite) {
13665   SETUP();
13666 
13667   START();
13668 
13669   ASSERT_LITERAL_POOL_SIZE(0);
13670   LiteralPool* literal_pool = masm.GetLiteralPool();
13671 
13672   Literal<int32_t> lit_32_update_before_pool(0xbad, literal_pool);
13673   Literal<int32_t> lit_32_update_after_pool(0xbad, literal_pool);
13674   Literal<int64_t> lit_64_update_before_pool(0xbad, literal_pool);
13675   Literal<int64_t> lit_64_update_after_pool(0xbad, literal_pool);
13676 
13677   ASSERT_LITERAL_POOL_SIZE(0);
13678 
13679   lit_32_update_before_pool.UpdateValue(32);
13680   lit_64_update_before_pool.UpdateValue(64);
13681 
13682   __ Ldr(w1, &lit_32_update_before_pool);
13683   __ Ldr(x2, &lit_64_update_before_pool);
13684   __ Ldr(w3, &lit_32_update_after_pool);
13685   __ Ldr(x4, &lit_64_update_after_pool);
13686 
13687   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13688 
13689   VIXL_ASSERT(lit_32_update_after_pool.IsPlaced());
13690   VIXL_ASSERT(lit_64_update_after_pool.IsPlaced());
13691   lit_32_update_after_pool.UpdateValue(128, &masm);
13692   lit_64_update_after_pool.UpdateValue(256, &masm);
13693 
13694   END();
13695 
13696   if (CAN_RUN()) {
13697     RUN();
13698 
13699     ASSERT_EQUAL_64(32, x1);
13700     ASSERT_EQUAL_64(64, x2);
13701     ASSERT_EQUAL_64(128, x3);
13702     ASSERT_EQUAL_64(256, x4);
13703   }
13704 }
13705 
13706 
TEST(literal_deletion_policies)13707 TEST(literal_deletion_policies) {
13708   SETUP();
13709 
13710   START();
13711 
13712   // We cannot check exactly when the deletion of the literals occur, but we
13713   // check that usage of the deletion policies is not broken.
13714 
13715   ASSERT_LITERAL_POOL_SIZE(0);
13716   LiteralPool* literal_pool = masm.GetLiteralPool();
13717 
13718   Literal<int32_t> lit_manual(0xbad, literal_pool);
13719   Literal<int32_t>* lit_deleted_on_placement =
13720       new Literal<int32_t>(0xbad,
13721                            literal_pool,
13722                            RawLiteral::kDeletedOnPlacementByPool);
13723   Literal<int32_t>* lit_deleted_on_pool_destruction =
13724       new Literal<int32_t>(0xbad,
13725                            literal_pool,
13726                            RawLiteral::kDeletedOnPoolDestruction);
13727 
13728   ASSERT_LITERAL_POOL_SIZE(0);
13729 
13730   lit_manual.UpdateValue(32);
13731   lit_deleted_on_placement->UpdateValue(64);
13732 
13733   __ Ldr(w1, &lit_manual);
13734   __ Ldr(w2, lit_deleted_on_placement);
13735   __ Ldr(w3, lit_deleted_on_pool_destruction);
13736 
13737   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13738 
13739   VIXL_ASSERT(lit_manual.IsPlaced());
13740   VIXL_ASSERT(lit_deleted_on_pool_destruction->IsPlaced());
13741   lit_deleted_on_pool_destruction->UpdateValue(128, &masm);
13742 
13743   END();
13744 
13745   if (CAN_RUN()) {
13746     RUN();
13747 
13748     ASSERT_EQUAL_64(32, x1);
13749     ASSERT_EQUAL_64(64, x2);
13750     ASSERT_EQUAL_64(128, x3);
13751   }
13752 }
13753 
13754 
TEST(generic_operand)13755 TEST(generic_operand) {
13756   SETUP_WITH_FEATURES(CPUFeatures::kFP);
13757 
13758   int32_t data_32_array[5] = {0xbadbeef,
13759                               0x11111111,
13760                               0xbadbeef,
13761                               0x33333333,
13762                               0xbadbeef};
13763   int64_t data_64_array[5] = {INT64_C(0xbadbadbadbeef),
13764                               INT64_C(0x1111111111111111),
13765                               INT64_C(0xbadbadbadbeef),
13766                               INT64_C(0x3333333333333333),
13767                               INT64_C(0xbadbadbadbeef)};
13768   size_t size_32 = sizeof(data_32_array[0]);
13769   size_t size_64 = sizeof(data_64_array[0]);
13770 
13771   START();
13772 
13773   intptr_t data_32_address = reinterpret_cast<intptr_t>(&data_32_array[0]);
13774   intptr_t data_64_address = reinterpret_cast<intptr_t>(&data_64_array[0]);
13775   Register data_32 = x27;
13776   Register data_64 = x28;
13777   __ Mov(data_32, data_32_address);
13778   __ Mov(data_64, data_64_address);
13779 
13780   __ Move(GenericOperand(w0),
13781           GenericOperand(MemOperand(data_32, 1 * size_32), size_32));
13782   __ Move(GenericOperand(s0),
13783           GenericOperand(MemOperand(data_32, 3 * size_32), size_32));
13784   __ Move(GenericOperand(x10),
13785           GenericOperand(MemOperand(data_64, 1 * size_64), size_64));
13786   __ Move(GenericOperand(d10),
13787           GenericOperand(MemOperand(data_64, 3 * size_64), size_64));
13788 
13789   __ Move(GenericOperand(w1), GenericOperand(w0));
13790   __ Move(GenericOperand(s1), GenericOperand(s0));
13791   __ Move(GenericOperand(x11), GenericOperand(x10));
13792   __ Move(GenericOperand(d11), GenericOperand(d10));
13793 
13794   __ Move(GenericOperand(MemOperand(data_32, 0 * size_32), size_32),
13795           GenericOperand(w1));
13796   __ Move(GenericOperand(MemOperand(data_32, 2 * size_32), size_32),
13797           GenericOperand(s1));
13798   __ Move(GenericOperand(MemOperand(data_64, 0 * size_64), size_64),
13799           GenericOperand(x11));
13800   __ Move(GenericOperand(MemOperand(data_64, 2 * size_64), size_64),
13801           GenericOperand(d11));
13802 
13803   __ Move(GenericOperand(MemOperand(data_32, 4 * size_32), size_32),
13804           GenericOperand(MemOperand(data_32, 0 * size_32), size_32));
13805   __ Move(GenericOperand(MemOperand(data_64, 4 * size_64), size_64),
13806           GenericOperand(MemOperand(data_64, 0 * size_64), size_64));
13807   END();
13808 
13809   if (CAN_RUN()) {
13810     RUN();
13811 
13812     ASSERT_EQUAL_64(data_32_address, data_32);
13813     ASSERT_EQUAL_64(data_64_address, data_64);
13814 
13815     ASSERT_EQUAL_32(0x11111111, w0);
13816     ASSERT_EQUAL_32(0x33333333, core.sreg_bits(0));
13817     ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x10);
13818     ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(10));
13819 
13820     ASSERT_EQUAL_32(0x11111111, w1);
13821     ASSERT_EQUAL_32(0x33333333, core.sreg_bits(1));
13822     ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x11);
13823     ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(11));
13824 
13825     VIXL_CHECK(data_32_array[0] == 0x11111111);
13826     VIXL_CHECK(data_32_array[1] == 0x11111111);
13827     VIXL_CHECK(data_32_array[2] == 0x33333333);
13828     VIXL_CHECK(data_32_array[3] == 0x33333333);
13829     VIXL_CHECK(data_32_array[4] == 0x11111111);
13830 
13831     VIXL_CHECK(data_64_array[0] == INT64_C(0x1111111111111111));
13832     VIXL_CHECK(data_64_array[1] == INT64_C(0x1111111111111111));
13833     VIXL_CHECK(data_64_array[2] == INT64_C(0x3333333333333333));
13834     VIXL_CHECK(data_64_array[3] == INT64_C(0x3333333333333333));
13835     VIXL_CHECK(data_64_array[4] == INT64_C(0x1111111111111111));
13836   }
13837 }
13838 
13839 
13840 // Test feature detection of calls to runtime functions.
13841 
13842 // C++11 should be sufficient to provide simulated runtime calls, except for a
13843 // GCC bug before 4.9.1.
13844 #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && (__cplusplus >= 201103L) && \
13845     (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1)) &&               \
13846     !defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT)
13847 #error \
13848     "C++11 should be sufficient to provide support for simulated runtime calls."
13849 #endif  // #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && ...
13850 
13851 #if (__cplusplus >= 201103L) && \
13852     !defined(VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT)
13853 #error \
13854     "C++11 should be sufficient to provide support for `MacroAssembler::CallRuntime()`."
13855 #endif  // #if (__cplusplus >= 201103L) && ...
13856 
13857 #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
runtime_call_add_one(int32_t a)13858 int32_t runtime_call_add_one(int32_t a) { return a + 1; }
13859 
runtime_call_add_doubles(double a,double b,double c)13860 double runtime_call_add_doubles(double a, double b, double c) {
13861   return a + b + c;
13862 }
13863 
runtime_call_one_argument_on_stack(int64_t arg1,int64_t arg2,int64_t arg3,int64_t arg4,int64_t arg5,int64_t arg6,int64_t arg7,int64_t arg8,int64_t arg9)13864 int64_t runtime_call_one_argument_on_stack(int64_t arg1 __attribute__((unused)),
13865                                            int64_t arg2 __attribute__((unused)),
13866                                            int64_t arg3 __attribute__((unused)),
13867                                            int64_t arg4 __attribute__((unused)),
13868                                            int64_t arg5 __attribute__((unused)),
13869                                            int64_t arg6 __attribute__((unused)),
13870                                            int64_t arg7 __attribute__((unused)),
13871                                            int64_t arg8 __attribute__((unused)),
13872                                            int64_t arg9) {
13873   return arg9;
13874 }
13875 
runtime_call_two_arguments_on_stack(int64_t arg1,int64_t arg2,int64_t arg3,int64_t arg4,int64_t arg5,int64_t arg6,int64_t arg7,int64_t arg8,double arg9,double arg10)13876 double runtime_call_two_arguments_on_stack(int64_t arg1 __attribute__((unused)),
13877                                            int64_t arg2 __attribute__((unused)),
13878                                            int64_t arg3 __attribute__((unused)),
13879                                            int64_t arg4 __attribute__((unused)),
13880                                            int64_t arg5 __attribute__((unused)),
13881                                            int64_t arg6 __attribute__((unused)),
13882                                            int64_t arg7 __attribute__((unused)),
13883                                            int64_t arg8 __attribute__((unused)),
13884                                            double arg9,
13885                                            double arg10) {
13886   return arg9 - arg10;
13887 }
13888 
runtime_call_store_at_address(int64_t * address)13889 void runtime_call_store_at_address(int64_t* address) { *address = 0xf00d; }
13890 
runtime_call_no_args()13891 int32_t runtime_call_no_args() { return 1; }
13892 
13893 enum RuntimeCallTestEnum { Enum0 };
13894 
runtime_call_enum(RuntimeCallTestEnum e)13895 RuntimeCallTestEnum runtime_call_enum(RuntimeCallTestEnum e) { return e; }
13896 
13897 enum class RuntimeCallTestEnumClass { Enum0 };
13898 
runtime_call_enum_class(RuntimeCallTestEnumClass e)13899 RuntimeCallTestEnumClass runtime_call_enum_class(RuntimeCallTestEnumClass e) {
13900   return e;
13901 }
13902 
test_int8_t(int8_t x)13903 int8_t test_int8_t(int8_t x) { return x; }
test_uint8_t(uint8_t x)13904 uint8_t test_uint8_t(uint8_t x) { return x; }
test_int16_t(int16_t x)13905 int16_t test_int16_t(int16_t x) { return x; }
test_uint16_t(uint16_t x)13906 uint16_t test_uint16_t(uint16_t x) { return x; }
13907 
TEST(runtime_calls)13908 TEST(runtime_calls) {
13909   SETUP_WITH_FEATURES(CPUFeatures::kFP);
13910 
13911 #ifndef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
13912   if (masm.GenerateSimulatorCode()) {
13913     // This configuration is unsupported and a `VIXL_UNREACHABLE()` would fire
13914     // while trying to generate `CallRuntime`. This configuration should only be
13915     // reachable with C++11 and a (buggy) version of GCC pre-4.9.1.
13916     return;
13917   }
13918 #endif
13919 
13920   START();
13921 
13922   // Test `CallRuntime`.
13923 
13924   __ Mov(w0, 0);
13925   __ CallRuntime(runtime_call_add_one);
13926   __ Mov(w20, w0);
13927 
13928   __ Fmov(d0, 0.0);
13929   __ Fmov(d1, 1.5);
13930   __ Fmov(d2, 2.5);
13931   __ CallRuntime(runtime_call_add_doubles);
13932   __ Fmov(d20, d0);
13933 
13934   __ Mov(x0, 0x123);
13935   __ Push(x0, x0);
13936   __ CallRuntime(runtime_call_one_argument_on_stack);
13937   __ Mov(x21, x0);
13938   __ Pop(x0, x1);
13939 
13940   __ Fmov(d0, 314.0);
13941   __ Fmov(d1, 4.0);
13942   __ Push(d1, d0);
13943   __ CallRuntime(runtime_call_two_arguments_on_stack);
13944   __ Fmov(d21, d0);
13945   __ Pop(d1, d0);
13946 
13947   // Test that the template mechanisms don't break with enums.
13948   __ Mov(w0, 0);
13949   __ CallRuntime(runtime_call_enum);
13950   __ Mov(w0, 0);
13951   __ CallRuntime(runtime_call_enum_class);
13952 
13953   // Test `TailCallRuntime`.
13954 
13955   Label function, after_function;
13956   __ B(&after_function);
13957   __ Bind(&function);
13958   __ Mov(x22, 0);
13959   __ Mov(w0, 123);
13960   __ TailCallRuntime(runtime_call_add_one);
13961   // Control should not fall through.
13962   __ Mov(x22, 0xbad);
13963   __ Ret();
13964   __ Bind(&after_function);
13965 
13966   // Call our placeholder function, taking care to preserve the link register.
13967   __ Push(ip0, lr);
13968   __ Bl(&function);
13969   __ Pop(lr, ip0);
13970   // Save the result.
13971   __ Mov(w23, w0);
13972 
13973   __ Mov(x24, 0);
13974   int test_values[] = {static_cast<int8_t>(-1),
13975                        static_cast<uint8_t>(-1),
13976                        static_cast<int16_t>(-1),
13977                        static_cast<uint16_t>(-1),
13978                        -256,
13979                        -1,
13980                        0,
13981                        1,
13982                        256};
13983   for (size_t i = 0; i < sizeof(test_values) / sizeof(test_values[0]); ++i) {
13984     Label pass_int8, pass_uint8, pass_int16, pass_uint16;
13985     int x = test_values[i];
13986     __ Mov(w0, x);
13987     __ CallRuntime(test_int8_t);
13988     __ Sxtb(w0, w0);
13989     __ Cmp(w0, ExtractSignedBitfield32(7, 0, x));
13990     __ Cinc(x24, x24, ne);
13991     __ Mov(w0, x);
13992     __ CallRuntime(test_uint8_t);
13993     __ Uxtb(w0, w0);
13994     __ Cmp(w0, ExtractUnsignedBitfield32(7, 0, x));
13995     __ Cinc(x24, x24, ne);
13996     __ Mov(w0, x);
13997     __ CallRuntime(test_int16_t);
13998     __ Sxth(w0, w0);
13999     __ Cmp(w0, ExtractSignedBitfield32(15, 0, x));
14000     __ Cinc(x24, x24, ne);
14001     __ Mov(w0, x);
14002     __ CallRuntime(test_uint16_t);
14003     __ Uxth(w0, w0);
14004     __ Cmp(w0, ExtractUnsignedBitfield32(15, 0, x));
14005     __ Cinc(x24, x24, ne);
14006   }
14007 
14008 
14009   int64_t value = 0xbadbeef;
14010   __ Mov(x0, reinterpret_cast<uint64_t>(&value));
14011   __ CallRuntime(runtime_call_store_at_address);
14012 
14013   __ Mov(w0, 0);
14014   __ CallRuntime(runtime_call_no_args);
14015   __ Mov(w25, w0);
14016 
14017   END();
14018 
14019 #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || \
14020     !defined(VIXL_INCLUDE_SIMULATOR_AARCH64)
14021   if (CAN_RUN()) {
14022     RUN();
14023 
14024     ASSERT_EQUAL_32(1, w20);
14025     ASSERT_EQUAL_FP64(4.0, d20);
14026     ASSERT_EQUAL_64(0x123, x21);
14027     ASSERT_EQUAL_FP64(310.0, d21);
14028     VIXL_CHECK(value == 0xf00d);
14029     ASSERT_EQUAL_64(0, x22);
14030     ASSERT_EQUAL_32(124, w23);
14031     ASSERT_EQUAL_64(0, x24);
14032     ASSERT_EQUAL_32(1, w25);
14033   }
14034 #endif  // #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || ...
14035 }
14036 
14037 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
void_func()14038 void void_func() {}
uint32_func()14039 uint32_t uint32_func() { return 2; }
void_param_func(uint32_t x)14040 void void_param_func(uint32_t x) { USE(x); }
uint32_param_func(uint32_t x)14041 uint32_t uint32_param_func(uint32_t x) { return ++x; }
14042 
void_placeholder()14043 void void_placeholder() {}
uint32_placeholder()14044 uint32_t uint32_placeholder() { return 4; }
void_param_placeholder(uint32_t x)14045 void void_param_placeholder(uint32_t x) { USE(x); }
uint32_param_placeholder(uint32_t x)14046 uint32_t uint32_param_placeholder(uint32_t x) { return ++x; }
14047 
14048 #define DO_TEST_BRANCH_INTERCEPTION(func)        \
14049   __ Mov(x16, reinterpret_cast<uint64_t>(func)); \
14050   __ Blr(x16);
14051 
TEST(branch_interception)14052 TEST(branch_interception) {
14053   SETUP();
14054   START();
14055 
14056   // Test default branch interception, i.e: do a runtime call to the function.
14057   DO_TEST_BRANCH_INTERCEPTION(void_func);
14058   DO_TEST_BRANCH_INTERCEPTION(uint32_func);
14059   __ Mov(w20, w0);
14060   DO_TEST_BRANCH_INTERCEPTION(void_param_func);
14061   __ Mov(w0, 2);
14062   DO_TEST_BRANCH_INTERCEPTION(uint32_param_func);
14063   __ Mov(w21, w0);
14064 
14065   // Test interceptions with callbacks.
14066   DO_TEST_BRANCH_INTERCEPTION(void_placeholder);
14067   __ Mov(w22, w0);
14068   DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder);
14069   __ Mov(w23, w0);
14070   __ Mov(w0, 4);
14071   DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder);
14072   __ Mov(w24, w0);
14073   DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder);
14074   __ Mov(w25, w0);
14075 
14076   END();
14077 
14078   simulator.RegisterBranchInterception(void_func);
14079   simulator.RegisterBranchInterception(uint32_func);
14080   simulator.RegisterBranchInterception(void_param_func);
14081   simulator.RegisterBranchInterception(uint32_param_func);
14082 
14083   auto callback = [&simulator](uint64_t original_target) {
14084     USE(original_target);
14085     simulator.WriteWRegister(0, 1);
14086   };
14087 
14088   simulator.RegisterBranchInterception(void_placeholder, callback);
14089   simulator.RegisterBranchInterception(uint32_placeholder, callback);
14090   simulator.RegisterBranchInterception(void_param_placeholder, callback);
14091   simulator.RegisterBranchInterception(uint32_param_placeholder, callback);
14092 
14093   if (CAN_RUN()) {
14094     RUN();
14095 
14096     ASSERT_EQUAL_32(2, w20);
14097     ASSERT_EQUAL_32(3, w21);
14098     ASSERT_EQUAL_32(1, w22);
14099     ASSERT_EQUAL_32(1, w23);
14100     ASSERT_EQUAL_32(1, w24);
14101     ASSERT_EQUAL_32(1, w25);
14102   }
14103 }
14104 #endif  // #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14105 #endif  // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
14106 
14107 
TEST(optimised_mov_register)14108 TEST(optimised_mov_register) {
14109   SETUP();
14110 
14111   START();
14112   Label start;
14113   __ Bind(&start);
14114   __ Mov(x0, x0);
14115   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0);
14116   __ Mov(w0, w0, kDiscardForSameWReg);
14117   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0);
14118   __ Mov(w0, w0);
14119   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == kInstructionSize);
14120 
14121   END();
14122 
14123   if (CAN_RUN()) {
14124     RUN();
14125   }
14126 }
14127 
14128 
TEST(nop)14129 TEST(nop) {
14130   MacroAssembler masm;
14131 
14132   Label start;
14133   __ Bind(&start);
14134   __ Nop();
14135   // `MacroAssembler::Nop` must generate at least one nop.
14136   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= kInstructionSize);
14137 
14138   masm.FinalizeCode();
14139 }
14140 
14141 
TEST(mte_addg_subg)14142 TEST(mte_addg_subg) {
14143   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
14144 
14145   START();
14146   __ Mov(x0, 0x5555000055555555);
14147 
14148   // Add/subtract an address offset, changing tag each time.
14149   __ Addg(x1, x0, 16, 2);
14150   __ Subg(x2, x1, 16, 1);
14151 
14152   // Add/subtract address offsets, keep tag.
14153   __ Addg(x3, x0, 1008, 0);
14154   __ Subg(x4, x3, 1008, 0);
14155 
14156   // Change tag only. Check wraparound.
14157   __ Addg(x5, x0, 0, 15);
14158   __ Subg(x6, x0, 0, 14);
14159 
14160   // Do nothing.
14161   __ Addg(x7, x0, 0, 0);
14162   __ Subg(x8, x0, 0, 0);
14163 
14164   // Use stack pointer as source/destination.
14165   __ Mov(x20, sp);  // Store original sp.
14166 
14167   __ Subg(sp, sp, 32, 0);  // Claim 32 bytes.
14168   __ Sub(x9, sp, x20);     // Subtract original sp and store difference.
14169 
14170   __ Mov(sp, x20);  // Restore original sp.
14171   __ Claim(32);
14172   __ Addg(sp, sp, 32, 0);  // Drop 32 bytes.
14173   __ Sub(x10, sp, x20);    // Subtract original sp and store difference.
14174 
14175   __ Mov(sp, x20);        // Restore sp (should be no-op)
14176   __ Addg(sp, sp, 0, 1);  // Tag the sp.
14177   __ Sub(x11, sp, x20);  // Subtract original sp and store for later comparison.
14178   __ Mov(sp, x20);       // Restore sp.
14179 
14180   END();
14181 
14182   if (CAN_RUN()) {
14183     RUN();
14184 
14185     ASSERT_EQUAL_64(0x5755000055555565, x1);
14186     ASSERT_EQUAL_64(0x5855000055555555, x2);
14187     ASSERT_EQUAL_64(0x5555000055555945, x3);
14188     ASSERT_EQUAL_64(0x5555000055555555, x4);
14189     ASSERT_EQUAL_64(0x5455000055555555, x5);
14190     ASSERT_EQUAL_64(0x5355000055555555, x6);
14191     ASSERT_EQUAL_64(0x5555000055555555, x7);
14192     ASSERT_EQUAL_64(0x5555000055555555, x8);
14193     ASSERT_EQUAL_64(-32, x9);
14194     ASSERT_EQUAL_64(0, x10);
14195     ASSERT_EQUAL_64(UINT64_C(1) << 56, x11);
14196   }
14197 }
14198 
TEST(mte_subp)14199 TEST(mte_subp) {
14200   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
14201 
14202   START();
14203   __ Mov(x0, 0x5555555555555555);
14204   __ Mov(x1, -42);
14205 
14206   // Test subp with equivalent sbfx/sub(s) operations.
14207   __ Sbfx(x10, x0, 0, 56);
14208   __ Sbfx(x11, x1, 0, 56);
14209 
14210   __ Subp(x4, x0, x1);
14211   __ Sub(x5, x10, x11);
14212 
14213   __ Subp(x6, x1, x0);
14214   __ Sub(x7, x11, x10);
14215 
14216   __ Subps(x8, x0, x1);
14217   __ Mrs(x18, NZCV);
14218   __ Subs(x9, x10, x11);
14219   __ Mrs(x19, NZCV);
14220 
14221   __ Cmpp(x1, x0);
14222   __ Mrs(x20, NZCV);
14223   __ Cmp(x11, x10);
14224   __ Mrs(x21, NZCV);
14225 
14226   // Test equal pointers with mismatched tags compare equal and produce a zero
14227   // difference with subps.
14228   __ Mov(x2, 0x20);  // Exclude tag 5.
14229   __ Irg(x3, x0, x2);
14230   __ Subps(x22, x0, x3);
14231 
14232   END();
14233 
14234   if (CAN_RUN()) {
14235     RUN();
14236 
14237     ASSERT_EQUAL_64(x5, x4);
14238     ASSERT_EQUAL_64(x7, x6);
14239     ASSERT_EQUAL_64(x9, x8);
14240     ASSERT_EQUAL_64(x19, x18);
14241     ASSERT_EQUAL_64(x20, x21);
14242     ASSERT_EQUAL_64(0, x22);
14243     ASSERT_EQUAL_NZCV(ZCFlag);
14244   }
14245 }
14246 
TEST(mte_gmi)14247 TEST(mte_gmi) {
14248   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
14249 
14250   START();
14251   __ Mov(x0, 0xaaaa);
14252   __ Mov(x20, 0x12345678);
14253 
14254   __ Gmi(x0, x20, x0);  // Add mask bit 0.
14255   __ Addg(x20, x20, 0, 1);
14256   __ Gmi(x1, x20, x0);  // No effect.
14257   __ Addg(x20, x20, 0, 1);
14258   __ Gmi(x2, x20, x1);  // Add mask bit 2.
14259   __ Addg(x20, x20, 0, 1);
14260   __ Gmi(x3, x20, x2);  // No effect.
14261   __ Addg(x20, x20, 0, 1);
14262   __ Gmi(x4, x20, x3);  // Add mask bit 4.
14263   __ Addg(x20, x20, 0, 1);
14264   __ Gmi(x5, x20, x4);  // No effect.
14265   __ Addg(x20, x20, 0, 9);
14266   __ Gmi(x6, x20, x5);   // Add mask bit 14.
14267   __ Gmi(x7, x20, xzr);  // Only mask bit 14.
14268   END();
14269 
14270   if (CAN_RUN()) {
14271     RUN();
14272 
14273     ASSERT_EQUAL_64(0xaaab, x0);
14274     ASSERT_EQUAL_64(0xaaab, x1);
14275     ASSERT_EQUAL_64(0xaaaf, x2);
14276     ASSERT_EQUAL_64(0xaaaf, x3);
14277     ASSERT_EQUAL_64(0xaabf, x4);
14278     ASSERT_EQUAL_64(0xaabf, x5);
14279     ASSERT_EQUAL_64(0xeabf, x6);
14280     ASSERT_EQUAL_64(0x4000, x7);
14281   }
14282 }
14283 
TEST(mte_irg)14284 TEST(mte_irg) {
14285   SETUP_WITH_FEATURES(CPUFeatures::kMTE);
14286 
14287   START();
14288   __ Mov(x10, 8);
14289   __ Mov(x0, 0x5555555555555555);
14290   // Insert a random tag repeatedly. If the loop doesn't exit in the expected
14291   // way, it's statistically likely that a random tag was never inserted.
14292   Label loop, failed, done;
14293   __ Bind(&loop);
14294   __ Irg(x1, x0);
14295   __ Sub(x10, x10, 1);
14296   __ Cbz(x10, &failed);  // Exit if loop count exceeded.
14297   __ Cmp(x1, 0x5555555555555555);
14298   __ B(eq, &loop);  // Loop if the tag hasn't changed.
14299 
14300   // Check non-tag bits have not changed.
14301   __ Bic(x1, x1, 0x0f00000000000000);
14302   __ Subs(x1, x1, 0x5055555555555555);
14303   __ B(&done);
14304 
14305   __ Bind(&failed);
14306   __ Mov(x1, 1);
14307 
14308   __ Bind(&done);
14309 
14310   // Insert random tags, excluding oddly-numbered tags, and set a bit in a
14311   // result register for each tag used.
14312   // After 128 rounds, it's statistically likely that all even bits in the
14313   // least-significant half word will be set.
14314   __ Mov(x3, 0);
14315   __ Mov(x4, 1);
14316   __ Mov(x10, 128);
14317   __ Mov(x11, 0xaaaa);
14318 
14319   Label loop2;
14320   __ Bind(&loop2);
14321   __ Irg(x2, x1, x11);
14322   __ Lsr(x2, x2, 56);
14323   __ Lsl(x2, x4, x2);
14324   __ Orr(x3, x3, x2);
14325   __ Subs(x10, x10, 1);
14326   __ B(ne, &loop2);
14327   __ Mov(x2, x3);
14328 
14329   // Check that excluding all tags results in zero tag insertion.
14330   __ Mov(x3, 0xffffffffffffffff);
14331   __ Irg(x3, x3, x3);
14332   END();
14333 
14334   if (CAN_RUN()) {
14335     RUN();
14336 
14337     ASSERT_EQUAL_64(0, x1);
14338     ASSERT_EQUAL_64(0x5555, x2);
14339     ASSERT_EQUAL_64(0xf0ffffffffffffff, x3);
14340   }
14341 }
14342 
TEST(mops_set)14343 TEST(mops_set) {
14344   SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14345 
14346   uint8_t dst[16];
14347   memset(dst, 0x55, ArrayLength(dst));
14348   uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst);
14349 
14350   START();
14351   __ Mov(x0, dst_addr);
14352   __ Add(x1, x0, 1);
14353   __ Mov(x2, 13);
14354   __ Mov(x3, 0x1234aa);
14355 
14356   // Set 13 bytes dst[1] onwards to 0xaa.
14357   __ Setp(x1, x2, x3);
14358   __ Setm(x1, x2, x3);
14359   __ Sete(x1, x2, x3);
14360   __ Mrs(x20, NZCV);
14361 
14362   // x2 is now zero, so this should do nothing.
14363   __ Setp(x1, x2, x3);
14364   __ Setm(x1, x2, x3);
14365   __ Sete(x1, x2, x3);
14366   __ Mrs(x21, NZCV);
14367 
14368   // Set dst[15] to zero using the masm helper.
14369   __ Add(x1, x0, 15);
14370   __ Mov(x2, 1);
14371   __ Set(x1, x2, xzr);
14372   __ Mrs(x22, NZCV);
14373 
14374   // Load dst for comparison.
14375   __ Ldp(x10, x11, MemOperand(x0));
14376   END();
14377 
14378   if (CAN_RUN()) {
14379     // Permitted results:
14380     //            NZCV    Xd                Xn
14381     //  Option A: ....    end of buffer     0
14382     //  Option B: ..C.    end of buffer     0
14383 
14384     std::vector<uint64_t> allowed_flags = {NoFlag, CFlag};
14385 
14386     RUN();
14387     ASSERT_EQUAL_64(allowed_flags, x20);
14388     ASSERT_EQUAL_64(allowed_flags, x21);
14389     ASSERT_EQUAL_64(allowed_flags, x22);
14390     ASSERT_EQUAL_64(dst_addr + 16, x1);
14391     ASSERT_EQUAL_64(0, x2);
14392     ASSERT_EQUAL_64(0x1234aa, x3);
14393     ASSERT_EQUAL_64(0xaaaa'aaaa'aaaa'aa55, x10);
14394     ASSERT_EQUAL_64(0x0055'aaaa'aaaa'aaaa, x11);
14395   }
14396 }
14397 
TEST(mops_setn)14398 TEST(mops_setn) {
14399   SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14400 
14401   // In simulation, non-temporal set is handled by the same code as normal set,
14402   // so only a basic test is required beyond that already provided above.
14403 
14404   uint8_t dst[16] = {0x55};
14405   uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst);
14406 
14407   START();
14408   __ Mov(x0, dst_addr);
14409   __ Mov(x1, x0);
14410   __ Mov(x2, 16);
14411   __ Mov(x3, 0x42);
14412   __ Setn(x1, x2, x3);
14413   __ Mrs(x20, NZCV);
14414   __ Ldp(x10, x11, MemOperand(x0));
14415   END();
14416 
14417   if (CAN_RUN()) {
14418     // Permitted results:
14419     //            NZCV    Xd                Xn
14420     //  Option A: ....    end of buffer     0
14421     //  Option B: ..C.    end of buffer     0
14422 
14423     std::vector<uint64_t> allowed_flags = {NoFlag, CFlag};
14424 
14425     RUN();
14426     ASSERT_EQUAL_64(allowed_flags, x20);
14427     ASSERT_EQUAL_64(dst_addr + 16, x1);
14428     ASSERT_EQUAL_64(0, x2);
14429     ASSERT_EQUAL_64(0x42, x3);
14430     ASSERT_EQUAL_64(0x4242'4242'4242'4242, x10);
14431     ASSERT_EQUAL_64(0x4242'4242'4242'4242, x11);
14432   }
14433 }
14434 
TEST(mops_setg)14435 TEST(mops_setg) {
14436   SETUP_WITH_FEATURES(CPUFeatures::kMOPS, CPUFeatures::kMTE);
14437 
14438   uint8_t* dst = nullptr;
14439 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14440   const int dst_size = 32;
14441   dst = reinterpret_cast<uint8_t*>(
14442       simulator.Mmap(NULL,
14443                      dst_size * sizeof(uint8_t),
14444                      PROT_READ | PROT_WRITE | PROT_MTE,
14445                      MAP_PRIVATE | MAP_ANONYMOUS,
14446                      -1,
14447                      0));
14448 
14449   VIXL_ASSERT(dst != nullptr);
14450   uint8_t* untagged_ptr = AddressUntag(dst);
14451   memset(untagged_ptr, 0xc9, dst_size);
14452 #else
14453 // TODO: Port the memory allocation to work on MTE supported platform natively.
14454 // Note that `CAN_RUN` prevents running in MTE-unsupported environments.
14455 #endif
14456 
14457   uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst);
14458   uint64_t tag_mask = 0xf0ff'ffff'ffff'ffff;
14459 
14460   START();
14461   __ Mov(x0, dst_addr);
14462   __ Gmi(x2, x0, xzr);
14463   __ Irg(x1, x0, x2);  // Choose new tag for setg destination.
14464   __ Mov(x2, 16);
14465   __ Mov(x3, 0x42);
14466   __ Setg(x1, x2, x3);
14467   __ Mrs(x20, NZCV);
14468 
14469   __ Ubfx(x4, x1, 56, 4);  // Extract new tag.
14470   __ Bfi(x0, x4, 56, 4);   // Tag dst_addr so set region can be loaded.
14471   __ Ldp(x10, x11, MemOperand(x0));
14472 
14473   __ Mov(x0, dst_addr);
14474   __ Ldp(x12, x13, MemOperand(x0, 16));  // Unset region has original tag.
14475 
14476   __ And(x1, x1, tag_mask);  // Strip tag for repeatable checks.
14477   END();
14478 
14479   if (CAN_RUN()) {
14480     // Permitted results:
14481     //            NZCV    Xd                Xn
14482     //  Option A: ....    end of buffer     0
14483     //  Option B: ..C.    end of buffer     0
14484 
14485     std::vector<uint64_t> allowed_flags = {NoFlag, CFlag};
14486 
14487     RUN();
14488     ASSERT_EQUAL_64(allowed_flags, x20);
14489     ASSERT_EQUAL_64((dst_addr & tag_mask) + 16, x1);
14490     ASSERT_EQUAL_64(0, x2);
14491     ASSERT_EQUAL_64(0x42, x3);
14492     ASSERT_EQUAL_64(0x4242'4242'4242'4242, x10);
14493     ASSERT_EQUAL_64(0x4242'4242'4242'4242, x11);
14494     ASSERT_EQUAL_64(0xc9c9'c9c9'c9c9'c9c9, x12);
14495     ASSERT_EQUAL_64(0xc9c9'c9c9'c9c9'c9c9, x13);
14496   }
14497 
14498 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
14499   simulator.Munmap(dst, dst_size, PROT_MTE);
14500 #endif
14501 }
14502 
TEST(mops_cpy)14503 TEST(mops_cpy) {
14504   SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14505 
14506   uint8_t buf[16];
14507   uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14508 
14509   for (unsigned i = 0; i < ArrayLength(buf); i++) {
14510     buf[i] = i;
14511   }
14512 
14513   START();
14514   __ Mov(x0, buf_addr);
14515 
14516   // Copy first eight bytes into second eight.
14517   __ Mov(x1, x0);     // src = &buf[0]
14518   __ Add(x2, x0, 8);  // dst = &buf[8]
14519   __ Mov(x3, 8);      // count = 8
14520   __ Cpyp(x2, x1, x3);
14521   __ Cpym(x2, x1, x3);
14522   __ Cpye(x2, x1, x3);
14523   __ Ldp(x10, x11, MemOperand(x0));
14524   __ Mrs(x20, NZCV);
14525 
14526   // Copy first eight bytes to overlapping offset, forcing backwards copy.
14527   __ Mov(x4, x0);     // src = &buf[0]
14528   __ Add(x5, x0, 4);  // dst = &buf[4]
14529   __ Mov(x6, 8);      // count = 8
14530   __ Cpy(x5, x4, x6);
14531   __ Ldp(x12, x13, MemOperand(x0));
14532   __ Mrs(x21, NZCV);
14533 
14534   // Copy last eight bytes to overlapping offset, forcing forwards copy.
14535   __ Add(x7, x0, 8);  // src = &buf[8]
14536   __ Add(x8, x0, 6);  // dst = &buf[6]
14537   __ Mov(x9, 8);      // count = 8
14538   __ Cpy(x8, x7, x9);
14539   __ Ldp(x14, x15, MemOperand(x0));
14540   __ Mrs(x22, NZCV);
14541   END();
14542 
14543   if (CAN_RUN()) {
14544     // Permitted results:
14545     //                        NZCV    Xs/Xd               Xn
14546     //  Option A (forwards) : ....    ends of buffers     0
14547     //  Option A (backwards): ....    starts of buffers   0
14548     //  Option B (forwards) : ..C.    ends of buffers     0
14549     //  Option B (backwards): N.C.    starts of buffers   0
14550 
14551     std::vector<uint64_t> allowed_backwards_flags = {NoFlag, NCFlag};
14552     std::vector<uint64_t> allowed_forwards_flags = {NoFlag, CFlag};
14553 
14554     RUN();
14555     // IMPLEMENTATION DEFINED direction
14556     if (static_cast<uintptr_t>(core.xreg(2)) > buf_addr) {
14557       // Forwards
14558       ASSERT_EQUAL_64(buf_addr + 8, x1);
14559       ASSERT_EQUAL_64(buf_addr + 16, x2);
14560       ASSERT_EQUAL_64(allowed_forwards_flags, x20);
14561     } else {
14562       // Backwards
14563       ASSERT_EQUAL_64(buf_addr, x1);
14564       ASSERT_EQUAL_64(buf_addr + 8, x2);
14565       ASSERT_EQUAL_64(allowed_backwards_flags, x20);
14566     }
14567     ASSERT_EQUAL_64(0, x3);  // Xn
14568     ASSERT_EQUAL_64(0x0706'0504'0302'0100, x10);
14569     ASSERT_EQUAL_64(0x0706'0504'0302'0100, x11);
14570 
14571     ASSERT_EQUAL_64(buf_addr, x4);      // Xs
14572     ASSERT_EQUAL_64(buf_addr + 4, x5);  // Xd
14573     ASSERT_EQUAL_64(0, x6);             // Xn
14574     ASSERT_EQUAL_64(0x0302'0100'0302'0100, x12);
14575     ASSERT_EQUAL_64(0x0706'0504'0706'0504, x13);
14576     ASSERT_EQUAL_64(allowed_backwards_flags, x21);
14577 
14578     ASSERT_EQUAL_64(buf_addr + 16, x7);  // Xs
14579     ASSERT_EQUAL_64(buf_addr + 14, x8);  // Xd
14580     ASSERT_EQUAL_64(0, x9);              // Xn
14581     ASSERT_EQUAL_64(0x0504'0100'0302'0100, x14);
14582     ASSERT_EQUAL_64(0x0706'0706'0504'0706, x15);
14583     ASSERT_EQUAL_64(allowed_forwards_flags, x22);
14584   }
14585 }
14586 
TEST(mops_cpyn)14587 TEST(mops_cpyn) {
14588   SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14589 
14590   // In simulation, non-temporal cpy is handled by the same code as normal cpy,
14591   // so only a basic test is required beyond that already provided above.
14592 
14593   uint8_t buf[16];
14594   uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14595 
14596   for (unsigned i = 0; i < ArrayLength(buf); i++) {
14597     buf[i] = i;
14598   }
14599 
14600   START();
14601   __ Mov(x0, buf_addr);
14602 
14603   __ Add(x1, x0, 1);  // src = &buf[1]
14604   __ Mov(x2, x0);     // dst = &buf[0]
14605   __ Mov(x3, 15);     // count = 15
14606   __ Cpyn(x2, x1, x3);
14607   __ Ldp(x10, x11, MemOperand(x0));
14608   __ Mrs(x20, NZCV);
14609 
14610   __ Add(x4, x0, 1);  // src = &buf[1]
14611   __ Mov(x5, x0);     // dst = &buf[0]
14612   __ Mov(x6, 15);     // count = 15
14613   __ Cpyrn(x5, x4, x6);
14614   __ Ldp(x12, x13, MemOperand(x0));
14615   __ Mrs(x21, NZCV);
14616 
14617   __ Add(x7, x0, 1);  // src = &buf[1]
14618   __ Mov(x8, x0);     // dst = &buf[0]
14619   __ Mov(x9, 15);     // count = 15
14620   __ Cpywn(x8, x7, x9);
14621   __ Ldp(x14, x15, MemOperand(x0));
14622   __ Mrs(x22, NZCV);
14623   END();
14624 
14625   if (CAN_RUN()) {
14626     // Permitted results:
14627     //                        NZCV    Xs/Xd               Xn
14628     //  Option A (forwards) : ....    ends of buffers     0
14629     //  Option A (backwards): ....    starts of buffers   0
14630     //  Option B (forwards) : ..C.    ends of buffers     0
14631     //  Option B (backwards): N.C.    starts of buffers   0
14632     //
14633     // All cases overlap to force a forwards copy.
14634 
14635     std::vector<uint64_t> allowed_forwards_flags = {NoFlag, CFlag};
14636 
14637     RUN();
14638     ASSERT_EQUAL_64(buf_addr + 16, x1);  // Xs
14639     ASSERT_EQUAL_64(buf_addr + 15, x2);  // Xd
14640     ASSERT_EQUAL_64(0, x3);              // Xn
14641     ASSERT_EQUAL_64(allowed_forwards_flags, x20);
14642     ASSERT_EQUAL_64(0x0807'0605'0403'0201, x10);
14643     ASSERT_EQUAL_64(0x0f0f'0e0d'0c0b'0a09, x11);
14644 
14645     ASSERT_EQUAL_64(buf_addr + 16, x4);  // Xs
14646     ASSERT_EQUAL_64(buf_addr + 15, x5);  // Xd
14647     ASSERT_EQUAL_64(0, x6);              // Xn
14648     ASSERT_EQUAL_64(allowed_forwards_flags, x21);
14649     ASSERT_EQUAL_64(0x0908'0706'0504'0302, x12);
14650     ASSERT_EQUAL_64(0x0f0f'0f0e'0d0c'0b0a, x13);
14651 
14652     ASSERT_EQUAL_64(buf_addr + 16, x7);  // Xs
14653     ASSERT_EQUAL_64(buf_addr + 15, x8);  // Xd
14654     ASSERT_EQUAL_64(0, x9);              // Xn
14655     ASSERT_EQUAL_64(allowed_forwards_flags, x22);
14656     ASSERT_EQUAL_64(0x0a09'0807'0605'0403, x14);
14657     ASSERT_EQUAL_64(0x0f0f'0f0f'0e0d'0c0b, x15);
14658   }
14659 }
14660 
TEST(mops_cpyf)14661 TEST(mops_cpyf) {
14662   SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14663 
14664   uint8_t buf[16];
14665   uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14666 
14667   for (unsigned i = 0; i < ArrayLength(buf); i++) {
14668     buf[i] = i;
14669   }
14670 
14671   // As `mops_cpy`, but `cpyf` always copies forwards, so is only useful for
14672   // non-overlapping buffers, or those where the source address is greater than
14673   // the destination address.
14674 
14675   START();
14676   __ Mov(x0, buf_addr);
14677 
14678   // Copy first eight bytes into second eight, without overlap.
14679   __ Mov(x1, x0);     // src = &buf[0]
14680   __ Add(x2, x0, 8);  // dst = &buf[8]
14681   __ Mov(x3, 8);      // count = 8
14682   __ Cpyfp(x2, x1, x3);
14683   __ Cpyfm(x2, x1, x3);
14684   __ Cpyfe(x2, x1, x3);
14685   __ Ldp(x10, x11, MemOperand(x0));
14686   __ Mrs(x20, NZCV);
14687 
14688   // Copy last eight bytes to overlapping offset where src < dst.
14689   __ Add(x4, x0, 8);  // src = &buf[8]
14690   __ Add(x5, x0, 6);  // dst = &buf[6]
14691   __ Mov(x6, 8);      // count = 8
14692   __ Cpyf(x5, x4, x6);
14693   __ Ldp(x12, x13, MemOperand(x0));
14694   __ Mrs(x21, NZCV);
14695 
14696   // Copy first eight bytes to overlapping offset where src > dst.
14697   __ Mov(x7, x0);     // src = &buf[0]
14698   __ Add(x8, x0, 4);  // dst = &buf[4]
14699   __ Mov(x9, 8);      // count = 8
14700   __ Cpyf(x8, x7, x9);
14701   // The only testable result is the first and last four bytes, which are not
14702   // written at all.
14703   __ Ldr(w14, MemOperand(x0));
14704   __ Ldr(w15, MemOperand(x0, 12));
14705   __ Mrs(x22, NZCV);
14706 
14707   END();
14708 
14709   if (CAN_RUN()) {
14710     // Permitted results:
14711     //            NZCV    Xs/Xd               Xn
14712     //  Option A: ....    ends of buffers     0
14713     //  Option B: ..C.    ends of buffers     0
14714 
14715     std::vector<uint64_t> allowed_forwards_flags = {NoFlag, CFlag};
14716 
14717     RUN();
14718 
14719     // No overlap.
14720     ASSERT_EQUAL_64(buf_addr + 8, x1);   // Xs
14721     ASSERT_EQUAL_64(buf_addr + 16, x2);  // Xd
14722     ASSERT_EQUAL_64(0, x3);              // Xn
14723     ASSERT_EQUAL_64(allowed_forwards_flags, x20);
14724     ASSERT_EQUAL_64(0x0706'0504'0302'0100, x10);
14725     ASSERT_EQUAL_64(0x0706'0504'0302'0100, x11);
14726 
14727     // Overlap, src > dst.
14728     ASSERT_EQUAL_64(buf_addr + 16, x4);  // Xs
14729     ASSERT_EQUAL_64(buf_addr + 14, x5);  // Xd
14730     ASSERT_EQUAL_64(0, x6);              // Xn
14731     ASSERT_EQUAL_64(0x0100'0504'0302'0100, x12);
14732     ASSERT_EQUAL_64(0x0706'0706'0504'0302, x13);
14733     ASSERT_EQUAL_64(allowed_forwards_flags, x21);
14734 
14735     // Overlap, src < dst.
14736     ASSERT_EQUAL_64(buf_addr + 8, x7);   // Xs
14737     ASSERT_EQUAL_64(buf_addr + 12, x8);  // Xd
14738     ASSERT_EQUAL_64(0, x9);              // Xn
14739     // We can only reliably test that the operation didn't write outside the
14740     // specified region.
14741     ASSERT_EQUAL_32(0x0302'0100, w14);
14742     ASSERT_EQUAL_32(0x0706'0706, w15);
14743     ASSERT_EQUAL_64(allowed_forwards_flags, x22);
14744   }
14745 }
14746 
TEST(mops_cpyfn)14747 TEST(mops_cpyfn) {
14748   SETUP_WITH_FEATURES(CPUFeatures::kMOPS);
14749 
14750   // In simulation, non-temporal cpy is handled by the same code as normal cpy,
14751   // so only a basic test is required beyond that already provided above.
14752 
14753   uint8_t buf[16];
14754   uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
14755 
14756   for (unsigned i = 0; i < ArrayLength(buf); i++) {
14757     buf[i] = i;
14758   }
14759 
14760   START();
14761   __ Mov(x0, buf_addr);
14762 
14763   __ Add(x1, x0, 1);  // src = &buf[1]
14764   __ Mov(x2, x0);     // dst = &buf[0]
14765   __ Mov(x3, 15);     // count = 15
14766   __ Cpyfn(x2, x1, x3);
14767   __ Ldp(x10, x11, MemOperand(x0));
14768   __ Mrs(x20, NZCV);
14769 
14770   __ Add(x4, x0, 1);  // src = &buf[1]
14771   __ Mov(x5, x0);     // dst = &buf[0]
14772   __ Mov(x6, 15);     // count = 15
14773   __ Cpyfrn(x5, x4, x6);
14774   __ Ldp(x12, x13, MemOperand(x0));
14775   __ Mrs(x21, NZCV);
14776 
14777   __ Add(x7, x0, 1);  // src = &buf[1]
14778   __ Mov(x8, x0);     // dst = &buf[0]
14779   __ Mov(x9, 15);     // count = 15
14780   __ Cpyfwn(x8, x7, x9);
14781   __ Ldp(x14, x15, MemOperand(x0));
14782   __ Mrs(x22, NZCV);
14783   END();
14784 
14785   if (CAN_RUN()) {
14786     // Permitted results:
14787     //            NZCV    Xs/Xd               Xn
14788     //  Option A: ....    ends of buffers     0
14789     //  Option B: ..C.    ends of buffers     0
14790 
14791     std::vector<uint64_t> allowed_flags = {NoFlag, CFlag};
14792 
14793     RUN();
14794     ASSERT_EQUAL_64(buf_addr + 16, x1);  // Xs
14795     ASSERT_EQUAL_64(buf_addr + 15, x2);  // Xd
14796     ASSERT_EQUAL_64(0, x3);              // Xn
14797     ASSERT_EQUAL_64(allowed_flags, x20);
14798     ASSERT_EQUAL_64(0x0807'0605'0403'0201, x10);
14799     ASSERT_EQUAL_64(0x0f0f'0e0d'0c0b'0a09, x11);
14800 
14801     ASSERT_EQUAL_64(buf_addr + 16, x4);  // Xs
14802     ASSERT_EQUAL_64(buf_addr + 15, x5);  // Xd
14803     ASSERT_EQUAL_64(0, x6);              // Xn
14804     ASSERT_EQUAL_64(allowed_flags, x21);
14805     ASSERT_EQUAL_64(0x0908'0706'0504'0302, x12);
14806     ASSERT_EQUAL_64(0x0f0f'0f0e'0d0c'0b0a, x13);
14807 
14808     ASSERT_EQUAL_64(buf_addr + 16, x7);  // Xs
14809     ASSERT_EQUAL_64(buf_addr + 15, x8);  // Xd
14810     ASSERT_EQUAL_64(0, x9);              // Xn
14811     ASSERT_EQUAL_64(allowed_flags, x22);
14812     ASSERT_EQUAL_64(0x0a09'0807'0605'0403, x14);
14813     ASSERT_EQUAL_64(0x0f0f'0f0f'0e0d'0c0b, x15);
14814   }
14815 }
14816 
TEST(cssc_abs)14817 TEST(cssc_abs) {
14818   SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14819 
14820   START();
14821   __ Mov(x0, -1);
14822   __ Mov(x1, 1);
14823   __ Mov(x2, 0);
14824   __ Mov(x3, 0x7fff'ffff);
14825   __ Mov(x4, 0x8000'0000);
14826   __ Mov(x5, 0x8000'0001);
14827   __ Mov(x6, 0x7fff'ffff'ffff'ffff);
14828   __ Mov(x7, 0x8000'0000'0000'0000);
14829   __ Mov(x8, 0x8000'0000'0000'0001);
14830 
14831   __ Abs(w10, w0);
14832   __ Abs(x11, x0);
14833   __ Abs(w12, w1);
14834   __ Abs(x13, x1);
14835   __ Abs(w14, w2);
14836   __ Abs(x15, x2);
14837 
14838   __ Abs(w19, w3);
14839   __ Abs(x20, x3);
14840   __ Abs(w21, w4);
14841   __ Abs(x22, x4);
14842   __ Abs(w23, w5);
14843   __ Abs(x24, x5);
14844   __ Abs(w25, w6);
14845   __ Abs(x26, x6);
14846   __ Abs(w27, w7);
14847   __ Abs(x28, x7);
14848   __ Abs(w29, w8);
14849   __ Abs(x30, x8);
14850   END();
14851 
14852   if (CAN_RUN()) {
14853     RUN();
14854 
14855     ASSERT_EQUAL_64(1, x10);
14856     ASSERT_EQUAL_64(1, x11);
14857     ASSERT_EQUAL_64(1, x12);
14858     ASSERT_EQUAL_64(1, x13);
14859     ASSERT_EQUAL_64(0, x14);
14860     ASSERT_EQUAL_64(0, x15);
14861     ASSERT_EQUAL_64(0x7fff'ffff, x19);
14862     ASSERT_EQUAL_64(0x7fff'ffff, x20);
14863     ASSERT_EQUAL_64(0x8000'0000, x21);
14864     ASSERT_EQUAL_64(0x8000'0000, x22);
14865     ASSERT_EQUAL_64(0x7fff'ffff, x23);
14866     ASSERT_EQUAL_64(0x8000'0001, x24);
14867     ASSERT_EQUAL_64(1, x25);
14868     ASSERT_EQUAL_64(0x7fff'ffff'ffff'ffff, x26);
14869     ASSERT_EQUAL_64(0, x27);
14870     ASSERT_EQUAL_64(0x8000'0000'0000'0000, x28);
14871     ASSERT_EQUAL_64(1, x29);
14872     ASSERT_EQUAL_64(0x7fff'ffff'ffff'ffff, x30);
14873   }
14874 }
14875 
TEST(cssc_cnt)14876 TEST(cssc_cnt) {
14877   SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14878 
14879   START();
14880   __ Mov(x0, -1);
14881   __ Mov(x1, 1);
14882   __ Mov(x2, 0);
14883   __ Mov(x3, 0x7fff'ffff);
14884   __ Mov(x4, 0x8000'0000);
14885   __ Mov(x5, 0x8000'0001);
14886   __ Mov(x6, 0x7fff'ffff'ffff'ffff);
14887   __ Mov(x7, 0x4242'4242'aaaa'aaaa);
14888 
14889   __ Cnt(w10, w0);
14890   __ Cnt(x11, x0);
14891   __ Cnt(w12, w1);
14892   __ Cnt(x13, x1);
14893   __ Cnt(w14, w2);
14894   __ Cnt(x15, x2);
14895   __ Cnt(w19, w3);
14896   __ Cnt(x20, x3);
14897   __ Cnt(w21, w4);
14898   __ Cnt(x22, x4);
14899   __ Cnt(w23, w5);
14900   __ Cnt(x24, x5);
14901   __ Cnt(w25, w6);
14902   __ Cnt(x26, x6);
14903   __ Cnt(w27, w7);
14904   __ Cnt(x28, x7);
14905   END();
14906 
14907   if (CAN_RUN()) {
14908     RUN();
14909 
14910     ASSERT_EQUAL_64(32, x10);
14911     ASSERT_EQUAL_64(64, x11);
14912     ASSERT_EQUAL_64(1, x12);
14913     ASSERT_EQUAL_64(1, x13);
14914     ASSERT_EQUAL_64(0, x14);
14915     ASSERT_EQUAL_64(0, x15);
14916     ASSERT_EQUAL_64(31, x19);
14917     ASSERT_EQUAL_64(31, x20);
14918     ASSERT_EQUAL_64(1, x21);
14919     ASSERT_EQUAL_64(1, x22);
14920     ASSERT_EQUAL_64(2, x23);
14921     ASSERT_EQUAL_64(2, x24);
14922     ASSERT_EQUAL_64(32, x25);
14923     ASSERT_EQUAL_64(63, x26);
14924     ASSERT_EQUAL_64(16, x27);
14925     ASSERT_EQUAL_64(24, x28);
14926   }
14927 }
14928 
TEST(cssc_ctz)14929 TEST(cssc_ctz) {
14930   SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14931 
14932   START();
14933   __ Mov(x0, -1);
14934   __ Mov(x1, 1);
14935   __ Mov(x2, 2);
14936   __ Mov(x3, 0x7fff'ff00);
14937   __ Mov(x4, 0x8000'4000);
14938   __ Mov(x5, 0x4000'0001);
14939   __ Mov(x6, 0x0000'0001'0000'0000);
14940   __ Mov(x7, 0x4200'0000'0000'0000);
14941 
14942   __ Ctz(w10, w0);
14943   __ Ctz(x11, x0);
14944   __ Ctz(w12, w1);
14945   __ Ctz(x13, x1);
14946   __ Ctz(w14, w2);
14947   __ Ctz(x15, x2);
14948   __ Ctz(w19, w3);
14949   __ Ctz(x20, x3);
14950   __ Ctz(w21, w4);
14951   __ Ctz(x22, x4);
14952   __ Ctz(w23, w5);
14953   __ Ctz(x24, x5);
14954   __ Ctz(w25, w6);
14955   __ Ctz(x26, x6);
14956   __ Ctz(w27, w7);
14957   __ Ctz(x28, x7);
14958   END();
14959 
14960   if (CAN_RUN()) {
14961     RUN();
14962 
14963     ASSERT_EQUAL_64(0, x10);
14964     ASSERT_EQUAL_64(0, x11);
14965     ASSERT_EQUAL_64(0, x12);
14966     ASSERT_EQUAL_64(0, x13);
14967     ASSERT_EQUAL_64(1, x14);
14968     ASSERT_EQUAL_64(1, x15);
14969     ASSERT_EQUAL_64(8, x19);
14970     ASSERT_EQUAL_64(8, x20);
14971     ASSERT_EQUAL_64(14, x21);
14972     ASSERT_EQUAL_64(14, x22);
14973     ASSERT_EQUAL_64(0, x23);
14974     ASSERT_EQUAL_64(0, x24);
14975     ASSERT_EQUAL_64(32, x25);
14976     ASSERT_EQUAL_64(32, x26);
14977     ASSERT_EQUAL_64(32, x27);
14978     ASSERT_EQUAL_64(57, x28);
14979   }
14980 }
14981 
14982 using MinMaxOp = void (MacroAssembler::*)(const Register&,
14983                                           const Register&,
14984                                           const Operand&);
14985 
MinMaxHelper(MinMaxOp op,bool is_signed,uint64_t a,uint64_t b,uint32_t wexp,uint64_t xexp)14986 static void MinMaxHelper(MinMaxOp op,
14987                          bool is_signed,
14988                          uint64_t a,
14989                          uint64_t b,
14990                          uint32_t wexp,
14991                          uint64_t xexp) {
14992   SETUP_WITH_FEATURES(CPUFeatures::kCSSC);
14993 
14994   START();
14995   __ Mov(x0, a);
14996   __ Mov(x1, b);
14997   if ((is_signed && IsInt8(b)) || (!is_signed && IsUint8(b))) {
14998     (masm.*op)(w10, w0, b);
14999     (masm.*op)(x11, x0, b);
15000   } else {
15001     (masm.*op)(w10, w0, w1);
15002     (masm.*op)(x11, x0, x1);
15003   }
15004   END();
15005 
15006   if (CAN_RUN()) {
15007     RUN();
15008     ASSERT_EQUAL_64(wexp, x10);
15009     ASSERT_EQUAL_64(xexp, x11);
15010   }
15011 }
15012 
TEST(cssc_umin)15013 TEST(cssc_umin) {
15014   MinMaxOp op = &MacroAssembler::Umin;
15015   uint32_t s32min = 0x8000'0000;
15016   uint32_t s32max = 0x7fff'ffff;
15017   uint64_t s64min = 0x8000'0000'0000'0000;
15018   uint64_t s64max = 0x7fff'ffff'ffff'ffff;
15019 
15020   MinMaxHelper(op, false, 0, 0, 0, 0);
15021   MinMaxHelper(op, false, 128, 255, 128, 128);
15022   MinMaxHelper(op, false, 0, 0xffff'ffff'ffff'ffff, 0, 0);
15023   MinMaxHelper(op, false, s32max, s32min, s32max, s32max);
15024   MinMaxHelper(op, false, s32min, s32max, s32max, s32max);
15025   MinMaxHelper(op, false, s64max, s32min, s32min, s32min);
15026   MinMaxHelper(op, false, s64min, s64max, 0, s64max);
15027 }
15028 
TEST(cssc_umax)15029 TEST(cssc_umax) {
15030   MinMaxOp op = &MacroAssembler::Umax;
15031   uint32_t s32min = 0x8000'0000;
15032   uint32_t s32max = 0x7fff'ffff;
15033   uint64_t s64min = 0x8000'0000'0000'0000;
15034   uint64_t s64max = 0x7fff'ffff'ffff'ffff;
15035 
15036   MinMaxHelper(op, false, 0, 0, 0, 0);
15037   MinMaxHelper(op, false, 128, 255, 255, 255);
15038   MinMaxHelper(op,
15039                false,
15040                0,
15041                0xffff'ffff'ffff'ffff,
15042                0xffff'ffff,
15043                0xffff'ffff'ffff'ffff);
15044   MinMaxHelper(op, false, s32max, s32min, s32min, s32min);
15045   MinMaxHelper(op, false, s32min, s32max, s32min, s32min);
15046   MinMaxHelper(op, false, s64max, s32min, 0xffff'ffff, s64max);
15047   MinMaxHelper(op, false, s64min, s64max, 0xffff'ffff, s64min);
15048 }
15049 
TEST(cssc_smin)15050 TEST(cssc_smin) {
15051   MinMaxOp op = &MacroAssembler::Smin;
15052   uint32_t s32min = 0x8000'0000;
15053   uint32_t s32max = 0x7fff'ffff;
15054   uint64_t s64min = 0x8000'0000'0000'0000;
15055   uint64_t s64max = 0x7fff'ffff'ffff'ffff;
15056 
15057   MinMaxHelper(op, true, 0, 0, 0, 0);
15058   MinMaxHelper(op, true, 128, 255, 128, 128);
15059   MinMaxHelper(op,
15060                true,
15061                0,
15062                0xffff'ffff'ffff'ffff,
15063                0xffff'ffff,
15064                0xffff'ffff'ffff'ffff);
15065   MinMaxHelper(op, true, s32max, s32min, s32min, s32max);
15066   MinMaxHelper(op, true, s32min, s32max, s32min, s32max);
15067   MinMaxHelper(op, true, s64max, s32min, s32min, s32min);
15068   MinMaxHelper(op, true, s64min, s64max, 0xffff'ffff, s64min);
15069 }
15070 
TEST(cssc_smax)15071 TEST(cssc_smax) {
15072   MinMaxOp op = &MacroAssembler::Smax;
15073   uint32_t s32min = 0x8000'0000;
15074   uint32_t s32max = 0x7fff'ffff;
15075   uint64_t s64min = 0x8000'0000'0000'0000;
15076   uint64_t s64max = 0x7fff'ffff'ffff'ffff;
15077 
15078   MinMaxHelper(op, true, 0, 0, 0, 0);
15079   MinMaxHelper(op, true, 128, 255, 255, 255);
15080   MinMaxHelper(op, true, 0, 0xffff'ffff'ffff'ffff, 0, 0);
15081   MinMaxHelper(op, true, s32max, s32min, s32max, s32min);
15082   MinMaxHelper(op, true, s32min, s32max, s32max, s32min);
15083   MinMaxHelper(op, true, s64max, s32min, 0xffff'ffff, s64max);
15084   MinMaxHelper(op, true, s64min, s64max, 0, s64max);
15085 }
15086 
ChkfeatHelper(uint64_t initial,uint64_t chkfeat,CPUFeatures require)15087 static void ChkfeatHelper(uint64_t initial,
15088                           uint64_t chkfeat,
15089                           CPUFeatures require) {
15090   SETUP_WITH_FEATURES(require);
15091 
15092   START();
15093   __ Mov(x16, initial);
15094   __ Chkfeat(x16);
15095   __ Mov(x0, x16);
15096 
15097   __ Mov(x1, initial);
15098   __ Chkfeat(x1);
15099   END();
15100 
15101   if (CAN_RUN()) {
15102     RUN_WITHOUT_SEEN_FEATURE_CHECK();
15103     ASSERT_EQUAL_64(chkfeat, x0);
15104     ASSERT_EQUAL_64(x0, x1);
15105   }
15106 }
15107 
TEST(chkfeat)15108 TEST(chkfeat) { ChkfeatHelper(0x0, 0x0, CPUFeatures::None()); }
15109 
TEST(chkfeat_gcs)15110 TEST(chkfeat_gcs) { ChkfeatHelper(0x1, 0x0, CPUFeatures::kGCS); }
15111 
TEST(chkfeat_unused)15112 TEST(chkfeat_unused) {
15113   // Bits 1-63 are reserved. This test ensures that they are unmodified by
15114   // `chkfeat`, but it will need to be updated if these bits are assigned in the
15115   // future.
15116   ChkfeatHelper(0xffff'ffff'ffff'fffe,
15117                 0xffff'ffff'ffff'fffe,
15118                 CPUFeatures::None());
15119 }
15120 
TEST(gcs_feature_off)15121 TEST(gcs_feature_off) {
15122   SETUP();
15123 
15124   START();
15125 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
15126   simulator.DisableGCSCheck();
15127 #else
15128 // TODO: Disable GCS via operating system for this test, here and in the
15129 // gcs_off_pac_on test below.
15130 #endif
15131   __ Mov(x16, 0x0123'4567'89ab'cdef);
15132   __ Chkfeat(x16);
15133 
15134   // This sequence would fail with GCS enabled.
15135   Label lab, end;
15136   __ Bl(&lab);
15137   __ B(&end);
15138 
15139   __ Bind(&lab);
15140   __ Adr(lr, &end);
15141   __ Ret();
15142 
15143   __ Bind(&end);
15144   END();
15145 
15146   if (CAN_RUN()) {
15147     // TODO: This will currently fail on GCS-supporting hardware.
15148     RUN();
15149     ASSERT_EQUAL_64(0x0123'4567'89ab'cdef, x16);
15150   }
15151 }
15152 
TEST(gcs_gcspushm)15153 TEST(gcs_gcspushm) {
15154   SETUP_WITH_FEATURES(CPUFeatures::kGCS);
15155 
15156   Label ret;
15157   START();
15158   __ Adr(x0, &ret);
15159   __ Gcspushm(x0);
15160   __ Ret(x0);
15161   __ Nop();
15162   __ Bind(&ret);
15163   END();
15164 
15165   if (CAN_RUN()) {
15166     RUN();
15167   }
15168 }
15169 
TEST(gcs_gcspopm)15170 TEST(gcs_gcspopm) {
15171   SETUP_WITH_FEATURES(CPUFeatures::kGCS);
15172 
15173   Label lab, ret;
15174   START();
15175   __ Adr(x0, &ret);
15176   __ Bl(&lab);
15177   __ Bind(&ret);
15178   __ Nop();
15179   __ Bind(&lab);
15180   __ Gcspopm(x1);
15181   END();
15182 
15183   if (CAN_RUN()) {
15184     RUN();
15185     ASSERT_EQUAL_64(x0, x1);
15186   }
15187 }
15188 
TEST(gcs_gcsss1)15189 TEST(gcs_gcsss1) {
15190   SETUP_WITH_FEATURES(CPUFeatures::kGCS);
15191 
15192   START();
15193 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
15194   uint64_t new_gcs = simulator.GetGCSManager().AllocateStack();
15195   __ Mov(x0, new_gcs);
15196 #else
15197 // TODO: Request new GCS from the operating system.
15198 #endif
15199 
15200   // Partial stack swap to check GCS has changed, and a token is at the top
15201   // of the new stack.
15202   __ Gcsss1(x0);
15203   __ Gcspopm(x1);
15204 
15205   __ Bic(x0, x0, 7);  // Clear LSB of new GCS.
15206   __ Bic(x2, x1, 7);  // Clear LSB of old GCS.
15207   __ Cmp(x0, x2);
15208   __ Cset(x0, eq);
15209   __ And(x1, x1, 7);  // In progress token.
15210   END();
15211 
15212   if (CAN_RUN()) {
15213     RUN();
15214     ASSERT_EQUAL_64(0, x0);  // GCS must not be equal.
15215     ASSERT_EQUAL_64(5, x1);  // In progress token must be present.
15216   }
15217 }
15218 
15219 // TODO: Add extra tests for combinations of PAC and GCS enabled.
TEST(gcs_stack_swap)15220 TEST(gcs_stack_swap) {
15221   SETUP_WITH_FEATURES(CPUFeatures::kGCS);
15222 
15223   START();
15224   Label stack_swap, sub_fn, end;
15225 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
15226   uint64_t new_gcs = simulator.GetGCSManager().AllocateStack();
15227   __ Mov(x0, new_gcs);
15228 #else
15229 // TODO: Request new GCS from the operating system.
15230 #endif
15231   __ Bl(&stack_swap);
15232   __ B(&end);
15233 
15234   __ Bind(&stack_swap);
15235   __ Gcsss1(x0);  // x0 = new GCS.
15236   __ Gcsss2(x1);  // x1 = old GCS.
15237   __ Mov(x29, lr);
15238   __ Bl(&sub_fn);
15239   __ Mov(lr, x29);
15240   __ Gcsss1(x1);  // Restore old GCS.
15241   __ Gcsss2(x0);
15242   __ Ret();
15243 
15244   __ Bind(&sub_fn);
15245   __ Mov(x2, 42);
15246   __ Ret();
15247 
15248   __ Bind(&end);
15249   END();
15250 
15251   if (CAN_RUN()) {
15252     RUN();
15253     ASSERT_EQUAL_64(42, x2);
15254   }
15255 }
15256 
TEST(gcs_off_pac_on)15257 TEST(gcs_off_pac_on) {
15258   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
15259 
15260   START();
15261 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
15262   simulator.DisableGCSCheck();
15263 #else
15264 // TODO: Disable GCS via operating system for this test, and enable for native.
15265 #endif
15266   __ Mov(x16, 1);
15267   __ Chkfeat(x16);
15268   __ Mov(x1, x16);
15269 
15270   Label fn1, after_fn1;
15271 
15272   __ Mov(x28, sp);
15273   __ Mov(x29, lr);
15274   __ Mov(sp, 0x477d469dec0b8760);
15275 
15276   __ Mov(x0, 0);
15277   __ B(&after_fn1);
15278 
15279   __ Bind(&fn1);
15280   __ Mov(x0, 42);
15281   __ Paciasp();
15282   __ Retaa();
15283 
15284   __ Bind(&after_fn1);
15285   __ Bl(&fn1);
15286 
15287   __ Mov(sp, x28);
15288   __ Mov(lr, x29);
15289   END();
15290 
15291   if (CAN_RUN()) {
15292     RUN();
15293 
15294     ASSERT_EQUAL_64(42, x0);
15295     ASSERT_EQUAL_64(1, x1);
15296   }
15297 }
15298 
15299 #ifdef VIXL_NEGATIVE_TESTING
TEST(gcs_negative_test)15300 TEST(gcs_negative_test) {
15301   SETUP_WITH_FEATURES(CPUFeatures::kGCS);
15302 
15303   Label fn, bad_return_addr, done;
15304   START();
15305   __ Bl(&fn);
15306   __ Nop();  // GCS enforces that fn() returns here...
15307 
15308   __ Bind(&bad_return_addr);
15309   __ B(&done);  // ... but this test attempts to return here.
15310 
15311   __ Bind(&fn);
15312   __ Adr(lr, &bad_return_addr);
15313   __ Ret();
15314 
15315   __ Bind(&done);
15316   END();
15317 
15318   if (CAN_RUN()) {
15319     MUST_FAIL_WITH_MESSAGE(RUN(), "GCS failed");
15320   }
15321 }
15322 #endif  // VIXL_NEGATIVE_TESTING
15323 
TEST(dc_zva)15324 TEST(dc_zva) {
15325   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
15326 
15327   const int zva_blocksize = 64;  // Assumed blocksize.
15328   uint8_t buf[2 * zva_blocksize];
15329   uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf);
15330   uintptr_t aligned_addr = AlignUp(buf_addr, zva_blocksize);
15331 
15332   START();
15333   // Skip this test if the ZVA blocksize is not 64 bytes.
15334   // Set up initial register values to allow the test to pass when skipped.
15335   Label skip;
15336   __ Movi(q0.V16B(), 0);
15337   __ Movi(q1.V16B(), 0);
15338   __ Movi(q2.V16B(), 0);
15339   __ Movi(q3.V16B(), 0);
15340 
15341   __ Mrs(x1, DCZID_EL0);
15342   __ Cmp(x1, 4);  // 4 => DC ZVA enabled with 64-byte blocks.
15343   __ B(ne, &skip);
15344 
15345   // Fill aligned region with a pattern.
15346   __ Mov(x0, aligned_addr);
15347   __ Movi(q0.V16B(), 0x55);
15348   __ Movi(q1.V16B(), 0xaa);
15349   __ Movi(q2.V16B(), 0x55);
15350   __ Movi(q3.V16B(), 0xaa);
15351   __ St4(q0.V16B(), q1.V16B(), q2.V16B(), q3.V16B(), MemOperand(x0));
15352 
15353   // Misalign the address to check DC ZVA re-aligns.
15354   __ Add(x0, x0, 42);
15355 
15356   // Clear the aligned region.
15357   __ Dc(ZVA, x0);
15358 
15359   // Reload the aligned region to check contents.
15360   __ Mov(x0, aligned_addr);
15361   __ Ld1(q0.V16B(), q1.V16B(), q2.V16B(), q3.V16B(), MemOperand(x0));
15362 
15363   __ Bind(&skip);
15364   END();
15365 
15366   if (CAN_RUN()) {
15367     RUN();
15368     if (core.xreg(1) == 4) {
15369       ASSERT_EQUAL_128(0, 0, q0);
15370       ASSERT_EQUAL_128(0, 0, q1);
15371       ASSERT_EQUAL_128(0, 0, q2);
15372       ASSERT_EQUAL_128(0, 0, q3);
15373     } else {
15374       printf("SKIPPED: DC ZVA chunksize not 64-bytes");
15375     }
15376   }
15377 }
15378 
15379 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
15380 // Test the pseudo-instructions that control CPUFeatures dynamically in the
15381 // Simulator. These are used by the test infrastructure itself, but in a fairly
15382 // limited way.
15383 
RunHelperWithFeatureCombinations(void (* helper)(const CPUFeatures & base,const CPUFeatures & f))15384 static void RunHelperWithFeatureCombinations(
15385     void (*helper)(const CPUFeatures& base, const CPUFeatures& f)) {
15386   // Iterate, testing the first n features in this list.
15387   CPUFeatures::Feature features[] = {
15388       // Put kNone first, so that the first iteration uses an empty feature set.
15389       CPUFeatures::kNone,
15390       // The remaining features used are arbitrary.
15391       CPUFeatures::kIDRegisterEmulation,
15392       CPUFeatures::kDCPoP,
15393       CPUFeatures::kPAuth,
15394       CPUFeatures::kFcma,
15395       CPUFeatures::kAES,
15396       CPUFeatures::kNEON,
15397       CPUFeatures::kCRC32,
15398       CPUFeatures::kFP,
15399       CPUFeatures::kPmull1Q,
15400       CPUFeatures::kSM4,
15401       CPUFeatures::kSM3,
15402       CPUFeatures::kDotProduct,
15403   };
15404   VIXL_ASSERT(CPUFeatures(CPUFeatures::kNone) == CPUFeatures::None());
15405   // The features are not necessarily encoded in kInstructionSize-sized slots,
15406   // so the MacroAssembler must pad the list to align the following instruction.
15407   // Ensure that we have enough features in the list to cover all interesting
15408   // alignment cases, even if the highest common factor of kInstructionSize and
15409   // an encoded feature is one.
15410   VIXL_STATIC_ASSERT(ARRAY_SIZE(features) > kInstructionSize);
15411 
15412   CPUFeatures base = CPUFeatures::None();
15413   for (size_t i = 0; i < ARRAY_SIZE(features); i++) {
15414     base.Combine(features[i]);
15415     CPUFeatures f = CPUFeatures::None();
15416     for (size_t j = 0; j < ARRAY_SIZE(features); j++) {
15417       f.Combine(features[j]);
15418       helper(base, f);
15419     }
15420   }
15421 }
15422 
SetSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)15423 static void SetSimulatorCPUFeaturesHelper(const CPUFeatures& base,
15424                                           const CPUFeatures& f) {
15425   SETUP_WITH_FEATURES(base);
15426   START();
15427 
15428   __ SetSimulatorCPUFeatures(f);
15429 
15430   END();
15431   if (CAN_RUN()) {
15432     RUN_WITHOUT_SEEN_FEATURE_CHECK();
15433     VIXL_CHECK(*(simulator.GetCPUFeatures()) == f);
15434   }
15435 }
15436 
TEST(configure_cpu_features_set)15437 TEST(configure_cpu_features_set) {
15438   RunHelperWithFeatureCombinations(SetSimulatorCPUFeaturesHelper);
15439 }
15440 
EnableSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)15441 static void EnableSimulatorCPUFeaturesHelper(const CPUFeatures& base,
15442                                              const CPUFeatures& f) {
15443   SETUP_WITH_FEATURES(base);
15444   START();
15445 
15446   __ EnableSimulatorCPUFeatures(f);
15447 
15448   END();
15449   if (CAN_RUN()) {
15450     RUN_WITHOUT_SEEN_FEATURE_CHECK();
15451     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.With(f));
15452   }
15453 }
15454 
TEST(configure_cpu_features_enable)15455 TEST(configure_cpu_features_enable) {
15456   RunHelperWithFeatureCombinations(EnableSimulatorCPUFeaturesHelper);
15457 }
15458 
DisableSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)15459 static void DisableSimulatorCPUFeaturesHelper(const CPUFeatures& base,
15460                                               const CPUFeatures& f) {
15461   SETUP_WITH_FEATURES(base);
15462   START();
15463 
15464   __ DisableSimulatorCPUFeatures(f);
15465 
15466   END();
15467   if (CAN_RUN()) {
15468     RUN_WITHOUT_SEEN_FEATURE_CHECK();
15469     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.Without(f));
15470   }
15471 }
15472 
TEST(configure_cpu_features_disable)15473 TEST(configure_cpu_features_disable) {
15474   RunHelperWithFeatureCombinations(DisableSimulatorCPUFeaturesHelper);
15475 }
15476 
SaveRestoreSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)15477 static void SaveRestoreSimulatorCPUFeaturesHelper(const CPUFeatures& base,
15478                                                   const CPUFeatures& f) {
15479   SETUP_WITH_FEATURES(base);
15480   START();
15481 
15482   {
15483     __ SaveSimulatorCPUFeatures();
15484     __ SetSimulatorCPUFeatures(f);
15485     {
15486       __ SaveSimulatorCPUFeatures();
15487       __ SetSimulatorCPUFeatures(CPUFeatures::All());
15488       __ RestoreSimulatorCPUFeatures();
15489     }
15490     __ RestoreSimulatorCPUFeatures();
15491   }
15492 
15493   END();
15494   if (CAN_RUN()) {
15495     RUN_WITHOUT_SEEN_FEATURE_CHECK();
15496     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base);
15497   }
15498 }
15499 
TEST(configure_cpu_features_save_restore)15500 TEST(configure_cpu_features_save_restore) {
15501   RunHelperWithFeatureCombinations(SaveRestoreSimulatorCPUFeaturesHelper);
15502 }
15503 
SimulationCPUFeaturesScopeHelper(const CPUFeatures & base,const CPUFeatures & f)15504 static void SimulationCPUFeaturesScopeHelper(const CPUFeatures& base,
15505                                              const CPUFeatures& f) {
15506   SETUP_WITH_FEATURES(base);
15507   START();
15508 
15509   {
15510     SimulationCPUFeaturesScope scope_a(&masm, f);
15511     {
15512       SimulationCPUFeaturesScope scope_b(&masm, CPUFeatures::All());
15513       {
15514         SimulationCPUFeaturesScope scope_c(&masm, CPUFeatures::None());
15515         // The scope arguments should combine with 'Enable', so we should be
15516         // able to use any CPUFeatures here.
15517         __ Fadd(v0.V4S(), v1.V4S(), v2.V4S());  // Requires {FP, NEON}.
15518       }
15519     }
15520   }
15521 
15522   END();
15523   if (CAN_RUN()) {
15524     RUN_WITHOUT_SEEN_FEATURE_CHECK();
15525     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base);
15526   }
15527 }
15528 
TEST(configure_cpu_features_scope)15529 TEST(configure_cpu_features_scope) {
15530   RunHelperWithFeatureCombinations(SimulationCPUFeaturesScopeHelper);
15531 }
15532 #endif
15533 
15534 
15535 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
TEST(large_sim_stack)15536 TEST(large_sim_stack) {
15537   SimStack builder;
15538   builder.SetUsableSize(16 * 1024);  // The default is 8kB.
15539   SimStack::Allocated stack = builder.Allocate();
15540   uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
15541   uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
15542   SETUP_CUSTOM_SIM(std::move(stack));
15543   START();
15544 
15545   // Check that we can access the extremes of the stack.
15546   __ Mov(x0, base);
15547   __ Mov(x1, limit);
15548   __ Mov(x2, sp);
15549   __ Add(sp, x1, 1);  // Avoid accessing memory below `sp`.
15550 
15551   __ Mov(x10, 42);
15552   __ Poke(x10, 0);
15553   __ Peek(x10, base - limit - kXRegSizeInBytes - 1);
15554 
15555   __ Mov(sp, x2);
15556 
15557   END();
15558   if (CAN_RUN()) {
15559     RUN();
15560   }
15561 }
15562 
15563 #ifdef VIXL_NEGATIVE_TESTING
TEST(sim_stack_limit_guard_read)15564 TEST(sim_stack_limit_guard_read) {
15565   SimStack builder;
15566   SimStack::Allocated stack = builder.Allocate();
15567   uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
15568   SETUP_CUSTOM_SIM(std::move(stack));
15569   START();
15570 
15571   __ Mov(x1, limit);
15572   __ Mov(x2, sp);
15573   __ Add(sp, x1, 1);  // Avoid accessing memory below `sp`.
15574 
15575   // `sp` points to the lowest usable byte of the stack.
15576   __ Mov(w10, 42);
15577   __ Ldrb(w10, MemOperand(sp, -1));
15578 
15579   __ Mov(sp, x2);
15580 
15581   END();
15582   if (CAN_RUN()) {
15583     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
15584   }
15585 }
15586 
TEST(sim_stack_limit_guard_write)15587 TEST(sim_stack_limit_guard_write) {
15588   SimStack builder;
15589   SimStack::Allocated stack = builder.Allocate();
15590   uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
15591   SETUP_CUSTOM_SIM(std::move(stack));
15592   START();
15593 
15594   __ Mov(x1, limit);
15595   __ Mov(x2, sp);
15596   __ Add(sp, x1, 1);  // Avoid accessing memory below `sp`.
15597 
15598   // `sp` points to the lowest usable byte of the stack.
15599   __ Mov(w10, 42);
15600   __ Strb(w10, MemOperand(sp, -1));
15601 
15602   __ Mov(sp, x2);
15603 
15604   END();
15605   if (CAN_RUN()) {
15606     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
15607   }
15608 }
15609 
TEST(sim_stack_base_guard_read)15610 TEST(sim_stack_base_guard_read) {
15611   SimStack builder;
15612   SimStack::Allocated stack = builder.Allocate();
15613   uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
15614   SETUP_CUSTOM_SIM(std::move(stack));
15615   START();
15616 
15617   __ Mov(x0, base);
15618   // `base` (x0) is the byte after the highest usable byte of the stack.
15619   // The last byte of this access will hit the guard region.
15620   __ Mov(x10, 42);
15621   __ Ldr(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
15622 
15623   END();
15624   if (CAN_RUN()) {
15625     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
15626   }
15627 }
15628 
TEST(sim_stack_base_guard_write)15629 TEST(sim_stack_base_guard_write) {
15630   SimStack builder;
15631   SimStack::Allocated stack = builder.Allocate();
15632   uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
15633   SETUP_CUSTOM_SIM(std::move(stack));
15634   START();
15635 
15636   __ Mov(x0, base);
15637   // `base` (x0) is the byte after the highest usable byte of the stack.
15638   // The last byte of this access will hit the guard region.
15639   __ Mov(x10, 42);
15640   __ Str(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
15641 
15642   END();
15643   if (CAN_RUN()) {
15644     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
15645   }
15646 }
15647 #endif
15648 #endif
15649 
TEST(scalar_movi)15650 TEST(scalar_movi) {
15651   SETUP_WITH_FEATURES(CPUFeatures::kFP, CPUFeatures::kNEON);
15652   START();
15653 
15654   // Make sure that V0 is initialized to a non-zero value.
15655   __ Movi(v0.V16B(), 0xFF);
15656   // This constant value can't be encoded in a MOVI instruction,
15657   // so the program would use a fallback path that must set the
15658   // upper 64 bits of the destination vector to 0.
15659   __ Movi(v0.V1D(), 0xDECAFC0FFEE);
15660   __ Mov(x0, v0.V2D(), 1);
15661 
15662   END();
15663 
15664   if (CAN_RUN()) {
15665     RUN();
15666 
15667     ASSERT_EQUAL_64(0, x0);
15668   }
15669 }
15670 
15671 }  // namespace aarch64
15672 }  // namespace vixl
15673