xref: /aosp_15_r20/external/vixl/test/aarch64/test-assembler-aarch64.cc (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1*f5c631daSSadaf Ebrahimi // Copyright 2015, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi //   * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi //   * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi //     and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi //   * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi //     used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi //     specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi 
27*f5c631daSSadaf Ebrahimi #include <sys/mman.h>
28*f5c631daSSadaf Ebrahimi 
29*f5c631daSSadaf Ebrahimi #include <cfloat>
30*f5c631daSSadaf Ebrahimi #include <cmath>
31*f5c631daSSadaf Ebrahimi #include <cstdio>
32*f5c631daSSadaf Ebrahimi #include <cstdlib>
33*f5c631daSSadaf Ebrahimi #include <cstring>
34*f5c631daSSadaf Ebrahimi 
35*f5c631daSSadaf Ebrahimi #include "test-runner.h"
36*f5c631daSSadaf Ebrahimi #include "test-utils.h"
37*f5c631daSSadaf Ebrahimi #include "aarch64/test-utils-aarch64.h"
38*f5c631daSSadaf Ebrahimi 
39*f5c631daSSadaf Ebrahimi #include "aarch64/cpu-aarch64.h"
40*f5c631daSSadaf Ebrahimi #include "aarch64/disasm-aarch64.h"
41*f5c631daSSadaf Ebrahimi #include "aarch64/macro-assembler-aarch64.h"
42*f5c631daSSadaf Ebrahimi #include "aarch64/simulator-aarch64.h"
43*f5c631daSSadaf Ebrahimi #include "test-assembler-aarch64.h"
44*f5c631daSSadaf Ebrahimi 
45*f5c631daSSadaf Ebrahimi namespace vixl {
46*f5c631daSSadaf Ebrahimi namespace aarch64 {
47*f5c631daSSadaf Ebrahimi 
TEST(preshift_immediates)48*f5c631daSSadaf Ebrahimi TEST(preshift_immediates) {
49*f5c631daSSadaf Ebrahimi   SETUP();
50*f5c631daSSadaf Ebrahimi 
51*f5c631daSSadaf Ebrahimi   START();
52*f5c631daSSadaf Ebrahimi   // Test operations involving immediates that could be generated using a
53*f5c631daSSadaf Ebrahimi   // pre-shifted encodable immediate followed by a post-shift applied to
54*f5c631daSSadaf Ebrahimi   // the arithmetic or logical operation.
55*f5c631daSSadaf Ebrahimi 
56*f5c631daSSadaf Ebrahimi   // Save sp.
57*f5c631daSSadaf Ebrahimi   __ Mov(x29, sp);
58*f5c631daSSadaf Ebrahimi 
59*f5c631daSSadaf Ebrahimi   // Set the registers to known values.
60*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x1000);
61*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x1004);
62*f5c631daSSadaf Ebrahimi 
63*f5c631daSSadaf Ebrahimi   // Arithmetic ops.
64*f5c631daSSadaf Ebrahimi   __ Add(x1, x0, 0x1f7de);
65*f5c631daSSadaf Ebrahimi   __ Add(w2, w0, 0xffffff1);
66*f5c631daSSadaf Ebrahimi   __ Adds(x3, x0, 0x18001);
67*f5c631daSSadaf Ebrahimi   __ Adds(w4, w0, 0xffffff1);
68*f5c631daSSadaf Ebrahimi   __ Sub(x5, x0, 0x1f7de);
69*f5c631daSSadaf Ebrahimi   __ Sub(w6, w0, 0xffffff1);
70*f5c631daSSadaf Ebrahimi   __ Subs(x7, x0, 0x18001);
71*f5c631daSSadaf Ebrahimi   __ Subs(w8, w0, 0xffffff1);
72*f5c631daSSadaf Ebrahimi 
73*f5c631daSSadaf Ebrahimi   // Logical ops.
74*f5c631daSSadaf Ebrahimi   __ And(x9, x0, 0x1f7de);
75*f5c631daSSadaf Ebrahimi   __ Orr(w10, w0, 0xffffff1);
76*f5c631daSSadaf Ebrahimi   __ Eor(x11, x0, 0x18001);
77*f5c631daSSadaf Ebrahimi 
78*f5c631daSSadaf Ebrahimi   // Ops using the stack pointer.
79*f5c631daSSadaf Ebrahimi   __ Add(sp, sp, 0x18001);
80*f5c631daSSadaf Ebrahimi   __ Mov(x12, sp);
81*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x1004);
82*f5c631daSSadaf Ebrahimi 
83*f5c631daSSadaf Ebrahimi   __ Add(sp, sp, 0x1f7de);
84*f5c631daSSadaf Ebrahimi   __ Mov(x13, sp);
85*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x1004);
86*f5c631daSSadaf Ebrahimi 
87*f5c631daSSadaf Ebrahimi   __ Adds(x14, sp, 0x1f7de);
88*f5c631daSSadaf Ebrahimi 
89*f5c631daSSadaf Ebrahimi   __ Orr(sp, x0, 0x1f7de);
90*f5c631daSSadaf Ebrahimi   __ Mov(x15, sp);
91*f5c631daSSadaf Ebrahimi 
92*f5c631daSSadaf Ebrahimi   //  Restore sp.
93*f5c631daSSadaf Ebrahimi   __ Mov(sp, x29);
94*f5c631daSSadaf Ebrahimi   END();
95*f5c631daSSadaf Ebrahimi 
96*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
97*f5c631daSSadaf Ebrahimi     RUN();
98*f5c631daSSadaf Ebrahimi 
99*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1000, x0);
100*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x207de, x1);
101*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10000ff1, x2);
102*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x19001, x3);
103*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10000ff1, x4);
104*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffe1822, x5);
105*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf000100f, x6);
106*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffe8fff, x7);
107*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf000100f, x8);
108*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1000, x9);
109*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff1, x10);
110*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x19001, x11);
111*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x19005, x12);
112*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x207e2, x13);
113*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x207e2, x14);
114*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1f7de, x15);
115*f5c631daSSadaf Ebrahimi   }
116*f5c631daSSadaf Ebrahimi }
117*f5c631daSSadaf Ebrahimi 
118*f5c631daSSadaf Ebrahimi 
TEST(stack_ops)119*f5c631daSSadaf Ebrahimi TEST(stack_ops) {
120*f5c631daSSadaf Ebrahimi   SETUP();
121*f5c631daSSadaf Ebrahimi 
122*f5c631daSSadaf Ebrahimi   START();
123*f5c631daSSadaf Ebrahimi   // save sp.
124*f5c631daSSadaf Ebrahimi   __ Mov(x29, sp);
125*f5c631daSSadaf Ebrahimi 
126*f5c631daSSadaf Ebrahimi   // Set the sp to a known value.
127*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x1004);
128*f5c631daSSadaf Ebrahimi   __ Mov(x0, sp);
129*f5c631daSSadaf Ebrahimi 
130*f5c631daSSadaf Ebrahimi   // Add immediate to the sp, and move the result to a normal register.
131*f5c631daSSadaf Ebrahimi   __ Add(sp, sp, 0x50);
132*f5c631daSSadaf Ebrahimi   __ Mov(x1, sp);
133*f5c631daSSadaf Ebrahimi 
134*f5c631daSSadaf Ebrahimi   // Add extended to the sp, and move the result to a normal register.
135*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0xfff);
136*f5c631daSSadaf Ebrahimi   __ Add(sp, sp, Operand(x17, SXTB));
137*f5c631daSSadaf Ebrahimi   __ Mov(x2, sp);
138*f5c631daSSadaf Ebrahimi 
139*f5c631daSSadaf Ebrahimi   // Create an sp using a logical instruction, and move to normal register.
140*f5c631daSSadaf Ebrahimi   __ Orr(sp, xzr, 0x1fff);
141*f5c631daSSadaf Ebrahimi   __ Mov(x3, sp);
142*f5c631daSSadaf Ebrahimi 
143*f5c631daSSadaf Ebrahimi   // Write wsp using a logical instruction.
144*f5c631daSSadaf Ebrahimi   __ Orr(wsp, wzr, 0xfffffff8);
145*f5c631daSSadaf Ebrahimi   __ Mov(x4, sp);
146*f5c631daSSadaf Ebrahimi 
147*f5c631daSSadaf Ebrahimi   // Write sp, and read back wsp.
148*f5c631daSSadaf Ebrahimi   __ Orr(sp, xzr, 0xfffffff8);
149*f5c631daSSadaf Ebrahimi   __ Mov(w5, wsp);
150*f5c631daSSadaf Ebrahimi 
151*f5c631daSSadaf Ebrahimi   // Test writing into wsp in cases where the immediate isn't encodable.
152*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!Assembler::IsImmLogical(0x1234, kWRegSize));
153*f5c631daSSadaf Ebrahimi   __ Orr(wsp, w5, 0x1234);
154*f5c631daSSadaf Ebrahimi   __ Mov(w6, wsp);
155*f5c631daSSadaf Ebrahimi 
156*f5c631daSSadaf Ebrahimi   //  restore sp.
157*f5c631daSSadaf Ebrahimi   __ Mov(sp, x29);
158*f5c631daSSadaf Ebrahimi   END();
159*f5c631daSSadaf Ebrahimi 
160*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
161*f5c631daSSadaf Ebrahimi     RUN();
162*f5c631daSSadaf Ebrahimi 
163*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1004, x0);
164*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1054, x1);
165*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1053, x2);
166*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1fff, x3);
167*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff8, x4);
168*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff8, x5);
169*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffc, x6);
170*f5c631daSSadaf Ebrahimi   }
171*f5c631daSSadaf Ebrahimi }
172*f5c631daSSadaf Ebrahimi 
173*f5c631daSSadaf Ebrahimi 
TEST(mvn)174*f5c631daSSadaf Ebrahimi TEST(mvn) {
175*f5c631daSSadaf Ebrahimi   SETUP();
176*f5c631daSSadaf Ebrahimi 
177*f5c631daSSadaf Ebrahimi   START();
178*f5c631daSSadaf Ebrahimi   __ Mvn(w0, 0xfff);
179*f5c631daSSadaf Ebrahimi   __ Mvn(x1, 0xfff);
180*f5c631daSSadaf Ebrahimi   __ Mvn(w2, Operand(w0, LSL, 1));
181*f5c631daSSadaf Ebrahimi   __ Mvn(x3, Operand(x1, LSL, 2));
182*f5c631daSSadaf Ebrahimi   __ Mvn(w4, Operand(w0, LSR, 3));
183*f5c631daSSadaf Ebrahimi   __ Mvn(x5, Operand(x1, LSR, 4));
184*f5c631daSSadaf Ebrahimi   __ Mvn(w6, Operand(w0, ASR, 11));
185*f5c631daSSadaf Ebrahimi   __ Mvn(x7, Operand(x1, ASR, 12));
186*f5c631daSSadaf Ebrahimi   __ Mvn(w8, Operand(w0, ROR, 13));
187*f5c631daSSadaf Ebrahimi   __ Mvn(x9, Operand(x1, ROR, 14));
188*f5c631daSSadaf Ebrahimi   __ Mvn(w10, Operand(w2, UXTB));
189*f5c631daSSadaf Ebrahimi   __ Mvn(x11, Operand(x2, SXTB, 1));
190*f5c631daSSadaf Ebrahimi   __ Mvn(w12, Operand(w2, UXTH, 2));
191*f5c631daSSadaf Ebrahimi   __ Mvn(x13, Operand(x2, SXTH, 3));
192*f5c631daSSadaf Ebrahimi   __ Mvn(x14, Operand(w2, UXTW, 4));
193*f5c631daSSadaf Ebrahimi   __ Mvn(x15, Operand(w2, SXTW, 4));
194*f5c631daSSadaf Ebrahimi   END();
195*f5c631daSSadaf Ebrahimi 
196*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
197*f5c631daSSadaf Ebrahimi     RUN();
198*f5c631daSSadaf Ebrahimi 
199*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffff000, x0);
200*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffff000, x1);
201*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00001fff, x2);
202*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000003fff, x3);
203*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xe00001ff, x4);
204*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf0000000000000ff, x5);
205*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001, x6);
206*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000000, x7);
207*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7ff80000, x8);
208*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3ffc000000000000, x9);
209*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff00, x10);
210*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000001, x11);
211*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff8003, x12);
212*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff0007, x13);
213*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffe000f, x14);
214*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffe000f, x15);
215*f5c631daSSadaf Ebrahimi   }
216*f5c631daSSadaf Ebrahimi }
217*f5c631daSSadaf Ebrahimi 
218*f5c631daSSadaf Ebrahimi 
TEST(mov_imm_w)219*f5c631daSSadaf Ebrahimi TEST(mov_imm_w) {
220*f5c631daSSadaf Ebrahimi   SETUP();
221*f5c631daSSadaf Ebrahimi 
222*f5c631daSSadaf Ebrahimi   START();
223*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0xffffffff);
224*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0xffff1234);
225*f5c631daSSadaf Ebrahimi   __ Mov(w2, 0x1234ffff);
226*f5c631daSSadaf Ebrahimi   __ Mov(w3, 0x00000000);
227*f5c631daSSadaf Ebrahimi   __ Mov(w4, 0x00001234);
228*f5c631daSSadaf Ebrahimi   __ Mov(w5, 0x12340000);
229*f5c631daSSadaf Ebrahimi   __ Mov(w6, 0x12345678);
230*f5c631daSSadaf Ebrahimi   __ Mov(w7, (int32_t)0x80000000);
231*f5c631daSSadaf Ebrahimi   __ Mov(w8, (int32_t)0xffff0000);
232*f5c631daSSadaf Ebrahimi   __ Mov(w9, kWMinInt);
233*f5c631daSSadaf Ebrahimi   END();
234*f5c631daSSadaf Ebrahimi 
235*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
236*f5c631daSSadaf Ebrahimi     RUN();
237*f5c631daSSadaf Ebrahimi 
238*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x0);
239*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff1234, x1);
240*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234ffff, x2);
241*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x3);
242*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00001234, x4);
243*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x12340000, x5);
244*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x12345678, x6);
245*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x80000000, x7);
246*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff0000, x8);
247*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(kWMinInt, w9);
248*f5c631daSSadaf Ebrahimi   }
249*f5c631daSSadaf Ebrahimi }
250*f5c631daSSadaf Ebrahimi 
251*f5c631daSSadaf Ebrahimi 
TEST(mov_imm_x)252*f5c631daSSadaf Ebrahimi TEST(mov_imm_x) {
253*f5c631daSSadaf Ebrahimi   SETUP();
254*f5c631daSSadaf Ebrahimi 
255*f5c631daSSadaf Ebrahimi   START();
256*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffffffffffff);
257*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xffffffffffff1234);
258*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xffffffff12345678);
259*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xffff1234ffff5678);
260*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x1234ffffffff5678);
261*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0x1234ffff5678ffff);
262*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x12345678ffffffff);
263*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0x1234ffffffffffff);
264*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0x123456789abcffff);
265*f5c631daSSadaf Ebrahimi   __ Mov(x9, 0x12345678ffff9abc);
266*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0x1234ffff56789abc);
267*f5c631daSSadaf Ebrahimi   __ Mov(x11, 0xffff123456789abc);
268*f5c631daSSadaf Ebrahimi   __ Mov(x12, 0x0000000000000000);
269*f5c631daSSadaf Ebrahimi   __ Mov(x13, 0x0000000000001234);
270*f5c631daSSadaf Ebrahimi   __ Mov(x14, 0x0000000012345678);
271*f5c631daSSadaf Ebrahimi   __ Mov(x15, 0x0000123400005678);
272*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0x1234000000005678);
273*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0x1234000056780000);
274*f5c631daSSadaf Ebrahimi   __ Mov(x20, 0x1234567800000000);
275*f5c631daSSadaf Ebrahimi   __ Mov(x21, 0x1234000000000000);
276*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0x123456789abc0000);
277*f5c631daSSadaf Ebrahimi   __ Mov(x23, 0x1234567800009abc);
278*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0x1234000056789abc);
279*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0x0000123456789abc);
280*f5c631daSSadaf Ebrahimi   __ Mov(x26, 0x123456789abcdef0);
281*f5c631daSSadaf Ebrahimi   __ Mov(x27, 0xffff000000000001);
282*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x8000ffff00000000);
283*f5c631daSSadaf Ebrahimi   END();
284*f5c631daSSadaf Ebrahimi 
285*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
286*f5c631daSSadaf Ebrahimi     RUN();
287*f5c631daSSadaf Ebrahimi 
288*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff1234, x1);
289*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff12345678, x2);
290*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff1234ffff5678, x3);
291*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234ffffffff5678, x4);
292*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234ffff5678ffff, x5);
293*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x12345678ffffffff, x6);
294*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234ffffffffffff, x7);
295*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcffff, x8);
296*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x12345678ffff9abc, x9);
297*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234ffff56789abc, x10);
298*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff123456789abc, x11);
299*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000000, x12);
300*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000001234, x13);
301*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x14);
302*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000123400005678, x15);
303*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234000000005678, x18);
304*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234000056780000, x19);
305*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567800000000, x20);
306*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234000000000000, x21);
307*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abc0000, x22);
308*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567800009abc, x23);
309*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234000056789abc, x24);
310*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000123456789abc, x25);
311*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef0, x26);
312*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff000000000001, x27);
313*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8000ffff00000000, x28);
314*f5c631daSSadaf Ebrahimi   }
315*f5c631daSSadaf Ebrahimi }
316*f5c631daSSadaf Ebrahimi 
317*f5c631daSSadaf Ebrahimi 
TEST(mov)318*f5c631daSSadaf Ebrahimi TEST(mov) {
319*f5c631daSSadaf Ebrahimi   SETUP();
320*f5c631daSSadaf Ebrahimi 
321*f5c631daSSadaf Ebrahimi   START();
322*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffffffffffff);
323*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xffffffffffffffff);
324*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xffffffffffffffff);
325*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xffffffffffffffff);
326*f5c631daSSadaf Ebrahimi 
327*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0123456789abcdef);
328*f5c631daSSadaf Ebrahimi 
329*f5c631daSSadaf Ebrahimi   {
330*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 3 * kInstructionSize);
331*f5c631daSSadaf Ebrahimi     __ movz(x1, UINT64_C(0xabcd) << 16);
332*f5c631daSSadaf Ebrahimi     __ movk(x2, UINT64_C(0xabcd) << 32);
333*f5c631daSSadaf Ebrahimi     __ movn(x3, UINT64_C(0xabcd) << 48);
334*f5c631daSSadaf Ebrahimi   }
335*f5c631daSSadaf Ebrahimi 
336*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x0123456789abcdef);
337*f5c631daSSadaf Ebrahimi   __ Mov(x5, x4);
338*f5c631daSSadaf Ebrahimi 
339*f5c631daSSadaf Ebrahimi   __ Mov(w6, -1);
340*f5c631daSSadaf Ebrahimi 
341*f5c631daSSadaf Ebrahimi   // Test that moves back to the same register have the desired effect. This
342*f5c631daSSadaf Ebrahimi   // is a no-op for X registers, and a truncation for W registers.
343*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0x0123456789abcdef);
344*f5c631daSSadaf Ebrahimi   __ Mov(x7, x7);
345*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0x0123456789abcdef);
346*f5c631daSSadaf Ebrahimi   __ Mov(w8, w8);
347*f5c631daSSadaf Ebrahimi   __ Mov(x9, 0x0123456789abcdef);
348*f5c631daSSadaf Ebrahimi   __ Mov(x9, Operand(x9));
349*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0x0123456789abcdef);
350*f5c631daSSadaf Ebrahimi   __ Mov(w10, Operand(w10));
351*f5c631daSSadaf Ebrahimi 
352*f5c631daSSadaf Ebrahimi   __ Mov(w11, 0xfff);
353*f5c631daSSadaf Ebrahimi   __ Mov(x12, 0xfff);
354*f5c631daSSadaf Ebrahimi   __ Mov(w13, Operand(w11, LSL, 1));
355*f5c631daSSadaf Ebrahimi   __ Mov(x14, Operand(x12, LSL, 2));
356*f5c631daSSadaf Ebrahimi   __ Mov(w15, Operand(w11, LSR, 3));
357*f5c631daSSadaf Ebrahimi   __ Mov(x18, Operand(x12, LSR, 4));
358*f5c631daSSadaf Ebrahimi   __ Mov(w19, Operand(w11, ASR, 11));
359*f5c631daSSadaf Ebrahimi   __ Mov(x20, Operand(x12, ASR, 12));
360*f5c631daSSadaf Ebrahimi   __ Mov(w21, Operand(w11, ROR, 13));
361*f5c631daSSadaf Ebrahimi   __ Mov(x22, Operand(x12, ROR, 14));
362*f5c631daSSadaf Ebrahimi   __ Mov(w23, Operand(w13, UXTB));
363*f5c631daSSadaf Ebrahimi   __ Mov(x24, Operand(x13, SXTB, 1));
364*f5c631daSSadaf Ebrahimi   __ Mov(w25, Operand(w13, UXTH, 2));
365*f5c631daSSadaf Ebrahimi   __ Mov(x26, Operand(x13, SXTH, 3));
366*f5c631daSSadaf Ebrahimi   __ Mov(x27, Operand(w13, UXTW, 4));
367*f5c631daSSadaf Ebrahimi 
368*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x0123456789abcdef);
369*f5c631daSSadaf Ebrahimi   __ Mov(w28, w28, kDiscardForSameWReg);
370*f5c631daSSadaf Ebrahimi   END();
371*f5c631daSSadaf Ebrahimi 
372*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
373*f5c631daSSadaf Ebrahimi     RUN();
374*f5c631daSSadaf Ebrahimi 
375*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x0);
376*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000abcd0000, x1);
377*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffabcdffffffff, x2);
378*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x5432ffffffffffff, x3);
379*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x4, x5);
380*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(-1, w6);
381*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x7);
382*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x89abcdef, w8);
383*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x9);
384*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x89abcdef, w10);
385*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000fff, x11);
386*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000fff, x12);
387*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00001ffe, x13);
388*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000003ffc, x14);
389*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000001ff, x15);
390*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000000000ff, x18);
391*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001, x19);
392*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000000, x20);
393*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7ff80000, x21);
394*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3ffc000000000000, x22);
395*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000fe, x23);
396*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffc, x24);
397*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00007ff8, x25);
398*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000fff0, x26);
399*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000001ffe0, x27);
400*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x28);
401*f5c631daSSadaf Ebrahimi   }
402*f5c631daSSadaf Ebrahimi }
403*f5c631daSSadaf Ebrahimi 
404*f5c631daSSadaf Ebrahimi 
TEST(mov_negative)405*f5c631daSSadaf Ebrahimi TEST(mov_negative) {
406*f5c631daSSadaf Ebrahimi   SETUP();
407*f5c631daSSadaf Ebrahimi 
408*f5c631daSSadaf Ebrahimi   START();
409*f5c631daSSadaf Ebrahimi   __ Mov(w11, 0xffffffff);
410*f5c631daSSadaf Ebrahimi   __ Mov(x12, 0xffffffffffffffff);
411*f5c631daSSadaf Ebrahimi 
412*f5c631daSSadaf Ebrahimi   __ Mov(w13, Operand(w11, LSL, 1));
413*f5c631daSSadaf Ebrahimi   __ Mov(w14, Operand(w11, LSR, 1));
414*f5c631daSSadaf Ebrahimi   __ Mov(w15, Operand(w11, ASR, 1));
415*f5c631daSSadaf Ebrahimi   __ Mov(w18, Operand(w11, ROR, 1));
416*f5c631daSSadaf Ebrahimi   __ Mov(w19, Operand(w11, UXTB, 1));
417*f5c631daSSadaf Ebrahimi   __ Mov(w20, Operand(w11, SXTB, 1));
418*f5c631daSSadaf Ebrahimi   __ Mov(w21, Operand(w11, UXTH, 1));
419*f5c631daSSadaf Ebrahimi   __ Mov(w22, Operand(w11, SXTH, 1));
420*f5c631daSSadaf Ebrahimi 
421*f5c631daSSadaf Ebrahimi   __ Mov(x23, Operand(x12, LSL, 1));
422*f5c631daSSadaf Ebrahimi   __ Mov(x24, Operand(x12, LSR, 1));
423*f5c631daSSadaf Ebrahimi   __ Mov(x25, Operand(x12, ASR, 1));
424*f5c631daSSadaf Ebrahimi   __ Mov(x26, Operand(x12, ROR, 1));
425*f5c631daSSadaf Ebrahimi   __ Mov(x27, Operand(x12, UXTH, 1));
426*f5c631daSSadaf Ebrahimi   __ Mov(x28, Operand(x12, SXTH, 1));
427*f5c631daSSadaf Ebrahimi   __ Mov(x29, Operand(x12, UXTW, 1));
428*f5c631daSSadaf Ebrahimi   __ Mov(x30, Operand(x12, SXTW, 1));
429*f5c631daSSadaf Ebrahimi   END();
430*f5c631daSSadaf Ebrahimi 
431*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
432*f5c631daSSadaf Ebrahimi     RUN();
433*f5c631daSSadaf Ebrahimi 
434*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x13);
435*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffff, x14);
436*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x15);
437*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x18);
438*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000001fe, x19);
439*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x20);
440*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0001fffe, x21);
441*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x22);
442*f5c631daSSadaf Ebrahimi 
443*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x23);
444*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffffffffffff, x24);
445*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x25);
446*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x26);
447*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000001fffe, x27);
448*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x28);
449*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001fffffffe, x29);
450*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x30);
451*f5c631daSSadaf Ebrahimi   }
452*f5c631daSSadaf Ebrahimi }
453*f5c631daSSadaf Ebrahimi 
454*f5c631daSSadaf Ebrahimi 
TEST(orr)455*f5c631daSSadaf Ebrahimi TEST(orr) {
456*f5c631daSSadaf Ebrahimi   SETUP();
457*f5c631daSSadaf Ebrahimi 
458*f5c631daSSadaf Ebrahimi   START();
459*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xf0f0);
460*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
461*f5c631daSSadaf Ebrahimi 
462*f5c631daSSadaf Ebrahimi   __ Orr(x2, x0, Operand(x1));
463*f5c631daSSadaf Ebrahimi   __ Orr(w3, w0, Operand(w1, LSL, 28));
464*f5c631daSSadaf Ebrahimi   __ Orr(x4, x0, Operand(x1, LSL, 32));
465*f5c631daSSadaf Ebrahimi   __ Orr(x5, x0, Operand(x1, LSR, 4));
466*f5c631daSSadaf Ebrahimi   __ Orr(w6, w0, Operand(w1, ASR, 4));
467*f5c631daSSadaf Ebrahimi   __ Orr(x7, x0, Operand(x1, ASR, 4));
468*f5c631daSSadaf Ebrahimi   __ Orr(w8, w0, Operand(w1, ROR, 12));
469*f5c631daSSadaf Ebrahimi   __ Orr(x9, x0, Operand(x1, ROR, 12));
470*f5c631daSSadaf Ebrahimi   __ Orr(w10, w0, 0xf);
471*f5c631daSSadaf Ebrahimi   __ Orr(x11, x0, 0xf0000000f0000000);
472*f5c631daSSadaf Ebrahimi   END();
473*f5c631daSSadaf Ebrahimi 
474*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
475*f5c631daSSadaf Ebrahimi     RUN();
476*f5c631daSSadaf Ebrahimi 
477*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000f000f0ff, x2);
478*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf000f0f0, x3);
479*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf00000ff0000f0f0, x4);
480*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000f00f0ff, x5);
481*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff00f0ff, x6);
482*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000f00f0ff, x7);
483*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0ffff0f0, x8);
484*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0ff00000000ff0f0, x9);
485*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f0ff, x10);
486*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf0000000f000f0f0, x11);
487*f5c631daSSadaf Ebrahimi   }
488*f5c631daSSadaf Ebrahimi }
489*f5c631daSSadaf Ebrahimi 
490*f5c631daSSadaf Ebrahimi 
TEST(orr_extend)491*f5c631daSSadaf Ebrahimi TEST(orr_extend) {
492*f5c631daSSadaf Ebrahimi   SETUP();
493*f5c631daSSadaf Ebrahimi 
494*f5c631daSSadaf Ebrahimi   START();
495*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
496*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x8000000080008080);
497*f5c631daSSadaf Ebrahimi   __ Orr(w6, w0, Operand(w1, UXTB));
498*f5c631daSSadaf Ebrahimi   __ Orr(x7, x0, Operand(x1, UXTH, 1));
499*f5c631daSSadaf Ebrahimi   __ Orr(w8, w0, Operand(w1, UXTW, 2));
500*f5c631daSSadaf Ebrahimi   __ Orr(x9, x0, Operand(x1, UXTX, 3));
501*f5c631daSSadaf Ebrahimi   __ Orr(w10, w0, Operand(w1, SXTB));
502*f5c631daSSadaf Ebrahimi   __ Orr(x11, x0, Operand(x1, SXTH, 1));
503*f5c631daSSadaf Ebrahimi   __ Orr(x12, x0, Operand(x1, SXTW, 2));
504*f5c631daSSadaf Ebrahimi   __ Orr(x13, x0, Operand(x1, SXTX, 3));
505*f5c631daSSadaf Ebrahimi   END();
506*f5c631daSSadaf Ebrahimi 
507*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
508*f5c631daSSadaf Ebrahimi     RUN();
509*f5c631daSSadaf Ebrahimi 
510*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000081, x6);
511*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000010101, x7);
512*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00020201, x8);
513*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000400040401, x9);
514*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff81, x10);
515*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff0101, x11);
516*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe00020201, x12);
517*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000400040401, x13);
518*f5c631daSSadaf Ebrahimi   }
519*f5c631daSSadaf Ebrahimi }
520*f5c631daSSadaf Ebrahimi 
521*f5c631daSSadaf Ebrahimi 
TEST(bitwise_wide_imm)522*f5c631daSSadaf Ebrahimi TEST(bitwise_wide_imm) {
523*f5c631daSSadaf Ebrahimi   SETUP();
524*f5c631daSSadaf Ebrahimi 
525*f5c631daSSadaf Ebrahimi   START();
526*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
527*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf0f0f0f0f0f0f0f0);
528*f5c631daSSadaf Ebrahimi 
529*f5c631daSSadaf Ebrahimi   __ Orr(x10, x0, 0x1234567890abcdef);
530*f5c631daSSadaf Ebrahimi   __ Orr(w11, w1, 0x90abcdef);
531*f5c631daSSadaf Ebrahimi 
532*f5c631daSSadaf Ebrahimi   __ Orr(w12, w0, kWMinInt);
533*f5c631daSSadaf Ebrahimi   __ Eor(w13, w0, kWMinInt);
534*f5c631daSSadaf Ebrahimi   END();
535*f5c631daSSadaf Ebrahimi 
536*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
537*f5c631daSSadaf Ebrahimi     RUN();
538*f5c631daSSadaf Ebrahimi 
539*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
540*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf0f0f0f0f0f0f0f0, x1);
541*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x10);
542*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000f0fbfdff, x11);
543*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(kWMinInt, w12);
544*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(kWMinInt, w13);
545*f5c631daSSadaf Ebrahimi   }
546*f5c631daSSadaf Ebrahimi }
547*f5c631daSSadaf Ebrahimi 
548*f5c631daSSadaf Ebrahimi 
TEST(orn)549*f5c631daSSadaf Ebrahimi TEST(orn) {
550*f5c631daSSadaf Ebrahimi   SETUP();
551*f5c631daSSadaf Ebrahimi 
552*f5c631daSSadaf Ebrahimi   START();
553*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xf0f0);
554*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
555*f5c631daSSadaf Ebrahimi 
556*f5c631daSSadaf Ebrahimi   __ Orn(x2, x0, Operand(x1));
557*f5c631daSSadaf Ebrahimi   __ Orn(w3, w0, Operand(w1, LSL, 4));
558*f5c631daSSadaf Ebrahimi   __ Orn(x4, x0, Operand(x1, LSL, 4));
559*f5c631daSSadaf Ebrahimi   __ Orn(x5, x0, Operand(x1, LSR, 1));
560*f5c631daSSadaf Ebrahimi   __ Orn(w6, w0, Operand(w1, ASR, 1));
561*f5c631daSSadaf Ebrahimi   __ Orn(x7, x0, Operand(x1, ASR, 1));
562*f5c631daSSadaf Ebrahimi   __ Orn(w8, w0, Operand(w1, ROR, 16));
563*f5c631daSSadaf Ebrahimi   __ Orn(x9, x0, Operand(x1, ROR, 16));
564*f5c631daSSadaf Ebrahimi   __ Orn(w10, w0, 0x0000ffff);
565*f5c631daSSadaf Ebrahimi   __ Orn(x11, x0, 0x0000ffff0000ffff);
566*f5c631daSSadaf Ebrahimi   END();
567*f5c631daSSadaf Ebrahimi 
568*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
569*f5c631daSSadaf Ebrahimi     RUN();
570*f5c631daSSadaf Ebrahimi 
571*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff0ffffff0, x2);
572*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffff0ff, x3);
573*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff0fffff0ff, x4);
574*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff87fffff0, x5);
575*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x07fffff0, x6);
576*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff87fffff0, x7);
577*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff00ffff, x8);
578*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff00ffffffffffff, x9);
579*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffff0f0, x10);
580*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff0000fffff0f0, x11);
581*f5c631daSSadaf Ebrahimi   }
582*f5c631daSSadaf Ebrahimi }
583*f5c631daSSadaf Ebrahimi 
584*f5c631daSSadaf Ebrahimi 
TEST(orn_extend)585*f5c631daSSadaf Ebrahimi TEST(orn_extend) {
586*f5c631daSSadaf Ebrahimi   SETUP();
587*f5c631daSSadaf Ebrahimi 
588*f5c631daSSadaf Ebrahimi   START();
589*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
590*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x8000000080008081);
591*f5c631daSSadaf Ebrahimi   __ Orn(w6, w0, Operand(w1, UXTB));
592*f5c631daSSadaf Ebrahimi   __ Orn(x7, x0, Operand(x1, UXTH, 1));
593*f5c631daSSadaf Ebrahimi   __ Orn(w8, w0, Operand(w1, UXTW, 2));
594*f5c631daSSadaf Ebrahimi   __ Orn(x9, x0, Operand(x1, UXTX, 3));
595*f5c631daSSadaf Ebrahimi   __ Orn(w10, w0, Operand(w1, SXTB));
596*f5c631daSSadaf Ebrahimi   __ Orn(x11, x0, Operand(x1, SXTH, 1));
597*f5c631daSSadaf Ebrahimi   __ Orn(x12, x0, Operand(x1, SXTW, 2));
598*f5c631daSSadaf Ebrahimi   __ Orn(x13, x0, Operand(x1, SXTX, 3));
599*f5c631daSSadaf Ebrahimi   END();
600*f5c631daSSadaf Ebrahimi 
601*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
602*f5c631daSSadaf Ebrahimi     RUN();
603*f5c631daSSadaf Ebrahimi 
604*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff7f, x6);
605*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
606*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffdfdfb, x8);
607*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
608*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000007f, x10);
609*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000fefd, x11);
610*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
611*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
612*f5c631daSSadaf Ebrahimi   }
613*f5c631daSSadaf Ebrahimi }
614*f5c631daSSadaf Ebrahimi 
615*f5c631daSSadaf Ebrahimi 
TEST(and_)616*f5c631daSSadaf Ebrahimi TEST(and_) {
617*f5c631daSSadaf Ebrahimi   SETUP();
618*f5c631daSSadaf Ebrahimi 
619*f5c631daSSadaf Ebrahimi   START();
620*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff0);
621*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
622*f5c631daSSadaf Ebrahimi 
623*f5c631daSSadaf Ebrahimi   __ And(x2, x0, Operand(x1));
624*f5c631daSSadaf Ebrahimi   __ And(w3, w0, Operand(w1, LSL, 4));
625*f5c631daSSadaf Ebrahimi   __ And(x4, x0, Operand(x1, LSL, 4));
626*f5c631daSSadaf Ebrahimi   __ And(x5, x0, Operand(x1, LSR, 1));
627*f5c631daSSadaf Ebrahimi   __ And(w6, w0, Operand(w1, ASR, 20));
628*f5c631daSSadaf Ebrahimi   __ And(x7, x0, Operand(x1, ASR, 20));
629*f5c631daSSadaf Ebrahimi   __ And(w8, w0, Operand(w1, ROR, 28));
630*f5c631daSSadaf Ebrahimi   __ And(x9, x0, Operand(x1, ROR, 28));
631*f5c631daSSadaf Ebrahimi   __ And(w10, w0, Operand(0xff00));
632*f5c631daSSadaf Ebrahimi   __ And(x11, x0, Operand(0xff));
633*f5c631daSSadaf Ebrahimi   END();
634*f5c631daSSadaf Ebrahimi 
635*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
636*f5c631daSSadaf Ebrahimi     RUN();
637*f5c631daSSadaf Ebrahimi 
638*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000f0, x2);
639*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000ff0, x3);
640*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000ff0, x4);
641*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000070, x5);
642*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ff00, x6);
643*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000f00, x7);
644*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000ff0, x8);
645*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x9);
646*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ff00, x10);
647*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000f0, x11);
648*f5c631daSSadaf Ebrahimi   }
649*f5c631daSSadaf Ebrahimi }
650*f5c631daSSadaf Ebrahimi 
651*f5c631daSSadaf Ebrahimi 
TEST(and_extend)652*f5c631daSSadaf Ebrahimi TEST(and_extend) {
653*f5c631daSSadaf Ebrahimi   SETUP();
654*f5c631daSSadaf Ebrahimi 
655*f5c631daSSadaf Ebrahimi   START();
656*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffffffffffff);
657*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x8000000080008081);
658*f5c631daSSadaf Ebrahimi   __ And(w6, w0, Operand(w1, UXTB));
659*f5c631daSSadaf Ebrahimi   __ And(x7, x0, Operand(x1, UXTH, 1));
660*f5c631daSSadaf Ebrahimi   __ And(w8, w0, Operand(w1, UXTW, 2));
661*f5c631daSSadaf Ebrahimi   __ And(x9, x0, Operand(x1, UXTX, 3));
662*f5c631daSSadaf Ebrahimi   __ And(w10, w0, Operand(w1, SXTB));
663*f5c631daSSadaf Ebrahimi   __ And(x11, x0, Operand(x1, SXTH, 1));
664*f5c631daSSadaf Ebrahimi   __ And(x12, x0, Operand(x1, SXTW, 2));
665*f5c631daSSadaf Ebrahimi   __ And(x13, x0, Operand(x1, SXTX, 3));
666*f5c631daSSadaf Ebrahimi   END();
667*f5c631daSSadaf Ebrahimi 
668*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
669*f5c631daSSadaf Ebrahimi     RUN();
670*f5c631daSSadaf Ebrahimi 
671*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000081, x6);
672*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000010102, x7);
673*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00020204, x8);
674*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000400040408, x9);
675*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff81, x10);
676*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff0102, x11);
677*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe00020204, x12);
678*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000400040408, x13);
679*f5c631daSSadaf Ebrahimi   }
680*f5c631daSSadaf Ebrahimi }
681*f5c631daSSadaf Ebrahimi 
682*f5c631daSSadaf Ebrahimi 
TEST(ands)683*f5c631daSSadaf Ebrahimi TEST(ands) {
684*f5c631daSSadaf Ebrahimi   SETUP();
685*f5c631daSSadaf Ebrahimi 
686*f5c631daSSadaf Ebrahimi   START();
687*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
688*f5c631daSSadaf Ebrahimi   __ Ands(w0, w1, Operand(w1));
689*f5c631daSSadaf Ebrahimi   END();
690*f5c631daSSadaf Ebrahimi 
691*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
692*f5c631daSSadaf Ebrahimi     RUN();
693*f5c631daSSadaf Ebrahimi 
694*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
695*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf00000ff, x0);
696*f5c631daSSadaf Ebrahimi   }
697*f5c631daSSadaf Ebrahimi 
698*f5c631daSSadaf Ebrahimi   START();
699*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff0);
700*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
701*f5c631daSSadaf Ebrahimi   __ Ands(w0, w0, Operand(w1, LSR, 4));
702*f5c631daSSadaf Ebrahimi   END();
703*f5c631daSSadaf Ebrahimi 
704*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
705*f5c631daSSadaf Ebrahimi     RUN();
706*f5c631daSSadaf Ebrahimi 
707*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZFlag);
708*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x0);
709*f5c631daSSadaf Ebrahimi   }
710*f5c631daSSadaf Ebrahimi 
711*f5c631daSSadaf Ebrahimi   START();
712*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x8000000000000000);
713*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x00000001);
714*f5c631daSSadaf Ebrahimi   __ Ands(x0, x0, Operand(x1, ROR, 1));
715*f5c631daSSadaf Ebrahimi   END();
716*f5c631daSSadaf Ebrahimi 
717*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
718*f5c631daSSadaf Ebrahimi     RUN();
719*f5c631daSSadaf Ebrahimi 
720*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
721*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8000000000000000, x0);
722*f5c631daSSadaf Ebrahimi   }
723*f5c631daSSadaf Ebrahimi 
724*f5c631daSSadaf Ebrahimi   START();
725*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff0);
726*f5c631daSSadaf Ebrahimi   __ Ands(w0, w0, Operand(0xf));
727*f5c631daSSadaf Ebrahimi   END();
728*f5c631daSSadaf Ebrahimi 
729*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
730*f5c631daSSadaf Ebrahimi     RUN();
731*f5c631daSSadaf Ebrahimi 
732*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZFlag);
733*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x0);
734*f5c631daSSadaf Ebrahimi   }
735*f5c631daSSadaf Ebrahimi 
736*f5c631daSSadaf Ebrahimi   START();
737*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xff000000);
738*f5c631daSSadaf Ebrahimi   __ Ands(w0, w0, Operand(0x80000000));
739*f5c631daSSadaf Ebrahimi   END();
740*f5c631daSSadaf Ebrahimi 
741*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
742*f5c631daSSadaf Ebrahimi     RUN();
743*f5c631daSSadaf Ebrahimi 
744*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
745*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x80000000, x0);
746*f5c631daSSadaf Ebrahimi   }
747*f5c631daSSadaf Ebrahimi }
748*f5c631daSSadaf Ebrahimi 
749*f5c631daSSadaf Ebrahimi 
TEST(bic)750*f5c631daSSadaf Ebrahimi TEST(bic) {
751*f5c631daSSadaf Ebrahimi   SETUP();
752*f5c631daSSadaf Ebrahimi 
753*f5c631daSSadaf Ebrahimi   START();
754*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff0);
755*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
756*f5c631daSSadaf Ebrahimi 
757*f5c631daSSadaf Ebrahimi   __ Bic(x2, x0, Operand(x1));
758*f5c631daSSadaf Ebrahimi   __ Bic(w3, w0, Operand(w1, LSL, 4));
759*f5c631daSSadaf Ebrahimi   __ Bic(x4, x0, Operand(x1, LSL, 4));
760*f5c631daSSadaf Ebrahimi   __ Bic(x5, x0, Operand(x1, LSR, 1));
761*f5c631daSSadaf Ebrahimi   __ Bic(w6, w0, Operand(w1, ASR, 20));
762*f5c631daSSadaf Ebrahimi   __ Bic(x7, x0, Operand(x1, ASR, 20));
763*f5c631daSSadaf Ebrahimi   __ Bic(w8, w0, Operand(w1, ROR, 28));
764*f5c631daSSadaf Ebrahimi   __ Bic(x9, x0, Operand(x1, ROR, 24));
765*f5c631daSSadaf Ebrahimi   __ Bic(x10, x0, Operand(0x1f));
766*f5c631daSSadaf Ebrahimi   __ Bic(x11, x0, Operand(0x100));
767*f5c631daSSadaf Ebrahimi 
768*f5c631daSSadaf Ebrahimi   // Test bic into sp when the constant cannot be encoded in the immediate
769*f5c631daSSadaf Ebrahimi   // field.
770*f5c631daSSadaf Ebrahimi   // Use x20 to preserve sp. We check for the result via x21 because the
771*f5c631daSSadaf Ebrahimi   // test infrastructure requires that sp be restored to its original value.
772*f5c631daSSadaf Ebrahimi   __ Mov(x20, sp);
773*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffff);
774*f5c631daSSadaf Ebrahimi   __ Bic(sp, x0, Operand(0xabcdef));
775*f5c631daSSadaf Ebrahimi   __ Mov(x21, sp);
776*f5c631daSSadaf Ebrahimi   __ Mov(sp, x20);
777*f5c631daSSadaf Ebrahimi   END();
778*f5c631daSSadaf Ebrahimi 
779*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
780*f5c631daSSadaf Ebrahimi     RUN();
781*f5c631daSSadaf Ebrahimi 
782*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ff00, x2);
783*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f000, x3);
784*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f000, x4);
785*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ff80, x5);
786*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000f0, x6);
787*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f0f0, x7);
788*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f000, x8);
789*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ff00, x9);
790*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ffe0, x10);
791*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000fef0, x11);
792*f5c631daSSadaf Ebrahimi 
793*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x543210, x21);
794*f5c631daSSadaf Ebrahimi   }
795*f5c631daSSadaf Ebrahimi }
796*f5c631daSSadaf Ebrahimi 
797*f5c631daSSadaf Ebrahimi 
TEST(bic_extend)798*f5c631daSSadaf Ebrahimi TEST(bic_extend) {
799*f5c631daSSadaf Ebrahimi   SETUP();
800*f5c631daSSadaf Ebrahimi 
801*f5c631daSSadaf Ebrahimi   START();
802*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffffffffffff);
803*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x8000000080008081);
804*f5c631daSSadaf Ebrahimi   __ Bic(w6, w0, Operand(w1, UXTB));
805*f5c631daSSadaf Ebrahimi   __ Bic(x7, x0, Operand(x1, UXTH, 1));
806*f5c631daSSadaf Ebrahimi   __ Bic(w8, w0, Operand(w1, UXTW, 2));
807*f5c631daSSadaf Ebrahimi   __ Bic(x9, x0, Operand(x1, UXTX, 3));
808*f5c631daSSadaf Ebrahimi   __ Bic(w10, w0, Operand(w1, SXTB));
809*f5c631daSSadaf Ebrahimi   __ Bic(x11, x0, Operand(x1, SXTH, 1));
810*f5c631daSSadaf Ebrahimi   __ Bic(x12, x0, Operand(x1, SXTW, 2));
811*f5c631daSSadaf Ebrahimi   __ Bic(x13, x0, Operand(x1, SXTX, 3));
812*f5c631daSSadaf Ebrahimi   END();
813*f5c631daSSadaf Ebrahimi 
814*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
815*f5c631daSSadaf Ebrahimi     RUN();
816*f5c631daSSadaf Ebrahimi 
817*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff7e, x6);
818*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
819*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffdfdfb, x8);
820*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
821*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000007e, x10);
822*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000fefd, x11);
823*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
824*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
825*f5c631daSSadaf Ebrahimi   }
826*f5c631daSSadaf Ebrahimi }
827*f5c631daSSadaf Ebrahimi 
828*f5c631daSSadaf Ebrahimi 
TEST(bics)829*f5c631daSSadaf Ebrahimi TEST(bics) {
830*f5c631daSSadaf Ebrahimi   SETUP();
831*f5c631daSSadaf Ebrahimi 
832*f5c631daSSadaf Ebrahimi   START();
833*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xffff);
834*f5c631daSSadaf Ebrahimi   __ Bics(w0, w1, Operand(w1));
835*f5c631daSSadaf Ebrahimi   END();
836*f5c631daSSadaf Ebrahimi 
837*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
838*f5c631daSSadaf Ebrahimi     RUN();
839*f5c631daSSadaf Ebrahimi 
840*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZFlag);
841*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x0);
842*f5c631daSSadaf Ebrahimi   }
843*f5c631daSSadaf Ebrahimi 
844*f5c631daSSadaf Ebrahimi   START();
845*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffff);
846*f5c631daSSadaf Ebrahimi   __ Bics(w0, w0, Operand(w0, LSR, 1));
847*f5c631daSSadaf Ebrahimi   END();
848*f5c631daSSadaf Ebrahimi 
849*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
850*f5c631daSSadaf Ebrahimi     RUN();
851*f5c631daSSadaf Ebrahimi 
852*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
853*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x80000000, x0);
854*f5c631daSSadaf Ebrahimi   }
855*f5c631daSSadaf Ebrahimi 
856*f5c631daSSadaf Ebrahimi   START();
857*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x8000000000000000);
858*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x00000001);
859*f5c631daSSadaf Ebrahimi   __ Bics(x0, x0, Operand(x1, ROR, 1));
860*f5c631daSSadaf Ebrahimi   END();
861*f5c631daSSadaf Ebrahimi 
862*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
863*f5c631daSSadaf Ebrahimi     RUN();
864*f5c631daSSadaf Ebrahimi 
865*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZFlag);
866*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x0);
867*f5c631daSSadaf Ebrahimi   }
868*f5c631daSSadaf Ebrahimi 
869*f5c631daSSadaf Ebrahimi   START();
870*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffffffffffff);
871*f5c631daSSadaf Ebrahimi   __ Bics(x0, x0, 0x7fffffffffffffff);
872*f5c631daSSadaf Ebrahimi   END();
873*f5c631daSSadaf Ebrahimi 
874*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
875*f5c631daSSadaf Ebrahimi     RUN();
876*f5c631daSSadaf Ebrahimi 
877*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
878*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8000000000000000, x0);
879*f5c631daSSadaf Ebrahimi   }
880*f5c631daSSadaf Ebrahimi 
881*f5c631daSSadaf Ebrahimi   START();
882*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0xffff0000);
883*f5c631daSSadaf Ebrahimi   __ Bics(w0, w0, 0xfffffff0);
884*f5c631daSSadaf Ebrahimi   END();
885*f5c631daSSadaf Ebrahimi 
886*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
887*f5c631daSSadaf Ebrahimi     RUN();
888*f5c631daSSadaf Ebrahimi 
889*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZFlag);
890*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000, x0);
891*f5c631daSSadaf Ebrahimi   }
892*f5c631daSSadaf Ebrahimi }
893*f5c631daSSadaf Ebrahimi 
894*f5c631daSSadaf Ebrahimi 
TEST(eor)895*f5c631daSSadaf Ebrahimi TEST(eor) {
896*f5c631daSSadaf Ebrahimi   SETUP();
897*f5c631daSSadaf Ebrahimi 
898*f5c631daSSadaf Ebrahimi   START();
899*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff0);
900*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
901*f5c631daSSadaf Ebrahimi 
902*f5c631daSSadaf Ebrahimi   __ Eor(x2, x0, Operand(x1));
903*f5c631daSSadaf Ebrahimi   __ Eor(w3, w0, Operand(w1, LSL, 4));
904*f5c631daSSadaf Ebrahimi   __ Eor(x4, x0, Operand(x1, LSL, 4));
905*f5c631daSSadaf Ebrahimi   __ Eor(x5, x0, Operand(x1, LSR, 1));
906*f5c631daSSadaf Ebrahimi   __ Eor(w6, w0, Operand(w1, ASR, 20));
907*f5c631daSSadaf Ebrahimi   __ Eor(x7, x0, Operand(x1, ASR, 20));
908*f5c631daSSadaf Ebrahimi   __ Eor(w8, w0, Operand(w1, ROR, 28));
909*f5c631daSSadaf Ebrahimi   __ Eor(x9, x0, Operand(x1, ROR, 28));
910*f5c631daSSadaf Ebrahimi   __ Eor(w10, w0, 0xff00ff00);
911*f5c631daSSadaf Ebrahimi   __ Eor(x11, x0, 0xff00ff00ff00ff00);
912*f5c631daSSadaf Ebrahimi   END();
913*f5c631daSSadaf Ebrahimi 
914*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
915*f5c631daSSadaf Ebrahimi     RUN();
916*f5c631daSSadaf Ebrahimi 
917*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000f000ff0f, x2);
918*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f000, x3);
919*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f0000f000, x4);
920*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000007800ff8f, x5);
921*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff00f0, x6);
922*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000f0f0, x7);
923*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000f00f, x8);
924*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000ff00000ffff, x9);
925*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff0000f0, x10);
926*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff00ff00ff0000f0, x11);
927*f5c631daSSadaf Ebrahimi   }
928*f5c631daSSadaf Ebrahimi }
929*f5c631daSSadaf Ebrahimi 
TEST(eor_extend)930*f5c631daSSadaf Ebrahimi TEST(eor_extend) {
931*f5c631daSSadaf Ebrahimi   SETUP();
932*f5c631daSSadaf Ebrahimi 
933*f5c631daSSadaf Ebrahimi   START();
934*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x1111111111111111);
935*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x8000000080008081);
936*f5c631daSSadaf Ebrahimi   __ Eor(w6, w0, Operand(w1, UXTB));
937*f5c631daSSadaf Ebrahimi   __ Eor(x7, x0, Operand(x1, UXTH, 1));
938*f5c631daSSadaf Ebrahimi   __ Eor(w8, w0, Operand(w1, UXTW, 2));
939*f5c631daSSadaf Ebrahimi   __ Eor(x9, x0, Operand(x1, UXTX, 3));
940*f5c631daSSadaf Ebrahimi   __ Eor(w10, w0, Operand(w1, SXTB));
941*f5c631daSSadaf Ebrahimi   __ Eor(x11, x0, Operand(x1, SXTH, 1));
942*f5c631daSSadaf Ebrahimi   __ Eor(x12, x0, Operand(x1, SXTW, 2));
943*f5c631daSSadaf Ebrahimi   __ Eor(x13, x0, Operand(x1, SXTX, 3));
944*f5c631daSSadaf Ebrahimi   END();
945*f5c631daSSadaf Ebrahimi 
946*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
947*f5c631daSSadaf Ebrahimi     RUN();
948*f5c631daSSadaf Ebrahimi 
949*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x11111190, x6);
950*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1111111111101013, x7);
951*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x11131315, x8);
952*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1111111511151519, x9);
953*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeee90, x10);
954*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeeeeeeeee1013, x11);
955*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeeeef11131315, x12);
956*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1111111511151519, x13);
957*f5c631daSSadaf Ebrahimi   }
958*f5c631daSSadaf Ebrahimi }
959*f5c631daSSadaf Ebrahimi 
960*f5c631daSSadaf Ebrahimi 
TEST(eon)961*f5c631daSSadaf Ebrahimi TEST(eon) {
962*f5c631daSSadaf Ebrahimi   SETUP();
963*f5c631daSSadaf Ebrahimi 
964*f5c631daSSadaf Ebrahimi   START();
965*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff0);
966*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xf00000ff);
967*f5c631daSSadaf Ebrahimi 
968*f5c631daSSadaf Ebrahimi   __ Eon(x2, x0, Operand(x1));
969*f5c631daSSadaf Ebrahimi   __ Eon(w3, w0, Operand(w1, LSL, 4));
970*f5c631daSSadaf Ebrahimi   __ Eon(x4, x0, Operand(x1, LSL, 4));
971*f5c631daSSadaf Ebrahimi   __ Eon(x5, x0, Operand(x1, LSR, 1));
972*f5c631daSSadaf Ebrahimi   __ Eon(w6, w0, Operand(w1, ASR, 20));
973*f5c631daSSadaf Ebrahimi   __ Eon(x7, x0, Operand(x1, ASR, 20));
974*f5c631daSSadaf Ebrahimi   __ Eon(w8, w0, Operand(w1, ROR, 28));
975*f5c631daSSadaf Ebrahimi   __ Eon(x9, x0, Operand(x1, ROR, 28));
976*f5c631daSSadaf Ebrahimi   __ Eon(w10, w0, 0x03c003c0);
977*f5c631daSSadaf Ebrahimi   __ Eon(x11, x0, 0x0000100000001000);
978*f5c631daSSadaf Ebrahimi   END();
979*f5c631daSSadaf Ebrahimi 
980*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
981*f5c631daSSadaf Ebrahimi     RUN();
982*f5c631daSSadaf Ebrahimi 
983*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff0fff00f0, x2);
984*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff0fff, x3);
985*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff0ffff0fff, x4);
986*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff87ff0070, x5);
987*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000ff0f, x6);
988*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff0f0f, x7);
989*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff0ff0, x8);
990*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffff00fffff0000, x9);
991*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfc3f03cf, x10);
992*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffefffffff100f, x11);
993*f5c631daSSadaf Ebrahimi   }
994*f5c631daSSadaf Ebrahimi }
995*f5c631daSSadaf Ebrahimi 
996*f5c631daSSadaf Ebrahimi 
TEST(eon_extend)997*f5c631daSSadaf Ebrahimi TEST(eon_extend) {
998*f5c631daSSadaf Ebrahimi   SETUP();
999*f5c631daSSadaf Ebrahimi 
1000*f5c631daSSadaf Ebrahimi   START();
1001*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x1111111111111111);
1002*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x8000000080008081);
1003*f5c631daSSadaf Ebrahimi   __ Eon(w6, w0, Operand(w1, UXTB));
1004*f5c631daSSadaf Ebrahimi   __ Eon(x7, x0, Operand(x1, UXTH, 1));
1005*f5c631daSSadaf Ebrahimi   __ Eon(w8, w0, Operand(w1, UXTW, 2));
1006*f5c631daSSadaf Ebrahimi   __ Eon(x9, x0, Operand(x1, UXTX, 3));
1007*f5c631daSSadaf Ebrahimi   __ Eon(w10, w0, Operand(w1, SXTB));
1008*f5c631daSSadaf Ebrahimi   __ Eon(x11, x0, Operand(x1, SXTH, 1));
1009*f5c631daSSadaf Ebrahimi   __ Eon(x12, x0, Operand(x1, SXTW, 2));
1010*f5c631daSSadaf Ebrahimi   __ Eon(x13, x0, Operand(x1, SXTX, 3));
1011*f5c631daSSadaf Ebrahimi   END();
1012*f5c631daSSadaf Ebrahimi 
1013*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1014*f5c631daSSadaf Ebrahimi     RUN();
1015*f5c631daSSadaf Ebrahimi 
1016*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeee6f, x6);
1017*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeeeeeeeefefec, x7);
1018*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeececea, x8);
1019*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x9);
1020*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1111116f, x10);
1021*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x111111111111efec, x11);
1022*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x11111110eeececea, x12);
1023*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x13);
1024*f5c631daSSadaf Ebrahimi   }
1025*f5c631daSSadaf Ebrahimi }
1026*f5c631daSSadaf Ebrahimi 
1027*f5c631daSSadaf Ebrahimi 
TEST(mul)1028*f5c631daSSadaf Ebrahimi TEST(mul) {
1029*f5c631daSSadaf Ebrahimi   SETUP();
1030*f5c631daSSadaf Ebrahimi 
1031*f5c631daSSadaf Ebrahimi   START();
1032*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0);
1033*f5c631daSSadaf Ebrahimi   __ Mov(x26, 1);
1034*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xffffffff);
1035*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0xffffffffffffffff);
1036*f5c631daSSadaf Ebrahimi 
1037*f5c631daSSadaf Ebrahimi   __ Mul(w0, w25, w25);
1038*f5c631daSSadaf Ebrahimi   __ Mul(w1, w25, w26);
1039*f5c631daSSadaf Ebrahimi   __ Mul(w2, w26, w18);
1040*f5c631daSSadaf Ebrahimi   __ Mul(w3, w18, w19);
1041*f5c631daSSadaf Ebrahimi   __ Mul(x4, x25, x25);
1042*f5c631daSSadaf Ebrahimi   __ Mul(x5, x26, x18);
1043*f5c631daSSadaf Ebrahimi   __ Mul(x6, x18, x19);
1044*f5c631daSSadaf Ebrahimi   __ Mul(x7, x19, x19);
1045*f5c631daSSadaf Ebrahimi   __ Smull(x8, w26, w18);
1046*f5c631daSSadaf Ebrahimi   __ Smull(x9, w18, w18);
1047*f5c631daSSadaf Ebrahimi   __ Smull(x10, w19, w19);
1048*f5c631daSSadaf Ebrahimi   __ Mneg(w11, w25, w25);
1049*f5c631daSSadaf Ebrahimi   __ Mneg(w12, w25, w26);
1050*f5c631daSSadaf Ebrahimi   __ Mneg(w13, w26, w18);
1051*f5c631daSSadaf Ebrahimi   __ Mneg(w14, w18, w19);
1052*f5c631daSSadaf Ebrahimi   __ Mneg(x20, x25, x25);
1053*f5c631daSSadaf Ebrahimi   __ Mneg(x21, x26, x18);
1054*f5c631daSSadaf Ebrahimi   __ Mneg(x22, x18, x19);
1055*f5c631daSSadaf Ebrahimi   __ Mneg(x23, x19, x19);
1056*f5c631daSSadaf Ebrahimi   END();
1057*f5c631daSSadaf Ebrahimi 
1058*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1059*f5c631daSSadaf Ebrahimi     RUN();
1060*f5c631daSSadaf Ebrahimi 
1061*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
1062*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x1);
1063*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x2);
1064*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x3);
1065*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x4);
1066*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x5);
1067*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff00000001, x6);
1068*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x7);
1069*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x8);
1070*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x9);
1071*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x10);
1072*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x11);
1073*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x12);
1074*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x13);
1075*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x14);
1076*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x20);
1077*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff00000001, x21);
1078*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x22);
1079*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x23);
1080*f5c631daSSadaf Ebrahimi   }
1081*f5c631daSSadaf Ebrahimi }
1082*f5c631daSSadaf Ebrahimi 
1083*f5c631daSSadaf Ebrahimi 
SmullHelper(int64_t expected,int64_t a,int64_t b)1084*f5c631daSSadaf Ebrahimi static void SmullHelper(int64_t expected, int64_t a, int64_t b) {
1085*f5c631daSSadaf Ebrahimi   SETUP();
1086*f5c631daSSadaf Ebrahimi   START();
1087*f5c631daSSadaf Ebrahimi   __ Mov(w0, a);
1088*f5c631daSSadaf Ebrahimi   __ Mov(w1, b);
1089*f5c631daSSadaf Ebrahimi   __ Smull(x2, w0, w1);
1090*f5c631daSSadaf Ebrahimi   END();
1091*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1092*f5c631daSSadaf Ebrahimi     RUN();
1093*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x2);
1094*f5c631daSSadaf Ebrahimi   }
1095*f5c631daSSadaf Ebrahimi }
1096*f5c631daSSadaf Ebrahimi 
1097*f5c631daSSadaf Ebrahimi 
TEST(smull)1098*f5c631daSSadaf Ebrahimi TEST(smull) {
1099*f5c631daSSadaf Ebrahimi   SmullHelper(0, 0, 0);
1100*f5c631daSSadaf Ebrahimi   SmullHelper(1, 1, 1);
1101*f5c631daSSadaf Ebrahimi   SmullHelper(-1, -1, 1);
1102*f5c631daSSadaf Ebrahimi   SmullHelper(1, -1, -1);
1103*f5c631daSSadaf Ebrahimi   SmullHelper(0xffffffff80000000, 0x80000000, 1);
1104*f5c631daSSadaf Ebrahimi   SmullHelper(0x0000000080000000, 0x00010000, 0x00008000);
1105*f5c631daSSadaf Ebrahimi }
1106*f5c631daSSadaf Ebrahimi 
1107*f5c631daSSadaf Ebrahimi 
TEST(madd)1108*f5c631daSSadaf Ebrahimi TEST(madd) {
1109*f5c631daSSadaf Ebrahimi   SETUP();
1110*f5c631daSSadaf Ebrahimi 
1111*f5c631daSSadaf Ebrahimi   START();
1112*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0);
1113*f5c631daSSadaf Ebrahimi   __ Mov(x17, 1);
1114*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xffffffff);
1115*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0xffffffffffffffff);
1116*f5c631daSSadaf Ebrahimi 
1117*f5c631daSSadaf Ebrahimi   __ Madd(w0, w16, w16, w16);
1118*f5c631daSSadaf Ebrahimi   __ Madd(w1, w16, w16, w17);
1119*f5c631daSSadaf Ebrahimi   __ Madd(w2, w16, w16, w18);
1120*f5c631daSSadaf Ebrahimi   __ Madd(w3, w16, w16, w19);
1121*f5c631daSSadaf Ebrahimi   __ Madd(w4, w16, w17, w17);
1122*f5c631daSSadaf Ebrahimi   __ Madd(w5, w17, w17, w18);
1123*f5c631daSSadaf Ebrahimi   __ Madd(w6, w17, w17, w19);
1124*f5c631daSSadaf Ebrahimi   __ Madd(w7, w17, w18, w16);
1125*f5c631daSSadaf Ebrahimi   __ Madd(w8, w17, w18, w18);
1126*f5c631daSSadaf Ebrahimi   __ Madd(w9, w18, w18, w17);
1127*f5c631daSSadaf Ebrahimi   __ Madd(w10, w18, w19, w18);
1128*f5c631daSSadaf Ebrahimi   __ Madd(w11, w19, w19, w19);
1129*f5c631daSSadaf Ebrahimi 
1130*f5c631daSSadaf Ebrahimi   __ Madd(x12, x16, x16, x16);
1131*f5c631daSSadaf Ebrahimi   __ Madd(x13, x16, x16, x17);
1132*f5c631daSSadaf Ebrahimi   __ Madd(x14, x16, x16, x18);
1133*f5c631daSSadaf Ebrahimi   __ Madd(x15, x16, x16, x19);
1134*f5c631daSSadaf Ebrahimi   __ Madd(x20, x16, x17, x17);
1135*f5c631daSSadaf Ebrahimi   __ Madd(x21, x17, x17, x18);
1136*f5c631daSSadaf Ebrahimi   __ Madd(x22, x17, x17, x19);
1137*f5c631daSSadaf Ebrahimi   __ Madd(x23, x17, x18, x16);
1138*f5c631daSSadaf Ebrahimi   __ Madd(x24, x17, x18, x18);
1139*f5c631daSSadaf Ebrahimi   __ Madd(x25, x18, x18, x17);
1140*f5c631daSSadaf Ebrahimi   __ Madd(x26, x18, x19, x18);
1141*f5c631daSSadaf Ebrahimi   __ Madd(x27, x19, x19, x19);
1142*f5c631daSSadaf Ebrahimi 
1143*f5c631daSSadaf Ebrahimi   END();
1144*f5c631daSSadaf Ebrahimi 
1145*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1146*f5c631daSSadaf Ebrahimi     RUN();
1147*f5c631daSSadaf Ebrahimi 
1148*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
1149*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x1);
1150*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x2);
1151*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x3);
1152*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x4);
1153*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x5);
1154*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x6);
1155*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x7);
1156*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x8);
1157*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x9);
1158*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x10);
1159*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x11);
1160*f5c631daSSadaf Ebrahimi 
1161*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x12);
1162*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x13);
1163*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1164*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1165*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x20);
1166*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000100000000, x21);
1167*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x22);
1168*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000ffffffff, x23);
1169*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001fffffffe, x24);
1170*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe00000002, x25);
1171*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x26);
1172*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x27);
1173*f5c631daSSadaf Ebrahimi   }
1174*f5c631daSSadaf Ebrahimi }
1175*f5c631daSSadaf Ebrahimi 
1176*f5c631daSSadaf Ebrahimi 
TEST(msub)1177*f5c631daSSadaf Ebrahimi TEST(msub) {
1178*f5c631daSSadaf Ebrahimi   SETUP();
1179*f5c631daSSadaf Ebrahimi 
1180*f5c631daSSadaf Ebrahimi   START();
1181*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0);
1182*f5c631daSSadaf Ebrahimi   __ Mov(x17, 1);
1183*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xffffffff);
1184*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0xffffffffffffffff);
1185*f5c631daSSadaf Ebrahimi 
1186*f5c631daSSadaf Ebrahimi   __ Msub(w0, w16, w16, w16);
1187*f5c631daSSadaf Ebrahimi   __ Msub(w1, w16, w16, w17);
1188*f5c631daSSadaf Ebrahimi   __ Msub(w2, w16, w16, w18);
1189*f5c631daSSadaf Ebrahimi   __ Msub(w3, w16, w16, w19);
1190*f5c631daSSadaf Ebrahimi   __ Msub(w4, w16, w17, w17);
1191*f5c631daSSadaf Ebrahimi   __ Msub(w5, w17, w17, w18);
1192*f5c631daSSadaf Ebrahimi   __ Msub(w6, w17, w17, w19);
1193*f5c631daSSadaf Ebrahimi   __ Msub(w7, w17, w18, w16);
1194*f5c631daSSadaf Ebrahimi   __ Msub(w8, w17, w18, w18);
1195*f5c631daSSadaf Ebrahimi   __ Msub(w9, w18, w18, w17);
1196*f5c631daSSadaf Ebrahimi   __ Msub(w10, w18, w19, w18);
1197*f5c631daSSadaf Ebrahimi   __ Msub(w11, w19, w19, w19);
1198*f5c631daSSadaf Ebrahimi 
1199*f5c631daSSadaf Ebrahimi   __ Msub(x12, x16, x16, x16);
1200*f5c631daSSadaf Ebrahimi   __ Msub(x13, x16, x16, x17);
1201*f5c631daSSadaf Ebrahimi   __ Msub(x14, x16, x16, x18);
1202*f5c631daSSadaf Ebrahimi   __ Msub(x15, x16, x16, x19);
1203*f5c631daSSadaf Ebrahimi   __ Msub(x20, x16, x17, x17);
1204*f5c631daSSadaf Ebrahimi   __ Msub(x21, x17, x17, x18);
1205*f5c631daSSadaf Ebrahimi   __ Msub(x22, x17, x17, x19);
1206*f5c631daSSadaf Ebrahimi   __ Msub(x23, x17, x18, x16);
1207*f5c631daSSadaf Ebrahimi   __ Msub(x24, x17, x18, x18);
1208*f5c631daSSadaf Ebrahimi   __ Msub(x25, x18, x18, x17);
1209*f5c631daSSadaf Ebrahimi   __ Msub(x26, x18, x19, x18);
1210*f5c631daSSadaf Ebrahimi   __ Msub(x27, x19, x19, x19);
1211*f5c631daSSadaf Ebrahimi 
1212*f5c631daSSadaf Ebrahimi   END();
1213*f5c631daSSadaf Ebrahimi 
1214*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1215*f5c631daSSadaf Ebrahimi     RUN();
1216*f5c631daSSadaf Ebrahimi 
1217*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
1218*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x1);
1219*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x2);
1220*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x3);
1221*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x4);
1222*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x5);
1223*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x6);
1224*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x7);
1225*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x8);
1226*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x9);
1227*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x10);
1228*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x11);
1229*f5c631daSSadaf Ebrahimi 
1230*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x12);
1231*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x13);
1232*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1233*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1234*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x20);
1235*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000fffffffe, x21);
1236*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x22);
1237*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff00000001, x23);
1238*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x24);
1239*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000200000000, x25);
1240*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001fffffffe, x26);
1241*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x27);
1242*f5c631daSSadaf Ebrahimi   }
1243*f5c631daSSadaf Ebrahimi }
1244*f5c631daSSadaf Ebrahimi 
1245*f5c631daSSadaf Ebrahimi 
TEST(smulh)1246*f5c631daSSadaf Ebrahimi TEST(smulh) {
1247*f5c631daSSadaf Ebrahimi   SETUP();
1248*f5c631daSSadaf Ebrahimi 
1249*f5c631daSSadaf Ebrahimi   START();
1250*f5c631daSSadaf Ebrahimi   __ Mov(x20, 0);
1251*f5c631daSSadaf Ebrahimi   __ Mov(x21, 1);
1252*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0x0000000100000000);
1253*f5c631daSSadaf Ebrahimi   __ Mov(x23, 0x0000000012345678);
1254*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0x0123456789abcdef);
1255*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0x0000000200000000);
1256*f5c631daSSadaf Ebrahimi   __ Mov(x26, 0x8000000000000000);
1257*f5c631daSSadaf Ebrahimi   __ Mov(x27, 0xffffffffffffffff);
1258*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x5555555555555555);
1259*f5c631daSSadaf Ebrahimi   __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
1260*f5c631daSSadaf Ebrahimi 
1261*f5c631daSSadaf Ebrahimi   __ Smulh(x0, x20, x24);
1262*f5c631daSSadaf Ebrahimi   __ Smulh(x1, x21, x24);
1263*f5c631daSSadaf Ebrahimi   __ Smulh(x2, x22, x23);
1264*f5c631daSSadaf Ebrahimi   __ Smulh(x3, x22, x24);
1265*f5c631daSSadaf Ebrahimi   __ Smulh(x4, x24, x25);
1266*f5c631daSSadaf Ebrahimi   __ Smulh(x5, x23, x27);
1267*f5c631daSSadaf Ebrahimi   __ Smulh(x6, x26, x26);
1268*f5c631daSSadaf Ebrahimi   __ Smulh(x7, x26, x27);
1269*f5c631daSSadaf Ebrahimi   __ Smulh(x8, x27, x27);
1270*f5c631daSSadaf Ebrahimi   __ Smulh(x9, x28, x28);
1271*f5c631daSSadaf Ebrahimi   __ Smulh(x10, x28, x29);
1272*f5c631daSSadaf Ebrahimi   __ Smulh(x11, x29, x29);
1273*f5c631daSSadaf Ebrahimi   END();
1274*f5c631daSSadaf Ebrahimi 
1275*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1276*f5c631daSSadaf Ebrahimi     RUN();
1277*f5c631daSSadaf Ebrahimi 
1278*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
1279*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x1);
1280*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x2);
1281*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000001234567, x3);
1282*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000002468acf, x4);
1283*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x5);
1284*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4000000000000000, x6);
1285*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x7);
1286*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x8);
1287*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1288*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xe38e38e38e38e38e, x10);
1289*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1c71c71c71c71c72, x11);
1290*f5c631daSSadaf Ebrahimi   }
1291*f5c631daSSadaf Ebrahimi }
1292*f5c631daSSadaf Ebrahimi 
1293*f5c631daSSadaf Ebrahimi 
TEST(umulh)1294*f5c631daSSadaf Ebrahimi TEST(umulh) {
1295*f5c631daSSadaf Ebrahimi   SETUP();
1296*f5c631daSSadaf Ebrahimi 
1297*f5c631daSSadaf Ebrahimi   START();
1298*f5c631daSSadaf Ebrahimi   __ Mov(x20, 0);
1299*f5c631daSSadaf Ebrahimi   __ Mov(x21, 1);
1300*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0x0000000100000000);
1301*f5c631daSSadaf Ebrahimi   __ Mov(x23, 0x0000000012345678);
1302*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0x0123456789abcdef);
1303*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0x0000000200000000);
1304*f5c631daSSadaf Ebrahimi   __ Mov(x26, 0x8000000000000000);
1305*f5c631daSSadaf Ebrahimi   __ Mov(x27, 0xffffffffffffffff);
1306*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x5555555555555555);
1307*f5c631daSSadaf Ebrahimi   __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
1308*f5c631daSSadaf Ebrahimi 
1309*f5c631daSSadaf Ebrahimi   __ Umulh(x0, x20, x24);
1310*f5c631daSSadaf Ebrahimi   __ Umulh(x1, x21, x24);
1311*f5c631daSSadaf Ebrahimi   __ Umulh(x2, x22, x23);
1312*f5c631daSSadaf Ebrahimi   __ Umulh(x3, x22, x24);
1313*f5c631daSSadaf Ebrahimi   __ Umulh(x4, x24, x25);
1314*f5c631daSSadaf Ebrahimi   __ Umulh(x5, x23, x27);
1315*f5c631daSSadaf Ebrahimi   __ Umulh(x6, x26, x26);
1316*f5c631daSSadaf Ebrahimi   __ Umulh(x7, x26, x27);
1317*f5c631daSSadaf Ebrahimi   __ Umulh(x8, x27, x27);
1318*f5c631daSSadaf Ebrahimi   __ Umulh(x9, x28, x28);
1319*f5c631daSSadaf Ebrahimi   __ Umulh(x10, x28, x29);
1320*f5c631daSSadaf Ebrahimi   __ Umulh(x11, x29, x29);
1321*f5c631daSSadaf Ebrahimi   END();
1322*f5c631daSSadaf Ebrahimi 
1323*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1324*f5c631daSSadaf Ebrahimi     RUN();
1325*f5c631daSSadaf Ebrahimi 
1326*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
1327*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x1);
1328*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x2);
1329*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000001234567, x3);
1330*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000002468acf, x4);
1331*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345677, x5);
1332*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4000000000000000, x6);
1333*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffffffffffff, x7);
1334*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x8);
1335*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1336*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x38e38e38e38e38e3, x10);
1337*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x71c71c71c71c71c6, x11);
1338*f5c631daSSadaf Ebrahimi   }
1339*f5c631daSSadaf Ebrahimi }
1340*f5c631daSSadaf Ebrahimi 
1341*f5c631daSSadaf Ebrahimi 
TEST(smaddl_umaddl_umull)1342*f5c631daSSadaf Ebrahimi TEST(smaddl_umaddl_umull) {
1343*f5c631daSSadaf Ebrahimi   SETUP();
1344*f5c631daSSadaf Ebrahimi 
1345*f5c631daSSadaf Ebrahimi   START();
1346*f5c631daSSadaf Ebrahimi   __ Mov(x17, 1);
1347*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0x00000000ffffffff);
1348*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0xffffffffffffffff);
1349*f5c631daSSadaf Ebrahimi   __ Mov(x20, 4);
1350*f5c631daSSadaf Ebrahimi   __ Mov(x21, 0x0000000200000000);
1351*f5c631daSSadaf Ebrahimi 
1352*f5c631daSSadaf Ebrahimi   __ Smaddl(x9, w17, w18, x20);
1353*f5c631daSSadaf Ebrahimi   __ Smaddl(x10, w18, w18, x20);
1354*f5c631daSSadaf Ebrahimi   __ Smaddl(x11, w19, w19, x20);
1355*f5c631daSSadaf Ebrahimi   __ Smaddl(x12, w19, w19, x21);
1356*f5c631daSSadaf Ebrahimi   __ Umaddl(x13, w17, w18, x20);
1357*f5c631daSSadaf Ebrahimi   __ Umaddl(x14, w18, w18, x20);
1358*f5c631daSSadaf Ebrahimi   __ Umaddl(x15, w19, w19, x20);
1359*f5c631daSSadaf Ebrahimi   __ Umaddl(x22, w19, w19, x21);
1360*f5c631daSSadaf Ebrahimi   __ Umull(x24, w19, w19);
1361*f5c631daSSadaf Ebrahimi   __ Umull(x25, w17, w18);
1362*f5c631daSSadaf Ebrahimi   END();
1363*f5c631daSSadaf Ebrahimi 
1364*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1365*f5c631daSSadaf Ebrahimi     RUN();
1366*f5c631daSSadaf Ebrahimi 
1367*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x9);
1368*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(5, x10);
1369*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(5, x11);
1370*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000200000001, x12);
1371*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000100000003, x13);
1372*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe00000005, x14);
1373*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe00000005, x15);
1374*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x22);
1375*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe00000001, x24);
1376*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000ffffffff, x25);
1377*f5c631daSSadaf Ebrahimi   }
1378*f5c631daSSadaf Ebrahimi }
1379*f5c631daSSadaf Ebrahimi 
1380*f5c631daSSadaf Ebrahimi 
TEST(smsubl_umsubl)1381*f5c631daSSadaf Ebrahimi TEST(smsubl_umsubl) {
1382*f5c631daSSadaf Ebrahimi   SETUP();
1383*f5c631daSSadaf Ebrahimi 
1384*f5c631daSSadaf Ebrahimi   START();
1385*f5c631daSSadaf Ebrahimi   __ Mov(x17, 1);
1386*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0x00000000ffffffff);
1387*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0xffffffffffffffff);
1388*f5c631daSSadaf Ebrahimi   __ Mov(x20, 4);
1389*f5c631daSSadaf Ebrahimi   __ Mov(x21, 0x0000000200000000);
1390*f5c631daSSadaf Ebrahimi 
1391*f5c631daSSadaf Ebrahimi   __ Smsubl(x9, w17, w18, x20);
1392*f5c631daSSadaf Ebrahimi   __ Smsubl(x10, w18, w18, x20);
1393*f5c631daSSadaf Ebrahimi   __ Smsubl(x11, w19, w19, x20);
1394*f5c631daSSadaf Ebrahimi   __ Smsubl(x12, w19, w19, x21);
1395*f5c631daSSadaf Ebrahimi   __ Umsubl(x13, w17, w18, x20);
1396*f5c631daSSadaf Ebrahimi   __ Umsubl(x14, w18, w18, x20);
1397*f5c631daSSadaf Ebrahimi   __ Umsubl(x15, w19, w19, x20);
1398*f5c631daSSadaf Ebrahimi   __ Umsubl(x22, w19, w19, x21);
1399*f5c631daSSadaf Ebrahimi   END();
1400*f5c631daSSadaf Ebrahimi 
1401*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1402*f5c631daSSadaf Ebrahimi     RUN();
1403*f5c631daSSadaf Ebrahimi 
1404*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(5, x9);
1405*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x10);
1406*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x11);
1407*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001ffffffff, x12);
1408*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff00000005, x13);
1409*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000200000003, x14);
1410*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000200000003, x15);
1411*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000003ffffffff, x22);
1412*f5c631daSSadaf Ebrahimi   }
1413*f5c631daSSadaf Ebrahimi }
1414*f5c631daSSadaf Ebrahimi 
1415*f5c631daSSadaf Ebrahimi 
TEST(div)1416*f5c631daSSadaf Ebrahimi TEST(div) {
1417*f5c631daSSadaf Ebrahimi   SETUP();
1418*f5c631daSSadaf Ebrahimi 
1419*f5c631daSSadaf Ebrahimi   START();
1420*f5c631daSSadaf Ebrahimi   __ Mov(x16, 1);
1421*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0xffffffff);
1422*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xffffffffffffffff);
1423*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0x80000000);
1424*f5c631daSSadaf Ebrahimi   __ Mov(x20, 0x8000000000000000);
1425*f5c631daSSadaf Ebrahimi   __ Mov(x21, 2);
1426*f5c631daSSadaf Ebrahimi 
1427*f5c631daSSadaf Ebrahimi   __ Udiv(w0, w16, w16);
1428*f5c631daSSadaf Ebrahimi   __ Udiv(w1, w17, w16);
1429*f5c631daSSadaf Ebrahimi   __ Sdiv(w2, w16, w16);
1430*f5c631daSSadaf Ebrahimi   __ Sdiv(w3, w16, w17);
1431*f5c631daSSadaf Ebrahimi   __ Sdiv(w4, w17, w18);
1432*f5c631daSSadaf Ebrahimi 
1433*f5c631daSSadaf Ebrahimi   __ Udiv(x5, x16, x16);
1434*f5c631daSSadaf Ebrahimi   __ Udiv(x6, x17, x18);
1435*f5c631daSSadaf Ebrahimi   __ Sdiv(x7, x16, x16);
1436*f5c631daSSadaf Ebrahimi   __ Sdiv(x8, x16, x17);
1437*f5c631daSSadaf Ebrahimi   __ Sdiv(x9, x17, x18);
1438*f5c631daSSadaf Ebrahimi 
1439*f5c631daSSadaf Ebrahimi   __ Udiv(w10, w19, w21);
1440*f5c631daSSadaf Ebrahimi   __ Sdiv(w11, w19, w21);
1441*f5c631daSSadaf Ebrahimi   __ Udiv(x12, x19, x21);
1442*f5c631daSSadaf Ebrahimi   __ Sdiv(x13, x19, x21);
1443*f5c631daSSadaf Ebrahimi   __ Udiv(x14, x20, x21);
1444*f5c631daSSadaf Ebrahimi   __ Sdiv(x15, x20, x21);
1445*f5c631daSSadaf Ebrahimi 
1446*f5c631daSSadaf Ebrahimi   __ Udiv(w22, w19, w17);
1447*f5c631daSSadaf Ebrahimi   __ Sdiv(w23, w19, w17);
1448*f5c631daSSadaf Ebrahimi   __ Udiv(x24, x20, x18);
1449*f5c631daSSadaf Ebrahimi   __ Sdiv(x25, x20, x18);
1450*f5c631daSSadaf Ebrahimi 
1451*f5c631daSSadaf Ebrahimi   __ Udiv(x26, x16, x21);
1452*f5c631daSSadaf Ebrahimi   __ Sdiv(x27, x16, x21);
1453*f5c631daSSadaf Ebrahimi   __ Udiv(x28, x18, x21);
1454*f5c631daSSadaf Ebrahimi   __ Sdiv(x29, x18, x21);
1455*f5c631daSSadaf Ebrahimi 
1456*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0);
1457*f5c631daSSadaf Ebrahimi   __ Udiv(w18, w16, w17);
1458*f5c631daSSadaf Ebrahimi   __ Sdiv(w19, w16, w17);
1459*f5c631daSSadaf Ebrahimi   __ Udiv(x20, x16, x17);
1460*f5c631daSSadaf Ebrahimi   __ Sdiv(x21, x16, x17);
1461*f5c631daSSadaf Ebrahimi   END();
1462*f5c631daSSadaf Ebrahimi 
1463*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1464*f5c631daSSadaf Ebrahimi     RUN();
1465*f5c631daSSadaf Ebrahimi 
1466*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x0);
1467*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x1);
1468*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x2);
1469*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x3);
1470*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x4);
1471*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x5);
1472*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x6);
1473*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x7);
1474*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x8);
1475*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff00000001, x9);
1476*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x40000000, x10);
1477*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xc0000000, x11);
1478*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000040000000, x12);
1479*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000040000000, x13);
1480*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4000000000000000, x14);
1481*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xc000000000000000, x15);
1482*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x22);
1483*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x80000000, x23);
1484*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x24);
1485*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8000000000000000, x25);
1486*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x26);
1487*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x27);
1488*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffffffffffff, x28);
1489*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x29);
1490*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x18);
1491*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x19);
1492*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x20);
1493*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x21);
1494*f5c631daSSadaf Ebrahimi   }
1495*f5c631daSSadaf Ebrahimi }
1496*f5c631daSSadaf Ebrahimi 
1497*f5c631daSSadaf Ebrahimi 
TEST(rbit_rev)1498*f5c631daSSadaf Ebrahimi TEST(rbit_rev) {
1499*f5c631daSSadaf Ebrahimi   SETUP();
1500*f5c631daSSadaf Ebrahimi 
1501*f5c631daSSadaf Ebrahimi   START();
1502*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0xfedcba9876543210);
1503*f5c631daSSadaf Ebrahimi   __ Rbit(w0, w24);
1504*f5c631daSSadaf Ebrahimi   __ Rbit(x1, x24);
1505*f5c631daSSadaf Ebrahimi   __ Rev16(w2, w24);
1506*f5c631daSSadaf Ebrahimi   __ Rev16(x3, x24);
1507*f5c631daSSadaf Ebrahimi   __ Rev(w4, w24);
1508*f5c631daSSadaf Ebrahimi   __ Rev32(x5, x24);
1509*f5c631daSSadaf Ebrahimi   __ Rev64(x6, x24);
1510*f5c631daSSadaf Ebrahimi   __ Rev(x7, x24);
1511*f5c631daSSadaf Ebrahimi   END();
1512*f5c631daSSadaf Ebrahimi 
1513*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1514*f5c631daSSadaf Ebrahimi     RUN();
1515*f5c631daSSadaf Ebrahimi 
1516*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x084c2a6e, x0);
1517*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x084c2a6e195d3b7f, x1);
1518*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x54761032, x2);
1519*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xdcfe98ba54761032, x3);
1520*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10325476, x4);
1521*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x98badcfe10325476, x5);
1522*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1032547698badcfe, x6);
1523*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1032547698badcfe, x7);
1524*f5c631daSSadaf Ebrahimi   }
1525*f5c631daSSadaf Ebrahimi }
1526*f5c631daSSadaf Ebrahimi 
1527*f5c631daSSadaf Ebrahimi typedef void (MacroAssembler::*TestBranchSignature)(const Register& rt,
1528*f5c631daSSadaf Ebrahimi                                                     unsigned bit_pos,
1529*f5c631daSSadaf Ebrahimi                                                     Label* label);
1530*f5c631daSSadaf Ebrahimi 
TbzRangePoolLimitHelper(TestBranchSignature test_branch)1531*f5c631daSSadaf Ebrahimi static void TbzRangePoolLimitHelper(TestBranchSignature test_branch) {
1532*f5c631daSSadaf Ebrahimi   const int kTbzRange = 32768;
1533*f5c631daSSadaf Ebrahimi   const int kNumLdrLiteral = kTbzRange / 4;
1534*f5c631daSSadaf Ebrahimi   const int fuzz_range = 2;
1535*f5c631daSSadaf Ebrahimi   for (int n = kNumLdrLiteral - fuzz_range; n <= kNumLdrLiteral + fuzz_range;
1536*f5c631daSSadaf Ebrahimi        ++n) {
1537*f5c631daSSadaf Ebrahimi     for (int margin = -32; margin < 32; margin += 4) {
1538*f5c631daSSadaf Ebrahimi       SETUP();
1539*f5c631daSSadaf Ebrahimi 
1540*f5c631daSSadaf Ebrahimi       START();
1541*f5c631daSSadaf Ebrahimi 
1542*f5c631daSSadaf Ebrahimi       // Emit 32KB of literals (equal to the range of TBZ).
1543*f5c631daSSadaf Ebrahimi       for (int i = 0; i < n; ++i) {
1544*f5c631daSSadaf Ebrahimi         __ Ldr(w0, 0x12345678);
1545*f5c631daSSadaf Ebrahimi       }
1546*f5c631daSSadaf Ebrahimi 
1547*f5c631daSSadaf Ebrahimi       const int kLiteralMargin = 128 * KBytes;
1548*f5c631daSSadaf Ebrahimi 
1549*f5c631daSSadaf Ebrahimi       // Emit enough NOPs to be just about to emit the literal pool.
1550*f5c631daSSadaf Ebrahimi       ptrdiff_t end =
1551*f5c631daSSadaf Ebrahimi           masm.GetCursorOffset() + (kLiteralMargin - n * 4 + margin);
1552*f5c631daSSadaf Ebrahimi       while (masm.GetCursorOffset() < end) {
1553*f5c631daSSadaf Ebrahimi         __ Nop();
1554*f5c631daSSadaf Ebrahimi       }
1555*f5c631daSSadaf Ebrahimi 
1556*f5c631daSSadaf Ebrahimi       // Add a TBZ instruction.
1557*f5c631daSSadaf Ebrahimi       Label label;
1558*f5c631daSSadaf Ebrahimi 
1559*f5c631daSSadaf Ebrahimi       (masm.*test_branch)(x0, 2, &label);
1560*f5c631daSSadaf Ebrahimi 
1561*f5c631daSSadaf Ebrahimi       // Add enough NOPs to surpass its range, to make sure we can encode the
1562*f5c631daSSadaf Ebrahimi       // veneer.
1563*f5c631daSSadaf Ebrahimi       end = masm.GetCursorOffset() + (kTbzRange - 4);
1564*f5c631daSSadaf Ebrahimi       {
1565*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm,
1566*f5c631daSSadaf Ebrahimi                                  kTbzRange,
1567*f5c631daSSadaf Ebrahimi                                  ExactAssemblyScope::kMaximumSize);
1568*f5c631daSSadaf Ebrahimi         while (masm.GetCursorOffset() < end) __ nop();
1569*f5c631daSSadaf Ebrahimi       }
1570*f5c631daSSadaf Ebrahimi 
1571*f5c631daSSadaf Ebrahimi       // Finally, bind the label.
1572*f5c631daSSadaf Ebrahimi       __ Bind(&label);
1573*f5c631daSSadaf Ebrahimi 
1574*f5c631daSSadaf Ebrahimi       END();
1575*f5c631daSSadaf Ebrahimi 
1576*f5c631daSSadaf Ebrahimi       if (CAN_RUN()) {
1577*f5c631daSSadaf Ebrahimi         RUN();
1578*f5c631daSSadaf Ebrahimi       }
1579*f5c631daSSadaf Ebrahimi     }
1580*f5c631daSSadaf Ebrahimi   }
1581*f5c631daSSadaf Ebrahimi }
1582*f5c631daSSadaf Ebrahimi 
TEST(test_branch_limits_literal_pool_size_tbz)1583*f5c631daSSadaf Ebrahimi TEST(test_branch_limits_literal_pool_size_tbz) {
1584*f5c631daSSadaf Ebrahimi   TbzRangePoolLimitHelper(&MacroAssembler::Tbz);
1585*f5c631daSSadaf Ebrahimi }
1586*f5c631daSSadaf Ebrahimi 
TEST(test_branch_limits_literal_pool_size_tbnz)1587*f5c631daSSadaf Ebrahimi TEST(test_branch_limits_literal_pool_size_tbnz) {
1588*f5c631daSSadaf Ebrahimi   TbzRangePoolLimitHelper(&MacroAssembler::Tbnz);
1589*f5c631daSSadaf Ebrahimi }
1590*f5c631daSSadaf Ebrahimi 
TEST(clz_cls)1591*f5c631daSSadaf Ebrahimi TEST(clz_cls) {
1592*f5c631daSSadaf Ebrahimi   SETUP();
1593*f5c631daSSadaf Ebrahimi 
1594*f5c631daSSadaf Ebrahimi   START();
1595*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0x0008000000800000);
1596*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0xff800000fff80000);
1597*f5c631daSSadaf Ebrahimi   __ Mov(x26, 0);
1598*f5c631daSSadaf Ebrahimi   __ Clz(w0, w24);
1599*f5c631daSSadaf Ebrahimi   __ Clz(x1, x24);
1600*f5c631daSSadaf Ebrahimi   __ Clz(w2, w25);
1601*f5c631daSSadaf Ebrahimi   __ Clz(x3, x25);
1602*f5c631daSSadaf Ebrahimi   __ Clz(w4, w26);
1603*f5c631daSSadaf Ebrahimi   __ Clz(x5, x26);
1604*f5c631daSSadaf Ebrahimi   __ Cls(w6, w24);
1605*f5c631daSSadaf Ebrahimi   __ Cls(x7, x24);
1606*f5c631daSSadaf Ebrahimi   __ Cls(w8, w25);
1607*f5c631daSSadaf Ebrahimi   __ Cls(x9, x25);
1608*f5c631daSSadaf Ebrahimi   __ Cls(w10, w26);
1609*f5c631daSSadaf Ebrahimi   __ Cls(x11, x26);
1610*f5c631daSSadaf Ebrahimi   END();
1611*f5c631daSSadaf Ebrahimi 
1612*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1613*f5c631daSSadaf Ebrahimi     RUN();
1614*f5c631daSSadaf Ebrahimi 
1615*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(8, x0);
1616*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(12, x1);
1617*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x2);
1618*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x3);
1619*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(32, x4);
1620*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(64, x5);
1621*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(7, x6);
1622*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(11, x7);
1623*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(12, x8);
1624*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(8, x9);
1625*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(31, x10);
1626*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(63, x11);
1627*f5c631daSSadaf Ebrahimi   }
1628*f5c631daSSadaf Ebrahimi }
1629*f5c631daSSadaf Ebrahimi 
1630*f5c631daSSadaf Ebrahimi 
TEST(pacia_pacib_autia_autib)1631*f5c631daSSadaf Ebrahimi TEST(pacia_pacib_autia_autib) {
1632*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1633*f5c631daSSadaf Ebrahimi 
1634*f5c631daSSadaf Ebrahimi   START();
1635*f5c631daSSadaf Ebrahimi 
1636*f5c631daSSadaf Ebrahimi   Register pointer = x24;
1637*f5c631daSSadaf Ebrahimi   Register modifier = x25;
1638*f5c631daSSadaf Ebrahimi 
1639*f5c631daSSadaf Ebrahimi   __ Mov(pointer, 0x0000000012345678);
1640*f5c631daSSadaf Ebrahimi   __ Mov(modifier, 0x477d469dec0b8760);
1641*f5c631daSSadaf Ebrahimi 
1642*f5c631daSSadaf Ebrahimi   // Generate PACs using keys A and B.
1643*f5c631daSSadaf Ebrahimi   __ Mov(x0, pointer);
1644*f5c631daSSadaf Ebrahimi   __ Pacia(x0, modifier);
1645*f5c631daSSadaf Ebrahimi 
1646*f5c631daSSadaf Ebrahimi   __ Mov(x1, pointer);
1647*f5c631daSSadaf Ebrahimi   __ Pacib(x1, modifier);
1648*f5c631daSSadaf Ebrahimi 
1649*f5c631daSSadaf Ebrahimi   // Authenticate the pointers above.
1650*f5c631daSSadaf Ebrahimi   __ Mov(x2, x0);
1651*f5c631daSSadaf Ebrahimi   __ Autia(x2, modifier);
1652*f5c631daSSadaf Ebrahimi 
1653*f5c631daSSadaf Ebrahimi   __ Mov(x3, x1);
1654*f5c631daSSadaf Ebrahimi   __ Autib(x3, modifier);
1655*f5c631daSSadaf Ebrahimi 
1656*f5c631daSSadaf Ebrahimi   // Attempt to authenticate incorrect pointers.
1657*f5c631daSSadaf Ebrahimi   __ Mov(x4, x1);
1658*f5c631daSSadaf Ebrahimi   __ Autia(x4, modifier);
1659*f5c631daSSadaf Ebrahimi 
1660*f5c631daSSadaf Ebrahimi   __ Mov(x5, x0);
1661*f5c631daSSadaf Ebrahimi   __ Autib(x5, modifier);
1662*f5c631daSSadaf Ebrahimi 
1663*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
1664*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
1665*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0x007f000000000000);
1666*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
1667*f5c631daSSadaf Ebrahimi 
1668*f5c631daSSadaf Ebrahimi   END();
1669*f5c631daSSadaf Ebrahimi 
1670*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1671*f5c631daSSadaf Ebrahimi     RUN();
1672*f5c631daSSadaf Ebrahimi 
1673*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
1674*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
1675*f5c631daSSadaf Ebrahimi     // collision.
1676*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
1677*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
1678*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x0, x1);
1679*f5c631daSSadaf Ebrahimi 
1680*f5c631daSSadaf Ebrahimi     // Pointers correctly authenticated.
1681*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x2);
1682*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x3);
1683*f5c631daSSadaf Ebrahimi 
1684*f5c631daSSadaf Ebrahimi     // Pointers corrupted after failing to authenticate.
1685*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x4);
1686*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x5);
1687*f5c631daSSadaf Ebrahimi   }
1688*f5c631daSSadaf Ebrahimi }
1689*f5c631daSSadaf Ebrahimi 
1690*f5c631daSSadaf Ebrahimi 
TEST(paciza_pacizb_autiza_autizb)1691*f5c631daSSadaf Ebrahimi TEST(paciza_pacizb_autiza_autizb) {
1692*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1693*f5c631daSSadaf Ebrahimi 
1694*f5c631daSSadaf Ebrahimi   START();
1695*f5c631daSSadaf Ebrahimi 
1696*f5c631daSSadaf Ebrahimi   Register pointer = x24;
1697*f5c631daSSadaf Ebrahimi 
1698*f5c631daSSadaf Ebrahimi   __ Mov(pointer, 0x0000000012345678);
1699*f5c631daSSadaf Ebrahimi 
1700*f5c631daSSadaf Ebrahimi   // Generate PACs using keys A and B.
1701*f5c631daSSadaf Ebrahimi   __ Mov(x0, pointer);
1702*f5c631daSSadaf Ebrahimi   __ Paciza(x0);
1703*f5c631daSSadaf Ebrahimi 
1704*f5c631daSSadaf Ebrahimi   __ Mov(x1, pointer);
1705*f5c631daSSadaf Ebrahimi   __ Pacizb(x1);
1706*f5c631daSSadaf Ebrahimi 
1707*f5c631daSSadaf Ebrahimi   // Authenticate the pointers above.
1708*f5c631daSSadaf Ebrahimi   __ Mov(x2, x0);
1709*f5c631daSSadaf Ebrahimi   __ Autiza(x2);
1710*f5c631daSSadaf Ebrahimi 
1711*f5c631daSSadaf Ebrahimi   __ Mov(x3, x1);
1712*f5c631daSSadaf Ebrahimi   __ Autizb(x3);
1713*f5c631daSSadaf Ebrahimi 
1714*f5c631daSSadaf Ebrahimi   // Attempt to authenticate incorrect pointers.
1715*f5c631daSSadaf Ebrahimi   __ Mov(x4, x1);
1716*f5c631daSSadaf Ebrahimi   __ Autiza(x4);
1717*f5c631daSSadaf Ebrahimi 
1718*f5c631daSSadaf Ebrahimi   __ Mov(x5, x0);
1719*f5c631daSSadaf Ebrahimi   __ Autizb(x5);
1720*f5c631daSSadaf Ebrahimi 
1721*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
1722*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
1723*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0x007f000000000000);
1724*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
1725*f5c631daSSadaf Ebrahimi 
1726*f5c631daSSadaf Ebrahimi   END();
1727*f5c631daSSadaf Ebrahimi 
1728*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1729*f5c631daSSadaf Ebrahimi     RUN();
1730*f5c631daSSadaf Ebrahimi 
1731*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
1732*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
1733*f5c631daSSadaf Ebrahimi     // collision.
1734*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
1735*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
1736*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x0, x1);
1737*f5c631daSSadaf Ebrahimi 
1738*f5c631daSSadaf Ebrahimi     // Pointers correctly authenticated.
1739*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x2);
1740*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x3);
1741*f5c631daSSadaf Ebrahimi 
1742*f5c631daSSadaf Ebrahimi     // Pointers corrupted after failing to authenticate.
1743*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x4);
1744*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x5);
1745*f5c631daSSadaf Ebrahimi   }
1746*f5c631daSSadaf Ebrahimi }
1747*f5c631daSSadaf Ebrahimi 
1748*f5c631daSSadaf Ebrahimi 
TEST(pacda_pacdb_autda_autdb)1749*f5c631daSSadaf Ebrahimi TEST(pacda_pacdb_autda_autdb) {
1750*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1751*f5c631daSSadaf Ebrahimi 
1752*f5c631daSSadaf Ebrahimi   START();
1753*f5c631daSSadaf Ebrahimi 
1754*f5c631daSSadaf Ebrahimi   Register pointer = x24;
1755*f5c631daSSadaf Ebrahimi   Register modifier = x25;
1756*f5c631daSSadaf Ebrahimi 
1757*f5c631daSSadaf Ebrahimi   __ Mov(pointer, 0x0000000012345678);
1758*f5c631daSSadaf Ebrahimi   __ Mov(modifier, 0x477d469dec0b8760);
1759*f5c631daSSadaf Ebrahimi 
1760*f5c631daSSadaf Ebrahimi   // Generate PACs using keys A and B.
1761*f5c631daSSadaf Ebrahimi   __ Mov(x0, pointer);
1762*f5c631daSSadaf Ebrahimi   __ Pacda(x0, modifier);
1763*f5c631daSSadaf Ebrahimi 
1764*f5c631daSSadaf Ebrahimi   __ Mov(x1, pointer);
1765*f5c631daSSadaf Ebrahimi   __ Pacdb(x1, modifier);
1766*f5c631daSSadaf Ebrahimi 
1767*f5c631daSSadaf Ebrahimi   // Authenticate the pointers above.
1768*f5c631daSSadaf Ebrahimi   __ Mov(x2, x0);
1769*f5c631daSSadaf Ebrahimi   __ Autda(x2, modifier);
1770*f5c631daSSadaf Ebrahimi 
1771*f5c631daSSadaf Ebrahimi   __ Mov(x3, x1);
1772*f5c631daSSadaf Ebrahimi   __ Autdb(x3, modifier);
1773*f5c631daSSadaf Ebrahimi 
1774*f5c631daSSadaf Ebrahimi   // Attempt to authenticate incorrect pointers.
1775*f5c631daSSadaf Ebrahimi   __ Mov(x4, x1);
1776*f5c631daSSadaf Ebrahimi   __ Autda(x4, modifier);
1777*f5c631daSSadaf Ebrahimi 
1778*f5c631daSSadaf Ebrahimi   __ Mov(x5, x0);
1779*f5c631daSSadaf Ebrahimi   __ Autdb(x5, modifier);
1780*f5c631daSSadaf Ebrahimi 
1781*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
1782*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
1783*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0x007f000000000000);
1784*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
1785*f5c631daSSadaf Ebrahimi 
1786*f5c631daSSadaf Ebrahimi   END();
1787*f5c631daSSadaf Ebrahimi 
1788*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1789*f5c631daSSadaf Ebrahimi     RUN();
1790*f5c631daSSadaf Ebrahimi 
1791*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
1792*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
1793*f5c631daSSadaf Ebrahimi     // collision.
1794*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
1795*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
1796*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x0, x1);
1797*f5c631daSSadaf Ebrahimi 
1798*f5c631daSSadaf Ebrahimi     // Pointers correctly authenticated.
1799*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x2);
1800*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x3);
1801*f5c631daSSadaf Ebrahimi 
1802*f5c631daSSadaf Ebrahimi     // Pointers corrupted after failing to authenticate.
1803*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x4);
1804*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x5);
1805*f5c631daSSadaf Ebrahimi   }
1806*f5c631daSSadaf Ebrahimi }
1807*f5c631daSSadaf Ebrahimi 
1808*f5c631daSSadaf Ebrahimi 
TEST(pacdza_pacdzb_autdza_autdzb)1809*f5c631daSSadaf Ebrahimi TEST(pacdza_pacdzb_autdza_autdzb) {
1810*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
1811*f5c631daSSadaf Ebrahimi 
1812*f5c631daSSadaf Ebrahimi   START();
1813*f5c631daSSadaf Ebrahimi 
1814*f5c631daSSadaf Ebrahimi   Register pointer = x24;
1815*f5c631daSSadaf Ebrahimi 
1816*f5c631daSSadaf Ebrahimi   __ Mov(pointer, 0x0000000012345678);
1817*f5c631daSSadaf Ebrahimi 
1818*f5c631daSSadaf Ebrahimi   // Generate PACs using keys A and B.
1819*f5c631daSSadaf Ebrahimi   __ Mov(x0, pointer);
1820*f5c631daSSadaf Ebrahimi   __ Pacdza(x0);
1821*f5c631daSSadaf Ebrahimi 
1822*f5c631daSSadaf Ebrahimi   __ Mov(x1, pointer);
1823*f5c631daSSadaf Ebrahimi   __ Pacdzb(x1);
1824*f5c631daSSadaf Ebrahimi 
1825*f5c631daSSadaf Ebrahimi   // Authenticate the pointers above.
1826*f5c631daSSadaf Ebrahimi   __ Mov(x2, x0);
1827*f5c631daSSadaf Ebrahimi   __ Autdza(x2);
1828*f5c631daSSadaf Ebrahimi 
1829*f5c631daSSadaf Ebrahimi   __ Mov(x3, x1);
1830*f5c631daSSadaf Ebrahimi   __ Autdzb(x3);
1831*f5c631daSSadaf Ebrahimi 
1832*f5c631daSSadaf Ebrahimi   // Attempt to authenticate incorrect pointers.
1833*f5c631daSSadaf Ebrahimi   __ Mov(x4, x1);
1834*f5c631daSSadaf Ebrahimi   __ Autdza(x4);
1835*f5c631daSSadaf Ebrahimi 
1836*f5c631daSSadaf Ebrahimi   __ Mov(x5, x0);
1837*f5c631daSSadaf Ebrahimi   __ Autdzb(x5);
1838*f5c631daSSadaf Ebrahimi 
1839*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
1840*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
1841*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0x007f000000000000);
1842*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
1843*f5c631daSSadaf Ebrahimi 
1844*f5c631daSSadaf Ebrahimi   END();
1845*f5c631daSSadaf Ebrahimi 
1846*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1847*f5c631daSSadaf Ebrahimi     RUN();
1848*f5c631daSSadaf Ebrahimi 
1849*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
1850*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
1851*f5c631daSSadaf Ebrahimi     // collision.
1852*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
1853*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
1854*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x0, x1);
1855*f5c631daSSadaf Ebrahimi 
1856*f5c631daSSadaf Ebrahimi     // Pointers correctly authenticated.
1857*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x2);
1858*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x3);
1859*f5c631daSSadaf Ebrahimi 
1860*f5c631daSSadaf Ebrahimi     // Pointers corrupted after failing to authenticate.
1861*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x4);
1862*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x5);
1863*f5c631daSSadaf Ebrahimi   }
1864*f5c631daSSadaf Ebrahimi }
1865*f5c631daSSadaf Ebrahimi 
1866*f5c631daSSadaf Ebrahimi 
TEST(pacga_xpaci_xpacd)1867*f5c631daSSadaf Ebrahimi TEST(pacga_xpaci_xpacd) {
1868*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth, CPUFeatures::kPAuthGeneric);
1869*f5c631daSSadaf Ebrahimi 
1870*f5c631daSSadaf Ebrahimi   START();
1871*f5c631daSSadaf Ebrahimi 
1872*f5c631daSSadaf Ebrahimi   Register pointer = x24;
1873*f5c631daSSadaf Ebrahimi   Register modifier = x25;
1874*f5c631daSSadaf Ebrahimi 
1875*f5c631daSSadaf Ebrahimi   __ Mov(pointer, 0x0000000012345678);
1876*f5c631daSSadaf Ebrahimi   __ Mov(modifier, 0x477d469dec0b8760);
1877*f5c631daSSadaf Ebrahimi 
1878*f5c631daSSadaf Ebrahimi   // Generate generic PAC.
1879*f5c631daSSadaf Ebrahimi   __ Pacga(x0, pointer, modifier);
1880*f5c631daSSadaf Ebrahimi 
1881*f5c631daSSadaf Ebrahimi   // Generate PACs using key A.
1882*f5c631daSSadaf Ebrahimi   __ Mov(x1, pointer);
1883*f5c631daSSadaf Ebrahimi   __ Mov(x2, pointer);
1884*f5c631daSSadaf Ebrahimi   __ Pacia(x1, modifier);
1885*f5c631daSSadaf Ebrahimi   __ Pacda(x2, modifier);
1886*f5c631daSSadaf Ebrahimi 
1887*f5c631daSSadaf Ebrahimi   // Strip PACs.
1888*f5c631daSSadaf Ebrahimi   __ Mov(x3, x1);
1889*f5c631daSSadaf Ebrahimi   __ Mov(x4, x2);
1890*f5c631daSSadaf Ebrahimi   __ Xpaci(x3);
1891*f5c631daSSadaf Ebrahimi   __ Xpacd(x4);
1892*f5c631daSSadaf Ebrahimi 
1893*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
1894*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
1895*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0xffffffff00000000);
1896*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
1897*f5c631daSSadaf Ebrahimi   __ And(x2, x2, 0x007f000000000000);
1898*f5c631daSSadaf Ebrahimi 
1899*f5c631daSSadaf Ebrahimi   END();
1900*f5c631daSSadaf Ebrahimi 
1901*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1902*f5c631daSSadaf Ebrahimi     RUN();
1903*f5c631daSSadaf Ebrahimi 
1904*f5c631daSSadaf Ebrahimi 
1905*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
1906*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
1907*f5c631daSSadaf Ebrahimi     // collision.
1908*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
1909*f5c631daSSadaf Ebrahimi 
1910*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
1911*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x2);
1912*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x1, x2);
1913*f5c631daSSadaf Ebrahimi 
1914*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x3);
1915*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(pointer, x4);
1916*f5c631daSSadaf Ebrahimi   }
1917*f5c631daSSadaf Ebrahimi }
1918*f5c631daSSadaf Ebrahimi 
1919*f5c631daSSadaf Ebrahimi 
TEST(label)1920*f5c631daSSadaf Ebrahimi TEST(label) {
1921*f5c631daSSadaf Ebrahimi   SETUP();
1922*f5c631daSSadaf Ebrahimi 
1923*f5c631daSSadaf Ebrahimi   Label label_1, label_2, label_3, label_4;
1924*f5c631daSSadaf Ebrahimi 
1925*f5c631daSSadaf Ebrahimi   START();
1926*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x1);
1927*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0);
1928*f5c631daSSadaf Ebrahimi   __ Mov(x22, lr);  // Save lr.
1929*f5c631daSSadaf Ebrahimi 
1930*f5c631daSSadaf Ebrahimi   __ B(&label_1);
1931*f5c631daSSadaf Ebrahimi   __ B(&label_1);
1932*f5c631daSSadaf Ebrahimi   __ B(&label_1);  // Multiple branches to the same label.
1933*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
1934*f5c631daSSadaf Ebrahimi   __ Bind(&label_2);
1935*f5c631daSSadaf Ebrahimi   __ B(&label_3);  // Forward branch.
1936*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
1937*f5c631daSSadaf Ebrahimi   __ Bind(&label_1);
1938*f5c631daSSadaf Ebrahimi   __ B(&label_2);  // Backward branch.
1939*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
1940*f5c631daSSadaf Ebrahimi   __ Bind(&label_3);
1941*f5c631daSSadaf Ebrahimi   __ Bl(&label_4);
1942*f5c631daSSadaf Ebrahimi   END();
1943*f5c631daSSadaf Ebrahimi 
1944*f5c631daSSadaf Ebrahimi   __ Bind(&label_4);
1945*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1);
1946*f5c631daSSadaf Ebrahimi   __ Mov(lr, x22);
1947*f5c631daSSadaf Ebrahimi   END();
1948*f5c631daSSadaf Ebrahimi 
1949*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1950*f5c631daSSadaf Ebrahimi     RUN();
1951*f5c631daSSadaf Ebrahimi 
1952*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1, x0);
1953*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1, x1);
1954*f5c631daSSadaf Ebrahimi   }
1955*f5c631daSSadaf Ebrahimi }
1956*f5c631daSSadaf Ebrahimi 
1957*f5c631daSSadaf Ebrahimi 
TEST(label_2)1958*f5c631daSSadaf Ebrahimi TEST(label_2) {
1959*f5c631daSSadaf Ebrahimi   SETUP();
1960*f5c631daSSadaf Ebrahimi 
1961*f5c631daSSadaf Ebrahimi   Label label_1, label_2, label_3;
1962*f5c631daSSadaf Ebrahimi   Label first_jump_to_3;
1963*f5c631daSSadaf Ebrahimi 
1964*f5c631daSSadaf Ebrahimi   START();
1965*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
1966*f5c631daSSadaf Ebrahimi 
1967*f5c631daSSadaf Ebrahimi   __ B(&label_1);
1968*f5c631daSSadaf Ebrahimi   ptrdiff_t offset_2 = masm.GetCursorOffset();
1969*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 1);
1970*f5c631daSSadaf Ebrahimi   __ B(&label_3);
1971*f5c631daSSadaf Ebrahimi   ptrdiff_t offset_1 = masm.GetCursorOffset();
1972*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 0);
1973*f5c631daSSadaf Ebrahimi   __ B(&label_2);
1974*f5c631daSSadaf Ebrahimi   ptrdiff_t offset_3 = masm.GetCursorOffset();
1975*f5c631daSSadaf Ebrahimi   __ Tbz(x0, 2, &first_jump_to_3);
1976*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 3);
1977*f5c631daSSadaf Ebrahimi   __ Bind(&first_jump_to_3);
1978*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 2);
1979*f5c631daSSadaf Ebrahimi   __ Tbz(x0, 3, &label_3);
1980*f5c631daSSadaf Ebrahimi 
1981*f5c631daSSadaf Ebrahimi   // Labels 1, 2, and 3 are bound before the current buffer offset. Branches to
1982*f5c631daSSadaf Ebrahimi   // label_1 and label_2 branch respectively forward and backward. Branches to
1983*f5c631daSSadaf Ebrahimi   // label 3 include both forward and backward branches.
1984*f5c631daSSadaf Ebrahimi   masm.BindToOffset(&label_1, offset_1);
1985*f5c631daSSadaf Ebrahimi   masm.BindToOffset(&label_2, offset_2);
1986*f5c631daSSadaf Ebrahimi   masm.BindToOffset(&label_3, offset_3);
1987*f5c631daSSadaf Ebrahimi 
1988*f5c631daSSadaf Ebrahimi   END();
1989*f5c631daSSadaf Ebrahimi 
1990*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
1991*f5c631daSSadaf Ebrahimi     RUN();
1992*f5c631daSSadaf Ebrahimi 
1993*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf, x0);
1994*f5c631daSSadaf Ebrahimi   }
1995*f5c631daSSadaf Ebrahimi }
1996*f5c631daSSadaf Ebrahimi 
1997*f5c631daSSadaf Ebrahimi 
TEST(adr)1998*f5c631daSSadaf Ebrahimi TEST(adr) {
1999*f5c631daSSadaf Ebrahimi   SETUP();
2000*f5c631daSSadaf Ebrahimi 
2001*f5c631daSSadaf Ebrahimi   Label label_1, label_2, label_3, label_4;
2002*f5c631daSSadaf Ebrahimi 
2003*f5c631daSSadaf Ebrahimi   START();
2004*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);       // Set to non-zero to indicate failure.
2005*f5c631daSSadaf Ebrahimi   __ Adr(x1, &label_3);  // Set to zero to indicate success.
2006*f5c631daSSadaf Ebrahimi 
2007*f5c631daSSadaf Ebrahimi   __ Adr(x2, &label_1);  // Multiple forward references to the same label.
2008*f5c631daSSadaf Ebrahimi   __ Adr(x3, &label_1);
2009*f5c631daSSadaf Ebrahimi   __ Adr(x4, &label_1);
2010*f5c631daSSadaf Ebrahimi 
2011*f5c631daSSadaf Ebrahimi   __ Bind(&label_2);
2012*f5c631daSSadaf Ebrahimi   __ Eor(x5, x2, Operand(x3));  // Ensure that x2,x3 and x4 are identical.
2013*f5c631daSSadaf Ebrahimi   __ Eor(x6, x2, Operand(x4));
2014*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, Operand(x5));
2015*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, Operand(x6));
2016*f5c631daSSadaf Ebrahimi   __ Br(x2);  // label_1, label_3
2017*f5c631daSSadaf Ebrahimi 
2018*f5c631daSSadaf Ebrahimi   __ Bind(&label_3);
2019*f5c631daSSadaf Ebrahimi   __ Adr(x2, &label_3);  // Self-reference (offset 0).
2020*f5c631daSSadaf Ebrahimi   __ Eor(x1, x1, Operand(x2));
2021*f5c631daSSadaf Ebrahimi   __ Adr(x2, &label_4);  // Simple forward reference.
2022*f5c631daSSadaf Ebrahimi   __ Br(x2);             // label_4
2023*f5c631daSSadaf Ebrahimi 
2024*f5c631daSSadaf Ebrahimi   __ Bind(&label_1);
2025*f5c631daSSadaf Ebrahimi   __ Adr(x2, &label_3);  // Multiple reverse references to the same label.
2026*f5c631daSSadaf Ebrahimi   __ Adr(x3, &label_3);
2027*f5c631daSSadaf Ebrahimi   __ Adr(x4, &label_3);
2028*f5c631daSSadaf Ebrahimi   __ Adr(x5, &label_2);  // Simple reverse reference.
2029*f5c631daSSadaf Ebrahimi   __ Br(x5);             // label_2
2030*f5c631daSSadaf Ebrahimi 
2031*f5c631daSSadaf Ebrahimi   __ Bind(&label_4);
2032*f5c631daSSadaf Ebrahimi   END();
2033*f5c631daSSadaf Ebrahimi 
2034*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2035*f5c631daSSadaf Ebrahimi     RUN();
2036*f5c631daSSadaf Ebrahimi 
2037*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x0);
2038*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x1);
2039*f5c631daSSadaf Ebrahimi   }
2040*f5c631daSSadaf Ebrahimi }
2041*f5c631daSSadaf Ebrahimi 
2042*f5c631daSSadaf Ebrahimi 
2043*f5c631daSSadaf Ebrahimi // Simple adrp tests: check that labels are linked and handled properly.
2044*f5c631daSSadaf Ebrahimi // This is similar to the adr test, but all the adrp instructions are put on the
2045*f5c631daSSadaf Ebrahimi // same page so that they return the same value.
TEST(adrp)2046*f5c631daSSadaf Ebrahimi TEST(adrp) {
2047*f5c631daSSadaf Ebrahimi   Label start;
2048*f5c631daSSadaf Ebrahimi   Label label_1, label_2, label_3;
2049*f5c631daSSadaf Ebrahimi 
2050*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM(2 * kPageSize, PageOffsetDependentCode);
2051*f5c631daSSadaf Ebrahimi   START();
2052*f5c631daSSadaf Ebrahimi 
2053*f5c631daSSadaf Ebrahimi   // Waste space until the start of a page.
2054*f5c631daSSadaf Ebrahimi   {
2055*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm,
2056*f5c631daSSadaf Ebrahimi                              kPageSize,
2057*f5c631daSSadaf Ebrahimi                              ExactAssemblyScope::kMaximumSize);
2058*f5c631daSSadaf Ebrahimi     const uintptr_t kPageOffsetMask = kPageSize - 1;
2059*f5c631daSSadaf Ebrahimi     while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2060*f5c631daSSadaf Ebrahimi       __ b(&start);
2061*f5c631daSSadaf Ebrahimi     }
2062*f5c631daSSadaf Ebrahimi     __ bind(&start);
2063*f5c631daSSadaf Ebrahimi   }
2064*f5c631daSSadaf Ebrahimi 
2065*f5c631daSSadaf Ebrahimi   // Simple forward reference.
2066*f5c631daSSadaf Ebrahimi   __ Adrp(x0, &label_2);
2067*f5c631daSSadaf Ebrahimi 
2068*f5c631daSSadaf Ebrahimi   __ Bind(&label_1);
2069*f5c631daSSadaf Ebrahimi 
2070*f5c631daSSadaf Ebrahimi   // Multiple forward references to the same label.
2071*f5c631daSSadaf Ebrahimi   __ Adrp(x1, &label_3);
2072*f5c631daSSadaf Ebrahimi   __ Adrp(x2, &label_3);
2073*f5c631daSSadaf Ebrahimi   __ Adrp(x3, &label_3);
2074*f5c631daSSadaf Ebrahimi 
2075*f5c631daSSadaf Ebrahimi   __ Bind(&label_2);
2076*f5c631daSSadaf Ebrahimi 
2077*f5c631daSSadaf Ebrahimi   // Self-reference (offset 0).
2078*f5c631daSSadaf Ebrahimi   __ Adrp(x4, &label_2);
2079*f5c631daSSadaf Ebrahimi 
2080*f5c631daSSadaf Ebrahimi   __ Bind(&label_3);
2081*f5c631daSSadaf Ebrahimi 
2082*f5c631daSSadaf Ebrahimi   // Simple reverse reference.
2083*f5c631daSSadaf Ebrahimi   __ Adrp(x5, &label_1);
2084*f5c631daSSadaf Ebrahimi 
2085*f5c631daSSadaf Ebrahimi   // Multiple reverse references to the same label.
2086*f5c631daSSadaf Ebrahimi   __ Adrp(x6, &label_2);
2087*f5c631daSSadaf Ebrahimi   __ Adrp(x7, &label_2);
2088*f5c631daSSadaf Ebrahimi   __ Adrp(x8, &label_2);
2089*f5c631daSSadaf Ebrahimi 
2090*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&start) < kPageSize);
2091*f5c631daSSadaf Ebrahimi   END();
2092*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2093*f5c631daSSadaf Ebrahimi     RUN();
2094*f5c631daSSadaf Ebrahimi 
2095*f5c631daSSadaf Ebrahimi     uint64_t expected = reinterpret_cast<uint64_t>(
2096*f5c631daSSadaf Ebrahimi         AlignDown(masm.GetLabelAddress<uint64_t*>(&start), kPageSize));
2097*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x0);
2098*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x1);
2099*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x2);
2100*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x3);
2101*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x4);
2102*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x5);
2103*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x6);
2104*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x7);
2105*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x8);
2106*f5c631daSSadaf Ebrahimi   }
2107*f5c631daSSadaf Ebrahimi }
2108*f5c631daSSadaf Ebrahimi 
2109*f5c631daSSadaf Ebrahimi 
AdrpPageBoundaryHelper(unsigned offset_into_page)2110*f5c631daSSadaf Ebrahimi static void AdrpPageBoundaryHelper(unsigned offset_into_page) {
2111*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(offset_into_page < kPageSize);
2112*f5c631daSSadaf Ebrahimi   VIXL_ASSERT((offset_into_page % kInstructionSize) == 0);
2113*f5c631daSSadaf Ebrahimi 
2114*f5c631daSSadaf Ebrahimi   const uintptr_t kPageOffsetMask = kPageSize - 1;
2115*f5c631daSSadaf Ebrahimi 
2116*f5c631daSSadaf Ebrahimi   // The test label is always bound on page 0. Adrp instructions are generated
2117*f5c631daSSadaf Ebrahimi   // on pages from kStartPage to kEndPage (inclusive).
2118*f5c631daSSadaf Ebrahimi   const int kStartPage = -16;
2119*f5c631daSSadaf Ebrahimi   const int kEndPage = 16;
2120*f5c631daSSadaf Ebrahimi   const int kMaxCodeSize = (kEndPage - kStartPage + 2) * kPageSize;
2121*f5c631daSSadaf Ebrahimi 
2122*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
2123*f5c631daSSadaf Ebrahimi   START();
2124*f5c631daSSadaf Ebrahimi 
2125*f5c631daSSadaf Ebrahimi   Label test;
2126*f5c631daSSadaf Ebrahimi   Label start;
2127*f5c631daSSadaf Ebrahimi 
2128*f5c631daSSadaf Ebrahimi   {
2129*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm,
2130*f5c631daSSadaf Ebrahimi                              kMaxCodeSize,
2131*f5c631daSSadaf Ebrahimi                              ExactAssemblyScope::kMaximumSize);
2132*f5c631daSSadaf Ebrahimi     // Initialize NZCV with `eq` flags.
2133*f5c631daSSadaf Ebrahimi     __ cmp(wzr, wzr);
2134*f5c631daSSadaf Ebrahimi     // Waste space until the start of a page.
2135*f5c631daSSadaf Ebrahimi     while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2136*f5c631daSSadaf Ebrahimi       __ b(&start);
2137*f5c631daSSadaf Ebrahimi     }
2138*f5c631daSSadaf Ebrahimi 
2139*f5c631daSSadaf Ebrahimi     // The first page.
2140*f5c631daSSadaf Ebrahimi     VIXL_STATIC_ASSERT(kStartPage < 0);
2141*f5c631daSSadaf Ebrahimi     {
2142*f5c631daSSadaf Ebrahimi       ExactAssemblyScope scope_page(&masm, kPageSize);
2143*f5c631daSSadaf Ebrahimi       __ bind(&start);
2144*f5c631daSSadaf Ebrahimi       __ adrp(x0, &test);
2145*f5c631daSSadaf Ebrahimi       __ adrp(x1, &test);
2146*f5c631daSSadaf Ebrahimi       for (size_t i = 2; i < (kPageSize / kInstructionSize); i += 2) {
2147*f5c631daSSadaf Ebrahimi         __ ccmp(x0, x1, NoFlag, eq);
2148*f5c631daSSadaf Ebrahimi         __ adrp(x1, &test);
2149*f5c631daSSadaf Ebrahimi       }
2150*f5c631daSSadaf Ebrahimi     }
2151*f5c631daSSadaf Ebrahimi 
2152*f5c631daSSadaf Ebrahimi     // Subsequent pages.
2153*f5c631daSSadaf Ebrahimi     VIXL_STATIC_ASSERT(kEndPage >= 0);
2154*f5c631daSSadaf Ebrahimi     for (int page = (kStartPage + 1); page <= kEndPage; page++) {
2155*f5c631daSSadaf Ebrahimi       ExactAssemblyScope scope_page(&masm, kPageSize);
2156*f5c631daSSadaf Ebrahimi       if (page == 0) {
2157*f5c631daSSadaf Ebrahimi         for (size_t i = 0; i < (kPageSize / kInstructionSize);) {
2158*f5c631daSSadaf Ebrahimi           if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
2159*f5c631daSSadaf Ebrahimi           __ ccmp(x0, x1, NoFlag, eq);
2160*f5c631daSSadaf Ebrahimi           if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
2161*f5c631daSSadaf Ebrahimi           __ adrp(x1, &test);
2162*f5c631daSSadaf Ebrahimi         }
2163*f5c631daSSadaf Ebrahimi       } else {
2164*f5c631daSSadaf Ebrahimi         for (size_t i = 0; i < (kPageSize / kInstructionSize); i += 2) {
2165*f5c631daSSadaf Ebrahimi           __ ccmp(x0, x1, NoFlag, eq);
2166*f5c631daSSadaf Ebrahimi           __ adrp(x1, &test);
2167*f5c631daSSadaf Ebrahimi         }
2168*f5c631daSSadaf Ebrahimi       }
2169*f5c631daSSadaf Ebrahimi     }
2170*f5c631daSSadaf Ebrahimi   }
2171*f5c631daSSadaf Ebrahimi 
2172*f5c631daSSadaf Ebrahimi   // Every adrp instruction pointed to the same label (`test`), so they should
2173*f5c631daSSadaf Ebrahimi   // all have produced the same result.
2174*f5c631daSSadaf Ebrahimi 
2175*f5c631daSSadaf Ebrahimi   END();
2176*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2177*f5c631daSSadaf Ebrahimi     RUN();
2178*f5c631daSSadaf Ebrahimi 
2179*f5c631daSSadaf Ebrahimi     uintptr_t expected =
2180*f5c631daSSadaf Ebrahimi         AlignDown(masm.GetLabelAddress<uintptr_t>(&test), kPageSize);
2181*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x0);
2182*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x1);
2183*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
2184*f5c631daSSadaf Ebrahimi   }
2185*f5c631daSSadaf Ebrahimi }
2186*f5c631daSSadaf Ebrahimi 
2187*f5c631daSSadaf Ebrahimi 
2188*f5c631daSSadaf Ebrahimi // Test that labels are correctly referenced by adrp across page boundaries.
TEST(adrp_page_boundaries)2189*f5c631daSSadaf Ebrahimi TEST(adrp_page_boundaries) {
2190*f5c631daSSadaf Ebrahimi   VIXL_STATIC_ASSERT(kPageSize == 4096);
2191*f5c631daSSadaf Ebrahimi   AdrpPageBoundaryHelper(kInstructionSize * 0);
2192*f5c631daSSadaf Ebrahimi   AdrpPageBoundaryHelper(kInstructionSize * 1);
2193*f5c631daSSadaf Ebrahimi   AdrpPageBoundaryHelper(kInstructionSize * 512);
2194*f5c631daSSadaf Ebrahimi   AdrpPageBoundaryHelper(kInstructionSize * 1022);
2195*f5c631daSSadaf Ebrahimi   AdrpPageBoundaryHelper(kInstructionSize * 1023);
2196*f5c631daSSadaf Ebrahimi }
2197*f5c631daSSadaf Ebrahimi 
2198*f5c631daSSadaf Ebrahimi 
AdrpOffsetHelper(int64_t offset)2199*f5c631daSSadaf Ebrahimi static void AdrpOffsetHelper(int64_t offset) {
2200*f5c631daSSadaf Ebrahimi   const size_t kPageOffsetMask = kPageSize - 1;
2201*f5c631daSSadaf Ebrahimi   const int kMaxCodeSize = 2 * kPageSize;
2202*f5c631daSSadaf Ebrahimi 
2203*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
2204*f5c631daSSadaf Ebrahimi   START();
2205*f5c631daSSadaf Ebrahimi 
2206*f5c631daSSadaf Ebrahimi   Label page;
2207*f5c631daSSadaf Ebrahimi 
2208*f5c631daSSadaf Ebrahimi   {
2209*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm,
2210*f5c631daSSadaf Ebrahimi                              kMaxCodeSize,
2211*f5c631daSSadaf Ebrahimi                              ExactAssemblyScope::kMaximumSize);
2212*f5c631daSSadaf Ebrahimi     // Initialize NZCV with `eq` flags.
2213*f5c631daSSadaf Ebrahimi     __ cmp(wzr, wzr);
2214*f5c631daSSadaf Ebrahimi     // Waste space until the start of a page.
2215*f5c631daSSadaf Ebrahimi     while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
2216*f5c631daSSadaf Ebrahimi       __ b(&page);
2217*f5c631daSSadaf Ebrahimi     }
2218*f5c631daSSadaf Ebrahimi     __ bind(&page);
2219*f5c631daSSadaf Ebrahimi 
2220*f5c631daSSadaf Ebrahimi     {
2221*f5c631daSSadaf Ebrahimi       ExactAssemblyScope scope_page(&masm, kPageSize);
2222*f5c631daSSadaf Ebrahimi       // Every adrp instruction on this page should return the same value.
2223*f5c631daSSadaf Ebrahimi       __ adrp(x0, offset);
2224*f5c631daSSadaf Ebrahimi       __ adrp(x1, offset);
2225*f5c631daSSadaf Ebrahimi       for (size_t i = 2; i < kPageSize / kInstructionSize; i += 2) {
2226*f5c631daSSadaf Ebrahimi         __ ccmp(x0, x1, NoFlag, eq);
2227*f5c631daSSadaf Ebrahimi         __ adrp(x1, offset);
2228*f5c631daSSadaf Ebrahimi       }
2229*f5c631daSSadaf Ebrahimi     }
2230*f5c631daSSadaf Ebrahimi   }
2231*f5c631daSSadaf Ebrahimi 
2232*f5c631daSSadaf Ebrahimi   END();
2233*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2234*f5c631daSSadaf Ebrahimi     RUN();
2235*f5c631daSSadaf Ebrahimi 
2236*f5c631daSSadaf Ebrahimi     uintptr_t expected =
2237*f5c631daSSadaf Ebrahimi         masm.GetLabelAddress<uintptr_t>(&page) + (kPageSize * offset);
2238*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x0);
2239*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, x1);
2240*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
2241*f5c631daSSadaf Ebrahimi   }
2242*f5c631daSSadaf Ebrahimi }
2243*f5c631daSSadaf Ebrahimi 
2244*f5c631daSSadaf Ebrahimi 
2245*f5c631daSSadaf Ebrahimi // Check that adrp produces the correct result for a specific offset.
TEST(adrp_offset)2246*f5c631daSSadaf Ebrahimi TEST(adrp_offset) {
2247*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(0);
2248*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(1);
2249*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(-1);
2250*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(4);
2251*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(-4);
2252*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(0x000fffff);
2253*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(-0x000fffff);
2254*f5c631daSSadaf Ebrahimi   AdrpOffsetHelper(-0x00100000);
2255*f5c631daSSadaf Ebrahimi }
2256*f5c631daSSadaf Ebrahimi 
2257*f5c631daSSadaf Ebrahimi 
TEST(branch_cond)2258*f5c631daSSadaf Ebrahimi TEST(branch_cond) {
2259*f5c631daSSadaf Ebrahimi   SETUP();
2260*f5c631daSSadaf Ebrahimi 
2261*f5c631daSSadaf Ebrahimi   Label done, wrong;
2262*f5c631daSSadaf Ebrahimi 
2263*f5c631daSSadaf Ebrahimi   START();
2264*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x1);
2265*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1);
2266*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x8000000000000000);
2267*f5c631daSSadaf Ebrahimi 
2268*f5c631daSSadaf Ebrahimi   // For each 'cmp' instruction below, condition codes other than the ones
2269*f5c631daSSadaf Ebrahimi   // following it would branch.
2270*f5c631daSSadaf Ebrahimi 
2271*f5c631daSSadaf Ebrahimi   __ Cmp(x1, 0);
2272*f5c631daSSadaf Ebrahimi   __ B(&wrong, eq);
2273*f5c631daSSadaf Ebrahimi   __ B(&wrong, lo);
2274*f5c631daSSadaf Ebrahimi   __ B(&wrong, mi);
2275*f5c631daSSadaf Ebrahimi   __ B(&wrong, vs);
2276*f5c631daSSadaf Ebrahimi   __ B(&wrong, ls);
2277*f5c631daSSadaf Ebrahimi   __ B(&wrong, lt);
2278*f5c631daSSadaf Ebrahimi   __ B(&wrong, le);
2279*f5c631daSSadaf Ebrahimi   Label ok_1;
2280*f5c631daSSadaf Ebrahimi   __ B(&ok_1, ne);
2281*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2282*f5c631daSSadaf Ebrahimi   __ Bind(&ok_1);
2283*f5c631daSSadaf Ebrahimi 
2284*f5c631daSSadaf Ebrahimi   __ Cmp(x1, 1);
2285*f5c631daSSadaf Ebrahimi   __ B(&wrong, ne);
2286*f5c631daSSadaf Ebrahimi   __ B(&wrong, lo);
2287*f5c631daSSadaf Ebrahimi   __ B(&wrong, mi);
2288*f5c631daSSadaf Ebrahimi   __ B(&wrong, vs);
2289*f5c631daSSadaf Ebrahimi   __ B(&wrong, hi);
2290*f5c631daSSadaf Ebrahimi   __ B(&wrong, lt);
2291*f5c631daSSadaf Ebrahimi   __ B(&wrong, gt);
2292*f5c631daSSadaf Ebrahimi   Label ok_2;
2293*f5c631daSSadaf Ebrahimi   __ B(&ok_2, pl);
2294*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2295*f5c631daSSadaf Ebrahimi   __ Bind(&ok_2);
2296*f5c631daSSadaf Ebrahimi 
2297*f5c631daSSadaf Ebrahimi   __ Cmp(x1, 2);
2298*f5c631daSSadaf Ebrahimi   __ B(&wrong, eq);
2299*f5c631daSSadaf Ebrahimi   __ B(&wrong, hs);
2300*f5c631daSSadaf Ebrahimi   __ B(&wrong, pl);
2301*f5c631daSSadaf Ebrahimi   __ B(&wrong, vs);
2302*f5c631daSSadaf Ebrahimi   __ B(&wrong, hi);
2303*f5c631daSSadaf Ebrahimi   __ B(&wrong, ge);
2304*f5c631daSSadaf Ebrahimi   __ B(&wrong, gt);
2305*f5c631daSSadaf Ebrahimi   Label ok_3;
2306*f5c631daSSadaf Ebrahimi   __ B(&ok_3, vc);
2307*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2308*f5c631daSSadaf Ebrahimi   __ Bind(&ok_3);
2309*f5c631daSSadaf Ebrahimi 
2310*f5c631daSSadaf Ebrahimi   __ Cmp(x2, 1);
2311*f5c631daSSadaf Ebrahimi   __ B(&wrong, eq);
2312*f5c631daSSadaf Ebrahimi   __ B(&wrong, lo);
2313*f5c631daSSadaf Ebrahimi   __ B(&wrong, mi);
2314*f5c631daSSadaf Ebrahimi   __ B(&wrong, vc);
2315*f5c631daSSadaf Ebrahimi   __ B(&wrong, ls);
2316*f5c631daSSadaf Ebrahimi   __ B(&wrong, ge);
2317*f5c631daSSadaf Ebrahimi   __ B(&wrong, gt);
2318*f5c631daSSadaf Ebrahimi   Label ok_4;
2319*f5c631daSSadaf Ebrahimi   __ B(&ok_4, le);
2320*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2321*f5c631daSSadaf Ebrahimi   __ Bind(&ok_4);
2322*f5c631daSSadaf Ebrahimi 
2323*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow al as a branch condition.
2324*f5c631daSSadaf Ebrahimi   Label ok_5;
2325*f5c631daSSadaf Ebrahimi   {
2326*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
2327*f5c631daSSadaf Ebrahimi     __ b(&ok_5, al);
2328*f5c631daSSadaf Ebrahimi   }
2329*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2330*f5c631daSSadaf Ebrahimi   __ Bind(&ok_5);
2331*f5c631daSSadaf Ebrahimi 
2332*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow nv as a branch condition.
2333*f5c631daSSadaf Ebrahimi   Label ok_6;
2334*f5c631daSSadaf Ebrahimi   {
2335*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
2336*f5c631daSSadaf Ebrahimi     __ b(&ok_6, nv);
2337*f5c631daSSadaf Ebrahimi   }
2338*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2339*f5c631daSSadaf Ebrahimi   __ Bind(&ok_6);
2340*f5c631daSSadaf Ebrahimi 
2341*f5c631daSSadaf Ebrahimi   __ B(&done);
2342*f5c631daSSadaf Ebrahimi 
2343*f5c631daSSadaf Ebrahimi   __ Bind(&wrong);
2344*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2345*f5c631daSSadaf Ebrahimi 
2346*f5c631daSSadaf Ebrahimi   __ Bind(&done);
2347*f5c631daSSadaf Ebrahimi   END();
2348*f5c631daSSadaf Ebrahimi 
2349*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2350*f5c631daSSadaf Ebrahimi     RUN();
2351*f5c631daSSadaf Ebrahimi 
2352*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1, x0);
2353*f5c631daSSadaf Ebrahimi   }
2354*f5c631daSSadaf Ebrahimi }
2355*f5c631daSSadaf Ebrahimi 
2356*f5c631daSSadaf Ebrahimi 
TEST(branch_to_reg)2357*f5c631daSSadaf Ebrahimi TEST(branch_to_reg) {
2358*f5c631daSSadaf Ebrahimi   SETUP();
2359*f5c631daSSadaf Ebrahimi 
2360*f5c631daSSadaf Ebrahimi   // Test br.
2361*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2362*f5c631daSSadaf Ebrahimi 
2363*f5c631daSSadaf Ebrahimi   START();
2364*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2365*f5c631daSSadaf Ebrahimi 
2366*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2367*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2368*f5c631daSSadaf Ebrahimi 
2369*f5c631daSSadaf Ebrahimi   __ Bind(&fn1);
2370*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2371*f5c631daSSadaf Ebrahimi   __ Mov(x1, 42);
2372*f5c631daSSadaf Ebrahimi   __ Br(x0);
2373*f5c631daSSadaf Ebrahimi 
2374*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2375*f5c631daSSadaf Ebrahimi   __ Bl(&fn1);
2376*f5c631daSSadaf Ebrahimi 
2377*f5c631daSSadaf Ebrahimi   // Test blr.
2378*f5c631daSSadaf Ebrahimi   Label fn2, after_fn2, after_bl2;
2379*f5c631daSSadaf Ebrahimi 
2380*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0);
2381*f5c631daSSadaf Ebrahimi   __ B(&after_fn2);
2382*f5c631daSSadaf Ebrahimi 
2383*f5c631daSSadaf Ebrahimi   __ Bind(&fn2);
2384*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2385*f5c631daSSadaf Ebrahimi   __ Mov(x2, 84);
2386*f5c631daSSadaf Ebrahimi   __ Blr(x0);
2387*f5c631daSSadaf Ebrahimi 
2388*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn2);
2389*f5c631daSSadaf Ebrahimi   __ Bl(&fn2);
2390*f5c631daSSadaf Ebrahimi   __ Bind(&after_bl2);
2391*f5c631daSSadaf Ebrahimi   __ Mov(x3, lr);
2392*f5c631daSSadaf Ebrahimi   __ Adr(x4, &after_bl2);
2393*f5c631daSSadaf Ebrahimi   __ Adr(x5, &after_fn2);
2394*f5c631daSSadaf Ebrahimi 
2395*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2396*f5c631daSSadaf Ebrahimi   END();
2397*f5c631daSSadaf Ebrahimi 
2398*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2399*f5c631daSSadaf Ebrahimi     RUN();
2400*f5c631daSSadaf Ebrahimi 
2401*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x4, x0);
2402*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x5, x3);
2403*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(42, x1);
2404*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(84, x2);
2405*f5c631daSSadaf Ebrahimi   }
2406*f5c631daSSadaf Ebrahimi }
2407*f5c631daSSadaf Ebrahimi 
TEST(branch_to_reg_auth_a)2408*f5c631daSSadaf Ebrahimi TEST(branch_to_reg_auth_a) {
2409*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2410*f5c631daSSadaf Ebrahimi 
2411*f5c631daSSadaf Ebrahimi   START();
2412*f5c631daSSadaf Ebrahimi 
2413*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2414*f5c631daSSadaf Ebrahimi 
2415*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x477d469dec0b8760);
2416*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2417*f5c631daSSadaf Ebrahimi 
2418*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2419*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2420*f5c631daSSadaf Ebrahimi 
2421*f5c631daSSadaf Ebrahimi   __ Bind(&fn1);
2422*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2423*f5c631daSSadaf Ebrahimi   __ Mov(x1, 42);
2424*f5c631daSSadaf Ebrahimi   __ Pacia(x0, x28);
2425*f5c631daSSadaf Ebrahimi   __ Braa(x0, x28);
2426*f5c631daSSadaf Ebrahimi 
2427*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2428*f5c631daSSadaf Ebrahimi   __ Bl(&fn1);
2429*f5c631daSSadaf Ebrahimi 
2430*f5c631daSSadaf Ebrahimi   Label fn2, after_fn2, after_bl2;
2431*f5c631daSSadaf Ebrahimi 
2432*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0);
2433*f5c631daSSadaf Ebrahimi   __ B(&after_fn2);
2434*f5c631daSSadaf Ebrahimi 
2435*f5c631daSSadaf Ebrahimi   __ Bind(&fn2);
2436*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2437*f5c631daSSadaf Ebrahimi   __ Mov(x2, 84);
2438*f5c631daSSadaf Ebrahimi   __ Pacia(x0, x28);
2439*f5c631daSSadaf Ebrahimi   __ Blraa(x0, x28);
2440*f5c631daSSadaf Ebrahimi 
2441*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn2);
2442*f5c631daSSadaf Ebrahimi   __ Bl(&fn2);
2443*f5c631daSSadaf Ebrahimi   __ Bind(&after_bl2);
2444*f5c631daSSadaf Ebrahimi   __ Mov(x3, lr);
2445*f5c631daSSadaf Ebrahimi   __ Adr(x4, &after_bl2);
2446*f5c631daSSadaf Ebrahimi   __ Adr(x5, &after_fn2);
2447*f5c631daSSadaf Ebrahimi 
2448*f5c631daSSadaf Ebrahimi   __ Xpaci(x0);
2449*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2450*f5c631daSSadaf Ebrahimi   END();
2451*f5c631daSSadaf Ebrahimi 
2452*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2453*f5c631daSSadaf Ebrahimi     RUN();
2454*f5c631daSSadaf Ebrahimi 
2455*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x4, x0);
2456*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x5, x3);
2457*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(42, x1);
2458*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(84, x2);
2459*f5c631daSSadaf Ebrahimi   }
2460*f5c631daSSadaf Ebrahimi }
2461*f5c631daSSadaf Ebrahimi 
TEST(return_to_reg_auth)2462*f5c631daSSadaf Ebrahimi TEST(return_to_reg_auth) {
2463*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2464*f5c631daSSadaf Ebrahimi 
2465*f5c631daSSadaf Ebrahimi   START();
2466*f5c631daSSadaf Ebrahimi 
2467*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2468*f5c631daSSadaf Ebrahimi 
2469*f5c631daSSadaf Ebrahimi   __ Mov(x28, sp);
2470*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2471*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x477d469dec0b8760);
2472*f5c631daSSadaf Ebrahimi 
2473*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
2474*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2475*f5c631daSSadaf Ebrahimi 
2476*f5c631daSSadaf Ebrahimi   __ Bind(&fn1);
2477*f5c631daSSadaf Ebrahimi   __ Mov(x0, 42);
2478*f5c631daSSadaf Ebrahimi   __ Paciasp();
2479*f5c631daSSadaf Ebrahimi   __ Retaa();
2480*f5c631daSSadaf Ebrahimi 
2481*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2482*f5c631daSSadaf Ebrahimi   __ Bl(&fn1);
2483*f5c631daSSadaf Ebrahimi 
2484*f5c631daSSadaf Ebrahimi   Label fn2, after_fn2;
2485*f5c631daSSadaf Ebrahimi 
2486*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2487*f5c631daSSadaf Ebrahimi   __ B(&after_fn2);
2488*f5c631daSSadaf Ebrahimi 
2489*f5c631daSSadaf Ebrahimi   __ Bind(&fn2);
2490*f5c631daSSadaf Ebrahimi   __ Mov(x1, 84);
2491*f5c631daSSadaf Ebrahimi   __ Pacibsp();
2492*f5c631daSSadaf Ebrahimi   __ Retab();
2493*f5c631daSSadaf Ebrahimi 
2494*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn2);
2495*f5c631daSSadaf Ebrahimi   __ Bl(&fn2);
2496*f5c631daSSadaf Ebrahimi 
2497*f5c631daSSadaf Ebrahimi   __ Mov(sp, x28);
2498*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2499*f5c631daSSadaf Ebrahimi   END();
2500*f5c631daSSadaf Ebrahimi 
2501*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2502*f5c631daSSadaf Ebrahimi     RUN();
2503*f5c631daSSadaf Ebrahimi 
2504*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(42, x0);
2505*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(84, x1);
2506*f5c631daSSadaf Ebrahimi   }
2507*f5c631daSSadaf Ebrahimi }
2508*f5c631daSSadaf Ebrahimi 
TEST(return_to_reg_auth_guarded)2509*f5c631daSSadaf Ebrahimi TEST(return_to_reg_auth_guarded) {
2510*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2511*f5c631daSSadaf Ebrahimi 
2512*f5c631daSSadaf Ebrahimi   START();
2513*f5c631daSSadaf Ebrahimi 
2514*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2515*f5c631daSSadaf Ebrahimi 
2516*f5c631daSSadaf Ebrahimi   __ Mov(x28, sp);
2517*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2518*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x477d469dec0b8760);
2519*f5c631daSSadaf Ebrahimi 
2520*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
2521*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2522*f5c631daSSadaf Ebrahimi 
2523*f5c631daSSadaf Ebrahimi   __ Bind(&fn1, EmitPACIASP);
2524*f5c631daSSadaf Ebrahimi   __ Mov(x0, 42);
2525*f5c631daSSadaf Ebrahimi   __ Retaa();
2526*f5c631daSSadaf Ebrahimi 
2527*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2528*f5c631daSSadaf Ebrahimi   __ Adr(x2, &fn1);
2529*f5c631daSSadaf Ebrahimi   __ Blr(x2);
2530*f5c631daSSadaf Ebrahimi 
2531*f5c631daSSadaf Ebrahimi   Label fn2, after_fn2;
2532*f5c631daSSadaf Ebrahimi 
2533*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2534*f5c631daSSadaf Ebrahimi   __ B(&after_fn2);
2535*f5c631daSSadaf Ebrahimi 
2536*f5c631daSSadaf Ebrahimi   __ Bind(&fn2, EmitPACIBSP);
2537*f5c631daSSadaf Ebrahimi   __ Mov(x1, 84);
2538*f5c631daSSadaf Ebrahimi   __ Retab();
2539*f5c631daSSadaf Ebrahimi 
2540*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn2);
2541*f5c631daSSadaf Ebrahimi   __ Adr(x2, &fn2);
2542*f5c631daSSadaf Ebrahimi   __ Blr(x2);
2543*f5c631daSSadaf Ebrahimi 
2544*f5c631daSSadaf Ebrahimi   __ Mov(sp, x28);
2545*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2546*f5c631daSSadaf Ebrahimi   END();
2547*f5c631daSSadaf Ebrahimi 
2548*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2549*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
2550*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
2551*f5c631daSSadaf Ebrahimi #else
2552*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
2553*f5c631daSSadaf Ebrahimi #endif
2554*f5c631daSSadaf Ebrahimi     RUN();
2555*f5c631daSSadaf Ebrahimi 
2556*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(42, x0);
2557*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(84, x1);
2558*f5c631daSSadaf Ebrahimi   }
2559*f5c631daSSadaf Ebrahimi }
2560*f5c631daSSadaf Ebrahimi 
2561*f5c631daSSadaf Ebrahimi #ifdef VIXL_NEGATIVE_TESTING
TEST(branch_to_reg_auth_fail)2562*f5c631daSSadaf Ebrahimi TEST(branch_to_reg_auth_fail) {
2563*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2564*f5c631daSSadaf Ebrahimi 
2565*f5c631daSSadaf Ebrahimi   START();
2566*f5c631daSSadaf Ebrahimi 
2567*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2568*f5c631daSSadaf Ebrahimi 
2569*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2570*f5c631daSSadaf Ebrahimi 
2571*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2572*f5c631daSSadaf Ebrahimi 
2573*f5c631daSSadaf Ebrahimi   __ Bind(&fn1);
2574*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2575*f5c631daSSadaf Ebrahimi   __ Pacizb(x0);
2576*f5c631daSSadaf Ebrahimi   __ Blraaz(x0);
2577*f5c631daSSadaf Ebrahimi 
2578*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2579*f5c631daSSadaf Ebrahimi   // There is a small but not negligible chance (1 in 127 runs) that the PAC
2580*f5c631daSSadaf Ebrahimi   // codes for keys A and B will collide and BLRAAZ won't abort. To mitigate
2581*f5c631daSSadaf Ebrahimi   // this, we simply repeat the test a few more times.
2582*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < 32; i++) {
2583*f5c631daSSadaf Ebrahimi     __ Bl(&fn1);
2584*f5c631daSSadaf Ebrahimi   }
2585*f5c631daSSadaf Ebrahimi 
2586*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2587*f5c631daSSadaf Ebrahimi   END();
2588*f5c631daSSadaf Ebrahimi 
2589*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2590*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
2591*f5c631daSSadaf Ebrahimi   }
2592*f5c631daSSadaf Ebrahimi }
2593*f5c631daSSadaf Ebrahimi #endif  // VIXL_NEGATIVE_TESTING
2594*f5c631daSSadaf Ebrahimi 
2595*f5c631daSSadaf Ebrahimi #ifdef VIXL_NEGATIVE_TESTING
TEST(return_to_reg_auth_fail)2596*f5c631daSSadaf Ebrahimi TEST(return_to_reg_auth_fail) {
2597*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2598*f5c631daSSadaf Ebrahimi 
2599*f5c631daSSadaf Ebrahimi   START();
2600*f5c631daSSadaf Ebrahimi 
2601*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2602*f5c631daSSadaf Ebrahimi 
2603*f5c631daSSadaf Ebrahimi   __ Mov(x28, sp);
2604*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2605*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x477d469dec0b8760);
2606*f5c631daSSadaf Ebrahimi 
2607*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2608*f5c631daSSadaf Ebrahimi 
2609*f5c631daSSadaf Ebrahimi   __ Bind(&fn1);
2610*f5c631daSSadaf Ebrahimi   __ Paciasp();
2611*f5c631daSSadaf Ebrahimi   __ Retab();
2612*f5c631daSSadaf Ebrahimi 
2613*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2614*f5c631daSSadaf Ebrahimi   // There is a small but not negligible chance (1 in 127 runs) that the PAC
2615*f5c631daSSadaf Ebrahimi   // codes for keys A and B will collide and RETAB won't abort. To mitigate
2616*f5c631daSSadaf Ebrahimi   // this, we simply repeat the test a few more times.
2617*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < 32; i++) {
2618*f5c631daSSadaf Ebrahimi     __ Bl(&fn1);
2619*f5c631daSSadaf Ebrahimi   }
2620*f5c631daSSadaf Ebrahimi 
2621*f5c631daSSadaf Ebrahimi   __ Mov(sp, x28);
2622*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2623*f5c631daSSadaf Ebrahimi   END();
2624*f5c631daSSadaf Ebrahimi 
2625*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2626*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
2627*f5c631daSSadaf Ebrahimi   }
2628*f5c631daSSadaf Ebrahimi }
2629*f5c631daSSadaf Ebrahimi #endif  // VIXL_NEGATIVE_TESTING
2630*f5c631daSSadaf Ebrahimi 
TEST(branch_to_reg_auth_a_zero)2631*f5c631daSSadaf Ebrahimi TEST(branch_to_reg_auth_a_zero) {
2632*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
2633*f5c631daSSadaf Ebrahimi 
2634*f5c631daSSadaf Ebrahimi   START();
2635*f5c631daSSadaf Ebrahimi 
2636*f5c631daSSadaf Ebrahimi   Label fn1, after_fn1;
2637*f5c631daSSadaf Ebrahimi 
2638*f5c631daSSadaf Ebrahimi   __ Mov(x29, lr);
2639*f5c631daSSadaf Ebrahimi 
2640*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2641*f5c631daSSadaf Ebrahimi   __ B(&after_fn1);
2642*f5c631daSSadaf Ebrahimi 
2643*f5c631daSSadaf Ebrahimi   __ Bind(&fn1);
2644*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2645*f5c631daSSadaf Ebrahimi   __ Mov(x1, 42);
2646*f5c631daSSadaf Ebrahimi   __ Paciza(x0);
2647*f5c631daSSadaf Ebrahimi   __ Braaz(x0);
2648*f5c631daSSadaf Ebrahimi 
2649*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn1);
2650*f5c631daSSadaf Ebrahimi   __ Bl(&fn1);
2651*f5c631daSSadaf Ebrahimi 
2652*f5c631daSSadaf Ebrahimi   Label fn2, after_fn2, after_bl2;
2653*f5c631daSSadaf Ebrahimi 
2654*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0);
2655*f5c631daSSadaf Ebrahimi   __ B(&after_fn2);
2656*f5c631daSSadaf Ebrahimi 
2657*f5c631daSSadaf Ebrahimi   __ Bind(&fn2);
2658*f5c631daSSadaf Ebrahimi   __ Mov(x0, lr);
2659*f5c631daSSadaf Ebrahimi   __ Mov(x2, 84);
2660*f5c631daSSadaf Ebrahimi   __ Paciza(x0);
2661*f5c631daSSadaf Ebrahimi   __ Blraaz(x0);
2662*f5c631daSSadaf Ebrahimi 
2663*f5c631daSSadaf Ebrahimi   __ Bind(&after_fn2);
2664*f5c631daSSadaf Ebrahimi   __ Bl(&fn2);
2665*f5c631daSSadaf Ebrahimi   __ Bind(&after_bl2);
2666*f5c631daSSadaf Ebrahimi   __ Mov(x3, lr);
2667*f5c631daSSadaf Ebrahimi   __ Adr(x4, &after_bl2);
2668*f5c631daSSadaf Ebrahimi   __ Adr(x5, &after_fn2);
2669*f5c631daSSadaf Ebrahimi 
2670*f5c631daSSadaf Ebrahimi   __ Xpaci(x0);
2671*f5c631daSSadaf Ebrahimi   __ Mov(lr, x29);
2672*f5c631daSSadaf Ebrahimi   END();
2673*f5c631daSSadaf Ebrahimi 
2674*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2675*f5c631daSSadaf Ebrahimi     RUN();
2676*f5c631daSSadaf Ebrahimi 
2677*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x4, x0);
2678*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x5, x3);
2679*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(42, x1);
2680*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(84, x2);
2681*f5c631daSSadaf Ebrahimi   }
2682*f5c631daSSadaf Ebrahimi }
2683*f5c631daSSadaf Ebrahimi 
2684*f5c631daSSadaf Ebrahimi 
TEST(compare_branch)2685*f5c631daSSadaf Ebrahimi TEST(compare_branch) {
2686*f5c631daSSadaf Ebrahimi   SETUP();
2687*f5c631daSSadaf Ebrahimi 
2688*f5c631daSSadaf Ebrahimi   START();
2689*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
2690*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2691*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0);
2692*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0);
2693*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0);
2694*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0);
2695*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0);
2696*f5c631daSSadaf Ebrahimi   __ Mov(x17, 42);
2697*f5c631daSSadaf Ebrahimi 
2698*f5c631daSSadaf Ebrahimi   Label zt, zt_end;
2699*f5c631daSSadaf Ebrahimi   __ Cbz(w16, &zt);
2700*f5c631daSSadaf Ebrahimi   __ B(&zt_end);
2701*f5c631daSSadaf Ebrahimi   __ Bind(&zt);
2702*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
2703*f5c631daSSadaf Ebrahimi   __ Bind(&zt_end);
2704*f5c631daSSadaf Ebrahimi 
2705*f5c631daSSadaf Ebrahimi   Label zf, zf_end;
2706*f5c631daSSadaf Ebrahimi   __ Cbz(x17, &zf);
2707*f5c631daSSadaf Ebrahimi   __ B(&zf_end);
2708*f5c631daSSadaf Ebrahimi   __ Bind(&zf);
2709*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
2710*f5c631daSSadaf Ebrahimi   __ Bind(&zf_end);
2711*f5c631daSSadaf Ebrahimi 
2712*f5c631daSSadaf Ebrahimi   Label nzt, nzt_end;
2713*f5c631daSSadaf Ebrahimi   __ Cbnz(w17, &nzt);
2714*f5c631daSSadaf Ebrahimi   __ B(&nzt_end);
2715*f5c631daSSadaf Ebrahimi   __ Bind(&nzt);
2716*f5c631daSSadaf Ebrahimi   __ Mov(x2, 1);
2717*f5c631daSSadaf Ebrahimi   __ Bind(&nzt_end);
2718*f5c631daSSadaf Ebrahimi 
2719*f5c631daSSadaf Ebrahimi   Label nzf, nzf_end;
2720*f5c631daSSadaf Ebrahimi   __ Cbnz(x16, &nzf);
2721*f5c631daSSadaf Ebrahimi   __ B(&nzf_end);
2722*f5c631daSSadaf Ebrahimi   __ Bind(&nzf);
2723*f5c631daSSadaf Ebrahimi   __ Mov(x3, 1);
2724*f5c631daSSadaf Ebrahimi   __ Bind(&nzf_end);
2725*f5c631daSSadaf Ebrahimi 
2726*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xffffffff00000000);
2727*f5c631daSSadaf Ebrahimi 
2728*f5c631daSSadaf Ebrahimi   Label a, a_end;
2729*f5c631daSSadaf Ebrahimi   __ Cbz(w18, &a);
2730*f5c631daSSadaf Ebrahimi   __ B(&a_end);
2731*f5c631daSSadaf Ebrahimi   __ Bind(&a);
2732*f5c631daSSadaf Ebrahimi   __ Mov(x4, 1);
2733*f5c631daSSadaf Ebrahimi   __ Bind(&a_end);
2734*f5c631daSSadaf Ebrahimi 
2735*f5c631daSSadaf Ebrahimi   Label b, b_end;
2736*f5c631daSSadaf Ebrahimi   __ Cbnz(w18, &b);
2737*f5c631daSSadaf Ebrahimi   __ B(&b_end);
2738*f5c631daSSadaf Ebrahimi   __ Bind(&b);
2739*f5c631daSSadaf Ebrahimi   __ Mov(x5, 1);
2740*f5c631daSSadaf Ebrahimi   __ Bind(&b_end);
2741*f5c631daSSadaf Ebrahimi 
2742*f5c631daSSadaf Ebrahimi   END();
2743*f5c631daSSadaf Ebrahimi 
2744*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2745*f5c631daSSadaf Ebrahimi     RUN();
2746*f5c631daSSadaf Ebrahimi 
2747*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x0);
2748*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x1);
2749*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x2);
2750*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x3);
2751*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x4);
2752*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x5);
2753*f5c631daSSadaf Ebrahimi   }
2754*f5c631daSSadaf Ebrahimi }
2755*f5c631daSSadaf Ebrahimi 
2756*f5c631daSSadaf Ebrahimi 
TEST(test_branch)2757*f5c631daSSadaf Ebrahimi TEST(test_branch) {
2758*f5c631daSSadaf Ebrahimi   SETUP();
2759*f5c631daSSadaf Ebrahimi 
2760*f5c631daSSadaf Ebrahimi   START();
2761*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
2762*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
2763*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0);
2764*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0);
2765*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0xaaaaaaaaaaaaaaaa);
2766*f5c631daSSadaf Ebrahimi 
2767*f5c631daSSadaf Ebrahimi   Label bz, bz_end;
2768*f5c631daSSadaf Ebrahimi   __ Tbz(w16, 0, &bz);
2769*f5c631daSSadaf Ebrahimi   __ B(&bz_end);
2770*f5c631daSSadaf Ebrahimi   __ Bind(&bz);
2771*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
2772*f5c631daSSadaf Ebrahimi   __ Bind(&bz_end);
2773*f5c631daSSadaf Ebrahimi 
2774*f5c631daSSadaf Ebrahimi   Label bo, bo_end;
2775*f5c631daSSadaf Ebrahimi   __ Tbz(x16, 63, &bo);
2776*f5c631daSSadaf Ebrahimi   __ B(&bo_end);
2777*f5c631daSSadaf Ebrahimi   __ Bind(&bo);
2778*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
2779*f5c631daSSadaf Ebrahimi   __ Bind(&bo_end);
2780*f5c631daSSadaf Ebrahimi 
2781*f5c631daSSadaf Ebrahimi   Label nbz, nbz_end;
2782*f5c631daSSadaf Ebrahimi   __ Tbnz(x16, 61, &nbz);
2783*f5c631daSSadaf Ebrahimi   __ B(&nbz_end);
2784*f5c631daSSadaf Ebrahimi   __ Bind(&nbz);
2785*f5c631daSSadaf Ebrahimi   __ Mov(x2, 1);
2786*f5c631daSSadaf Ebrahimi   __ Bind(&nbz_end);
2787*f5c631daSSadaf Ebrahimi 
2788*f5c631daSSadaf Ebrahimi   Label nbo, nbo_end;
2789*f5c631daSSadaf Ebrahimi   __ Tbnz(w16, 2, &nbo);
2790*f5c631daSSadaf Ebrahimi   __ B(&nbo_end);
2791*f5c631daSSadaf Ebrahimi   __ Bind(&nbo);
2792*f5c631daSSadaf Ebrahimi   __ Mov(x3, 1);
2793*f5c631daSSadaf Ebrahimi   __ Bind(&nbo_end);
2794*f5c631daSSadaf Ebrahimi   END();
2795*f5c631daSSadaf Ebrahimi 
2796*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2797*f5c631daSSadaf Ebrahimi     RUN();
2798*f5c631daSSadaf Ebrahimi 
2799*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x0);
2800*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x1);
2801*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x2);
2802*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x3);
2803*f5c631daSSadaf Ebrahimi   }
2804*f5c631daSSadaf Ebrahimi }
2805*f5c631daSSadaf Ebrahimi 
2806*f5c631daSSadaf Ebrahimi 
TEST(branch_type)2807*f5c631daSSadaf Ebrahimi TEST(branch_type) {
2808*f5c631daSSadaf Ebrahimi   SETUP();
2809*f5c631daSSadaf Ebrahimi 
2810*f5c631daSSadaf Ebrahimi   Label fail, done;
2811*f5c631daSSadaf Ebrahimi 
2812*f5c631daSSadaf Ebrahimi   START();
2813*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
2814*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0x7);
2815*f5c631daSSadaf Ebrahimi   __ Mov(x11, 0x0);
2816*f5c631daSSadaf Ebrahimi 
2817*f5c631daSSadaf Ebrahimi   // Test non taken branches.
2818*f5c631daSSadaf Ebrahimi   __ Cmp(x10, 0x7);
2819*f5c631daSSadaf Ebrahimi   __ B(&fail, ne);
2820*f5c631daSSadaf Ebrahimi   __ B(&fail, never);
2821*f5c631daSSadaf Ebrahimi   __ B(&fail, reg_zero, x10);
2822*f5c631daSSadaf Ebrahimi   __ B(&fail, reg_not_zero, x11);
2823*f5c631daSSadaf Ebrahimi   __ B(&fail, reg_bit_clear, x10, 0);
2824*f5c631daSSadaf Ebrahimi   __ B(&fail, reg_bit_set, x10, 3);
2825*f5c631daSSadaf Ebrahimi 
2826*f5c631daSSadaf Ebrahimi   // Test taken branches.
2827*f5c631daSSadaf Ebrahimi   Label l1, l2, l3, l4, l5;
2828*f5c631daSSadaf Ebrahimi   __ Cmp(x10, 0x7);
2829*f5c631daSSadaf Ebrahimi   __ B(&l1, eq);
2830*f5c631daSSadaf Ebrahimi   __ B(&fail);
2831*f5c631daSSadaf Ebrahimi   __ Bind(&l1);
2832*f5c631daSSadaf Ebrahimi   __ B(&l2, always);
2833*f5c631daSSadaf Ebrahimi   __ B(&fail);
2834*f5c631daSSadaf Ebrahimi   __ Bind(&l2);
2835*f5c631daSSadaf Ebrahimi   __ B(&l3, reg_not_zero, x10);
2836*f5c631daSSadaf Ebrahimi   __ B(&fail);
2837*f5c631daSSadaf Ebrahimi   __ Bind(&l3);
2838*f5c631daSSadaf Ebrahimi   __ B(&l4, reg_bit_clear, x10, 15);
2839*f5c631daSSadaf Ebrahimi   __ B(&fail);
2840*f5c631daSSadaf Ebrahimi   __ Bind(&l4);
2841*f5c631daSSadaf Ebrahimi   __ B(&l5, reg_bit_set, x10, 1);
2842*f5c631daSSadaf Ebrahimi   __ B(&fail);
2843*f5c631daSSadaf Ebrahimi   __ Bind(&l5);
2844*f5c631daSSadaf Ebrahimi 
2845*f5c631daSSadaf Ebrahimi   __ B(&done);
2846*f5c631daSSadaf Ebrahimi 
2847*f5c631daSSadaf Ebrahimi   __ Bind(&fail);
2848*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x1);
2849*f5c631daSSadaf Ebrahimi 
2850*f5c631daSSadaf Ebrahimi   __ Bind(&done);
2851*f5c631daSSadaf Ebrahimi 
2852*f5c631daSSadaf Ebrahimi   END();
2853*f5c631daSSadaf Ebrahimi 
2854*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2855*f5c631daSSadaf Ebrahimi     RUN();
2856*f5c631daSSadaf Ebrahimi 
2857*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x0);
2858*f5c631daSSadaf Ebrahimi   }
2859*f5c631daSSadaf Ebrahimi }
2860*f5c631daSSadaf Ebrahimi 
2861*f5c631daSSadaf Ebrahimi 
TEST(ldr_str_offset)2862*f5c631daSSadaf Ebrahimi TEST(ldr_str_offset) {
2863*f5c631daSSadaf Ebrahimi   SETUP();
2864*f5c631daSSadaf Ebrahimi 
2865*f5c631daSSadaf Ebrahimi   uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
2866*f5c631daSSadaf Ebrahimi   uint64_t dst[5] = {0, 0, 0, 0, 0};
2867*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2868*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2869*f5c631daSSadaf Ebrahimi 
2870*f5c631daSSadaf Ebrahimi   START();
2871*f5c631daSSadaf Ebrahimi   __ Mov(x17, src_base);
2872*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base);
2873*f5c631daSSadaf Ebrahimi   __ Ldr(w0, MemOperand(x17));
2874*f5c631daSSadaf Ebrahimi   __ Str(w0, MemOperand(x18));
2875*f5c631daSSadaf Ebrahimi   __ Ldr(w1, MemOperand(x17, 4));
2876*f5c631daSSadaf Ebrahimi   __ Str(w1, MemOperand(x18, 12));
2877*f5c631daSSadaf Ebrahimi   __ Ldr(x2, MemOperand(x17, 8));
2878*f5c631daSSadaf Ebrahimi   __ Str(x2, MemOperand(x18, 16));
2879*f5c631daSSadaf Ebrahimi   __ Ldrb(w3, MemOperand(x17, 1));
2880*f5c631daSSadaf Ebrahimi   __ Strb(w3, MemOperand(x18, 25));
2881*f5c631daSSadaf Ebrahimi   __ Ldrh(w4, MemOperand(x17, 2));
2882*f5c631daSSadaf Ebrahimi   __ Strh(w4, MemOperand(x18, 33));
2883*f5c631daSSadaf Ebrahimi   END();
2884*f5c631daSSadaf Ebrahimi 
2885*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2886*f5c631daSSadaf Ebrahimi     RUN();
2887*f5c631daSSadaf Ebrahimi 
2888*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x76543210, x0);
2889*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x76543210, dst[0]);
2890*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba98, x1);
2891*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
2892*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x2);
2893*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
2894*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x32, x3);
2895*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3200, dst[3]);
2896*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7654, x4);
2897*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x765400, dst[4]);
2898*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x17);
2899*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x18);
2900*f5c631daSSadaf Ebrahimi   }
2901*f5c631daSSadaf Ebrahimi }
2902*f5c631daSSadaf Ebrahimi 
2903*f5c631daSSadaf Ebrahimi 
TEST(ldr_str_wide)2904*f5c631daSSadaf Ebrahimi TEST(ldr_str_wide) {
2905*f5c631daSSadaf Ebrahimi   SETUP();
2906*f5c631daSSadaf Ebrahimi 
2907*f5c631daSSadaf Ebrahimi   uint32_t src[8192];
2908*f5c631daSSadaf Ebrahimi   uint32_t dst[8192];
2909*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2910*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2911*f5c631daSSadaf Ebrahimi   memset(src, 0xaa, 8192 * sizeof(src[0]));
2912*f5c631daSSadaf Ebrahimi   memset(dst, 0xaa, 8192 * sizeof(dst[0]));
2913*f5c631daSSadaf Ebrahimi   src[0] = 0;
2914*f5c631daSSadaf Ebrahimi   src[6144] = 6144;
2915*f5c631daSSadaf Ebrahimi   src[8191] = 8191;
2916*f5c631daSSadaf Ebrahimi 
2917*f5c631daSSadaf Ebrahimi   START();
2918*f5c631daSSadaf Ebrahimi   __ Mov(x22, src_base);
2919*f5c631daSSadaf Ebrahimi   __ Mov(x23, dst_base);
2920*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base);
2921*f5c631daSSadaf Ebrahimi   __ Mov(x25, dst_base);
2922*f5c631daSSadaf Ebrahimi   __ Mov(x26, src_base);
2923*f5c631daSSadaf Ebrahimi   __ Mov(x27, dst_base);
2924*f5c631daSSadaf Ebrahimi 
2925*f5c631daSSadaf Ebrahimi   __ Ldr(w0, MemOperand(x22, 8191 * sizeof(src[0])));
2926*f5c631daSSadaf Ebrahimi   __ Str(w0, MemOperand(x23, 8191 * sizeof(dst[0])));
2927*f5c631daSSadaf Ebrahimi   __ Ldr(w1, MemOperand(x24, 4096 * sizeof(src[0]), PostIndex));
2928*f5c631daSSadaf Ebrahimi   __ Str(w1, MemOperand(x25, 4096 * sizeof(dst[0]), PostIndex));
2929*f5c631daSSadaf Ebrahimi   __ Ldr(w2, MemOperand(x26, 6144 * sizeof(src[0]), PreIndex));
2930*f5c631daSSadaf Ebrahimi   __ Str(w2, MemOperand(x27, 6144 * sizeof(dst[0]), PreIndex));
2931*f5c631daSSadaf Ebrahimi   END();
2932*f5c631daSSadaf Ebrahimi 
2933*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2934*f5c631daSSadaf Ebrahimi     RUN();
2935*f5c631daSSadaf Ebrahimi 
2936*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(8191, w0);
2937*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(8191, dst[8191]);
2938*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x22);
2939*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x23);
2940*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w1);
2941*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, dst[0]);
2942*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 4096 * sizeof(src[0]), x24);
2943*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 4096 * sizeof(dst[0]), x25);
2944*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(6144, w2);
2945*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(6144, dst[6144]);
2946*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 6144 * sizeof(src[0]), x26);
2947*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 6144 * sizeof(dst[0]), x27);
2948*f5c631daSSadaf Ebrahimi   }
2949*f5c631daSSadaf Ebrahimi }
2950*f5c631daSSadaf Ebrahimi 
2951*f5c631daSSadaf Ebrahimi 
TEST(ldr_str_preindex)2952*f5c631daSSadaf Ebrahimi TEST(ldr_str_preindex) {
2953*f5c631daSSadaf Ebrahimi   SETUP();
2954*f5c631daSSadaf Ebrahimi 
2955*f5c631daSSadaf Ebrahimi   uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
2956*f5c631daSSadaf Ebrahimi   uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
2957*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2958*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2959*f5c631daSSadaf Ebrahimi 
2960*f5c631daSSadaf Ebrahimi   START();
2961*f5c631daSSadaf Ebrahimi   __ Mov(x17, src_base);
2962*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base);
2963*f5c631daSSadaf Ebrahimi   __ Mov(x19, src_base);
2964*f5c631daSSadaf Ebrahimi   __ Mov(x20, dst_base);
2965*f5c631daSSadaf Ebrahimi   __ Mov(x21, src_base + 16);
2966*f5c631daSSadaf Ebrahimi   __ Mov(x22, dst_base + 40);
2967*f5c631daSSadaf Ebrahimi   __ Mov(x23, src_base);
2968*f5c631daSSadaf Ebrahimi   __ Mov(x24, dst_base);
2969*f5c631daSSadaf Ebrahimi   __ Mov(x25, src_base);
2970*f5c631daSSadaf Ebrahimi   __ Mov(x26, dst_base);
2971*f5c631daSSadaf Ebrahimi   __ Ldr(w0, MemOperand(x17, 4, PreIndex));
2972*f5c631daSSadaf Ebrahimi   __ Str(w0, MemOperand(x18, 12, PreIndex));
2973*f5c631daSSadaf Ebrahimi   __ Ldr(x1, MemOperand(x19, 8, PreIndex));
2974*f5c631daSSadaf Ebrahimi   __ Str(x1, MemOperand(x20, 16, PreIndex));
2975*f5c631daSSadaf Ebrahimi   __ Ldr(w2, MemOperand(x21, -4, PreIndex));
2976*f5c631daSSadaf Ebrahimi   __ Str(w2, MemOperand(x22, -4, PreIndex));
2977*f5c631daSSadaf Ebrahimi   __ Ldrb(w3, MemOperand(x23, 1, PreIndex));
2978*f5c631daSSadaf Ebrahimi   __ Strb(w3, MemOperand(x24, 25, PreIndex));
2979*f5c631daSSadaf Ebrahimi   __ Ldrh(w4, MemOperand(x25, 3, PreIndex));
2980*f5c631daSSadaf Ebrahimi   __ Strh(w4, MemOperand(x26, 41, PreIndex));
2981*f5c631daSSadaf Ebrahimi   END();
2982*f5c631daSSadaf Ebrahimi 
2983*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
2984*f5c631daSSadaf Ebrahimi     RUN();
2985*f5c631daSSadaf Ebrahimi 
2986*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba98, x0);
2987*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
2988*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x1);
2989*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
2990*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, x2);
2991*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456700000000, dst[4]);
2992*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x32, x3);
2993*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3200, dst[3]);
2994*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x9876, x4);
2995*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x987600, dst[5]);
2996*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 4, x17);
2997*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 12, x18);
2998*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 8, x19);
2999*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 16, x20);
3000*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 12, x21);
3001*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 36, x22);
3002*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 1, x23);
3003*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 25, x24);
3004*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 3, x25);
3005*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 41, x26);
3006*f5c631daSSadaf Ebrahimi   }
3007*f5c631daSSadaf Ebrahimi }
3008*f5c631daSSadaf Ebrahimi 
3009*f5c631daSSadaf Ebrahimi 
TEST(ldr_str_postindex)3010*f5c631daSSadaf Ebrahimi TEST(ldr_str_postindex) {
3011*f5c631daSSadaf Ebrahimi   SETUP();
3012*f5c631daSSadaf Ebrahimi 
3013*f5c631daSSadaf Ebrahimi   uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
3014*f5c631daSSadaf Ebrahimi   uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
3015*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3016*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3017*f5c631daSSadaf Ebrahimi 
3018*f5c631daSSadaf Ebrahimi   START();
3019*f5c631daSSadaf Ebrahimi   __ Mov(x17, src_base + 4);
3020*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base + 12);
3021*f5c631daSSadaf Ebrahimi   __ Mov(x19, src_base + 8);
3022*f5c631daSSadaf Ebrahimi   __ Mov(x20, dst_base + 16);
3023*f5c631daSSadaf Ebrahimi   __ Mov(x21, src_base + 8);
3024*f5c631daSSadaf Ebrahimi   __ Mov(x22, dst_base + 32);
3025*f5c631daSSadaf Ebrahimi   __ Mov(x23, src_base + 1);
3026*f5c631daSSadaf Ebrahimi   __ Mov(x24, dst_base + 25);
3027*f5c631daSSadaf Ebrahimi   __ Mov(x25, src_base + 3);
3028*f5c631daSSadaf Ebrahimi   __ Mov(x26, dst_base + 41);
3029*f5c631daSSadaf Ebrahimi   __ Ldr(w0, MemOperand(x17, 4, PostIndex));
3030*f5c631daSSadaf Ebrahimi   __ Str(w0, MemOperand(x18, 12, PostIndex));
3031*f5c631daSSadaf Ebrahimi   __ Ldr(x1, MemOperand(x19, 8, PostIndex));
3032*f5c631daSSadaf Ebrahimi   __ Str(x1, MemOperand(x20, 16, PostIndex));
3033*f5c631daSSadaf Ebrahimi   __ Ldr(x2, MemOperand(x21, -8, PostIndex));
3034*f5c631daSSadaf Ebrahimi   __ Str(x2, MemOperand(x22, -32, PostIndex));
3035*f5c631daSSadaf Ebrahimi   __ Ldrb(w3, MemOperand(x23, 1, PostIndex));
3036*f5c631daSSadaf Ebrahimi   __ Strb(w3, MemOperand(x24, 5, PostIndex));
3037*f5c631daSSadaf Ebrahimi   __ Ldrh(w4, MemOperand(x25, -3, PostIndex));
3038*f5c631daSSadaf Ebrahimi   __ Strh(w4, MemOperand(x26, -41, PostIndex));
3039*f5c631daSSadaf Ebrahimi   END();
3040*f5c631daSSadaf Ebrahimi 
3041*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3042*f5c631daSSadaf Ebrahimi     RUN();
3043*f5c631daSSadaf Ebrahimi 
3044*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba98, x0);
3045*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
3046*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x1);
3047*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
3048*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x2);
3049*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, dst[4]);
3050*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x32, x3);
3051*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3200, dst[3]);
3052*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x9876, x4);
3053*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x987600, dst[5]);
3054*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 8, x17);
3055*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 24, x18);
3056*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 16, x19);
3057*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 32, x20);
3058*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x21);
3059*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x22);
3060*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 2, x23);
3061*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 30, x24);
3062*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x25);
3063*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x26);
3064*f5c631daSSadaf Ebrahimi   }
3065*f5c631daSSadaf Ebrahimi }
3066*f5c631daSSadaf Ebrahimi 
3067*f5c631daSSadaf Ebrahimi 
TEST(ldr_str_largeindex)3068*f5c631daSSadaf Ebrahimi TEST(ldr_str_largeindex) {
3069*f5c631daSSadaf Ebrahimi   SETUP();
3070*f5c631daSSadaf Ebrahimi 
3071*f5c631daSSadaf Ebrahimi   // This value won't fit in the immediate offset field of ldr/str instructions.
3072*f5c631daSSadaf Ebrahimi   int largeoffset = 0xabcdef;
3073*f5c631daSSadaf Ebrahimi 
3074*f5c631daSSadaf Ebrahimi   int64_t data[3] = {0x1122334455667788, 0, 0};
3075*f5c631daSSadaf Ebrahimi   uint64_t base_addr = reinterpret_cast<uintptr_t>(data);
3076*f5c631daSSadaf Ebrahimi   uint64_t drifted_addr = base_addr - largeoffset;
3077*f5c631daSSadaf Ebrahimi 
3078*f5c631daSSadaf Ebrahimi   // This test checks that we we can use large immediate offsets when
3079*f5c631daSSadaf Ebrahimi   // using PreIndex or PostIndex addressing mode of the MacroAssembler
3080*f5c631daSSadaf Ebrahimi   // Ldr/Str instructions.
3081*f5c631daSSadaf Ebrahimi 
3082*f5c631daSSadaf Ebrahimi   START();
3083*f5c631daSSadaf Ebrahimi   __ Mov(x19, drifted_addr);
3084*f5c631daSSadaf Ebrahimi   __ Ldr(x0, MemOperand(x19, largeoffset, PreIndex));
3085*f5c631daSSadaf Ebrahimi 
3086*f5c631daSSadaf Ebrahimi   __ Mov(x20, base_addr);
3087*f5c631daSSadaf Ebrahimi   __ Ldr(x1, MemOperand(x20, largeoffset, PostIndex));
3088*f5c631daSSadaf Ebrahimi 
3089*f5c631daSSadaf Ebrahimi   __ Mov(x21, drifted_addr);
3090*f5c631daSSadaf Ebrahimi   __ Str(x0, MemOperand(x21, largeoffset + 8, PreIndex));
3091*f5c631daSSadaf Ebrahimi 
3092*f5c631daSSadaf Ebrahimi   __ Mov(x22, base_addr + 16);
3093*f5c631daSSadaf Ebrahimi   __ Str(x0, MemOperand(x22, largeoffset, PostIndex));
3094*f5c631daSSadaf Ebrahimi   END();
3095*f5c631daSSadaf Ebrahimi 
3096*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3097*f5c631daSSadaf Ebrahimi     RUN();
3098*f5c631daSSadaf Ebrahimi 
3099*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667788, data[0]);
3100*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667788, data[1]);
3101*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667788, data[2]);
3102*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667788, x0);
3103*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667788, x1);
3104*f5c631daSSadaf Ebrahimi 
3105*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(base_addr, x19);
3106*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(base_addr + largeoffset, x20);
3107*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(base_addr + 8, x21);
3108*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(base_addr + 16 + largeoffset, x22);
3109*f5c631daSSadaf Ebrahimi   }
3110*f5c631daSSadaf Ebrahimi }
3111*f5c631daSSadaf Ebrahimi 
3112*f5c631daSSadaf Ebrahimi 
TEST(load_signed)3113*f5c631daSSadaf Ebrahimi TEST(load_signed) {
3114*f5c631daSSadaf Ebrahimi   SETUP();
3115*f5c631daSSadaf Ebrahimi 
3116*f5c631daSSadaf Ebrahimi   uint32_t src[2] = {0x80008080, 0x7fff7f7f};
3117*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3118*f5c631daSSadaf Ebrahimi 
3119*f5c631daSSadaf Ebrahimi   START();
3120*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base);
3121*f5c631daSSadaf Ebrahimi   __ Ldrsb(w0, MemOperand(x24));
3122*f5c631daSSadaf Ebrahimi   __ Ldrsb(w1, MemOperand(x24, 4));
3123*f5c631daSSadaf Ebrahimi   __ Ldrsh(w2, MemOperand(x24));
3124*f5c631daSSadaf Ebrahimi   __ Ldrsh(w3, MemOperand(x24, 4));
3125*f5c631daSSadaf Ebrahimi   __ Ldrsb(x4, MemOperand(x24));
3126*f5c631daSSadaf Ebrahimi   __ Ldrsb(x5, MemOperand(x24, 4));
3127*f5c631daSSadaf Ebrahimi   __ Ldrsh(x6, MemOperand(x24));
3128*f5c631daSSadaf Ebrahimi   __ Ldrsh(x7, MemOperand(x24, 4));
3129*f5c631daSSadaf Ebrahimi   __ Ldrsw(x8, MemOperand(x24));
3130*f5c631daSSadaf Ebrahimi   __ Ldrsw(x9, MemOperand(x24, 4));
3131*f5c631daSSadaf Ebrahimi   END();
3132*f5c631daSSadaf Ebrahimi 
3133*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3134*f5c631daSSadaf Ebrahimi     RUN();
3135*f5c631daSSadaf Ebrahimi 
3136*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff80, x0);
3137*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000007f, x1);
3138*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff8080, x2);
3139*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00007f7f, x3);
3140*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffff80, x4);
3141*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000007f, x5);
3142*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff8080, x6);
3143*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000007f7f, x7);
3144*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80008080, x8);
3145*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000007fff7f7f, x9);
3146*f5c631daSSadaf Ebrahimi   }
3147*f5c631daSSadaf Ebrahimi }
3148*f5c631daSSadaf Ebrahimi 
3149*f5c631daSSadaf Ebrahimi 
TEST(load_store_regoffset)3150*f5c631daSSadaf Ebrahimi TEST(load_store_regoffset) {
3151*f5c631daSSadaf Ebrahimi   SETUP();
3152*f5c631daSSadaf Ebrahimi 
3153*f5c631daSSadaf Ebrahimi   uint32_t src[3] = {1, 2, 3};
3154*f5c631daSSadaf Ebrahimi   uint32_t dst[4] = {0, 0, 0, 0};
3155*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3156*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3157*f5c631daSSadaf Ebrahimi 
3158*f5c631daSSadaf Ebrahimi   START();
3159*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3160*f5c631daSSadaf Ebrahimi   __ Mov(x17, dst_base);
3161*f5c631daSSadaf Ebrahimi   __ Mov(x18, src_base + 3 * sizeof(src[0]));
3162*f5c631daSSadaf Ebrahimi   __ Mov(x19, dst_base + 3 * sizeof(dst[0]));
3163*f5c631daSSadaf Ebrahimi   __ Mov(x20, dst_base + 4 * sizeof(dst[0]));
3164*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0);
3165*f5c631daSSadaf Ebrahimi   __ Mov(x25, 4);
3166*f5c631daSSadaf Ebrahimi   __ Mov(x26, -4);
3167*f5c631daSSadaf Ebrahimi   __ Mov(x27, 0xfffffffc);  // 32-bit -4.
3168*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0xfffffffe);  // 32-bit -2.
3169*f5c631daSSadaf Ebrahimi   __ Mov(x29, 0xffffffff);  // 32-bit -1.
3170*f5c631daSSadaf Ebrahimi 
3171*f5c631daSSadaf Ebrahimi   __ Ldr(w0, MemOperand(x16, x24));
3172*f5c631daSSadaf Ebrahimi   __ Ldr(x1, MemOperand(x16, x25));
3173*f5c631daSSadaf Ebrahimi   __ Ldr(w2, MemOperand(x18, x26));
3174*f5c631daSSadaf Ebrahimi   __ Ldr(w3, MemOperand(x18, x27, SXTW));
3175*f5c631daSSadaf Ebrahimi   __ Ldr(w4, MemOperand(x18, x28, SXTW, 2));
3176*f5c631daSSadaf Ebrahimi   __ Str(w0, MemOperand(x17, x24));
3177*f5c631daSSadaf Ebrahimi   __ Str(x1, MemOperand(x17, x25));
3178*f5c631daSSadaf Ebrahimi   __ Str(w2, MemOperand(x20, x29, SXTW, 2));
3179*f5c631daSSadaf Ebrahimi   END();
3180*f5c631daSSadaf Ebrahimi 
3181*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3182*f5c631daSSadaf Ebrahimi     RUN();
3183*f5c631daSSadaf Ebrahimi 
3184*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x0);
3185*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000300000002, x1);
3186*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x2);
3187*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x3);
3188*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x4);
3189*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(1, dst[0]);
3190*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(2, dst[1]);
3191*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(3, dst[2]);
3192*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(3, dst[3]);
3193*f5c631daSSadaf Ebrahimi   }
3194*f5c631daSSadaf Ebrahimi }
3195*f5c631daSSadaf Ebrahimi 
3196*f5c631daSSadaf Ebrahimi 
TEST(load_pauth)3197*f5c631daSSadaf Ebrahimi TEST(load_pauth) {
3198*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
3199*f5c631daSSadaf Ebrahimi 
3200*f5c631daSSadaf Ebrahimi   uint64_t src[4] = {1, 2, 3, 4};
3201*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3202*f5c631daSSadaf Ebrahimi 
3203*f5c631daSSadaf Ebrahimi   START();
3204*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3205*f5c631daSSadaf Ebrahimi   __ Mov(x17, src_base);
3206*f5c631daSSadaf Ebrahimi   __ Mov(x18, src_base + 4 * sizeof(src[0]));
3207*f5c631daSSadaf Ebrahimi   __ Mov(x19, src_base + 4 * sizeof(src[0]));
3208*f5c631daSSadaf Ebrahimi 
3209*f5c631daSSadaf Ebrahimi   // Add PAC codes to addresses
3210*f5c631daSSadaf Ebrahimi   __ Pacdza(x16);
3211*f5c631daSSadaf Ebrahimi   __ Pacdzb(x17);
3212*f5c631daSSadaf Ebrahimi   __ Pacdza(x18);
3213*f5c631daSSadaf Ebrahimi   __ Pacdzb(x19);
3214*f5c631daSSadaf Ebrahimi 
3215*f5c631daSSadaf Ebrahimi   __ Ldraa(x0, MemOperand(x16));
3216*f5c631daSSadaf Ebrahimi   __ Ldraa(x1, MemOperand(x16, sizeof(src[0])));
3217*f5c631daSSadaf Ebrahimi   __ Ldraa(x2, MemOperand(x16, 2 * sizeof(src[0]), PreIndex));
3218*f5c631daSSadaf Ebrahimi   __ Ldraa(x3, MemOperand(x18, -sizeof(src[0])));
3219*f5c631daSSadaf Ebrahimi   __ Ldrab(x4, MemOperand(x17));
3220*f5c631daSSadaf Ebrahimi   __ Ldrab(x5, MemOperand(x17, sizeof(src[0])));
3221*f5c631daSSadaf Ebrahimi   __ Ldrab(x6, MemOperand(x17, 2 * sizeof(src[0]), PreIndex));
3222*f5c631daSSadaf Ebrahimi   __ Ldrab(x7, MemOperand(x19, -sizeof(src[0])));
3223*f5c631daSSadaf Ebrahimi   END();
3224*f5c631daSSadaf Ebrahimi 
3225*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3226*f5c631daSSadaf Ebrahimi     RUN();
3227*f5c631daSSadaf Ebrahimi 
3228*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x0);
3229*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x1);
3230*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x2);
3231*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(4, x3);
3232*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x4);
3233*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x5);
3234*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x6);
3235*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(4, x7);
3236*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x16);
3237*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x17);
3238*f5c631daSSadaf Ebrahimi   }
3239*f5c631daSSadaf Ebrahimi }
3240*f5c631daSSadaf Ebrahimi 
3241*f5c631daSSadaf Ebrahimi 
3242*f5c631daSSadaf Ebrahimi #ifdef VIXL_NEGATIVE_TESTING
TEST(load_pauth_negative_test)3243*f5c631daSSadaf Ebrahimi TEST(load_pauth_negative_test) {
3244*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
3245*f5c631daSSadaf Ebrahimi 
3246*f5c631daSSadaf Ebrahimi   uint64_t src[4] = {1, 2, 3, 4};
3247*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3248*f5c631daSSadaf Ebrahimi 
3249*f5c631daSSadaf Ebrahimi   START();
3250*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3251*f5c631daSSadaf Ebrahimi 
3252*f5c631daSSadaf Ebrahimi   // There is a small but not negligible chance (1 in 127 runs) that the PAC
3253*f5c631daSSadaf Ebrahimi   // codes for keys A and B will collide and LDRAB won't abort. To mitigate
3254*f5c631daSSadaf Ebrahimi   // this, we simply repeat the test a few more times.
3255*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < 32; i++) {
3256*f5c631daSSadaf Ebrahimi     __ Add(x17, x16, i);
3257*f5c631daSSadaf Ebrahimi     __ Pacdza(x17);
3258*f5c631daSSadaf Ebrahimi     __ Ldrab(x0, MemOperand(x17));
3259*f5c631daSSadaf Ebrahimi   }
3260*f5c631daSSadaf Ebrahimi   END();
3261*f5c631daSSadaf Ebrahimi 
3262*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3263*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer.");
3264*f5c631daSSadaf Ebrahimi   }
3265*f5c631daSSadaf Ebrahimi }
3266*f5c631daSSadaf Ebrahimi #endif  // VIXL_NEGATIVE_TESTING
3267*f5c631daSSadaf Ebrahimi 
3268*f5c631daSSadaf Ebrahimi 
TEST(ldp_stp_offset)3269*f5c631daSSadaf Ebrahimi TEST(ldp_stp_offset) {
3270*f5c631daSSadaf Ebrahimi   SETUP();
3271*f5c631daSSadaf Ebrahimi 
3272*f5c631daSSadaf Ebrahimi   uint64_t src[3] = {0x0011223344556677,
3273*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3274*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988};
3275*f5c631daSSadaf Ebrahimi   uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
3276*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3277*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3278*f5c631daSSadaf Ebrahimi 
3279*f5c631daSSadaf Ebrahimi   START();
3280*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3281*f5c631daSSadaf Ebrahimi   __ Mov(x17, dst_base);
3282*f5c631daSSadaf Ebrahimi   __ Mov(x18, src_base + 24);
3283*f5c631daSSadaf Ebrahimi   __ Mov(x19, dst_base + 56);
3284*f5c631daSSadaf Ebrahimi   __ Ldp(w0, w1, MemOperand(x16));
3285*f5c631daSSadaf Ebrahimi   __ Ldp(w2, w3, MemOperand(x16, 4));
3286*f5c631daSSadaf Ebrahimi   __ Ldp(x4, x5, MemOperand(x16, 8));
3287*f5c631daSSadaf Ebrahimi   __ Ldp(w6, w7, MemOperand(x18, -12));
3288*f5c631daSSadaf Ebrahimi   __ Ldp(x8, x9, MemOperand(x18, -16));
3289*f5c631daSSadaf Ebrahimi   __ Stp(w0, w1, MemOperand(x17));
3290*f5c631daSSadaf Ebrahimi   __ Stp(w2, w3, MemOperand(x17, 8));
3291*f5c631daSSadaf Ebrahimi   __ Stp(x4, x5, MemOperand(x17, 16));
3292*f5c631daSSadaf Ebrahimi   __ Stp(w6, w7, MemOperand(x19, -24));
3293*f5c631daSSadaf Ebrahimi   __ Stp(x8, x9, MemOperand(x19, -16));
3294*f5c631daSSadaf Ebrahimi   END();
3295*f5c631daSSadaf Ebrahimi 
3296*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3297*f5c631daSSadaf Ebrahimi     RUN();
3298*f5c631daSSadaf Ebrahimi 
3299*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x0);
3300*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x1);
3301*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3302*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x2);
3303*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x3);
3304*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3305*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3306*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3307*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3308*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3309*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabb, x6);
3310*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x7);
3311*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3312*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3313*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3314*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3315*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3316*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x16);
3317*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x17);
3318*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 24, x18);
3319*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 56, x19);
3320*f5c631daSSadaf Ebrahimi   }
3321*f5c631daSSadaf Ebrahimi }
3322*f5c631daSSadaf Ebrahimi 
3323*f5c631daSSadaf Ebrahimi 
TEST(ldp_stp_offset_wide)3324*f5c631daSSadaf Ebrahimi TEST(ldp_stp_offset_wide) {
3325*f5c631daSSadaf Ebrahimi   SETUP();
3326*f5c631daSSadaf Ebrahimi 
3327*f5c631daSSadaf Ebrahimi   uint64_t src[3] = {0x0011223344556677,
3328*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3329*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988};
3330*f5c631daSSadaf Ebrahimi   uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
3331*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3332*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3333*f5c631daSSadaf Ebrahimi   // Move base too far from the array to force multiple instructions
3334*f5c631daSSadaf Ebrahimi   // to be emitted.
3335*f5c631daSSadaf Ebrahimi   const int64_t base_offset = 1024;
3336*f5c631daSSadaf Ebrahimi 
3337*f5c631daSSadaf Ebrahimi   START();
3338*f5c631daSSadaf Ebrahimi   __ Mov(x20, src_base - base_offset);
3339*f5c631daSSadaf Ebrahimi   __ Mov(x21, dst_base - base_offset);
3340*f5c631daSSadaf Ebrahimi   __ Mov(x18, src_base + base_offset + 24);
3341*f5c631daSSadaf Ebrahimi   __ Mov(x19, dst_base + base_offset + 56);
3342*f5c631daSSadaf Ebrahimi   __ Ldp(w0, w1, MemOperand(x20, base_offset));
3343*f5c631daSSadaf Ebrahimi   __ Ldp(w2, w3, MemOperand(x20, base_offset + 4));
3344*f5c631daSSadaf Ebrahimi   __ Ldp(x4, x5, MemOperand(x20, base_offset + 8));
3345*f5c631daSSadaf Ebrahimi   __ Ldp(w6, w7, MemOperand(x18, -12 - base_offset));
3346*f5c631daSSadaf Ebrahimi   __ Ldp(x8, x9, MemOperand(x18, -16 - base_offset));
3347*f5c631daSSadaf Ebrahimi   __ Stp(w0, w1, MemOperand(x21, base_offset));
3348*f5c631daSSadaf Ebrahimi   __ Stp(w2, w3, MemOperand(x21, base_offset + 8));
3349*f5c631daSSadaf Ebrahimi   __ Stp(x4, x5, MemOperand(x21, base_offset + 16));
3350*f5c631daSSadaf Ebrahimi   __ Stp(w6, w7, MemOperand(x19, -24 - base_offset));
3351*f5c631daSSadaf Ebrahimi   __ Stp(x8, x9, MemOperand(x19, -16 - base_offset));
3352*f5c631daSSadaf Ebrahimi   END();
3353*f5c631daSSadaf Ebrahimi 
3354*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3355*f5c631daSSadaf Ebrahimi     RUN();
3356*f5c631daSSadaf Ebrahimi 
3357*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x0);
3358*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x1);
3359*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3360*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x2);
3361*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x3);
3362*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3363*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3364*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3365*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3366*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3367*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabb, x6);
3368*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x7);
3369*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3370*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3371*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3372*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3373*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3374*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base - base_offset, x20);
3375*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base - base_offset, x21);
3376*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + base_offset + 24, x18);
3377*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + base_offset + 56, x19);
3378*f5c631daSSadaf Ebrahimi   }
3379*f5c631daSSadaf Ebrahimi }
3380*f5c631daSSadaf Ebrahimi 
3381*f5c631daSSadaf Ebrahimi 
TEST(ldnp_stnp_offset)3382*f5c631daSSadaf Ebrahimi TEST(ldnp_stnp_offset) {
3383*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3384*f5c631daSSadaf Ebrahimi 
3385*f5c631daSSadaf Ebrahimi   uint64_t src[4] = {0x0011223344556677,
3386*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3387*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988,
3388*f5c631daSSadaf Ebrahimi                      0x7766554433221100};
3389*f5c631daSSadaf Ebrahimi   uint64_t dst[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3390*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3391*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3392*f5c631daSSadaf Ebrahimi 
3393*f5c631daSSadaf Ebrahimi   START();
3394*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3395*f5c631daSSadaf Ebrahimi   __ Mov(x17, dst_base);
3396*f5c631daSSadaf Ebrahimi   __ Mov(x18, src_base + 24);
3397*f5c631daSSadaf Ebrahimi   __ Mov(x19, dst_base + 64);
3398*f5c631daSSadaf Ebrahimi   __ Mov(x20, src_base + 32);
3399*f5c631daSSadaf Ebrahimi 
3400*f5c631daSSadaf Ebrahimi   // Ensure address set up has happened before executing non-temporal ops.
3401*f5c631daSSadaf Ebrahimi   __ Dmb(InnerShareable, BarrierAll);
3402*f5c631daSSadaf Ebrahimi 
3403*f5c631daSSadaf Ebrahimi   __ Ldnp(w0, w1, MemOperand(x16));
3404*f5c631daSSadaf Ebrahimi   __ Ldnp(w2, w3, MemOperand(x16, 4));
3405*f5c631daSSadaf Ebrahimi   __ Ldnp(x4, x5, MemOperand(x16, 8));
3406*f5c631daSSadaf Ebrahimi   __ Ldnp(w6, w7, MemOperand(x18, -12));
3407*f5c631daSSadaf Ebrahimi   __ Ldnp(x8, x9, MemOperand(x18, -16));
3408*f5c631daSSadaf Ebrahimi   __ Ldnp(q16, q17, MemOperand(x16));
3409*f5c631daSSadaf Ebrahimi   __ Ldnp(q19, q18, MemOperand(x20, -32));
3410*f5c631daSSadaf Ebrahimi   __ Stnp(w0, w1, MemOperand(x17));
3411*f5c631daSSadaf Ebrahimi   __ Stnp(w2, w3, MemOperand(x17, 8));
3412*f5c631daSSadaf Ebrahimi   __ Stnp(x4, x5, MemOperand(x17, 16));
3413*f5c631daSSadaf Ebrahimi   __ Stnp(w6, w7, MemOperand(x19, -32));
3414*f5c631daSSadaf Ebrahimi   __ Stnp(x8, x9, MemOperand(x19, -24));
3415*f5c631daSSadaf Ebrahimi   __ Stnp(q17, q16, MemOperand(x19));
3416*f5c631daSSadaf Ebrahimi   __ Stnp(q18, q19, MemOperand(x19, 32));
3417*f5c631daSSadaf Ebrahimi   END();
3418*f5c631daSSadaf Ebrahimi 
3419*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3420*f5c631daSSadaf Ebrahimi     RUN();
3421*f5c631daSSadaf Ebrahimi 
3422*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x0);
3423*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x1);
3424*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
3425*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x2);
3426*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x3);
3427*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
3428*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3429*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
3430*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3431*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
3432*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabb, x6);
3433*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x7);
3434*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
3435*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
3436*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
3437*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
3438*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
3439*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q16);
3440*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q17);
3441*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q18);
3442*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q19);
3443*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[8]);
3444*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, dst[9]);
3445*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[10]);
3446*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[11]);
3447*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[12]);
3448*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, dst[13]);
3449*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[14]);
3450*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[15]);
3451*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x16);
3452*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x17);
3453*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 24, x18);
3454*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 64, x19);
3455*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 32, x20);
3456*f5c631daSSadaf Ebrahimi   }
3457*f5c631daSSadaf Ebrahimi }
3458*f5c631daSSadaf Ebrahimi 
TEST(ldp_stp_preindex)3459*f5c631daSSadaf Ebrahimi TEST(ldp_stp_preindex) {
3460*f5c631daSSadaf Ebrahimi   SETUP();
3461*f5c631daSSadaf Ebrahimi 
3462*f5c631daSSadaf Ebrahimi   uint64_t src[3] = {0x0011223344556677,
3463*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3464*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988};
3465*f5c631daSSadaf Ebrahimi   uint64_t dst[5] = {0, 0, 0, 0, 0};
3466*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3467*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3468*f5c631daSSadaf Ebrahimi 
3469*f5c631daSSadaf Ebrahimi   START();
3470*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3471*f5c631daSSadaf Ebrahimi   __ Mov(x17, dst_base);
3472*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base + 16);
3473*f5c631daSSadaf Ebrahimi   __ Ldp(w0, w1, MemOperand(x16, 4, PreIndex));
3474*f5c631daSSadaf Ebrahimi   __ Mov(x19, x16);
3475*f5c631daSSadaf Ebrahimi   __ Ldp(w2, w3, MemOperand(x16, -4, PreIndex));
3476*f5c631daSSadaf Ebrahimi   __ Stp(w2, w3, MemOperand(x17, 4, PreIndex));
3477*f5c631daSSadaf Ebrahimi   __ Mov(x20, x17);
3478*f5c631daSSadaf Ebrahimi   __ Stp(w0, w1, MemOperand(x17, -4, PreIndex));
3479*f5c631daSSadaf Ebrahimi   __ Ldp(x4, x5, MemOperand(x16, 8, PreIndex));
3480*f5c631daSSadaf Ebrahimi   __ Mov(x21, x16);
3481*f5c631daSSadaf Ebrahimi   __ Ldp(x6, x7, MemOperand(x16, -8, PreIndex));
3482*f5c631daSSadaf Ebrahimi   __ Stp(x7, x6, MemOperand(x18, 8, PreIndex));
3483*f5c631daSSadaf Ebrahimi   __ Mov(x22, x18);
3484*f5c631daSSadaf Ebrahimi   __ Stp(x5, x4, MemOperand(x18, -8, PreIndex));
3485*f5c631daSSadaf Ebrahimi   END();
3486*f5c631daSSadaf Ebrahimi 
3487*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3488*f5c631daSSadaf Ebrahimi     RUN();
3489*f5c631daSSadaf Ebrahimi 
3490*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x0);
3491*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x1);
3492*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x2);
3493*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x3);
3494*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
3495*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3496*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3497*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3498*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, x6);
3499*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
3500*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3501*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3502*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3503*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x16);
3504*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x17);
3505*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 16, x18);
3506*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 4, x19);
3507*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 4, x20);
3508*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 8, x21);
3509*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 24, x22);
3510*f5c631daSSadaf Ebrahimi   }
3511*f5c631daSSadaf Ebrahimi }
3512*f5c631daSSadaf Ebrahimi 
3513*f5c631daSSadaf Ebrahimi 
TEST(ldp_stp_preindex_wide)3514*f5c631daSSadaf Ebrahimi TEST(ldp_stp_preindex_wide) {
3515*f5c631daSSadaf Ebrahimi   SETUP();
3516*f5c631daSSadaf Ebrahimi 
3517*f5c631daSSadaf Ebrahimi   uint64_t src[3] = {0x0011223344556677,
3518*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3519*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988};
3520*f5c631daSSadaf Ebrahimi   uint64_t dst[5] = {0, 0, 0, 0, 0};
3521*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3522*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3523*f5c631daSSadaf Ebrahimi   // Move base too far from the array to force multiple instructions
3524*f5c631daSSadaf Ebrahimi   // to be emitted.
3525*f5c631daSSadaf Ebrahimi   const int64_t base_offset = 1024;
3526*f5c631daSSadaf Ebrahimi 
3527*f5c631daSSadaf Ebrahimi   START();
3528*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base - base_offset);
3529*f5c631daSSadaf Ebrahimi   __ Mov(x25, dst_base + base_offset);
3530*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base + base_offset + 16);
3531*f5c631daSSadaf Ebrahimi   __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PreIndex));
3532*f5c631daSSadaf Ebrahimi   __ Mov(x19, x24);
3533*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base - base_offset + 4);
3534*f5c631daSSadaf Ebrahimi   __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PreIndex));
3535*f5c631daSSadaf Ebrahimi   __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PreIndex));
3536*f5c631daSSadaf Ebrahimi   __ Mov(x20, x25);
3537*f5c631daSSadaf Ebrahimi   __ Mov(x25, dst_base + base_offset + 4);
3538*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base - base_offset);
3539*f5c631daSSadaf Ebrahimi   __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PreIndex));
3540*f5c631daSSadaf Ebrahimi   __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PreIndex));
3541*f5c631daSSadaf Ebrahimi   __ Mov(x21, x24);
3542*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base - base_offset + 8);
3543*f5c631daSSadaf Ebrahimi   __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PreIndex));
3544*f5c631daSSadaf Ebrahimi   __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PreIndex));
3545*f5c631daSSadaf Ebrahimi   __ Mov(x22, x18);
3546*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base + base_offset + 16 + 8);
3547*f5c631daSSadaf Ebrahimi   __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PreIndex));
3548*f5c631daSSadaf Ebrahimi   END();
3549*f5c631daSSadaf Ebrahimi 
3550*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3551*f5c631daSSadaf Ebrahimi     RUN();
3552*f5c631daSSadaf Ebrahimi 
3553*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x0);
3554*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x1);
3555*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x2);
3556*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x3);
3557*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
3558*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3559*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
3560*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
3561*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, x6);
3562*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
3563*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3564*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3565*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3566*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x24);
3567*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x25);
3568*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 16, x18);
3569*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 4, x19);
3570*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 4, x20);
3571*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 8, x21);
3572*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 24, x22);
3573*f5c631daSSadaf Ebrahimi   }
3574*f5c631daSSadaf Ebrahimi }
3575*f5c631daSSadaf Ebrahimi 
3576*f5c631daSSadaf Ebrahimi 
TEST(ldp_stp_postindex)3577*f5c631daSSadaf Ebrahimi TEST(ldp_stp_postindex) {
3578*f5c631daSSadaf Ebrahimi   SETUP();
3579*f5c631daSSadaf Ebrahimi 
3580*f5c631daSSadaf Ebrahimi   uint64_t src[4] = {0x0011223344556677,
3581*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3582*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988,
3583*f5c631daSSadaf Ebrahimi                      0x7766554433221100};
3584*f5c631daSSadaf Ebrahimi   uint64_t dst[5] = {0, 0, 0, 0, 0};
3585*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3586*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3587*f5c631daSSadaf Ebrahimi 
3588*f5c631daSSadaf Ebrahimi   START();
3589*f5c631daSSadaf Ebrahimi   __ Mov(x16, src_base);
3590*f5c631daSSadaf Ebrahimi   __ Mov(x17, dst_base);
3591*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base + 16);
3592*f5c631daSSadaf Ebrahimi   __ Ldp(w0, w1, MemOperand(x16, 4, PostIndex));
3593*f5c631daSSadaf Ebrahimi   __ Mov(x19, x16);
3594*f5c631daSSadaf Ebrahimi   __ Ldp(w2, w3, MemOperand(x16, -4, PostIndex));
3595*f5c631daSSadaf Ebrahimi   __ Stp(w2, w3, MemOperand(x17, 4, PostIndex));
3596*f5c631daSSadaf Ebrahimi   __ Mov(x20, x17);
3597*f5c631daSSadaf Ebrahimi   __ Stp(w0, w1, MemOperand(x17, -4, PostIndex));
3598*f5c631daSSadaf Ebrahimi   __ Ldp(x4, x5, MemOperand(x16, 8, PostIndex));
3599*f5c631daSSadaf Ebrahimi   __ Mov(x21, x16);
3600*f5c631daSSadaf Ebrahimi   __ Ldp(x6, x7, MemOperand(x16, -8, PostIndex));
3601*f5c631daSSadaf Ebrahimi   __ Stp(x7, x6, MemOperand(x18, 8, PostIndex));
3602*f5c631daSSadaf Ebrahimi   __ Mov(x22, x18);
3603*f5c631daSSadaf Ebrahimi   __ Stp(x5, x4, MemOperand(x18, -8, PostIndex));
3604*f5c631daSSadaf Ebrahimi   END();
3605*f5c631daSSadaf Ebrahimi 
3606*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3607*f5c631daSSadaf Ebrahimi     RUN();
3608*f5c631daSSadaf Ebrahimi 
3609*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x0);
3610*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x1);
3611*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x2);
3612*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x3);
3613*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
3614*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3615*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, x4);
3616*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
3617*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
3618*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
3619*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3620*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3621*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3622*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x16);
3623*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x17);
3624*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 16, x18);
3625*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 4, x19);
3626*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 4, x20);
3627*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 8, x21);
3628*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 24, x22);
3629*f5c631daSSadaf Ebrahimi   }
3630*f5c631daSSadaf Ebrahimi }
3631*f5c631daSSadaf Ebrahimi 
3632*f5c631daSSadaf Ebrahimi 
TEST(ldp_stp_postindex_wide)3633*f5c631daSSadaf Ebrahimi TEST(ldp_stp_postindex_wide) {
3634*f5c631daSSadaf Ebrahimi   SETUP();
3635*f5c631daSSadaf Ebrahimi 
3636*f5c631daSSadaf Ebrahimi   uint64_t src[4] = {0x0011223344556677,
3637*f5c631daSSadaf Ebrahimi                      0x8899aabbccddeeff,
3638*f5c631daSSadaf Ebrahimi                      0xffeeddccbbaa9988,
3639*f5c631daSSadaf Ebrahimi                      0x7766554433221100};
3640*f5c631daSSadaf Ebrahimi   uint64_t dst[5] = {0, 0, 0, 0, 0};
3641*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3642*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3643*f5c631daSSadaf Ebrahimi   // Move base too far from the array to force multiple instructions
3644*f5c631daSSadaf Ebrahimi   // to be emitted.
3645*f5c631daSSadaf Ebrahimi   const int64_t base_offset = 1024;
3646*f5c631daSSadaf Ebrahimi 
3647*f5c631daSSadaf Ebrahimi   START();
3648*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base);
3649*f5c631daSSadaf Ebrahimi   __ Mov(x25, dst_base);
3650*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base + 16);
3651*f5c631daSSadaf Ebrahimi   __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PostIndex));
3652*f5c631daSSadaf Ebrahimi   __ Mov(x19, x24);
3653*f5c631daSSadaf Ebrahimi   __ Sub(x24, x24, base_offset);
3654*f5c631daSSadaf Ebrahimi   __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PostIndex));
3655*f5c631daSSadaf Ebrahimi   __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PostIndex));
3656*f5c631daSSadaf Ebrahimi   __ Mov(x20, x25);
3657*f5c631daSSadaf Ebrahimi   __ Sub(x24, x24, base_offset);
3658*f5c631daSSadaf Ebrahimi   __ Add(x25, x25, base_offset);
3659*f5c631daSSadaf Ebrahimi   __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PostIndex));
3660*f5c631daSSadaf Ebrahimi   __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PostIndex));
3661*f5c631daSSadaf Ebrahimi   __ Mov(x21, x24);
3662*f5c631daSSadaf Ebrahimi   __ Sub(x24, x24, base_offset);
3663*f5c631daSSadaf Ebrahimi   __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PostIndex));
3664*f5c631daSSadaf Ebrahimi   __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PostIndex));
3665*f5c631daSSadaf Ebrahimi   __ Mov(x22, x18);
3666*f5c631daSSadaf Ebrahimi   __ Add(x18, x18, base_offset);
3667*f5c631daSSadaf Ebrahimi   __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PostIndex));
3668*f5c631daSSadaf Ebrahimi   END();
3669*f5c631daSSadaf Ebrahimi 
3670*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3671*f5c631daSSadaf Ebrahimi     RUN();
3672*f5c631daSSadaf Ebrahimi 
3673*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x44556677, x0);
3674*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x1);
3675*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00112233, x2);
3676*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xccddeeff, x3);
3677*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
3678*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3679*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, x4);
3680*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
3681*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
3682*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
3683*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3684*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3685*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3686*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + base_offset, x24);
3687*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base - base_offset, x25);
3688*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base - base_offset + 16, x18);
3689*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + base_offset + 4, x19);
3690*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base - base_offset + 4, x20);
3691*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + base_offset + 8, x21);
3692*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base - base_offset + 24, x22);
3693*f5c631daSSadaf Ebrahimi   }
3694*f5c631daSSadaf Ebrahimi }
3695*f5c631daSSadaf Ebrahimi 
3696*f5c631daSSadaf Ebrahimi 
TEST(ldp_sign_extend)3697*f5c631daSSadaf Ebrahimi TEST(ldp_sign_extend) {
3698*f5c631daSSadaf Ebrahimi   SETUP();
3699*f5c631daSSadaf Ebrahimi 
3700*f5c631daSSadaf Ebrahimi   uint32_t src[2] = {0x80000000, 0x7fffffff};
3701*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3702*f5c631daSSadaf Ebrahimi 
3703*f5c631daSSadaf Ebrahimi   START();
3704*f5c631daSSadaf Ebrahimi   __ Mov(x24, src_base);
3705*f5c631daSSadaf Ebrahimi   __ Ldpsw(x0, x1, MemOperand(x24));
3706*f5c631daSSadaf Ebrahimi   END();
3707*f5c631daSSadaf Ebrahimi 
3708*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3709*f5c631daSSadaf Ebrahimi     RUN();
3710*f5c631daSSadaf Ebrahimi 
3711*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x0);
3712*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000007fffffff, x1);
3713*f5c631daSSadaf Ebrahimi   }
3714*f5c631daSSadaf Ebrahimi }
3715*f5c631daSSadaf Ebrahimi 
3716*f5c631daSSadaf Ebrahimi 
TEST(ldur_stur)3717*f5c631daSSadaf Ebrahimi TEST(ldur_stur) {
3718*f5c631daSSadaf Ebrahimi   SETUP();
3719*f5c631daSSadaf Ebrahimi 
3720*f5c631daSSadaf Ebrahimi   int64_t src[2] = {0x0123456789abcdef, 0x0123456789abcdef};
3721*f5c631daSSadaf Ebrahimi   int64_t dst[5] = {0, 0, 0, 0, 0};
3722*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3723*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3724*f5c631daSSadaf Ebrahimi 
3725*f5c631daSSadaf Ebrahimi   START();
3726*f5c631daSSadaf Ebrahimi   __ Mov(x17, src_base);
3727*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base);
3728*f5c631daSSadaf Ebrahimi   __ Mov(x19, src_base + 16);
3729*f5c631daSSadaf Ebrahimi   __ Mov(x20, dst_base + 32);
3730*f5c631daSSadaf Ebrahimi   __ Mov(x21, dst_base + 40);
3731*f5c631daSSadaf Ebrahimi   __ Ldr(w0, MemOperand(x17, 1));
3732*f5c631daSSadaf Ebrahimi   __ Str(w0, MemOperand(x18, 2));
3733*f5c631daSSadaf Ebrahimi   __ Ldr(x1, MemOperand(x17, 3));
3734*f5c631daSSadaf Ebrahimi   __ Str(x1, MemOperand(x18, 9));
3735*f5c631daSSadaf Ebrahimi   __ Ldr(w2, MemOperand(x19, -9));
3736*f5c631daSSadaf Ebrahimi   __ Str(w2, MemOperand(x20, -5));
3737*f5c631daSSadaf Ebrahimi   __ Ldrb(w3, MemOperand(x19, -1));
3738*f5c631daSSadaf Ebrahimi   __ Strb(w3, MemOperand(x21, -1));
3739*f5c631daSSadaf Ebrahimi   END();
3740*f5c631daSSadaf Ebrahimi 
3741*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3742*f5c631daSSadaf Ebrahimi     RUN();
3743*f5c631daSSadaf Ebrahimi 
3744*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x6789abcd, x0);
3745*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00006789abcd0000, dst[0]);
3746*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xabcdef0123456789, x1);
3747*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xcdef012345678900, dst[1]);
3748*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000ab, dst[2]);
3749*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xabcdef01, x2);
3750*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00abcdef01000000, dst[3]);
3751*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001, x3);
3752*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0100000000000000, dst[4]);
3753*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base, x17);
3754*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base, x18);
3755*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(src_base + 16, x19);
3756*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(dst_base + 32, x20);
3757*f5c631daSSadaf Ebrahimi   }
3758*f5c631daSSadaf Ebrahimi }
3759*f5c631daSSadaf Ebrahimi 
3760*f5c631daSSadaf Ebrahimi 
TEST(ldur_stur_neon)3761*f5c631daSSadaf Ebrahimi TEST(ldur_stur_neon) {
3762*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3763*f5c631daSSadaf Ebrahimi 
3764*f5c631daSSadaf Ebrahimi   int64_t src[3] = {0x0123456789abcdef, 0x0123456789abcdef, 0x0123456789abcdef};
3765*f5c631daSSadaf Ebrahimi   int64_t dst[5] = {0, 0, 0, 0, 0};
3766*f5c631daSSadaf Ebrahimi   uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3767*f5c631daSSadaf Ebrahimi   uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3768*f5c631daSSadaf Ebrahimi 
3769*f5c631daSSadaf Ebrahimi   START();
3770*f5c631daSSadaf Ebrahimi   __ Mov(x17, src_base);
3771*f5c631daSSadaf Ebrahimi   __ Mov(x18, dst_base);
3772*f5c631daSSadaf Ebrahimi   __ Ldr(b0, MemOperand(x17));
3773*f5c631daSSadaf Ebrahimi   __ Str(b0, MemOperand(x18));
3774*f5c631daSSadaf Ebrahimi   __ Ldr(h1, MemOperand(x17, 1));
3775*f5c631daSSadaf Ebrahimi   __ Str(h1, MemOperand(x18, 1));
3776*f5c631daSSadaf Ebrahimi   __ Ldr(s2, MemOperand(x17, 2));
3777*f5c631daSSadaf Ebrahimi   __ Str(s2, MemOperand(x18, 3));
3778*f5c631daSSadaf Ebrahimi   __ Ldr(d3, MemOperand(x17, 3));
3779*f5c631daSSadaf Ebrahimi   __ Str(d3, MemOperand(x18, 7));
3780*f5c631daSSadaf Ebrahimi   __ Ldr(q4, MemOperand(x17, 4));
3781*f5c631daSSadaf Ebrahimi   __ Str(q4, MemOperand(x18, 15));
3782*f5c631daSSadaf Ebrahimi   END();
3783*f5c631daSSadaf Ebrahimi 
3784*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3785*f5c631daSSadaf Ebrahimi     RUN();
3786*f5c631daSSadaf Ebrahimi 
3787*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0, 0xef, q0);
3788*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0, 0xabcd, q1);
3789*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0, 0x456789ab, q2);
3790*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0, 0xabcdef0123456789, q3);
3791*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x89abcdef01234567, 0x89abcdef01234567, q4);
3792*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89456789ababcdef, dst[0]);
3793*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x67abcdef01234567, dst[1]);
3794*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x6789abcdef012345, dst[2]);
3795*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0089abcdef012345, dst[3]);
3796*f5c631daSSadaf Ebrahimi   }
3797*f5c631daSSadaf Ebrahimi }
3798*f5c631daSSadaf Ebrahimi 
3799*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal)3800*f5c631daSSadaf Ebrahimi TEST(ldr_literal) {
3801*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3802*f5c631daSSadaf Ebrahimi 
3803*f5c631daSSadaf Ebrahimi   START();
3804*f5c631daSSadaf Ebrahimi   __ Ldr(x2, 0x1234567890abcdef);
3805*f5c631daSSadaf Ebrahimi   __ Ldr(w3, 0xfedcba09);
3806*f5c631daSSadaf Ebrahimi   __ Ldrsw(x4, 0x7fffffff);
3807*f5c631daSSadaf Ebrahimi   __ Ldrsw(x5, 0x80000000);
3808*f5c631daSSadaf Ebrahimi   __ Ldr(q11, 0x1234000056780000, 0xabcd0000ef000000);
3809*f5c631daSSadaf Ebrahimi   __ Ldr(d13, 1.234);
3810*f5c631daSSadaf Ebrahimi   __ Ldr(s25, 2.5);
3811*f5c631daSSadaf Ebrahimi   END();
3812*f5c631daSSadaf Ebrahimi 
3813*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3814*f5c631daSSadaf Ebrahimi     RUN();
3815*f5c631daSSadaf Ebrahimi 
3816*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
3817*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x3);
3818*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffff, x4);
3819*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x5);
3820*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
3821*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d13);
3822*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s25);
3823*f5c631daSSadaf Ebrahimi   }
3824*f5c631daSSadaf Ebrahimi }
3825*f5c631daSSadaf Ebrahimi 
3826*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_range)3827*f5c631daSSadaf Ebrahimi TEST(ldr_literal_range) {
3828*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3829*f5c631daSSadaf Ebrahimi 
3830*f5c631daSSadaf Ebrahimi   START();
3831*f5c631daSSadaf Ebrahimi   // Make sure the pool is empty;
3832*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
3833*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
3834*f5c631daSSadaf Ebrahimi 
3835*f5c631daSSadaf Ebrahimi   // Create some literal pool entries.
3836*f5c631daSSadaf Ebrahimi   __ Ldr(x0, 0x1234567890abcdef);
3837*f5c631daSSadaf Ebrahimi   __ Ldr(w1, 0xfedcba09);
3838*f5c631daSSadaf Ebrahimi   __ Ldrsw(x2, 0x7fffffff);
3839*f5c631daSSadaf Ebrahimi   __ Ldrsw(x3, 0x80000000);
3840*f5c631daSSadaf Ebrahimi   __ Ldr(q2, 0x1234000056780000, 0xabcd0000ef000000);
3841*f5c631daSSadaf Ebrahimi   __ Ldr(d0, 1.234);
3842*f5c631daSSadaf Ebrahimi   __ Ldr(s1, 2.5);
3843*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(48);
3844*f5c631daSSadaf Ebrahimi 
3845*f5c631daSSadaf Ebrahimi   // Emit more code than the maximum literal load range to ensure the pool
3846*f5c631daSSadaf Ebrahimi   // should be emitted.
3847*f5c631daSSadaf Ebrahimi   const ptrdiff_t end = masm.GetCursorOffset() + 2 * kMaxLoadLiteralRange;
3848*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < end) {
3849*f5c631daSSadaf Ebrahimi     __ Nop();
3850*f5c631daSSadaf Ebrahimi   }
3851*f5c631daSSadaf Ebrahimi 
3852*f5c631daSSadaf Ebrahimi   // The pool should have been emitted.
3853*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
3854*f5c631daSSadaf Ebrahimi 
3855*f5c631daSSadaf Ebrahimi   // These loads should be after the pool (and will require a new one).
3856*f5c631daSSadaf Ebrahimi   __ Ldr(x4, 0x34567890abcdef12);
3857*f5c631daSSadaf Ebrahimi   __ Ldr(w5, 0xdcba09fe);
3858*f5c631daSSadaf Ebrahimi   __ Ldrsw(x6, 0x7fffffff);
3859*f5c631daSSadaf Ebrahimi   __ Ldrsw(x7, 0x80000000);
3860*f5c631daSSadaf Ebrahimi   __ Ldr(q6, 0x1234000056780000, 0xabcd0000ef000000);
3861*f5c631daSSadaf Ebrahimi   __ Ldr(d4, 123.4);
3862*f5c631daSSadaf Ebrahimi   __ Ldr(s5, 250.0);
3863*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(48);
3864*f5c631daSSadaf Ebrahimi   END();
3865*f5c631daSSadaf Ebrahimi 
3866*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3867*f5c631daSSadaf Ebrahimi     RUN();
3868*f5c631daSSadaf Ebrahimi 
3869*f5c631daSSadaf Ebrahimi     // Check that the literals loaded correctly.
3870*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x0);
3871*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x1);
3872*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffff, x2);
3873*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x3);
3874*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q2);
3875*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d0);
3876*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s1);
3877*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x34567890abcdef12, x4);
3878*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xdcba09fe, x5);
3879*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffff, x6);
3880*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x7);
3881*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q6);
3882*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(123.4, d4);
3883*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(250.0, s5);
3884*f5c631daSSadaf Ebrahimi   }
3885*f5c631daSSadaf Ebrahimi }
3886*f5c631daSSadaf Ebrahimi 
3887*f5c631daSSadaf Ebrahimi 
3888*f5c631daSSadaf Ebrahimi template <typename T>
LoadIntValueHelper(T values[],int card)3889*f5c631daSSadaf Ebrahimi void LoadIntValueHelper(T values[], int card) {
3890*f5c631daSSadaf Ebrahimi   SETUP();
3891*f5c631daSSadaf Ebrahimi 
3892*f5c631daSSadaf Ebrahimi   const bool is_32bit = (sizeof(T) == 4);
3893*f5c631daSSadaf Ebrahimi   Register tgt1 = is_32bit ? Register(w1) : Register(x1);
3894*f5c631daSSadaf Ebrahimi   Register tgt2 = is_32bit ? Register(w2) : Register(x2);
3895*f5c631daSSadaf Ebrahimi 
3896*f5c631daSSadaf Ebrahimi   START();
3897*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
3898*f5c631daSSadaf Ebrahimi 
3899*f5c631daSSadaf Ebrahimi   // If one of the values differ then x0 will be one.
3900*f5c631daSSadaf Ebrahimi   for (int i = 0; i < card; ++i) {
3901*f5c631daSSadaf Ebrahimi     __ Mov(tgt1, values[i]);
3902*f5c631daSSadaf Ebrahimi     __ Ldr(tgt2, values[i]);
3903*f5c631daSSadaf Ebrahimi     __ Cmp(tgt1, tgt2);
3904*f5c631daSSadaf Ebrahimi     __ Cset(x0, ne);
3905*f5c631daSSadaf Ebrahimi   }
3906*f5c631daSSadaf Ebrahimi   END();
3907*f5c631daSSadaf Ebrahimi 
3908*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
3909*f5c631daSSadaf Ebrahimi     RUN();
3910*f5c631daSSadaf Ebrahimi 
3911*f5c631daSSadaf Ebrahimi     // If one of the values differs, the trace can be used to identify which
3912*f5c631daSSadaf Ebrahimi     // one.
3913*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
3914*f5c631daSSadaf Ebrahimi   }
3915*f5c631daSSadaf Ebrahimi }
3916*f5c631daSSadaf Ebrahimi 
3917*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_values_x)3918*f5c631daSSadaf Ebrahimi TEST(ldr_literal_values_x) {
3919*f5c631daSSadaf Ebrahimi   static const uint64_t kValues[] = {0x8000000000000000,
3920*f5c631daSSadaf Ebrahimi                                      0x7fffffffffffffff,
3921*f5c631daSSadaf Ebrahimi                                      0x0000000000000000,
3922*f5c631daSSadaf Ebrahimi                                      0xffffffffffffffff,
3923*f5c631daSSadaf Ebrahimi                                      0x00ff00ff00ff00ff,
3924*f5c631daSSadaf Ebrahimi                                      0x1234567890abcdef};
3925*f5c631daSSadaf Ebrahimi 
3926*f5c631daSSadaf Ebrahimi   LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
3927*f5c631daSSadaf Ebrahimi }
3928*f5c631daSSadaf Ebrahimi 
3929*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_values_w)3930*f5c631daSSadaf Ebrahimi TEST(ldr_literal_values_w) {
3931*f5c631daSSadaf Ebrahimi   static const uint32_t kValues[] = {0x80000000,
3932*f5c631daSSadaf Ebrahimi                                      0x7fffffff,
3933*f5c631daSSadaf Ebrahimi                                      0x00000000,
3934*f5c631daSSadaf Ebrahimi                                      0xffffffff,
3935*f5c631daSSadaf Ebrahimi                                      0x00ff00ff,
3936*f5c631daSSadaf Ebrahimi                                      0x12345678,
3937*f5c631daSSadaf Ebrahimi                                      0x90abcdef};
3938*f5c631daSSadaf Ebrahimi 
3939*f5c631daSSadaf Ebrahimi   LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
3940*f5c631daSSadaf Ebrahimi }
3941*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_custom)3942*f5c631daSSadaf Ebrahimi TEST(ldr_literal_custom) {
3943*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
3944*f5c631daSSadaf Ebrahimi 
3945*f5c631daSSadaf Ebrahimi   Label end_of_pool_before;
3946*f5c631daSSadaf Ebrahimi   Label end_of_pool_after;
3947*f5c631daSSadaf Ebrahimi 
3948*f5c631daSSadaf Ebrahimi   const size_t kSizeOfPoolInBytes = 44;
3949*f5c631daSSadaf Ebrahimi 
3950*f5c631daSSadaf Ebrahimi   Literal<uint64_t> before_x(0x1234567890abcdef);
3951*f5c631daSSadaf Ebrahimi   Literal<uint32_t> before_w(0xfedcba09);
3952*f5c631daSSadaf Ebrahimi   Literal<uint32_t> before_sx(0x80000000);
3953*f5c631daSSadaf Ebrahimi   Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000);
3954*f5c631daSSadaf Ebrahimi   Literal<double> before_d(1.234);
3955*f5c631daSSadaf Ebrahimi   Literal<float> before_s(2.5);
3956*f5c631daSSadaf Ebrahimi 
3957*f5c631daSSadaf Ebrahimi   Literal<uint64_t> after_x(0x1234567890abcdef);
3958*f5c631daSSadaf Ebrahimi   Literal<uint32_t> after_w(0xfedcba09);
3959*f5c631daSSadaf Ebrahimi   Literal<uint32_t> after_sx(0x80000000);
3960*f5c631daSSadaf Ebrahimi   Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000);
3961*f5c631daSSadaf Ebrahimi   Literal<double> after_d(1.234);
3962*f5c631daSSadaf Ebrahimi   Literal<float> after_s(2.5);
3963*f5c631daSSadaf Ebrahimi 
3964*f5c631daSSadaf Ebrahimi   START();
3965*f5c631daSSadaf Ebrahimi 
3966*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
3967*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_before);
3968*f5c631daSSadaf Ebrahimi   {
3969*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
3970*f5c631daSSadaf Ebrahimi     __ place(&before_x);
3971*f5c631daSSadaf Ebrahimi     __ place(&before_w);
3972*f5c631daSSadaf Ebrahimi     __ place(&before_sx);
3973*f5c631daSSadaf Ebrahimi     __ place(&before_q);
3974*f5c631daSSadaf Ebrahimi     __ place(&before_d);
3975*f5c631daSSadaf Ebrahimi     __ place(&before_s);
3976*f5c631daSSadaf Ebrahimi   }
3977*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_before);
3978*f5c631daSSadaf Ebrahimi 
3979*f5c631daSSadaf Ebrahimi   {
3980*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 12 * kInstructionSize);
3981*f5c631daSSadaf Ebrahimi     __ ldr(x2, &before_x);
3982*f5c631daSSadaf Ebrahimi     __ ldr(w3, &before_w);
3983*f5c631daSSadaf Ebrahimi     __ ldrsw(x5, &before_sx);
3984*f5c631daSSadaf Ebrahimi     __ ldr(q11, &before_q);
3985*f5c631daSSadaf Ebrahimi     __ ldr(d13, &before_d);
3986*f5c631daSSadaf Ebrahimi     __ ldr(s25, &before_s);
3987*f5c631daSSadaf Ebrahimi 
3988*f5c631daSSadaf Ebrahimi     __ ldr(x6, &after_x);
3989*f5c631daSSadaf Ebrahimi     __ ldr(w7, &after_w);
3990*f5c631daSSadaf Ebrahimi     __ ldrsw(x8, &after_sx);
3991*f5c631daSSadaf Ebrahimi     __ ldr(q18, &after_q);
3992*f5c631daSSadaf Ebrahimi     __ ldr(d14, &after_d);
3993*f5c631daSSadaf Ebrahimi     __ ldr(s26, &after_s);
3994*f5c631daSSadaf Ebrahimi   }
3995*f5c631daSSadaf Ebrahimi 
3996*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
3997*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_after);
3998*f5c631daSSadaf Ebrahimi   {
3999*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4000*f5c631daSSadaf Ebrahimi     __ place(&after_x);
4001*f5c631daSSadaf Ebrahimi     __ place(&after_w);
4002*f5c631daSSadaf Ebrahimi     __ place(&after_sx);
4003*f5c631daSSadaf Ebrahimi     __ place(&after_q);
4004*f5c631daSSadaf Ebrahimi     __ place(&after_d);
4005*f5c631daSSadaf Ebrahimi     __ place(&after_s);
4006*f5c631daSSadaf Ebrahimi   }
4007*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_after);
4008*f5c631daSSadaf Ebrahimi 
4009*f5c631daSSadaf Ebrahimi   END();
4010*f5c631daSSadaf Ebrahimi 
4011*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4012*f5c631daSSadaf Ebrahimi     RUN();
4013*f5c631daSSadaf Ebrahimi 
4014*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4015*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x3);
4016*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x5);
4017*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4018*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d13);
4019*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s25);
4020*f5c631daSSadaf Ebrahimi 
4021*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4022*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x7);
4023*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x8);
4024*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18);
4025*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d14);
4026*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s26);
4027*f5c631daSSadaf Ebrahimi   }
4028*f5c631daSSadaf Ebrahimi }
4029*f5c631daSSadaf Ebrahimi 
4030*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_custom_shared)4031*f5c631daSSadaf Ebrahimi TEST(ldr_literal_custom_shared) {
4032*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
4033*f5c631daSSadaf Ebrahimi 
4034*f5c631daSSadaf Ebrahimi   Label end_of_pool_before;
4035*f5c631daSSadaf Ebrahimi   Label end_of_pool_after;
4036*f5c631daSSadaf Ebrahimi 
4037*f5c631daSSadaf Ebrahimi   const size_t kSizeOfPoolInBytes = 40;
4038*f5c631daSSadaf Ebrahimi 
4039*f5c631daSSadaf Ebrahimi   Literal<uint64_t> before_x(0x1234567890abcdef);
4040*f5c631daSSadaf Ebrahimi   Literal<uint32_t> before_w(0xfedcba09);
4041*f5c631daSSadaf Ebrahimi   Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000);
4042*f5c631daSSadaf Ebrahimi   Literal<double> before_d(1.234);
4043*f5c631daSSadaf Ebrahimi   Literal<float> before_s(2.5);
4044*f5c631daSSadaf Ebrahimi 
4045*f5c631daSSadaf Ebrahimi   Literal<uint64_t> after_x(0x1234567890abcdef);
4046*f5c631daSSadaf Ebrahimi   Literal<uint32_t> after_w(0xfedcba09);
4047*f5c631daSSadaf Ebrahimi   Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000);
4048*f5c631daSSadaf Ebrahimi   Literal<double> after_d(1.234);
4049*f5c631daSSadaf Ebrahimi   Literal<float> after_s(2.5);
4050*f5c631daSSadaf Ebrahimi 
4051*f5c631daSSadaf Ebrahimi   START();
4052*f5c631daSSadaf Ebrahimi 
4053*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
4054*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_before);
4055*f5c631daSSadaf Ebrahimi   {
4056*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4057*f5c631daSSadaf Ebrahimi     __ place(&before_x);
4058*f5c631daSSadaf Ebrahimi     __ place(&before_w);
4059*f5c631daSSadaf Ebrahimi     __ place(&before_q);
4060*f5c631daSSadaf Ebrahimi     __ place(&before_d);
4061*f5c631daSSadaf Ebrahimi     __ place(&before_s);
4062*f5c631daSSadaf Ebrahimi   }
4063*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_before);
4064*f5c631daSSadaf Ebrahimi 
4065*f5c631daSSadaf Ebrahimi   // Load the entries several times to test that literals can be shared.
4066*f5c631daSSadaf Ebrahimi   for (int i = 0; i < 50; i++) {
4067*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 12 * kInstructionSize);
4068*f5c631daSSadaf Ebrahimi     __ ldr(x2, &before_x);
4069*f5c631daSSadaf Ebrahimi     __ ldr(w3, &before_w);
4070*f5c631daSSadaf Ebrahimi     __ ldrsw(x5, &before_w);  // Re-use before_w.
4071*f5c631daSSadaf Ebrahimi     __ ldr(q11, &before_q);
4072*f5c631daSSadaf Ebrahimi     __ ldr(d13, &before_d);
4073*f5c631daSSadaf Ebrahimi     __ ldr(s25, &before_s);
4074*f5c631daSSadaf Ebrahimi 
4075*f5c631daSSadaf Ebrahimi     __ ldr(x6, &after_x);
4076*f5c631daSSadaf Ebrahimi     __ ldr(w7, &after_w);
4077*f5c631daSSadaf Ebrahimi     __ ldrsw(x8, &after_w);  // Re-use after_w.
4078*f5c631daSSadaf Ebrahimi     __ ldr(q18, &after_q);
4079*f5c631daSSadaf Ebrahimi     __ ldr(d14, &after_d);
4080*f5c631daSSadaf Ebrahimi     __ ldr(s26, &after_s);
4081*f5c631daSSadaf Ebrahimi   }
4082*f5c631daSSadaf Ebrahimi 
4083*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
4084*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_after);
4085*f5c631daSSadaf Ebrahimi   {
4086*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4087*f5c631daSSadaf Ebrahimi     __ place(&after_x);
4088*f5c631daSSadaf Ebrahimi     __ place(&after_w);
4089*f5c631daSSadaf Ebrahimi     __ place(&after_q);
4090*f5c631daSSadaf Ebrahimi     __ place(&after_d);
4091*f5c631daSSadaf Ebrahimi     __ place(&after_s);
4092*f5c631daSSadaf Ebrahimi   }
4093*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_after);
4094*f5c631daSSadaf Ebrahimi 
4095*f5c631daSSadaf Ebrahimi   END();
4096*f5c631daSSadaf Ebrahimi 
4097*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4098*f5c631daSSadaf Ebrahimi     RUN();
4099*f5c631daSSadaf Ebrahimi 
4100*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4101*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x3);
4102*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffedcba09, x5);
4103*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11);
4104*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d13);
4105*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s25);
4106*f5c631daSSadaf Ebrahimi 
4107*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4108*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x7);
4109*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffedcba09, x8);
4110*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18);
4111*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d14);
4112*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s26);
4113*f5c631daSSadaf Ebrahimi   }
4114*f5c631daSSadaf Ebrahimi }
4115*f5c631daSSadaf Ebrahimi 
4116*f5c631daSSadaf Ebrahimi static const PrefetchOperation kPrfmOperations[] = {PLDL1KEEP,
4117*f5c631daSSadaf Ebrahimi                                                     PLDL1STRM,
4118*f5c631daSSadaf Ebrahimi                                                     PLDL2KEEP,
4119*f5c631daSSadaf Ebrahimi                                                     PLDL2STRM,
4120*f5c631daSSadaf Ebrahimi                                                     PLDL3KEEP,
4121*f5c631daSSadaf Ebrahimi                                                     PLDL3STRM,
4122*f5c631daSSadaf Ebrahimi 
4123*f5c631daSSadaf Ebrahimi                                                     PLIL1KEEP,
4124*f5c631daSSadaf Ebrahimi                                                     PLIL1STRM,
4125*f5c631daSSadaf Ebrahimi                                                     PLIL2KEEP,
4126*f5c631daSSadaf Ebrahimi                                                     PLIL2STRM,
4127*f5c631daSSadaf Ebrahimi                                                     PLIL3KEEP,
4128*f5c631daSSadaf Ebrahimi                                                     PLIL3STRM,
4129*f5c631daSSadaf Ebrahimi 
4130*f5c631daSSadaf Ebrahimi                                                     PSTL1KEEP,
4131*f5c631daSSadaf Ebrahimi                                                     PSTL1STRM,
4132*f5c631daSSadaf Ebrahimi                                                     PSTL2KEEP,
4133*f5c631daSSadaf Ebrahimi                                                     PSTL2STRM,
4134*f5c631daSSadaf Ebrahimi                                                     PSTL3KEEP,
4135*f5c631daSSadaf Ebrahimi                                                     PSTL3STRM};
4136*f5c631daSSadaf Ebrahimi 
TEST(prfm_offset)4137*f5c631daSSadaf Ebrahimi TEST(prfm_offset) {
4138*f5c631daSSadaf Ebrahimi   SETUP();
4139*f5c631daSSadaf Ebrahimi 
4140*f5c631daSSadaf Ebrahimi   START();
4141*f5c631daSSadaf Ebrahimi   // The address used in prfm doesn't have to be valid.
4142*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0123456789abcdef);
4143*f5c631daSSadaf Ebrahimi 
4144*f5c631daSSadaf Ebrahimi   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4145*f5c631daSSadaf Ebrahimi     // Unallocated prefetch operations are ignored, so test all of them.
4146*f5c631daSSadaf Ebrahimi     // We have to use the Assembler directly for this.
4147*f5c631daSSadaf Ebrahimi     ExactAssemblyScope guard(&masm, 3 * kInstructionSize);
4148*f5c631daSSadaf Ebrahimi     __ prfm(op, MemOperand(x0));
4149*f5c631daSSadaf Ebrahimi     __ prfm(op, MemOperand(x0, 8));
4150*f5c631daSSadaf Ebrahimi     __ prfm(op, MemOperand(x0, 32760));
4151*f5c631daSSadaf Ebrahimi   }
4152*f5c631daSSadaf Ebrahimi 
4153*f5c631daSSadaf Ebrahimi   for (PrefetchOperation op : kPrfmOperations) {
4154*f5c631daSSadaf Ebrahimi     // Also test named operations.
4155*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 32768));
4156*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 1));
4157*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 9));
4158*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 255));
4159*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 257));
4160*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, -1));
4161*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, -9));
4162*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, -255));
4163*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, -257));
4164*f5c631daSSadaf Ebrahimi 
4165*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 0xfedcba9876543210));
4166*f5c631daSSadaf Ebrahimi   }
4167*f5c631daSSadaf Ebrahimi 
4168*f5c631daSSadaf Ebrahimi   END();
4169*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4170*f5c631daSSadaf Ebrahimi     RUN();
4171*f5c631daSSadaf Ebrahimi   }
4172*f5c631daSSadaf Ebrahimi }
4173*f5c631daSSadaf Ebrahimi 
4174*f5c631daSSadaf Ebrahimi 
TEST(prfm_regoffset)4175*f5c631daSSadaf Ebrahimi TEST(prfm_regoffset) {
4176*f5c631daSSadaf Ebrahimi   SETUP();
4177*f5c631daSSadaf Ebrahimi 
4178*f5c631daSSadaf Ebrahimi   START();
4179*f5c631daSSadaf Ebrahimi   // The address used in prfm doesn't have to be valid.
4180*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0123456789abcdef);
4181*f5c631daSSadaf Ebrahimi 
4182*f5c631daSSadaf Ebrahimi   CPURegList inputs(CPURegister::kRegister, kXRegSize, 10, 18);
4183*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0);
4184*f5c631daSSadaf Ebrahimi   __ Mov(x11, 1);
4185*f5c631daSSadaf Ebrahimi   __ Mov(x12, 8);
4186*f5c631daSSadaf Ebrahimi   __ Mov(x13, 255);
4187*f5c631daSSadaf Ebrahimi   __ Mov(x14, -0);
4188*f5c631daSSadaf Ebrahimi   __ Mov(x15, -1);
4189*f5c631daSSadaf Ebrahimi   __ Mov(x16, -8);
4190*f5c631daSSadaf Ebrahimi   __ Mov(x17, -255);
4191*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xfedcba9876543210);
4192*f5c631daSSadaf Ebrahimi 
4193*f5c631daSSadaf Ebrahimi   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4194*f5c631daSSadaf Ebrahimi     // Unallocated prefetch operations are ignored, so test all of them.
4195*f5c631daSSadaf Ebrahimi     // We have to use the Assembler directly for this.
4196*f5c631daSSadaf Ebrahimi     ExactAssemblyScope guard(&masm, inputs.GetCount() * kInstructionSize);
4197*f5c631daSSadaf Ebrahimi     CPURegList loop = inputs;
4198*f5c631daSSadaf Ebrahimi     while (!loop.IsEmpty()) {
4199*f5c631daSSadaf Ebrahimi       __ prfm(op, MemOperand(x0, Register(loop.PopLowestIndex())));
4200*f5c631daSSadaf Ebrahimi     }
4201*f5c631daSSadaf Ebrahimi   }
4202*f5c631daSSadaf Ebrahimi 
4203*f5c631daSSadaf Ebrahimi   for (PrefetchOperation op : kPrfmOperations) {
4204*f5c631daSSadaf Ebrahimi     // Also test named operations.
4205*f5c631daSSadaf Ebrahimi     CPURegList loop = inputs;
4206*f5c631daSSadaf Ebrahimi     while (!loop.IsEmpty()) {
4207*f5c631daSSadaf Ebrahimi       Register input(loop.PopLowestIndex());
4208*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, UXTW));
4209*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, UXTW, 3));
4210*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, LSL));
4211*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, LSL, 3));
4212*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, SXTW));
4213*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, SXTW, 3));
4214*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, SXTX));
4215*f5c631daSSadaf Ebrahimi       __ Prfm(op, MemOperand(x0, input, SXTX, 3));
4216*f5c631daSSadaf Ebrahimi     }
4217*f5c631daSSadaf Ebrahimi   }
4218*f5c631daSSadaf Ebrahimi 
4219*f5c631daSSadaf Ebrahimi   END();
4220*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4221*f5c631daSSadaf Ebrahimi     RUN();
4222*f5c631daSSadaf Ebrahimi   }
4223*f5c631daSSadaf Ebrahimi }
4224*f5c631daSSadaf Ebrahimi 
4225*f5c631daSSadaf Ebrahimi 
TEST(prfm_literal_imm19)4226*f5c631daSSadaf Ebrahimi TEST(prfm_literal_imm19) {
4227*f5c631daSSadaf Ebrahimi   SETUP();
4228*f5c631daSSadaf Ebrahimi   START();
4229*f5c631daSSadaf Ebrahimi 
4230*f5c631daSSadaf Ebrahimi   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4231*f5c631daSSadaf Ebrahimi     // Unallocated prefetch operations are ignored, so test all of them.
4232*f5c631daSSadaf Ebrahimi     // We have to use the Assembler directly for this.
4233*f5c631daSSadaf Ebrahimi     ExactAssemblyScope guard(&masm, 3 * kInstructionSize);
4234*f5c631daSSadaf Ebrahimi     __ prfm(op, INT64_C(0));
4235*f5c631daSSadaf Ebrahimi     __ prfm(op, 1);
4236*f5c631daSSadaf Ebrahimi     __ prfm(op, -1);
4237*f5c631daSSadaf Ebrahimi   }
4238*f5c631daSSadaf Ebrahimi 
4239*f5c631daSSadaf Ebrahimi   for (PrefetchOperation op : kPrfmOperations) {
4240*f5c631daSSadaf Ebrahimi     // Also test named operations.
4241*f5c631daSSadaf Ebrahimi     ExactAssemblyScope guard(&masm, 4 * kInstructionSize);
4242*f5c631daSSadaf Ebrahimi     // The address used in prfm doesn't have to be valid.
4243*f5c631daSSadaf Ebrahimi     __ prfm(op, 1000);
4244*f5c631daSSadaf Ebrahimi     __ prfm(op, -1000);
4245*f5c631daSSadaf Ebrahimi     __ prfm(op, 0x3ffff);
4246*f5c631daSSadaf Ebrahimi     __ prfm(op, -0x40000);
4247*f5c631daSSadaf Ebrahimi   }
4248*f5c631daSSadaf Ebrahimi 
4249*f5c631daSSadaf Ebrahimi   END();
4250*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4251*f5c631daSSadaf Ebrahimi     RUN();
4252*f5c631daSSadaf Ebrahimi   }
4253*f5c631daSSadaf Ebrahimi }
4254*f5c631daSSadaf Ebrahimi 
4255*f5c631daSSadaf Ebrahimi 
TEST(prfm_literal)4256*f5c631daSSadaf Ebrahimi TEST(prfm_literal) {
4257*f5c631daSSadaf Ebrahimi   SETUP();
4258*f5c631daSSadaf Ebrahimi 
4259*f5c631daSSadaf Ebrahimi   Label end_of_pool_before;
4260*f5c631daSSadaf Ebrahimi   Label end_of_pool_after;
4261*f5c631daSSadaf Ebrahimi   Literal<uint64_t> before(0);
4262*f5c631daSSadaf Ebrahimi   Literal<uint64_t> after(0);
4263*f5c631daSSadaf Ebrahimi 
4264*f5c631daSSadaf Ebrahimi   START();
4265*f5c631daSSadaf Ebrahimi 
4266*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
4267*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_before);
4268*f5c631daSSadaf Ebrahimi   {
4269*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, before.GetSize());
4270*f5c631daSSadaf Ebrahimi     __ place(&before);
4271*f5c631daSSadaf Ebrahimi   }
4272*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_before);
4273*f5c631daSSadaf Ebrahimi 
4274*f5c631daSSadaf Ebrahimi   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4275*f5c631daSSadaf Ebrahimi     // Unallocated prefetch operations are ignored, so test all of them.
4276*f5c631daSSadaf Ebrahimi     // We have to use the Assembler directly for this.
4277*f5c631daSSadaf Ebrahimi     ExactAssemblyScope guard(&masm, 2 * kInstructionSize);
4278*f5c631daSSadaf Ebrahimi     __ prfm(op, &before);
4279*f5c631daSSadaf Ebrahimi     __ prfm(op, &after);
4280*f5c631daSSadaf Ebrahimi   }
4281*f5c631daSSadaf Ebrahimi 
4282*f5c631daSSadaf Ebrahimi   for (PrefetchOperation op : kPrfmOperations) {
4283*f5c631daSSadaf Ebrahimi     // Also test named operations.
4284*f5c631daSSadaf Ebrahimi     ExactAssemblyScope guard(&masm, 2 * kInstructionSize);
4285*f5c631daSSadaf Ebrahimi     __ prfm(op, &before);
4286*f5c631daSSadaf Ebrahimi     __ prfm(op, &after);
4287*f5c631daSSadaf Ebrahimi   }
4288*f5c631daSSadaf Ebrahimi 
4289*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
4290*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_after);
4291*f5c631daSSadaf Ebrahimi   {
4292*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, after.GetSize());
4293*f5c631daSSadaf Ebrahimi     __ place(&after);
4294*f5c631daSSadaf Ebrahimi   }
4295*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_after);
4296*f5c631daSSadaf Ebrahimi 
4297*f5c631daSSadaf Ebrahimi   END();
4298*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4299*f5c631daSSadaf Ebrahimi     RUN();
4300*f5c631daSSadaf Ebrahimi   }
4301*f5c631daSSadaf Ebrahimi }
4302*f5c631daSSadaf Ebrahimi 
4303*f5c631daSSadaf Ebrahimi 
TEST(prfm_wide)4304*f5c631daSSadaf Ebrahimi TEST(prfm_wide) {
4305*f5c631daSSadaf Ebrahimi   SETUP();
4306*f5c631daSSadaf Ebrahimi 
4307*f5c631daSSadaf Ebrahimi   START();
4308*f5c631daSSadaf Ebrahimi   // The address used in prfm doesn't have to be valid.
4309*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0123456789abcdef);
4310*f5c631daSSadaf Ebrahimi 
4311*f5c631daSSadaf Ebrahimi   for (PrefetchOperation op : kPrfmOperations) {
4312*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, 0x40000));
4313*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, -0x40001));
4314*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, UINT64_C(0x5555555555555555)));
4315*f5c631daSSadaf Ebrahimi     __ Prfm(op, MemOperand(x0, UINT64_C(0xfedcba9876543210)));
4316*f5c631daSSadaf Ebrahimi   }
4317*f5c631daSSadaf Ebrahimi 
4318*f5c631daSSadaf Ebrahimi   END();
4319*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4320*f5c631daSSadaf Ebrahimi     RUN();
4321*f5c631daSSadaf Ebrahimi   }
4322*f5c631daSSadaf Ebrahimi }
4323*f5c631daSSadaf Ebrahimi 
4324*f5c631daSSadaf Ebrahimi 
TEST(load_prfm_literal)4325*f5c631daSSadaf Ebrahimi TEST(load_prfm_literal) {
4326*f5c631daSSadaf Ebrahimi   // Test literals shared between both prfm and ldr.
4327*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
4328*f5c631daSSadaf Ebrahimi 
4329*f5c631daSSadaf Ebrahimi   Label end_of_pool_before;
4330*f5c631daSSadaf Ebrahimi   Label end_of_pool_after;
4331*f5c631daSSadaf Ebrahimi 
4332*f5c631daSSadaf Ebrahimi   const size_t kSizeOfPoolInBytes = 28;
4333*f5c631daSSadaf Ebrahimi 
4334*f5c631daSSadaf Ebrahimi   Literal<uint64_t> before_x(0x1234567890abcdef);
4335*f5c631daSSadaf Ebrahimi   Literal<uint32_t> before_w(0xfedcba09);
4336*f5c631daSSadaf Ebrahimi   Literal<uint32_t> before_sx(0x80000000);
4337*f5c631daSSadaf Ebrahimi   Literal<double> before_d(1.234);
4338*f5c631daSSadaf Ebrahimi   Literal<float> before_s(2.5);
4339*f5c631daSSadaf Ebrahimi   Literal<uint64_t> after_x(0x1234567890abcdef);
4340*f5c631daSSadaf Ebrahimi   Literal<uint32_t> after_w(0xfedcba09);
4341*f5c631daSSadaf Ebrahimi   Literal<uint32_t> after_sx(0x80000000);
4342*f5c631daSSadaf Ebrahimi   Literal<double> after_d(1.234);
4343*f5c631daSSadaf Ebrahimi   Literal<float> after_s(2.5);
4344*f5c631daSSadaf Ebrahimi 
4345*f5c631daSSadaf Ebrahimi   START();
4346*f5c631daSSadaf Ebrahimi 
4347*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
4348*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_before);
4349*f5c631daSSadaf Ebrahimi   {
4350*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4351*f5c631daSSadaf Ebrahimi     __ place(&before_x);
4352*f5c631daSSadaf Ebrahimi     __ place(&before_w);
4353*f5c631daSSadaf Ebrahimi     __ place(&before_sx);
4354*f5c631daSSadaf Ebrahimi     __ place(&before_d);
4355*f5c631daSSadaf Ebrahimi     __ place(&before_s);
4356*f5c631daSSadaf Ebrahimi   }
4357*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_before);
4358*f5c631daSSadaf Ebrahimi 
4359*f5c631daSSadaf Ebrahimi   for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) {
4360*f5c631daSSadaf Ebrahimi     // Unallocated prefetch operations are ignored, so test all of them.
4361*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4362*f5c631daSSadaf Ebrahimi 
4363*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_x);
4364*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_w);
4365*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_sx);
4366*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_d);
4367*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_s);
4368*f5c631daSSadaf Ebrahimi 
4369*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_x);
4370*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_w);
4371*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_sx);
4372*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_d);
4373*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_s);
4374*f5c631daSSadaf Ebrahimi   }
4375*f5c631daSSadaf Ebrahimi 
4376*f5c631daSSadaf Ebrahimi   for (PrefetchOperation op : kPrfmOperations) {
4377*f5c631daSSadaf Ebrahimi     // Also test named operations.
4378*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4379*f5c631daSSadaf Ebrahimi 
4380*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_x);
4381*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_w);
4382*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_sx);
4383*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_d);
4384*f5c631daSSadaf Ebrahimi     __ prfm(op, &before_s);
4385*f5c631daSSadaf Ebrahimi 
4386*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_x);
4387*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_w);
4388*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_sx);
4389*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_d);
4390*f5c631daSSadaf Ebrahimi     __ prfm(op, &after_s);
4391*f5c631daSSadaf Ebrahimi   }
4392*f5c631daSSadaf Ebrahimi 
4393*f5c631daSSadaf Ebrahimi   {
4394*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 10 * kInstructionSize);
4395*f5c631daSSadaf Ebrahimi     __ ldr(x2, &before_x);
4396*f5c631daSSadaf Ebrahimi     __ ldr(w3, &before_w);
4397*f5c631daSSadaf Ebrahimi     __ ldrsw(x5, &before_sx);
4398*f5c631daSSadaf Ebrahimi     __ ldr(d13, &before_d);
4399*f5c631daSSadaf Ebrahimi     __ ldr(s25, &before_s);
4400*f5c631daSSadaf Ebrahimi 
4401*f5c631daSSadaf Ebrahimi     __ ldr(x6, &after_x);
4402*f5c631daSSadaf Ebrahimi     __ ldr(w7, &after_w);
4403*f5c631daSSadaf Ebrahimi     __ ldrsw(x8, &after_sx);
4404*f5c631daSSadaf Ebrahimi     __ ldr(d14, &after_d);
4405*f5c631daSSadaf Ebrahimi     __ ldr(s26, &after_s);
4406*f5c631daSSadaf Ebrahimi   }
4407*f5c631daSSadaf Ebrahimi 
4408*f5c631daSSadaf Ebrahimi   // Manually generate a pool.
4409*f5c631daSSadaf Ebrahimi   __ B(&end_of_pool_after);
4410*f5c631daSSadaf Ebrahimi   {
4411*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes);
4412*f5c631daSSadaf Ebrahimi     __ place(&after_x);
4413*f5c631daSSadaf Ebrahimi     __ place(&after_w);
4414*f5c631daSSadaf Ebrahimi     __ place(&after_sx);
4415*f5c631daSSadaf Ebrahimi     __ place(&after_d);
4416*f5c631daSSadaf Ebrahimi     __ place(&after_s);
4417*f5c631daSSadaf Ebrahimi   }
4418*f5c631daSSadaf Ebrahimi   __ Bind(&end_of_pool_after);
4419*f5c631daSSadaf Ebrahimi 
4420*f5c631daSSadaf Ebrahimi   END();
4421*f5c631daSSadaf Ebrahimi 
4422*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4423*f5c631daSSadaf Ebrahimi     RUN();
4424*f5c631daSSadaf Ebrahimi 
4425*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x2);
4426*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x3);
4427*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x5);
4428*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d13);
4429*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s25);
4430*f5c631daSSadaf Ebrahimi 
4431*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x6);
4432*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba09, x7);
4433*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff80000000, x8);
4434*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.234, d14);
4435*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(2.5, s26);
4436*f5c631daSSadaf Ebrahimi   }
4437*f5c631daSSadaf Ebrahimi }
4438*f5c631daSSadaf Ebrahimi 
4439*f5c631daSSadaf Ebrahimi 
TEST(add_sub_imm)4440*f5c631daSSadaf Ebrahimi TEST(add_sub_imm) {
4441*f5c631daSSadaf Ebrahimi   SETUP();
4442*f5c631daSSadaf Ebrahimi 
4443*f5c631daSSadaf Ebrahimi   START();
4444*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
4445*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1111);
4446*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xffffffffffffffff);
4447*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0x8000000000000000);
4448*f5c631daSSadaf Ebrahimi 
4449*f5c631daSSadaf Ebrahimi   __ Add(x10, x0, Operand(0x123));
4450*f5c631daSSadaf Ebrahimi   __ Add(x11, x1, Operand(0x122000));
4451*f5c631daSSadaf Ebrahimi   __ Add(x12, x0, Operand(0xabc << 12));
4452*f5c631daSSadaf Ebrahimi   __ Add(x13, x2, Operand(1));
4453*f5c631daSSadaf Ebrahimi 
4454*f5c631daSSadaf Ebrahimi   __ Add(w14, w0, Operand(0x123));
4455*f5c631daSSadaf Ebrahimi   __ Add(w15, w1, Operand(0x122000));
4456*f5c631daSSadaf Ebrahimi   __ Add(w16, w0, Operand(0xabc << 12));
4457*f5c631daSSadaf Ebrahimi   __ Add(w17, w2, Operand(1));
4458*f5c631daSSadaf Ebrahimi 
4459*f5c631daSSadaf Ebrahimi   __ Sub(x20, x0, Operand(0x1));
4460*f5c631daSSadaf Ebrahimi   __ Sub(x21, x1, Operand(0x111));
4461*f5c631daSSadaf Ebrahimi   __ Sub(x22, x1, Operand(0x1 << 12));
4462*f5c631daSSadaf Ebrahimi   __ Sub(x23, x3, Operand(1));
4463*f5c631daSSadaf Ebrahimi 
4464*f5c631daSSadaf Ebrahimi   __ Sub(w24, w0, Operand(0x1));
4465*f5c631daSSadaf Ebrahimi   __ Sub(w25, w1, Operand(0x111));
4466*f5c631daSSadaf Ebrahimi   __ Sub(w26, w1, Operand(0x1 << 12));
4467*f5c631daSSadaf Ebrahimi   __ Sub(w27, w3, Operand(1));
4468*f5c631daSSadaf Ebrahimi   END();
4469*f5c631daSSadaf Ebrahimi 
4470*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4471*f5c631daSSadaf Ebrahimi     RUN();
4472*f5c631daSSadaf Ebrahimi 
4473*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123, x10);
4474*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123111, x11);
4475*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xabc000, x12);
4476*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x13);
4477*f5c631daSSadaf Ebrahimi 
4478*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x123, w14);
4479*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x123111, w15);
4480*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xabc000, w16);
4481*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x0, w17);
4482*f5c631daSSadaf Ebrahimi 
4483*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x20);
4484*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1000, x21);
4485*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x111, x22);
4486*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7fffffffffffffff, x23);
4487*f5c631daSSadaf Ebrahimi 
4488*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffff, w24);
4489*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1000, w25);
4490*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x111, w26);
4491*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffff, w27);
4492*f5c631daSSadaf Ebrahimi   }
4493*f5c631daSSadaf Ebrahimi }
4494*f5c631daSSadaf Ebrahimi 
4495*f5c631daSSadaf Ebrahimi 
TEST(add_sub_wide_imm)4496*f5c631daSSadaf Ebrahimi TEST(add_sub_wide_imm) {
4497*f5c631daSSadaf Ebrahimi   SETUP();
4498*f5c631daSSadaf Ebrahimi 
4499*f5c631daSSadaf Ebrahimi   START();
4500*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
4501*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1);
4502*f5c631daSSadaf Ebrahimi 
4503*f5c631daSSadaf Ebrahimi   __ Add(x10, x0, Operand(0x1234567890abcdef));
4504*f5c631daSSadaf Ebrahimi   __ Add(x11, x1, Operand(0xffffffff));
4505*f5c631daSSadaf Ebrahimi 
4506*f5c631daSSadaf Ebrahimi   __ Add(w12, w0, Operand(0x12345678));
4507*f5c631daSSadaf Ebrahimi   __ Add(w13, w1, Operand(0xffffffff));
4508*f5c631daSSadaf Ebrahimi 
4509*f5c631daSSadaf Ebrahimi   __ Add(w18, w0, Operand(kWMinInt));
4510*f5c631daSSadaf Ebrahimi   __ Sub(w19, w0, Operand(kWMinInt));
4511*f5c631daSSadaf Ebrahimi 
4512*f5c631daSSadaf Ebrahimi   __ Sub(x20, x0, Operand(0x1234567890abcdef));
4513*f5c631daSSadaf Ebrahimi   __ Sub(w21, w0, Operand(0x12345678));
4514*f5c631daSSadaf Ebrahimi 
4515*f5c631daSSadaf Ebrahimi   END();
4516*f5c631daSSadaf Ebrahimi 
4517*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4518*f5c631daSSadaf Ebrahimi     RUN();
4519*f5c631daSSadaf Ebrahimi 
4520*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x10);
4521*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x100000000, x11);
4522*f5c631daSSadaf Ebrahimi 
4523*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345678, w12);
4524*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x13);
4525*f5c631daSSadaf Ebrahimi 
4526*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(kWMinInt, w18);
4527*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(kWMinInt, w19);
4528*f5c631daSSadaf Ebrahimi 
4529*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-0x1234567890abcdef, x20);
4530*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(-0x12345678, w21);
4531*f5c631daSSadaf Ebrahimi   }
4532*f5c631daSSadaf Ebrahimi }
4533*f5c631daSSadaf Ebrahimi 
4534*f5c631daSSadaf Ebrahimi 
TEST(add_sub_shifted)4535*f5c631daSSadaf Ebrahimi TEST(add_sub_shifted) {
4536*f5c631daSSadaf Ebrahimi   SETUP();
4537*f5c631daSSadaf Ebrahimi 
4538*f5c631daSSadaf Ebrahimi   START();
4539*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
4540*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0123456789abcdef);
4541*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xfedcba9876543210);
4542*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xffffffffffffffff);
4543*f5c631daSSadaf Ebrahimi 
4544*f5c631daSSadaf Ebrahimi   __ Add(x10, x1, Operand(x2));
4545*f5c631daSSadaf Ebrahimi   __ Add(x11, x0, Operand(x1, LSL, 8));
4546*f5c631daSSadaf Ebrahimi   __ Add(x12, x0, Operand(x1, LSR, 8));
4547*f5c631daSSadaf Ebrahimi   __ Add(x13, x0, Operand(x1, ASR, 8));
4548*f5c631daSSadaf Ebrahimi   __ Add(x14, x0, Operand(x2, ASR, 8));
4549*f5c631daSSadaf Ebrahimi   __ Add(w15, w0, Operand(w1, ASR, 8));
4550*f5c631daSSadaf Ebrahimi   __ Add(w18, w3, Operand(w1, ROR, 8));
4551*f5c631daSSadaf Ebrahimi   __ Add(x19, x3, Operand(x1, ROR, 8));
4552*f5c631daSSadaf Ebrahimi 
4553*f5c631daSSadaf Ebrahimi   __ Sub(x20, x3, Operand(x2));
4554*f5c631daSSadaf Ebrahimi   __ Sub(x21, x3, Operand(x1, LSL, 8));
4555*f5c631daSSadaf Ebrahimi   __ Sub(x22, x3, Operand(x1, LSR, 8));
4556*f5c631daSSadaf Ebrahimi   __ Sub(x23, x3, Operand(x1, ASR, 8));
4557*f5c631daSSadaf Ebrahimi   __ Sub(x24, x3, Operand(x2, ASR, 8));
4558*f5c631daSSadaf Ebrahimi   __ Sub(w25, w3, Operand(w1, ASR, 8));
4559*f5c631daSSadaf Ebrahimi   __ Sub(w26, w3, Operand(w1, ROR, 8));
4560*f5c631daSSadaf Ebrahimi   __ Sub(x27, x3, Operand(x1, ROR, 8));
4561*f5c631daSSadaf Ebrahimi   END();
4562*f5c631daSSadaf Ebrahimi 
4563*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4564*f5c631daSSadaf Ebrahimi     RUN();
4565*f5c631daSSadaf Ebrahimi 
4566*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x10);
4567*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x23456789abcdef00, x11);
4568*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000123456789abcd, x12);
4569*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000123456789abcd, x13);
4570*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffedcba98765432, x14);
4571*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff89abcd, x15);
4572*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xef89abcc, x18);
4573*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xef0123456789abcc, x19);
4574*f5c631daSSadaf Ebrahimi 
4575*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x20);
4576*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xdcba9876543210ff, x21);
4577*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffedcba98765432, x22);
4578*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffedcba98765432, x23);
4579*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000123456789abcd, x24);
4580*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00765432, x25);
4581*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10765432, x26);
4582*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10fedcba98765432, x27);
4583*f5c631daSSadaf Ebrahimi   }
4584*f5c631daSSadaf Ebrahimi }
4585*f5c631daSSadaf Ebrahimi 
4586*f5c631daSSadaf Ebrahimi 
TEST(add_sub_extended)4587*f5c631daSSadaf Ebrahimi TEST(add_sub_extended) {
4588*f5c631daSSadaf Ebrahimi   SETUP();
4589*f5c631daSSadaf Ebrahimi 
4590*f5c631daSSadaf Ebrahimi   START();
4591*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
4592*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0123456789abcdef);
4593*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xfedcba9876543210);
4594*f5c631daSSadaf Ebrahimi   __ Mov(w3, 0x80);
4595*f5c631daSSadaf Ebrahimi 
4596*f5c631daSSadaf Ebrahimi   __ Add(x10, x0, Operand(x1, UXTB, 0));
4597*f5c631daSSadaf Ebrahimi   __ Add(x11, x0, Operand(x1, UXTB, 1));
4598*f5c631daSSadaf Ebrahimi   __ Add(x12, x0, Operand(x1, UXTH, 2));
4599*f5c631daSSadaf Ebrahimi   __ Add(x13, x0, Operand(x1, UXTW, 4));
4600*f5c631daSSadaf Ebrahimi 
4601*f5c631daSSadaf Ebrahimi   __ Add(x14, x0, Operand(x1, SXTB, 0));
4602*f5c631daSSadaf Ebrahimi   __ Add(x15, x0, Operand(x1, SXTB, 1));
4603*f5c631daSSadaf Ebrahimi   __ Add(x16, x0, Operand(x1, SXTH, 2));
4604*f5c631daSSadaf Ebrahimi   __ Add(x17, x0, Operand(x1, SXTW, 3));
4605*f5c631daSSadaf Ebrahimi   __ Add(x18, x0, Operand(x2, SXTB, 0));
4606*f5c631daSSadaf Ebrahimi   __ Add(x19, x0, Operand(x2, SXTB, 1));
4607*f5c631daSSadaf Ebrahimi   __ Add(x20, x0, Operand(x2, SXTH, 2));
4608*f5c631daSSadaf Ebrahimi   __ Add(x21, x0, Operand(x2, SXTW, 3));
4609*f5c631daSSadaf Ebrahimi 
4610*f5c631daSSadaf Ebrahimi   __ Add(x22, x1, Operand(x2, SXTB, 1));
4611*f5c631daSSadaf Ebrahimi   __ Sub(x23, x1, Operand(x2, SXTB, 1));
4612*f5c631daSSadaf Ebrahimi 
4613*f5c631daSSadaf Ebrahimi   __ Add(w24, w1, Operand(w2, UXTB, 2));
4614*f5c631daSSadaf Ebrahimi   __ Add(w25, w0, Operand(w1, SXTB, 0));
4615*f5c631daSSadaf Ebrahimi   __ Add(w26, w0, Operand(w1, SXTB, 1));
4616*f5c631daSSadaf Ebrahimi   __ Add(w27, w2, Operand(w1, SXTW, 3));
4617*f5c631daSSadaf Ebrahimi 
4618*f5c631daSSadaf Ebrahimi   __ Add(w28, w0, Operand(w1, SXTW, 3));
4619*f5c631daSSadaf Ebrahimi   __ Add(x29, x0, Operand(w1, SXTW, 3));
4620*f5c631daSSadaf Ebrahimi 
4621*f5c631daSSadaf Ebrahimi   __ Sub(x30, x0, Operand(w3, SXTB, 1));
4622*f5c631daSSadaf Ebrahimi   END();
4623*f5c631daSSadaf Ebrahimi 
4624*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4625*f5c631daSSadaf Ebrahimi     RUN();
4626*f5c631daSSadaf Ebrahimi 
4627*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xef, x10);
4628*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1de, x11);
4629*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x337bc, x12);
4630*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef0, x13);
4631*f5c631daSSadaf Ebrahimi 
4632*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffef, x14);
4633*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffde, x15);
4634*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff37bc, x16);
4635*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x17);
4636*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10, x18);
4637*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x20, x19);
4638*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xc840, x20);
4639*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3b2a19080, x21);
4640*f5c631daSSadaf Ebrahimi 
4641*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abce0f, x22);
4642*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdcf, x23);
4643*f5c631daSSadaf Ebrahimi 
4644*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x89abce2f, w24);
4645*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffef, w25);
4646*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffde, w26);
4647*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xc3b2a188, w27);
4648*f5c631daSSadaf Ebrahimi 
4649*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x4d5e6f78, w28);
4650*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x29);
4651*f5c631daSSadaf Ebrahimi 
4652*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(256, x30);
4653*f5c631daSSadaf Ebrahimi   }
4654*f5c631daSSadaf Ebrahimi }
4655*f5c631daSSadaf Ebrahimi 
4656*f5c631daSSadaf Ebrahimi 
TEST(add_sub_negative)4657*f5c631daSSadaf Ebrahimi TEST(add_sub_negative) {
4658*f5c631daSSadaf Ebrahimi   SETUP();
4659*f5c631daSSadaf Ebrahimi 
4660*f5c631daSSadaf Ebrahimi   START();
4661*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
4662*f5c631daSSadaf Ebrahimi   __ Mov(x1, 4687);
4663*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x1122334455667788);
4664*f5c631daSSadaf Ebrahimi   __ Mov(w3, 0x11223344);
4665*f5c631daSSadaf Ebrahimi   __ Mov(w4, 400000);
4666*f5c631daSSadaf Ebrahimi 
4667*f5c631daSSadaf Ebrahimi   __ Add(x10, x0, -42);
4668*f5c631daSSadaf Ebrahimi   __ Add(x11, x1, -687);
4669*f5c631daSSadaf Ebrahimi   __ Add(x12, x2, -0x88);
4670*f5c631daSSadaf Ebrahimi 
4671*f5c631daSSadaf Ebrahimi   __ Sub(x13, x0, -600);
4672*f5c631daSSadaf Ebrahimi   __ Sub(x14, x1, -313);
4673*f5c631daSSadaf Ebrahimi   __ Sub(x15, x2, -0x555);
4674*f5c631daSSadaf Ebrahimi 
4675*f5c631daSSadaf Ebrahimi   __ Add(w19, w3, -0x344);
4676*f5c631daSSadaf Ebrahimi   __ Add(w20, w4, -2000);
4677*f5c631daSSadaf Ebrahimi 
4678*f5c631daSSadaf Ebrahimi   __ Sub(w21, w3, -0xbc);
4679*f5c631daSSadaf Ebrahimi   __ Sub(w22, w4, -2000);
4680*f5c631daSSadaf Ebrahimi   END();
4681*f5c631daSSadaf Ebrahimi 
4682*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4683*f5c631daSSadaf Ebrahimi     RUN();
4684*f5c631daSSadaf Ebrahimi 
4685*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-42, x10);
4686*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(4000, x11);
4687*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667700, x12);
4688*f5c631daSSadaf Ebrahimi 
4689*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(600, x13);
4690*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(5000, x14);
4691*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1122334455667cdd, x15);
4692*f5c631daSSadaf Ebrahimi 
4693*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11223000, w19);
4694*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(398000, w20);
4695*f5c631daSSadaf Ebrahimi 
4696*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11223400, w21);
4697*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(402000, w22);
4698*f5c631daSSadaf Ebrahimi   }
4699*f5c631daSSadaf Ebrahimi }
4700*f5c631daSSadaf Ebrahimi 
4701*f5c631daSSadaf Ebrahimi 
TEST(add_sub_zero)4702*f5c631daSSadaf Ebrahimi TEST(add_sub_zero) {
4703*f5c631daSSadaf Ebrahimi   SETUP();
4704*f5c631daSSadaf Ebrahimi 
4705*f5c631daSSadaf Ebrahimi   START();
4706*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
4707*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
4708*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0);
4709*f5c631daSSadaf Ebrahimi 
4710*f5c631daSSadaf Ebrahimi   Label blob1;
4711*f5c631daSSadaf Ebrahimi   __ Bind(&blob1);
4712*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 0);
4713*f5c631daSSadaf Ebrahimi   __ Sub(x1, x1, 0);
4714*f5c631daSSadaf Ebrahimi   __ Sub(x2, x2, xzr);
4715*f5c631daSSadaf Ebrahimi   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob1) == 0);
4716*f5c631daSSadaf Ebrahimi 
4717*f5c631daSSadaf Ebrahimi   Label blob2;
4718*f5c631daSSadaf Ebrahimi   __ Bind(&blob2);
4719*f5c631daSSadaf Ebrahimi   __ Add(w3, w3, 0);
4720*f5c631daSSadaf Ebrahimi   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob2) != 0);
4721*f5c631daSSadaf Ebrahimi 
4722*f5c631daSSadaf Ebrahimi   Label blob3;
4723*f5c631daSSadaf Ebrahimi   __ Bind(&blob3);
4724*f5c631daSSadaf Ebrahimi   __ Sub(w3, w3, wzr);
4725*f5c631daSSadaf Ebrahimi   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob3) != 0);
4726*f5c631daSSadaf Ebrahimi 
4727*f5c631daSSadaf Ebrahimi   END();
4728*f5c631daSSadaf Ebrahimi 
4729*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4730*f5c631daSSadaf Ebrahimi     RUN();
4731*f5c631daSSadaf Ebrahimi 
4732*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x0);
4733*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x1);
4734*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x2);
4735*f5c631daSSadaf Ebrahimi   }
4736*f5c631daSSadaf Ebrahimi }
4737*f5c631daSSadaf Ebrahimi 
4738*f5c631daSSadaf Ebrahimi 
TEST(claim_drop_zero)4739*f5c631daSSadaf Ebrahimi TEST(claim_drop_zero) {
4740*f5c631daSSadaf Ebrahimi   SETUP();
4741*f5c631daSSadaf Ebrahimi 
4742*f5c631daSSadaf Ebrahimi   START();
4743*f5c631daSSadaf Ebrahimi 
4744*f5c631daSSadaf Ebrahimi   Label start;
4745*f5c631daSSadaf Ebrahimi   __ Bind(&start);
4746*f5c631daSSadaf Ebrahimi   __ Claim(Operand(0));
4747*f5c631daSSadaf Ebrahimi   __ Drop(Operand(0));
4748*f5c631daSSadaf Ebrahimi   __ Claim(Operand(xzr));
4749*f5c631daSSadaf Ebrahimi   __ Drop(Operand(xzr));
4750*f5c631daSSadaf Ebrahimi   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
4751*f5c631daSSadaf Ebrahimi 
4752*f5c631daSSadaf Ebrahimi   END();
4753*f5c631daSSadaf Ebrahimi 
4754*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4755*f5c631daSSadaf Ebrahimi     RUN();
4756*f5c631daSSadaf Ebrahimi   }
4757*f5c631daSSadaf Ebrahimi }
4758*f5c631daSSadaf Ebrahimi 
4759*f5c631daSSadaf Ebrahimi 
TEST(neg)4760*f5c631daSSadaf Ebrahimi TEST(neg) {
4761*f5c631daSSadaf Ebrahimi   SETUP();
4762*f5c631daSSadaf Ebrahimi 
4763*f5c631daSSadaf Ebrahimi   START();
4764*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xf123456789abcdef);
4765*f5c631daSSadaf Ebrahimi 
4766*f5c631daSSadaf Ebrahimi   // Immediate.
4767*f5c631daSSadaf Ebrahimi   __ Neg(x1, 0x123);
4768*f5c631daSSadaf Ebrahimi   __ Neg(w2, 0x123);
4769*f5c631daSSadaf Ebrahimi 
4770*f5c631daSSadaf Ebrahimi   // Shifted.
4771*f5c631daSSadaf Ebrahimi   __ Neg(x3, Operand(x0, LSL, 1));
4772*f5c631daSSadaf Ebrahimi   __ Neg(w4, Operand(w0, LSL, 2));
4773*f5c631daSSadaf Ebrahimi   __ Neg(x5, Operand(x0, LSR, 3));
4774*f5c631daSSadaf Ebrahimi   __ Neg(w6, Operand(w0, LSR, 4));
4775*f5c631daSSadaf Ebrahimi   __ Neg(x7, Operand(x0, ASR, 5));
4776*f5c631daSSadaf Ebrahimi   __ Neg(w8, Operand(w0, ASR, 6));
4777*f5c631daSSadaf Ebrahimi 
4778*f5c631daSSadaf Ebrahimi   // Extended.
4779*f5c631daSSadaf Ebrahimi   __ Neg(w9, Operand(w0, UXTB));
4780*f5c631daSSadaf Ebrahimi   __ Neg(x10, Operand(x0, SXTB, 1));
4781*f5c631daSSadaf Ebrahimi   __ Neg(w11, Operand(w0, UXTH, 2));
4782*f5c631daSSadaf Ebrahimi   __ Neg(x12, Operand(x0, SXTH, 3));
4783*f5c631daSSadaf Ebrahimi   __ Neg(w13, Operand(w0, UXTW, 4));
4784*f5c631daSSadaf Ebrahimi   __ Neg(x14, Operand(x0, SXTW, 4));
4785*f5c631daSSadaf Ebrahimi   END();
4786*f5c631daSSadaf Ebrahimi 
4787*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4788*f5c631daSSadaf Ebrahimi     RUN();
4789*f5c631daSSadaf Ebrahimi 
4790*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffedd, x1);
4791*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffedd, x2);
4792*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1db97530eca86422, x3);
4793*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xd950c844, x4);
4794*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xe1db97530eca8643, x5);
4795*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf7654322, x6);
4796*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0076e5d4c3b2a191, x7);
4797*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01d950c9, x8);
4798*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff11, x9);
4799*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000022, x10);
4800*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffcc844, x11);
4801*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000019088, x12);
4802*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x65432110, x13);
4803*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000765432110, x14);
4804*f5c631daSSadaf Ebrahimi   }
4805*f5c631daSSadaf Ebrahimi }
4806*f5c631daSSadaf Ebrahimi 
4807*f5c631daSSadaf Ebrahimi 
4808*f5c631daSSadaf Ebrahimi template <typename T, typename Op>
AdcsSbcsHelper(Op op,T left,T right,int carry,T expected,StatusFlags expected_flags)4809*f5c631daSSadaf Ebrahimi static void AdcsSbcsHelper(
4810*f5c631daSSadaf Ebrahimi     Op op, T left, T right, int carry, T expected, StatusFlags expected_flags) {
4811*f5c631daSSadaf Ebrahimi   int reg_size = sizeof(T) * 8;
4812*f5c631daSSadaf Ebrahimi   Register left_reg(0, reg_size);
4813*f5c631daSSadaf Ebrahimi   Register right_reg(1, reg_size);
4814*f5c631daSSadaf Ebrahimi   Register result_reg(2, reg_size);
4815*f5c631daSSadaf Ebrahimi 
4816*f5c631daSSadaf Ebrahimi   SETUP();
4817*f5c631daSSadaf Ebrahimi   START();
4818*f5c631daSSadaf Ebrahimi 
4819*f5c631daSSadaf Ebrahimi   __ Mov(left_reg, left);
4820*f5c631daSSadaf Ebrahimi   __ Mov(right_reg, right);
4821*f5c631daSSadaf Ebrahimi   __ Mov(x10, (carry ? CFlag : NoFlag));
4822*f5c631daSSadaf Ebrahimi 
4823*f5c631daSSadaf Ebrahimi   __ Msr(NZCV, x10);
4824*f5c631daSSadaf Ebrahimi   (masm.*op)(result_reg, left_reg, right_reg);
4825*f5c631daSSadaf Ebrahimi 
4826*f5c631daSSadaf Ebrahimi   END();
4827*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
4828*f5c631daSSadaf Ebrahimi     RUN();
4829*f5c631daSSadaf Ebrahimi 
4830*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(left, left_reg.X());
4831*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(right, right_reg.X());
4832*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, result_reg.X());
4833*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(expected_flags);
4834*f5c631daSSadaf Ebrahimi   }
4835*f5c631daSSadaf Ebrahimi }
4836*f5c631daSSadaf Ebrahimi 
4837*f5c631daSSadaf Ebrahimi 
TEST(adcs_sbcs_x)4838*f5c631daSSadaf Ebrahimi TEST(adcs_sbcs_x) {
4839*f5c631daSSadaf Ebrahimi   uint64_t inputs[] = {
4840*f5c631daSSadaf Ebrahimi       0x0000000000000000,
4841*f5c631daSSadaf Ebrahimi       0x0000000000000001,
4842*f5c631daSSadaf Ebrahimi       0x7ffffffffffffffe,
4843*f5c631daSSadaf Ebrahimi       0x7fffffffffffffff,
4844*f5c631daSSadaf Ebrahimi       0x8000000000000000,
4845*f5c631daSSadaf Ebrahimi       0x8000000000000001,
4846*f5c631daSSadaf Ebrahimi       0xfffffffffffffffe,
4847*f5c631daSSadaf Ebrahimi       0xffffffffffffffff,
4848*f5c631daSSadaf Ebrahimi   };
4849*f5c631daSSadaf Ebrahimi   static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]);
4850*f5c631daSSadaf Ebrahimi 
4851*f5c631daSSadaf Ebrahimi   struct Expected {
4852*f5c631daSSadaf Ebrahimi     uint64_t carry0_result;
4853*f5c631daSSadaf Ebrahimi     StatusFlags carry0_flags;
4854*f5c631daSSadaf Ebrahimi     uint64_t carry1_result;
4855*f5c631daSSadaf Ebrahimi     StatusFlags carry1_flags;
4856*f5c631daSSadaf Ebrahimi   };
4857*f5c631daSSadaf Ebrahimi 
4858*f5c631daSSadaf Ebrahimi   static const Expected expected_adcs_x[input_count][input_count] =
4859*f5c631daSSadaf Ebrahimi       {{{0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag},
4860*f5c631daSSadaf Ebrahimi         {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
4861*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
4862*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4863*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
4864*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4865*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4866*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}},
4867*f5c631daSSadaf Ebrahimi        {{0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
4868*f5c631daSSadaf Ebrahimi         {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag},
4869*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4870*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
4871*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4872*f5c631daSSadaf Ebrahimi         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
4873*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4874*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}},
4875*f5c631daSSadaf Ebrahimi        {{0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
4876*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4877*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag},
4878*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
4879*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4880*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4881*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
4882*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}},
4883*f5c631daSSadaf Ebrahimi        {{0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4884*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
4885*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
4886*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag},
4887*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4888*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4889*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4890*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}},
4891*f5c631daSSadaf Ebrahimi        {{0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
4892*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4893*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4894*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4895*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag},
4896*f5c631daSSadaf Ebrahimi         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
4897*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
4898*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}},
4899*f5c631daSSadaf Ebrahimi        {{0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4900*f5c631daSSadaf Ebrahimi         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
4901*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4902*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4903*f5c631daSSadaf Ebrahimi         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
4904*f5c631daSSadaf Ebrahimi         {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag},
4905*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4906*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}},
4907*f5c631daSSadaf Ebrahimi        {{0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4908*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4909*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
4910*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4911*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
4912*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4913*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag},
4914*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}},
4915*f5c631daSSadaf Ebrahimi        {{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4916*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4917*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4918*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
4919*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4920*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
4921*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
4922*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}}};
4923*f5c631daSSadaf Ebrahimi 
4924*f5c631daSSadaf Ebrahimi   static const Expected expected_sbcs_x[input_count][input_count] =
4925*f5c631daSSadaf Ebrahimi       {{{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4926*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4927*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4928*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NFlag, 0x8000000000000001, NFlag},
4929*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4930*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag},
4931*f5c631daSSadaf Ebrahimi         {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag},
4932*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}},
4933*f5c631daSSadaf Ebrahimi        {{0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4934*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4935*f5c631daSSadaf Ebrahimi         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
4936*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4937*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
4938*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4939*f5c631daSSadaf Ebrahimi         {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag},
4940*f5c631daSSadaf Ebrahimi         {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}},
4941*f5c631daSSadaf Ebrahimi        {{0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4942*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
4943*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4944*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4945*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
4946*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag},
4947*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag},
4948*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}},
4949*f5c631daSSadaf Ebrahimi        {{0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
4950*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4951*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4952*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4953*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag},
4954*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag},
4955*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag},
4956*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}},
4957*f5c631daSSadaf Ebrahimi        {{0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4958*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
4959*f5c631daSSadaf Ebrahimi         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
4960*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag},
4961*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4962*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag},
4963*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag},
4964*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}},
4965*f5c631daSSadaf Ebrahimi        {{0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
4966*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4967*f5c631daSSadaf Ebrahimi         {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag},
4968*f5c631daSSadaf Ebrahimi         {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag},
4969*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4970*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4971*f5c631daSSadaf Ebrahimi         {0x8000000000000002, NFlag, 0x8000000000000003, NFlag},
4972*f5c631daSSadaf Ebrahimi         {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}},
4973*f5c631daSSadaf Ebrahimi        {{0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
4974*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag},
4975*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4976*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag},
4977*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4978*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag},
4979*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag},
4980*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}},
4981*f5c631daSSadaf Ebrahimi        {{0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag},
4982*f5c631daSSadaf Ebrahimi         {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag},
4983*f5c631daSSadaf Ebrahimi         {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag},
4984*f5c631daSSadaf Ebrahimi         {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag},
4985*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag},
4986*f5c631daSSadaf Ebrahimi         {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag},
4987*f5c631daSSadaf Ebrahimi         {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag},
4988*f5c631daSSadaf Ebrahimi         {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}}};
4989*f5c631daSSadaf Ebrahimi 
4990*f5c631daSSadaf Ebrahimi   for (size_t left = 0; left < input_count; left++) {
4991*f5c631daSSadaf Ebrahimi     for (size_t right = 0; right < input_count; right++) {
4992*f5c631daSSadaf Ebrahimi       const Expected& expected = expected_adcs_x[left][right];
4993*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Adcs,
4994*f5c631daSSadaf Ebrahimi                      inputs[left],
4995*f5c631daSSadaf Ebrahimi                      inputs[right],
4996*f5c631daSSadaf Ebrahimi                      0,
4997*f5c631daSSadaf Ebrahimi                      expected.carry0_result,
4998*f5c631daSSadaf Ebrahimi                      expected.carry0_flags);
4999*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Adcs,
5000*f5c631daSSadaf Ebrahimi                      inputs[left],
5001*f5c631daSSadaf Ebrahimi                      inputs[right],
5002*f5c631daSSadaf Ebrahimi                      1,
5003*f5c631daSSadaf Ebrahimi                      expected.carry1_result,
5004*f5c631daSSadaf Ebrahimi                      expected.carry1_flags);
5005*f5c631daSSadaf Ebrahimi     }
5006*f5c631daSSadaf Ebrahimi   }
5007*f5c631daSSadaf Ebrahimi 
5008*f5c631daSSadaf Ebrahimi   for (size_t left = 0; left < input_count; left++) {
5009*f5c631daSSadaf Ebrahimi     for (size_t right = 0; right < input_count; right++) {
5010*f5c631daSSadaf Ebrahimi       const Expected& expected = expected_sbcs_x[left][right];
5011*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5012*f5c631daSSadaf Ebrahimi                      inputs[left],
5013*f5c631daSSadaf Ebrahimi                      inputs[right],
5014*f5c631daSSadaf Ebrahimi                      0,
5015*f5c631daSSadaf Ebrahimi                      expected.carry0_result,
5016*f5c631daSSadaf Ebrahimi                      expected.carry0_flags);
5017*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5018*f5c631daSSadaf Ebrahimi                      inputs[left],
5019*f5c631daSSadaf Ebrahimi                      inputs[right],
5020*f5c631daSSadaf Ebrahimi                      1,
5021*f5c631daSSadaf Ebrahimi                      expected.carry1_result,
5022*f5c631daSSadaf Ebrahimi                      expected.carry1_flags);
5023*f5c631daSSadaf Ebrahimi     }
5024*f5c631daSSadaf Ebrahimi   }
5025*f5c631daSSadaf Ebrahimi }
5026*f5c631daSSadaf Ebrahimi 
5027*f5c631daSSadaf Ebrahimi 
TEST(adcs_sbcs_w)5028*f5c631daSSadaf Ebrahimi TEST(adcs_sbcs_w) {
5029*f5c631daSSadaf Ebrahimi   uint32_t inputs[] = {
5030*f5c631daSSadaf Ebrahimi       0x00000000,
5031*f5c631daSSadaf Ebrahimi       0x00000001,
5032*f5c631daSSadaf Ebrahimi       0x7ffffffe,
5033*f5c631daSSadaf Ebrahimi       0x7fffffff,
5034*f5c631daSSadaf Ebrahimi       0x80000000,
5035*f5c631daSSadaf Ebrahimi       0x80000001,
5036*f5c631daSSadaf Ebrahimi       0xfffffffe,
5037*f5c631daSSadaf Ebrahimi       0xffffffff,
5038*f5c631daSSadaf Ebrahimi   };
5039*f5c631daSSadaf Ebrahimi   static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]);
5040*f5c631daSSadaf Ebrahimi 
5041*f5c631daSSadaf Ebrahimi   struct Expected {
5042*f5c631daSSadaf Ebrahimi     uint32_t carry0_result;
5043*f5c631daSSadaf Ebrahimi     StatusFlags carry0_flags;
5044*f5c631daSSadaf Ebrahimi     uint32_t carry1_result;
5045*f5c631daSSadaf Ebrahimi     StatusFlags carry1_flags;
5046*f5c631daSSadaf Ebrahimi   };
5047*f5c631daSSadaf Ebrahimi 
5048*f5c631daSSadaf Ebrahimi   static const Expected expected_adcs_w[input_count][input_count] =
5049*f5c631daSSadaf Ebrahimi       {{{0x00000000, ZFlag, 0x00000001, NoFlag},
5050*f5c631daSSadaf Ebrahimi         {0x00000001, NoFlag, 0x00000002, NoFlag},
5051*f5c631daSSadaf Ebrahimi         {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5052*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5053*f5c631daSSadaf Ebrahimi         {0x80000000, NFlag, 0x80000001, NFlag},
5054*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag},
5055*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5056*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag}},
5057*f5c631daSSadaf Ebrahimi        {{0x00000001, NoFlag, 0x00000002, NoFlag},
5058*f5c631daSSadaf Ebrahimi         {0x00000002, NoFlag, 0x00000003, NoFlag},
5059*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5060*f5c631daSSadaf Ebrahimi         {0x80000000, NVFlag, 0x80000001, NVFlag},
5061*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag},
5062*f5c631daSSadaf Ebrahimi         {0x80000002, NFlag, 0x80000003, NFlag},
5063*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5064*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag}},
5065*f5c631daSSadaf Ebrahimi        {{0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5066*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5067*f5c631daSSadaf Ebrahimi         {0xfffffffc, NVFlag, 0xfffffffd, NVFlag},
5068*f5c631daSSadaf Ebrahimi         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5069*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5070*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5071*f5c631daSSadaf Ebrahimi         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5072*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}},
5073*f5c631daSSadaf Ebrahimi        {{0x7fffffff, NoFlag, 0x80000000, NVFlag},
5074*f5c631daSSadaf Ebrahimi         {0x80000000, NVFlag, 0x80000001, NVFlag},
5075*f5c631daSSadaf Ebrahimi         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5076*f5c631daSSadaf Ebrahimi         {0xfffffffe, NVFlag, 0xffffffff, NVFlag},
5077*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5078*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag},
5079*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5080*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CFlag, 0x7fffffff, CFlag}},
5081*f5c631daSSadaf Ebrahimi        {{0x80000000, NFlag, 0x80000001, NFlag},
5082*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag},
5083*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5084*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5085*f5c631daSSadaf Ebrahimi         {0x00000000, ZCVFlag, 0x00000001, CVFlag},
5086*f5c631daSSadaf Ebrahimi         {0x00000001, CVFlag, 0x00000002, CVFlag},
5087*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5088*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag}},
5089*f5c631daSSadaf Ebrahimi        {{0x80000001, NFlag, 0x80000002, NFlag},
5090*f5c631daSSadaf Ebrahimi         {0x80000002, NFlag, 0x80000003, NFlag},
5091*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5092*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag},
5093*f5c631daSSadaf Ebrahimi         {0x00000001, CVFlag, 0x00000002, CVFlag},
5094*f5c631daSSadaf Ebrahimi         {0x00000002, CVFlag, 0x00000003, CVFlag},
5095*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5096*f5c631daSSadaf Ebrahimi         {0x80000000, NCFlag, 0x80000001, NCFlag}},
5097*f5c631daSSadaf Ebrahimi        {{0xfffffffe, NFlag, 0xffffffff, NFlag},
5098*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5099*f5c631daSSadaf Ebrahimi         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5100*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5101*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5102*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5103*f5c631daSSadaf Ebrahimi         {0xfffffffc, NCFlag, 0xfffffffd, NCFlag},
5104*f5c631daSSadaf Ebrahimi         {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}},
5105*f5c631daSSadaf Ebrahimi        {{0xffffffff, NFlag, 0x00000000, ZCFlag},
5106*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag},
5107*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5108*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5109*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5110*f5c631daSSadaf Ebrahimi         {0x80000000, NCFlag, 0x80000001, NCFlag},
5111*f5c631daSSadaf Ebrahimi         {0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5112*f5c631daSSadaf Ebrahimi         {0xfffffffe, NCFlag, 0xffffffff, NCFlag}}};
5113*f5c631daSSadaf Ebrahimi 
5114*f5c631daSSadaf Ebrahimi   static const Expected expected_sbcs_w[input_count][input_count] =
5115*f5c631daSSadaf Ebrahimi       {{{0xffffffff, NFlag, 0x00000000, ZCFlag},
5116*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5117*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag},
5118*f5c631daSSadaf Ebrahimi         {0x80000000, NFlag, 0x80000001, NFlag},
5119*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5120*f5c631daSSadaf Ebrahimi         {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag},
5121*f5c631daSSadaf Ebrahimi         {0x00000001, NoFlag, 0x00000002, NoFlag},
5122*f5c631daSSadaf Ebrahimi         {0x00000000, ZFlag, 0x00000001, NoFlag}},
5123*f5c631daSSadaf Ebrahimi        {{0x00000000, ZCFlag, 0x00000001, CFlag},
5124*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5125*f5c631daSSadaf Ebrahimi         {0x80000002, NFlag, 0x80000003, NFlag},
5126*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag},
5127*f5c631daSSadaf Ebrahimi         {0x80000000, NVFlag, 0x80000001, NVFlag},
5128*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5129*f5c631daSSadaf Ebrahimi         {0x00000002, NoFlag, 0x00000003, NoFlag},
5130*f5c631daSSadaf Ebrahimi         {0x00000001, NoFlag, 0x00000002, NoFlag}},
5131*f5c631daSSadaf Ebrahimi        {{0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5132*f5c631daSSadaf Ebrahimi         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5133*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5134*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5135*f5c631daSSadaf Ebrahimi         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5136*f5c631daSSadaf Ebrahimi         {0xfffffffc, NVFlag, 0xfffffffd, NVFlag},
5137*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag},
5138*f5c631daSSadaf Ebrahimi         {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}},
5139*f5c631daSSadaf Ebrahimi        {{0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5140*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5141*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag},
5142*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5143*f5c631daSSadaf Ebrahimi         {0xfffffffe, NVFlag, 0xffffffff, NVFlag},
5144*f5c631daSSadaf Ebrahimi         {0xfffffffd, NVFlag, 0xfffffffe, NVFlag},
5145*f5c631daSSadaf Ebrahimi         {0x80000000, NVFlag, 0x80000001, NVFlag},
5146*f5c631daSSadaf Ebrahimi         {0x7fffffff, NoFlag, 0x80000000, NVFlag}},
5147*f5c631daSSadaf Ebrahimi        {{0x7fffffff, CVFlag, 0x80000000, NCFlag},
5148*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5149*f5c631daSSadaf Ebrahimi         {0x00000001, CVFlag, 0x00000002, CVFlag},
5150*f5c631daSSadaf Ebrahimi         {0x00000000, ZCVFlag, 0x00000001, CVFlag},
5151*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5152*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag},
5153*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag},
5154*f5c631daSSadaf Ebrahimi         {0x80000000, NFlag, 0x80000001, NFlag}},
5155*f5c631daSSadaf Ebrahimi        {{0x80000000, NCFlag, 0x80000001, NCFlag},
5156*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5157*f5c631daSSadaf Ebrahimi         {0x00000002, CVFlag, 0x00000003, CVFlag},
5158*f5c631daSSadaf Ebrahimi         {0x00000001, CVFlag, 0x00000002, CVFlag},
5159*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag},
5160*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5161*f5c631daSSadaf Ebrahimi         {0x80000002, NFlag, 0x80000003, NFlag},
5162*f5c631daSSadaf Ebrahimi         {0x80000001, NFlag, 0x80000002, NFlag}},
5163*f5c631daSSadaf Ebrahimi        {{0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5164*f5c631daSSadaf Ebrahimi         {0xfffffffc, NCFlag, 0xfffffffd, NCFlag},
5165*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5166*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag},
5167*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5168*f5c631daSSadaf Ebrahimi         {0x7ffffffc, CFlag, 0x7ffffffd, CFlag},
5169*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag},
5170*f5c631daSSadaf Ebrahimi         {0xfffffffe, NFlag, 0xffffffff, NFlag}},
5171*f5c631daSSadaf Ebrahimi        {{0xfffffffe, NCFlag, 0xffffffff, NCFlag},
5172*f5c631daSSadaf Ebrahimi         {0xfffffffd, NCFlag, 0xfffffffe, NCFlag},
5173*f5c631daSSadaf Ebrahimi         {0x80000000, NCFlag, 0x80000001, NCFlag},
5174*f5c631daSSadaf Ebrahimi         {0x7fffffff, CVFlag, 0x80000000, NCFlag},
5175*f5c631daSSadaf Ebrahimi         {0x7ffffffe, CFlag, 0x7fffffff, CFlag},
5176*f5c631daSSadaf Ebrahimi         {0x7ffffffd, CFlag, 0x7ffffffe, CFlag},
5177*f5c631daSSadaf Ebrahimi         {0x00000000, ZCFlag, 0x00000001, CFlag},
5178*f5c631daSSadaf Ebrahimi         {0xffffffff, NFlag, 0x00000000, ZCFlag}}};
5179*f5c631daSSadaf Ebrahimi 
5180*f5c631daSSadaf Ebrahimi   for (size_t left = 0; left < input_count; left++) {
5181*f5c631daSSadaf Ebrahimi     for (size_t right = 0; right < input_count; right++) {
5182*f5c631daSSadaf Ebrahimi       const Expected& expected = expected_adcs_w[left][right];
5183*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Adcs,
5184*f5c631daSSadaf Ebrahimi                      inputs[left],
5185*f5c631daSSadaf Ebrahimi                      inputs[right],
5186*f5c631daSSadaf Ebrahimi                      0,
5187*f5c631daSSadaf Ebrahimi                      expected.carry0_result,
5188*f5c631daSSadaf Ebrahimi                      expected.carry0_flags);
5189*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Adcs,
5190*f5c631daSSadaf Ebrahimi                      inputs[left],
5191*f5c631daSSadaf Ebrahimi                      inputs[right],
5192*f5c631daSSadaf Ebrahimi                      1,
5193*f5c631daSSadaf Ebrahimi                      expected.carry1_result,
5194*f5c631daSSadaf Ebrahimi                      expected.carry1_flags);
5195*f5c631daSSadaf Ebrahimi     }
5196*f5c631daSSadaf Ebrahimi   }
5197*f5c631daSSadaf Ebrahimi 
5198*f5c631daSSadaf Ebrahimi   for (size_t left = 0; left < input_count; left++) {
5199*f5c631daSSadaf Ebrahimi     for (size_t right = 0; right < input_count; right++) {
5200*f5c631daSSadaf Ebrahimi       const Expected& expected = expected_sbcs_w[left][right];
5201*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5202*f5c631daSSadaf Ebrahimi                      inputs[left],
5203*f5c631daSSadaf Ebrahimi                      inputs[right],
5204*f5c631daSSadaf Ebrahimi                      0,
5205*f5c631daSSadaf Ebrahimi                      expected.carry0_result,
5206*f5c631daSSadaf Ebrahimi                      expected.carry0_flags);
5207*f5c631daSSadaf Ebrahimi       AdcsSbcsHelper(&MacroAssembler::Sbcs,
5208*f5c631daSSadaf Ebrahimi                      inputs[left],
5209*f5c631daSSadaf Ebrahimi                      inputs[right],
5210*f5c631daSSadaf Ebrahimi                      1,
5211*f5c631daSSadaf Ebrahimi                      expected.carry1_result,
5212*f5c631daSSadaf Ebrahimi                      expected.carry1_flags);
5213*f5c631daSSadaf Ebrahimi     }
5214*f5c631daSSadaf Ebrahimi   }
5215*f5c631daSSadaf Ebrahimi }
5216*f5c631daSSadaf Ebrahimi 
5217*f5c631daSSadaf Ebrahimi 
TEST(adc_sbc_shift)5218*f5c631daSSadaf Ebrahimi TEST(adc_sbc_shift) {
5219*f5c631daSSadaf Ebrahimi   SETUP();
5220*f5c631daSSadaf Ebrahimi 
5221*f5c631daSSadaf Ebrahimi   START();
5222*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
5223*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
5224*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x0123456789abcdef);
5225*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xfedcba9876543210);
5226*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0xffffffffffffffff);
5227*f5c631daSSadaf Ebrahimi 
5228*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5229*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5230*f5c631daSSadaf Ebrahimi 
5231*f5c631daSSadaf Ebrahimi   __ Adc(x5, x2, Operand(x3));
5232*f5c631daSSadaf Ebrahimi   __ Adc(x6, x0, Operand(x1, LSL, 60));
5233*f5c631daSSadaf Ebrahimi   __ Sbc(x7, x4, Operand(x3, LSR, 4));
5234*f5c631daSSadaf Ebrahimi   __ Adc(x8, x2, Operand(x3, ASR, 4));
5235*f5c631daSSadaf Ebrahimi   __ Adc(x9, x2, Operand(x3, ROR, 8));
5236*f5c631daSSadaf Ebrahimi 
5237*f5c631daSSadaf Ebrahimi   __ Adc(w10, w2, Operand(w3));
5238*f5c631daSSadaf Ebrahimi   __ Adc(w11, w0, Operand(w1, LSL, 30));
5239*f5c631daSSadaf Ebrahimi   __ Sbc(w12, w4, Operand(w3, LSR, 4));
5240*f5c631daSSadaf Ebrahimi   __ Adc(w13, w2, Operand(w3, ASR, 4));
5241*f5c631daSSadaf Ebrahimi   __ Adc(w14, w2, Operand(w3, ROR, 8));
5242*f5c631daSSadaf Ebrahimi 
5243*f5c631daSSadaf Ebrahimi   // Set the C flag.
5244*f5c631daSSadaf Ebrahimi   __ Cmp(w0, Operand(w0));
5245*f5c631daSSadaf Ebrahimi 
5246*f5c631daSSadaf Ebrahimi   __ Adc(x18, x2, Operand(x3));
5247*f5c631daSSadaf Ebrahimi   __ Adc(x19, x0, Operand(x1, LSL, 60));
5248*f5c631daSSadaf Ebrahimi   __ Sbc(x20, x4, Operand(x3, LSR, 4));
5249*f5c631daSSadaf Ebrahimi   __ Adc(x21, x2, Operand(x3, ASR, 4));
5250*f5c631daSSadaf Ebrahimi   __ Adc(x22, x2, Operand(x3, ROR, 8));
5251*f5c631daSSadaf Ebrahimi 
5252*f5c631daSSadaf Ebrahimi   __ Adc(w23, w2, Operand(w3));
5253*f5c631daSSadaf Ebrahimi   __ Adc(w24, w0, Operand(w1, LSL, 30));
5254*f5c631daSSadaf Ebrahimi   __ Sbc(w25, w4, Operand(w3, LSR, 4));
5255*f5c631daSSadaf Ebrahimi   __ Adc(w26, w2, Operand(w3, ASR, 4));
5256*f5c631daSSadaf Ebrahimi   __ Adc(w27, w2, Operand(w3, ROR, 8));
5257*f5c631daSSadaf Ebrahimi   END();
5258*f5c631daSSadaf Ebrahimi 
5259*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5260*f5c631daSSadaf Ebrahimi     RUN();
5261*f5c631daSSadaf Ebrahimi 
5262*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x5);
5263*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(1) << 60, x6);
5264*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf0123456789abcdd, x7);
5265*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0111111111111110, x8);
5266*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1222222222222221, x9);
5267*f5c631daSSadaf Ebrahimi 
5268*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffff, w10);
5269*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(INT32_C(1) << 30, w11);
5270*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xf89abcdd, w12);
5271*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x91111110, w13);
5272*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x9a222221, w14);
5273*f5c631daSSadaf Ebrahimi 
5274*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff + 1, x18);
5275*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((INT64_C(1) << 60) + 1, x19);
5276*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf0123456789abcdd + 1, x20);
5277*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0111111111111110 + 1, x21);
5278*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1222222222222221 + 1, x22);
5279*f5c631daSSadaf Ebrahimi 
5280*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffff + 1, w23);
5281*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, w24);
5282*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xf89abcdd + 1, w25);
5283*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x91111110 + 1, w26);
5284*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x9a222221 + 1, w27);
5285*f5c631daSSadaf Ebrahimi   }
5286*f5c631daSSadaf Ebrahimi }
5287*f5c631daSSadaf Ebrahimi 
5288*f5c631daSSadaf Ebrahimi 
TEST(adc_sbc_extend)5289*f5c631daSSadaf Ebrahimi TEST(adc_sbc_extend) {
5290*f5c631daSSadaf Ebrahimi   SETUP();
5291*f5c631daSSadaf Ebrahimi 
5292*f5c631daSSadaf Ebrahimi   START();
5293*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5294*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5295*f5c631daSSadaf Ebrahimi 
5296*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
5297*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
5298*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x0123456789abcdef);
5299*f5c631daSSadaf Ebrahimi 
5300*f5c631daSSadaf Ebrahimi   __ Adc(x10, x1, Operand(w2, UXTB, 1));
5301*f5c631daSSadaf Ebrahimi   __ Adc(x11, x1, Operand(x2, SXTH, 2));
5302*f5c631daSSadaf Ebrahimi   __ Sbc(x12, x1, Operand(w2, UXTW, 4));
5303*f5c631daSSadaf Ebrahimi   __ Adc(x13, x1, Operand(x2, UXTX, 4));
5304*f5c631daSSadaf Ebrahimi 
5305*f5c631daSSadaf Ebrahimi   __ Adc(w14, w1, Operand(w2, UXTB, 1));
5306*f5c631daSSadaf Ebrahimi   __ Adc(w15, w1, Operand(w2, SXTH, 2));
5307*f5c631daSSadaf Ebrahimi   __ Adc(w9, w1, Operand(w2, UXTW, 4));
5308*f5c631daSSadaf Ebrahimi 
5309*f5c631daSSadaf Ebrahimi   // Set the C flag.
5310*f5c631daSSadaf Ebrahimi   __ Cmp(w0, Operand(w0));
5311*f5c631daSSadaf Ebrahimi 
5312*f5c631daSSadaf Ebrahimi   __ Adc(x20, x1, Operand(w2, UXTB, 1));
5313*f5c631daSSadaf Ebrahimi   __ Adc(x21, x1, Operand(x2, SXTH, 2));
5314*f5c631daSSadaf Ebrahimi   __ Sbc(x22, x1, Operand(w2, UXTW, 4));
5315*f5c631daSSadaf Ebrahimi   __ Adc(x23, x1, Operand(x2, UXTX, 4));
5316*f5c631daSSadaf Ebrahimi 
5317*f5c631daSSadaf Ebrahimi   __ Adc(w24, w1, Operand(w2, UXTB, 1));
5318*f5c631daSSadaf Ebrahimi   __ Adc(w25, w1, Operand(w2, SXTH, 2));
5319*f5c631daSSadaf Ebrahimi   __ Adc(w26, w1, Operand(w2, UXTW, 4));
5320*f5c631daSSadaf Ebrahimi   END();
5321*f5c631daSSadaf Ebrahimi 
5322*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5323*f5c631daSSadaf Ebrahimi     RUN();
5324*f5c631daSSadaf Ebrahimi 
5325*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1df, x10);
5326*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff37bd, x11);
5327*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff765432110, x12);
5328*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, x13);
5329*f5c631daSSadaf Ebrahimi 
5330*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1df, w14);
5331*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffff37bd, w15);
5332*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x9abcdef1, w9);
5333*f5c631daSSadaf Ebrahimi 
5334*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1df + 1, x20);
5335*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff37bd + 1, x21);
5336*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff765432110 + 1, x22);
5337*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1 + 1, x23);
5338*f5c631daSSadaf Ebrahimi 
5339*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1df + 1, w24);
5340*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffff37bd + 1, w25);
5341*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x9abcdef1 + 1, w26);
5342*f5c631daSSadaf Ebrahimi   }
5343*f5c631daSSadaf Ebrahimi 
5344*f5c631daSSadaf Ebrahimi   // Check that adc correctly sets the condition flags.
5345*f5c631daSSadaf Ebrahimi   START();
5346*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xff);
5347*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xffffffffffffffff);
5348*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5349*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5350*f5c631daSSadaf Ebrahimi   __ Adcs(x10, x0, Operand(x1, SXTX, 1));
5351*f5c631daSSadaf Ebrahimi   END();
5352*f5c631daSSadaf Ebrahimi 
5353*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5354*f5c631daSSadaf Ebrahimi     RUN();
5355*f5c631daSSadaf Ebrahimi 
5356*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(CFlag);
5357*f5c631daSSadaf Ebrahimi   }
5358*f5c631daSSadaf Ebrahimi 
5359*f5c631daSSadaf Ebrahimi   START();
5360*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x7fffffffffffffff);
5361*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
5362*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5363*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5364*f5c631daSSadaf Ebrahimi   __ Adcs(x10, x0, Operand(x1, UXTB, 2));
5365*f5c631daSSadaf Ebrahimi   END();
5366*f5c631daSSadaf Ebrahimi 
5367*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5368*f5c631daSSadaf Ebrahimi     RUN();
5369*f5c631daSSadaf Ebrahimi 
5370*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NVFlag);
5371*f5c631daSSadaf Ebrahimi   }
5372*f5c631daSSadaf Ebrahimi 
5373*f5c631daSSadaf Ebrahimi   START();
5374*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x7fffffffffffffff);
5375*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5376*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5377*f5c631daSSadaf Ebrahimi   __ Adcs(x10, x0, Operand(1));
5378*f5c631daSSadaf Ebrahimi   END();
5379*f5c631daSSadaf Ebrahimi 
5380*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5381*f5c631daSSadaf Ebrahimi     RUN();
5382*f5c631daSSadaf Ebrahimi 
5383*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NVFlag);
5384*f5c631daSSadaf Ebrahimi   }
5385*f5c631daSSadaf Ebrahimi }
5386*f5c631daSSadaf Ebrahimi 
5387*f5c631daSSadaf Ebrahimi 
TEST(adc_sbc_wide_imm)5388*f5c631daSSadaf Ebrahimi TEST(adc_sbc_wide_imm) {
5389*f5c631daSSadaf Ebrahimi   SETUP();
5390*f5c631daSSadaf Ebrahimi 
5391*f5c631daSSadaf Ebrahimi   START();
5392*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
5393*f5c631daSSadaf Ebrahimi 
5394*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5395*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5396*f5c631daSSadaf Ebrahimi 
5397*f5c631daSSadaf Ebrahimi   __ Adc(x7, x0, Operand(0x1234567890abcdef));
5398*f5c631daSSadaf Ebrahimi   __ Adc(w8, w0, Operand(0xffffffff));
5399*f5c631daSSadaf Ebrahimi   __ Sbc(x9, x0, Operand(0x1234567890abcdef));
5400*f5c631daSSadaf Ebrahimi   __ Sbc(w10, w0, Operand(0xffffffff));
5401*f5c631daSSadaf Ebrahimi   __ Ngc(x11, Operand(0xffffffff00000000));
5402*f5c631daSSadaf Ebrahimi   __ Ngc(w12, Operand(0xffff0000));
5403*f5c631daSSadaf Ebrahimi 
5404*f5c631daSSadaf Ebrahimi   // Set the C flag.
5405*f5c631daSSadaf Ebrahimi   __ Cmp(w0, Operand(w0));
5406*f5c631daSSadaf Ebrahimi 
5407*f5c631daSSadaf Ebrahimi   __ Adc(x18, x0, Operand(0x1234567890abcdef));
5408*f5c631daSSadaf Ebrahimi   __ Adc(w19, w0, Operand(0xffffffff));
5409*f5c631daSSadaf Ebrahimi   __ Sbc(x20, x0, Operand(0x1234567890abcdef));
5410*f5c631daSSadaf Ebrahimi   __ Sbc(w21, w0, Operand(0xffffffff));
5411*f5c631daSSadaf Ebrahimi   __ Ngc(x22, Operand(0xffffffff00000000));
5412*f5c631daSSadaf Ebrahimi   __ Ngc(w23, Operand(0xffff0000));
5413*f5c631daSSadaf Ebrahimi   END();
5414*f5c631daSSadaf Ebrahimi 
5415*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5416*f5c631daSSadaf Ebrahimi     RUN();
5417*f5c631daSSadaf Ebrahimi 
5418*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef, x7);
5419*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x8);
5420*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xedcba9876f543210, x9);
5421*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x10);
5422*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x11);
5423*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff, x12);
5424*f5c631daSSadaf Ebrahimi 
5425*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1234567890abcdef + 1, x18);
5426*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x19);
5427*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xedcba9876f543211, x20);
5428*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x21);
5429*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000100000000, x22);
5430*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000010000, x23);
5431*f5c631daSSadaf Ebrahimi   }
5432*f5c631daSSadaf Ebrahimi }
5433*f5c631daSSadaf Ebrahimi 
5434*f5c631daSSadaf Ebrahimi 
TEST(rmif)5435*f5c631daSSadaf Ebrahimi TEST(rmif) {
5436*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
5437*f5c631daSSadaf Ebrahimi 
5438*f5c631daSSadaf Ebrahimi   START();
5439*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0123456789abcdef);
5440*f5c631daSSadaf Ebrahimi 
5441*f5c631daSSadaf Ebrahimi   // Set NZCV to 0b1011 (0xb)
5442*f5c631daSSadaf Ebrahimi   __ Rmif(x0, 0, NCVFlag);
5443*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
5444*f5c631daSSadaf Ebrahimi 
5445*f5c631daSSadaf Ebrahimi   // Set NZCV to 0b0111 (0x7)
5446*f5c631daSSadaf Ebrahimi   __ Rmif(x0, 6, NZCVFlag);
5447*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
5448*f5c631daSSadaf Ebrahimi 
5449*f5c631daSSadaf Ebrahimi   // Set Z to 0, NZCV = 0b0011 (0x3)
5450*f5c631daSSadaf Ebrahimi   __ Rmif(x0, 60, ZFlag);
5451*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
5452*f5c631daSSadaf Ebrahimi 
5453*f5c631daSSadaf Ebrahimi   // Set N to 1 and C to 0, NZCV = 0b1001 (0x9)
5454*f5c631daSSadaf Ebrahimi   __ Rmif(x0, 62, NCFlag);
5455*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
5456*f5c631daSSadaf Ebrahimi 
5457*f5c631daSSadaf Ebrahimi   // No change to NZCV
5458*f5c631daSSadaf Ebrahimi   __ Rmif(x0, 0, NoFlag);
5459*f5c631daSSadaf Ebrahimi   __ Mrs(x5, NZCV);
5460*f5c631daSSadaf Ebrahimi   END();
5461*f5c631daSSadaf Ebrahimi 
5462*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5463*f5c631daSSadaf Ebrahimi     RUN();
5464*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NCVFlag, w1);
5465*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCVFlag, w2);
5466*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(CVFlag, w3);
5467*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NVFlag, w4);
5468*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NVFlag, w5);
5469*f5c631daSSadaf Ebrahimi   }
5470*f5c631daSSadaf Ebrahimi }
5471*f5c631daSSadaf Ebrahimi 
5472*f5c631daSSadaf Ebrahimi 
TEST(setf8_setf16)5473*f5c631daSSadaf Ebrahimi TEST(setf8_setf16) {
5474*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
5475*f5c631daSSadaf Ebrahimi 
5476*f5c631daSSadaf Ebrahimi   START();
5477*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
5478*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1);
5479*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xff);
5480*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0x100);
5481*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x101);
5482*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xffff);
5483*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x10000);
5484*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0x10001);
5485*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0xfffffffff);
5486*f5c631daSSadaf Ebrahimi 
5487*f5c631daSSadaf Ebrahimi   __ Setf8(w0);
5488*f5c631daSSadaf Ebrahimi   __ Mrs(x9, NZCV);
5489*f5c631daSSadaf Ebrahimi   __ Setf8(w1);
5490*f5c631daSSadaf Ebrahimi   __ Mrs(x10, NZCV);
5491*f5c631daSSadaf Ebrahimi   __ Setf8(w2);
5492*f5c631daSSadaf Ebrahimi   __ Mrs(x11, NZCV);
5493*f5c631daSSadaf Ebrahimi   __ Setf8(w3);
5494*f5c631daSSadaf Ebrahimi   __ Mrs(x12, NZCV);
5495*f5c631daSSadaf Ebrahimi   __ Setf8(w4);
5496*f5c631daSSadaf Ebrahimi   __ Mrs(x13, NZCV);
5497*f5c631daSSadaf Ebrahimi   __ Setf8(w8);
5498*f5c631daSSadaf Ebrahimi   __ Mrs(x14, NZCV);
5499*f5c631daSSadaf Ebrahimi 
5500*f5c631daSSadaf Ebrahimi   __ Setf16(w0);
5501*f5c631daSSadaf Ebrahimi   __ Mrs(x15, NZCV);
5502*f5c631daSSadaf Ebrahimi   __ Setf16(w1);
5503*f5c631daSSadaf Ebrahimi   __ Mrs(x16, NZCV);
5504*f5c631daSSadaf Ebrahimi   __ Setf16(w5);
5505*f5c631daSSadaf Ebrahimi   __ Mrs(x17, NZCV);
5506*f5c631daSSadaf Ebrahimi   __ Setf16(w6);
5507*f5c631daSSadaf Ebrahimi   __ Mrs(x18, NZCV);
5508*f5c631daSSadaf Ebrahimi   __ Setf16(w7);
5509*f5c631daSSadaf Ebrahimi   __ Mrs(x19, NZCV);
5510*f5c631daSSadaf Ebrahimi   __ Setf16(w8);
5511*f5c631daSSadaf Ebrahimi   __ Mrs(x20, NZCV);
5512*f5c631daSSadaf Ebrahimi   END();
5513*f5c631daSSadaf Ebrahimi 
5514*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5515*f5c631daSSadaf Ebrahimi     RUN();
5516*f5c631daSSadaf Ebrahimi 
5517*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZFlag, w9);    // Zero
5518*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NoFlag, w10);  // Regular int8
5519*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NVFlag, w11);  // Negative but not sign-extended (overflow)
5520*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZVFlag, w12);  // Overflow with zero remainder
5521*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(VFlag, w13);   // Overflow with non-zero remainder
5522*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NFlag, w14);   // Negative and sign-extended
5523*f5c631daSSadaf Ebrahimi 
5524*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZFlag, w15);   // Zero
5525*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NoFlag, w16);  // Regular int16
5526*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NVFlag, w17);  // Negative but not sign-extended (overflow)
5527*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZVFlag, w18);  // Overflow with zero remainder
5528*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(VFlag, w19);   // Overflow with non-zero remainder
5529*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NFlag, w20);   // Negative and sign-extended
5530*f5c631daSSadaf Ebrahimi   }
5531*f5c631daSSadaf Ebrahimi }
5532*f5c631daSSadaf Ebrahimi 
5533*f5c631daSSadaf Ebrahimi 
TEST(flags)5534*f5c631daSSadaf Ebrahimi TEST(flags) {
5535*f5c631daSSadaf Ebrahimi   SETUP();
5536*f5c631daSSadaf Ebrahimi 
5537*f5c631daSSadaf Ebrahimi   START();
5538*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
5539*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1111111111111111);
5540*f5c631daSSadaf Ebrahimi   __ Neg(x10, Operand(x0));
5541*f5c631daSSadaf Ebrahimi   __ Neg(x11, Operand(x1));
5542*f5c631daSSadaf Ebrahimi   __ Neg(w12, Operand(w1));
5543*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5544*f5c631daSSadaf Ebrahimi   __ Adds(x0, x0, Operand(0));
5545*f5c631daSSadaf Ebrahimi   __ Ngc(x13, Operand(x0));
5546*f5c631daSSadaf Ebrahimi   // Set the C flag.
5547*f5c631daSSadaf Ebrahimi   __ Cmp(x0, Operand(x0));
5548*f5c631daSSadaf Ebrahimi   __ Ngc(w14, Operand(w0));
5549*f5c631daSSadaf Ebrahimi   END();
5550*f5c631daSSadaf Ebrahimi 
5551*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5552*f5c631daSSadaf Ebrahimi     RUN();
5553*f5c631daSSadaf Ebrahimi 
5554*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x10);
5555*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-0x1111111111111111, x11);
5556*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(-0x11111111, w12);
5557*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-1, x13);
5558*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w14);
5559*f5c631daSSadaf Ebrahimi   }
5560*f5c631daSSadaf Ebrahimi 
5561*f5c631daSSadaf Ebrahimi   START();
5562*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
5563*f5c631daSSadaf Ebrahimi   __ Cmp(x0, Operand(x0));
5564*f5c631daSSadaf Ebrahimi   END();
5565*f5c631daSSadaf Ebrahimi 
5566*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5567*f5c631daSSadaf Ebrahimi     RUN();
5568*f5c631daSSadaf Ebrahimi 
5569*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
5570*f5c631daSSadaf Ebrahimi   }
5571*f5c631daSSadaf Ebrahimi 
5572*f5c631daSSadaf Ebrahimi   START();
5573*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
5574*f5c631daSSadaf Ebrahimi   __ Cmp(w0, Operand(w0));
5575*f5c631daSSadaf Ebrahimi   END();
5576*f5c631daSSadaf Ebrahimi 
5577*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5578*f5c631daSSadaf Ebrahimi     RUN();
5579*f5c631daSSadaf Ebrahimi 
5580*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
5581*f5c631daSSadaf Ebrahimi   }
5582*f5c631daSSadaf Ebrahimi 
5583*f5c631daSSadaf Ebrahimi   START();
5584*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
5585*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1111111111111111);
5586*f5c631daSSadaf Ebrahimi   __ Cmp(x0, Operand(x1));
5587*f5c631daSSadaf Ebrahimi   END();
5588*f5c631daSSadaf Ebrahimi 
5589*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5590*f5c631daSSadaf Ebrahimi     RUN();
5591*f5c631daSSadaf Ebrahimi 
5592*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
5593*f5c631daSSadaf Ebrahimi   }
5594*f5c631daSSadaf Ebrahimi 
5595*f5c631daSSadaf Ebrahimi   START();
5596*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
5597*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x11111111);
5598*f5c631daSSadaf Ebrahimi   __ Cmp(w0, Operand(w1));
5599*f5c631daSSadaf Ebrahimi   END();
5600*f5c631daSSadaf Ebrahimi 
5601*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5602*f5c631daSSadaf Ebrahimi     RUN();
5603*f5c631daSSadaf Ebrahimi 
5604*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
5605*f5c631daSSadaf Ebrahimi   }
5606*f5c631daSSadaf Ebrahimi 
5607*f5c631daSSadaf Ebrahimi   START();
5608*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1111111111111111);
5609*f5c631daSSadaf Ebrahimi   __ Cmp(x1, Operand(0));
5610*f5c631daSSadaf Ebrahimi   END();
5611*f5c631daSSadaf Ebrahimi 
5612*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5613*f5c631daSSadaf Ebrahimi     RUN();
5614*f5c631daSSadaf Ebrahimi 
5615*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(CFlag);
5616*f5c631daSSadaf Ebrahimi   }
5617*f5c631daSSadaf Ebrahimi 
5618*f5c631daSSadaf Ebrahimi   START();
5619*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x11111111);
5620*f5c631daSSadaf Ebrahimi   __ Cmp(w1, Operand(0));
5621*f5c631daSSadaf Ebrahimi   END();
5622*f5c631daSSadaf Ebrahimi 
5623*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5624*f5c631daSSadaf Ebrahimi     RUN();
5625*f5c631daSSadaf Ebrahimi 
5626*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(CFlag);
5627*f5c631daSSadaf Ebrahimi   }
5628*f5c631daSSadaf Ebrahimi 
5629*f5c631daSSadaf Ebrahimi   START();
5630*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
5631*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x7fffffffffffffff);
5632*f5c631daSSadaf Ebrahimi   __ Cmn(x1, Operand(x0));
5633*f5c631daSSadaf Ebrahimi   END();
5634*f5c631daSSadaf Ebrahimi 
5635*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5636*f5c631daSSadaf Ebrahimi     RUN();
5637*f5c631daSSadaf Ebrahimi 
5638*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NVFlag);
5639*f5c631daSSadaf Ebrahimi   }
5640*f5c631daSSadaf Ebrahimi 
5641*f5c631daSSadaf Ebrahimi   START();
5642*f5c631daSSadaf Ebrahimi   __ Mov(w0, 1);
5643*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x7fffffff);
5644*f5c631daSSadaf Ebrahimi   __ Cmn(w1, Operand(w0));
5645*f5c631daSSadaf Ebrahimi   END();
5646*f5c631daSSadaf Ebrahimi 
5647*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5648*f5c631daSSadaf Ebrahimi     RUN();
5649*f5c631daSSadaf Ebrahimi 
5650*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NVFlag);
5651*f5c631daSSadaf Ebrahimi   }
5652*f5c631daSSadaf Ebrahimi 
5653*f5c631daSSadaf Ebrahimi   START();
5654*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
5655*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xffffffffffffffff);
5656*f5c631daSSadaf Ebrahimi   __ Cmn(x1, Operand(x0));
5657*f5c631daSSadaf Ebrahimi   END();
5658*f5c631daSSadaf Ebrahimi 
5659*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5660*f5c631daSSadaf Ebrahimi     RUN();
5661*f5c631daSSadaf Ebrahimi 
5662*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
5663*f5c631daSSadaf Ebrahimi   }
5664*f5c631daSSadaf Ebrahimi 
5665*f5c631daSSadaf Ebrahimi   START();
5666*f5c631daSSadaf Ebrahimi   __ Mov(w0, 1);
5667*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0xffffffff);
5668*f5c631daSSadaf Ebrahimi   __ Cmn(w1, Operand(w0));
5669*f5c631daSSadaf Ebrahimi   END();
5670*f5c631daSSadaf Ebrahimi 
5671*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5672*f5c631daSSadaf Ebrahimi     RUN();
5673*f5c631daSSadaf Ebrahimi 
5674*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
5675*f5c631daSSadaf Ebrahimi   }
5676*f5c631daSSadaf Ebrahimi 
5677*f5c631daSSadaf Ebrahimi   START();
5678*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
5679*f5c631daSSadaf Ebrahimi   __ Mov(w1, 1);
5680*f5c631daSSadaf Ebrahimi   // Clear the C flag.
5681*f5c631daSSadaf Ebrahimi   __ Adds(w0, w0, Operand(0));
5682*f5c631daSSadaf Ebrahimi   __ Ngcs(w0, Operand(w1));
5683*f5c631daSSadaf Ebrahimi   END();
5684*f5c631daSSadaf Ebrahimi 
5685*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5686*f5c631daSSadaf Ebrahimi     RUN();
5687*f5c631daSSadaf Ebrahimi 
5688*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(NFlag);
5689*f5c631daSSadaf Ebrahimi   }
5690*f5c631daSSadaf Ebrahimi 
5691*f5c631daSSadaf Ebrahimi   START();
5692*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
5693*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
5694*f5c631daSSadaf Ebrahimi   // Set the C flag.
5695*f5c631daSSadaf Ebrahimi   __ Cmp(w0, Operand(w0));
5696*f5c631daSSadaf Ebrahimi   __ Ngcs(w0, Operand(w1));
5697*f5c631daSSadaf Ebrahimi   END();
5698*f5c631daSSadaf Ebrahimi 
5699*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5700*f5c631daSSadaf Ebrahimi     RUN();
5701*f5c631daSSadaf Ebrahimi 
5702*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
5703*f5c631daSSadaf Ebrahimi   }
5704*f5c631daSSadaf Ebrahimi }
5705*f5c631daSSadaf Ebrahimi 
5706*f5c631daSSadaf Ebrahimi 
TEST(cmp_shift)5707*f5c631daSSadaf Ebrahimi TEST(cmp_shift) {
5708*f5c631daSSadaf Ebrahimi   SETUP();
5709*f5c631daSSadaf Ebrahimi 
5710*f5c631daSSadaf Ebrahimi   START();
5711*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0xf0000000);
5712*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0xf000000010000000);
5713*f5c631daSSadaf Ebrahimi   __ Mov(x20, 0xf0000000f0000000);
5714*f5c631daSSadaf Ebrahimi   __ Mov(x21, 0x7800000078000000);
5715*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0x3c0000003c000000);
5716*f5c631daSSadaf Ebrahimi   __ Mov(x23, 0x8000000780000000);
5717*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0x0000000f00000000);
5718*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0x00000003c0000000);
5719*f5c631daSSadaf Ebrahimi   __ Mov(x26, 0x8000000780000000);
5720*f5c631daSSadaf Ebrahimi   __ Mov(x27, 0xc0000003);
5721*f5c631daSSadaf Ebrahimi 
5722*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w21, LSL, 1));
5723*f5c631daSSadaf Ebrahimi   __ Mrs(x0, NZCV);
5724*f5c631daSSadaf Ebrahimi 
5725*f5c631daSSadaf Ebrahimi   __ Cmp(x20, Operand(x22, LSL, 2));
5726*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
5727*f5c631daSSadaf Ebrahimi 
5728*f5c631daSSadaf Ebrahimi   __ Cmp(w19, Operand(w23, LSR, 3));
5729*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
5730*f5c631daSSadaf Ebrahimi 
5731*f5c631daSSadaf Ebrahimi   __ Cmp(x18, Operand(x24, LSR, 4));
5732*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
5733*f5c631daSSadaf Ebrahimi 
5734*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w25, ASR, 2));
5735*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
5736*f5c631daSSadaf Ebrahimi 
5737*f5c631daSSadaf Ebrahimi   __ Cmp(x20, Operand(x26, ASR, 3));
5738*f5c631daSSadaf Ebrahimi   __ Mrs(x5, NZCV);
5739*f5c631daSSadaf Ebrahimi 
5740*f5c631daSSadaf Ebrahimi   __ Cmp(w27, Operand(w22, ROR, 28));
5741*f5c631daSSadaf Ebrahimi   __ Mrs(x6, NZCV);
5742*f5c631daSSadaf Ebrahimi 
5743*f5c631daSSadaf Ebrahimi   __ Cmp(x20, Operand(x21, ROR, 31));
5744*f5c631daSSadaf Ebrahimi   __ Mrs(x7, NZCV);
5745*f5c631daSSadaf Ebrahimi   END();
5746*f5c631daSSadaf Ebrahimi 
5747*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5748*f5c631daSSadaf Ebrahimi     RUN();
5749*f5c631daSSadaf Ebrahimi 
5750*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w0);
5751*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w1);
5752*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w2);
5753*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w3);
5754*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w4);
5755*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w5);
5756*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w6);
5757*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w7);
5758*f5c631daSSadaf Ebrahimi   }
5759*f5c631daSSadaf Ebrahimi }
5760*f5c631daSSadaf Ebrahimi 
5761*f5c631daSSadaf Ebrahimi 
TEST(cmp_extend)5762*f5c631daSSadaf Ebrahimi TEST(cmp_extend) {
5763*f5c631daSSadaf Ebrahimi   SETUP();
5764*f5c631daSSadaf Ebrahimi 
5765*f5c631daSSadaf Ebrahimi   START();
5766*f5c631daSSadaf Ebrahimi   __ Mov(w20, 0x2);
5767*f5c631daSSadaf Ebrahimi   __ Mov(w21, 0x1);
5768*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0xffffffffffffffff);
5769*f5c631daSSadaf Ebrahimi   __ Mov(x23, 0xff);
5770*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0xfffffffffffffffe);
5771*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0xffff);
5772*f5c631daSSadaf Ebrahimi   __ Mov(x26, 0xffffffff);
5773*f5c631daSSadaf Ebrahimi 
5774*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w21, LSL, 1));
5775*f5c631daSSadaf Ebrahimi   __ Mrs(x0, NZCV);
5776*f5c631daSSadaf Ebrahimi 
5777*f5c631daSSadaf Ebrahimi   __ Cmp(x22, Operand(x23, SXTB, 0));
5778*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
5779*f5c631daSSadaf Ebrahimi 
5780*f5c631daSSadaf Ebrahimi   __ Cmp(x24, Operand(x23, SXTB, 1));
5781*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
5782*f5c631daSSadaf Ebrahimi 
5783*f5c631daSSadaf Ebrahimi   __ Cmp(x24, Operand(x23, UXTB, 1));
5784*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
5785*f5c631daSSadaf Ebrahimi 
5786*f5c631daSSadaf Ebrahimi   __ Cmp(w22, Operand(w25, UXTH));
5787*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
5788*f5c631daSSadaf Ebrahimi 
5789*f5c631daSSadaf Ebrahimi   __ Cmp(x22, Operand(x25, SXTH));
5790*f5c631daSSadaf Ebrahimi   __ Mrs(x5, NZCV);
5791*f5c631daSSadaf Ebrahimi 
5792*f5c631daSSadaf Ebrahimi   __ Cmp(x22, Operand(x26, UXTW));
5793*f5c631daSSadaf Ebrahimi   __ Mrs(x6, NZCV);
5794*f5c631daSSadaf Ebrahimi 
5795*f5c631daSSadaf Ebrahimi   __ Cmp(x24, Operand(x26, SXTW, 1));
5796*f5c631daSSadaf Ebrahimi   __ Mrs(x7, NZCV);
5797*f5c631daSSadaf Ebrahimi   END();
5798*f5c631daSSadaf Ebrahimi 
5799*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5800*f5c631daSSadaf Ebrahimi     RUN();
5801*f5c631daSSadaf Ebrahimi 
5802*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w0);
5803*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w1);
5804*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w2);
5805*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NCFlag, w3);
5806*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NCFlag, w4);
5807*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w5);
5808*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NCFlag, w6);
5809*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w7);
5810*f5c631daSSadaf Ebrahimi   }
5811*f5c631daSSadaf Ebrahimi }
5812*f5c631daSSadaf Ebrahimi 
5813*f5c631daSSadaf Ebrahimi 
TEST(ccmp)5814*f5c631daSSadaf Ebrahimi TEST(ccmp) {
5815*f5c631daSSadaf Ebrahimi   SETUP();
5816*f5c631daSSadaf Ebrahimi 
5817*f5c631daSSadaf Ebrahimi   START();
5818*f5c631daSSadaf Ebrahimi   __ Mov(w16, 0);
5819*f5c631daSSadaf Ebrahimi   __ Mov(w17, 1);
5820*f5c631daSSadaf Ebrahimi   __ Cmp(w16, w16);
5821*f5c631daSSadaf Ebrahimi   __ Ccmp(w16, w17, NCFlag, eq);
5822*f5c631daSSadaf Ebrahimi   __ Mrs(x0, NZCV);
5823*f5c631daSSadaf Ebrahimi 
5824*f5c631daSSadaf Ebrahimi   __ Cmp(w16, w16);
5825*f5c631daSSadaf Ebrahimi   __ Ccmp(w16, w17, NCFlag, ne);
5826*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
5827*f5c631daSSadaf Ebrahimi 
5828*f5c631daSSadaf Ebrahimi   __ Cmp(x16, x16);
5829*f5c631daSSadaf Ebrahimi   __ Ccmn(x16, 2, NZCVFlag, eq);
5830*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
5831*f5c631daSSadaf Ebrahimi 
5832*f5c631daSSadaf Ebrahimi   __ Cmp(x16, x16);
5833*f5c631daSSadaf Ebrahimi   __ Ccmn(x16, 2, NZCVFlag, ne);
5834*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
5835*f5c631daSSadaf Ebrahimi 
5836*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow al as a condition.
5837*f5c631daSSadaf Ebrahimi   {
5838*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
5839*f5c631daSSadaf Ebrahimi     __ ccmp(x16, x16, NZCVFlag, al);
5840*f5c631daSSadaf Ebrahimi   }
5841*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
5842*f5c631daSSadaf Ebrahimi 
5843*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow nv as a condition.
5844*f5c631daSSadaf Ebrahimi   {
5845*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
5846*f5c631daSSadaf Ebrahimi     __ ccmp(x16, x16, NZCVFlag, nv);
5847*f5c631daSSadaf Ebrahimi   }
5848*f5c631daSSadaf Ebrahimi   __ Mrs(x5, NZCV);
5849*f5c631daSSadaf Ebrahimi 
5850*f5c631daSSadaf Ebrahimi   END();
5851*f5c631daSSadaf Ebrahimi 
5852*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5853*f5c631daSSadaf Ebrahimi     RUN();
5854*f5c631daSSadaf Ebrahimi 
5855*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NFlag, w0);
5856*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NCFlag, w1);
5857*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NoFlag, w2);
5858*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NZCVFlag, w3);
5859*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w4);
5860*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w5);
5861*f5c631daSSadaf Ebrahimi   }
5862*f5c631daSSadaf Ebrahimi }
5863*f5c631daSSadaf Ebrahimi 
5864*f5c631daSSadaf Ebrahimi 
TEST(ccmp_wide_imm)5865*f5c631daSSadaf Ebrahimi TEST(ccmp_wide_imm) {
5866*f5c631daSSadaf Ebrahimi   SETUP();
5867*f5c631daSSadaf Ebrahimi 
5868*f5c631daSSadaf Ebrahimi   START();
5869*f5c631daSSadaf Ebrahimi   __ Mov(w20, 0);
5870*f5c631daSSadaf Ebrahimi 
5871*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5872*f5c631daSSadaf Ebrahimi   __ Ccmp(w20, Operand(0x12345678), NZCVFlag, eq);
5873*f5c631daSSadaf Ebrahimi   __ Mrs(x0, NZCV);
5874*f5c631daSSadaf Ebrahimi 
5875*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5876*f5c631daSSadaf Ebrahimi   __ Ccmp(x20, Operand(0xffffffffffffffff), NZCVFlag, eq);
5877*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
5878*f5c631daSSadaf Ebrahimi   END();
5879*f5c631daSSadaf Ebrahimi 
5880*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5881*f5c631daSSadaf Ebrahimi     RUN();
5882*f5c631daSSadaf Ebrahimi 
5883*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NFlag, w0);
5884*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NoFlag, w1);
5885*f5c631daSSadaf Ebrahimi   }
5886*f5c631daSSadaf Ebrahimi }
5887*f5c631daSSadaf Ebrahimi 
5888*f5c631daSSadaf Ebrahimi 
TEST(ccmp_shift_extend)5889*f5c631daSSadaf Ebrahimi TEST(ccmp_shift_extend) {
5890*f5c631daSSadaf Ebrahimi   SETUP();
5891*f5c631daSSadaf Ebrahimi 
5892*f5c631daSSadaf Ebrahimi   START();
5893*f5c631daSSadaf Ebrahimi   __ Mov(w20, 0x2);
5894*f5c631daSSadaf Ebrahimi   __ Mov(w21, 0x1);
5895*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0xffffffffffffffff);
5896*f5c631daSSadaf Ebrahimi   __ Mov(x23, 0xff);
5897*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0xfffffffffffffffe);
5898*f5c631daSSadaf Ebrahimi 
5899*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5900*f5c631daSSadaf Ebrahimi   __ Ccmp(w20, Operand(w21, LSL, 1), NZCVFlag, eq);
5901*f5c631daSSadaf Ebrahimi   __ Mrs(x0, NZCV);
5902*f5c631daSSadaf Ebrahimi 
5903*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5904*f5c631daSSadaf Ebrahimi   __ Ccmp(x22, Operand(x23, SXTB, 0), NZCVFlag, eq);
5905*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
5906*f5c631daSSadaf Ebrahimi 
5907*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5908*f5c631daSSadaf Ebrahimi   __ Ccmp(x24, Operand(x23, SXTB, 1), NZCVFlag, eq);
5909*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
5910*f5c631daSSadaf Ebrahimi 
5911*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5912*f5c631daSSadaf Ebrahimi   __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, eq);
5913*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
5914*f5c631daSSadaf Ebrahimi 
5915*f5c631daSSadaf Ebrahimi   __ Cmp(w20, Operand(w20));
5916*f5c631daSSadaf Ebrahimi   __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, ne);
5917*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
5918*f5c631daSSadaf Ebrahimi   END();
5919*f5c631daSSadaf Ebrahimi 
5920*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5921*f5c631daSSadaf Ebrahimi     RUN();
5922*f5c631daSSadaf Ebrahimi 
5923*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w0);
5924*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w1);
5925*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w2);
5926*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NCFlag, w3);
5927*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NZCVFlag, w4);
5928*f5c631daSSadaf Ebrahimi   }
5929*f5c631daSSadaf Ebrahimi }
5930*f5c631daSSadaf Ebrahimi 
5931*f5c631daSSadaf Ebrahimi 
TEST(csel_reg)5932*f5c631daSSadaf Ebrahimi TEST(csel_reg) {
5933*f5c631daSSadaf Ebrahimi   SETUP();
5934*f5c631daSSadaf Ebrahimi 
5935*f5c631daSSadaf Ebrahimi   START();
5936*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0);
5937*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0x0000000f0000000f);
5938*f5c631daSSadaf Ebrahimi   __ Mov(x25, 0x0000001f0000001f);
5939*f5c631daSSadaf Ebrahimi 
5940*f5c631daSSadaf Ebrahimi   __ Cmp(w16, Operand(0));
5941*f5c631daSSadaf Ebrahimi   __ Csel(w0, w24, w25, eq);
5942*f5c631daSSadaf Ebrahimi   __ Csel(w1, w24, w25, ne);
5943*f5c631daSSadaf Ebrahimi   __ Csinc(w2, w24, w25, mi);
5944*f5c631daSSadaf Ebrahimi   __ Csinc(w3, w24, w25, pl);
5945*f5c631daSSadaf Ebrahimi 
5946*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow al or nv as a condition.
5947*f5c631daSSadaf Ebrahimi   {
5948*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
5949*f5c631daSSadaf Ebrahimi     __ csel(w13, w24, w25, al);
5950*f5c631daSSadaf Ebrahimi     __ csel(x14, x24, x25, nv);
5951*f5c631daSSadaf Ebrahimi   }
5952*f5c631daSSadaf Ebrahimi 
5953*f5c631daSSadaf Ebrahimi   __ Cmp(x16, Operand(1));
5954*f5c631daSSadaf Ebrahimi   __ Csinv(x4, x24, x25, gt);
5955*f5c631daSSadaf Ebrahimi   __ Csinv(x5, x24, x25, le);
5956*f5c631daSSadaf Ebrahimi   __ Csneg(x6, x24, x25, hs);
5957*f5c631daSSadaf Ebrahimi   __ Csneg(x7, x24, x25, lo);
5958*f5c631daSSadaf Ebrahimi 
5959*f5c631daSSadaf Ebrahimi   __ Cset(w8, ne);
5960*f5c631daSSadaf Ebrahimi   __ Csetm(w9, ne);
5961*f5c631daSSadaf Ebrahimi   __ Cinc(x10, x25, ne);
5962*f5c631daSSadaf Ebrahimi   __ Cinv(x11, x24, ne);
5963*f5c631daSSadaf Ebrahimi   __ Cneg(x12, x24, ne);
5964*f5c631daSSadaf Ebrahimi 
5965*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow al or nv as a condition.
5966*f5c631daSSadaf Ebrahimi   {
5967*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
5968*f5c631daSSadaf Ebrahimi     __ csel(w15, w24, w25, al);
5969*f5c631daSSadaf Ebrahimi     __ csel(x17, x24, x25, nv);
5970*f5c631daSSadaf Ebrahimi   }
5971*f5c631daSSadaf Ebrahimi 
5972*f5c631daSSadaf Ebrahimi   END();
5973*f5c631daSSadaf Ebrahimi 
5974*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
5975*f5c631daSSadaf Ebrahimi     RUN();
5976*f5c631daSSadaf Ebrahimi 
5977*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f, x0);
5978*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000001f, x1);
5979*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000020, x2);
5980*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f, x3);
5981*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffe0ffffffe0, x4);
5982*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f0000000f, x5);
5983*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffe0ffffffe1, x6);
5984*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f0000000f, x7);
5985*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001, x8);
5986*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff, x9);
5987*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000001f00000020, x10);
5988*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff0fffffff0, x11);
5989*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff0fffffff1, x12);
5990*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f, x13);
5991*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f0000000f, x14);
5992*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f, x15);
5993*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000f0000000f, x17);
5994*f5c631daSSadaf Ebrahimi   }
5995*f5c631daSSadaf Ebrahimi }
5996*f5c631daSSadaf Ebrahimi 
TEST(csel_zero)5997*f5c631daSSadaf Ebrahimi TEST(csel_zero) {
5998*f5c631daSSadaf Ebrahimi   SETUP();
5999*f5c631daSSadaf Ebrahimi 
6000*f5c631daSSadaf Ebrahimi   START();
6001*f5c631daSSadaf Ebrahimi 
6002*f5c631daSSadaf Ebrahimi   __ Mov(x15, 0x0);
6003*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0x0000001f0000002f);
6004*f5c631daSSadaf Ebrahimi 
6005*f5c631daSSadaf Ebrahimi   // Check results when zero registers are used as inputs
6006*f5c631daSSadaf Ebrahimi   // for Csinc, Csinv and Csneg for both true and false conditions.
6007*f5c631daSSadaf Ebrahimi   __ Cmp(x15, 0);
6008*f5c631daSSadaf Ebrahimi   __ Csinc(x0, x16, xzr, eq);
6009*f5c631daSSadaf Ebrahimi   __ Csinc(x1, xzr, x16, eq);
6010*f5c631daSSadaf Ebrahimi   __ Cmp(x15, 1);
6011*f5c631daSSadaf Ebrahimi   __ Csinc(w2, w16, wzr, eq);
6012*f5c631daSSadaf Ebrahimi   __ Csinc(w3, wzr, w16, eq);
6013*f5c631daSSadaf Ebrahimi 
6014*f5c631daSSadaf Ebrahimi   __ Csinc(x4, xzr, xzr, eq);
6015*f5c631daSSadaf Ebrahimi 
6016*f5c631daSSadaf Ebrahimi   __ Cmp(x15, 0);
6017*f5c631daSSadaf Ebrahimi   __ Csinv(x5, x16, xzr, eq);
6018*f5c631daSSadaf Ebrahimi   __ Csinv(x6, xzr, x16, eq);
6019*f5c631daSSadaf Ebrahimi   __ Cmp(x15, 1);
6020*f5c631daSSadaf Ebrahimi   __ Csinv(w7, w16, wzr, eq);
6021*f5c631daSSadaf Ebrahimi   __ Csinv(w8, wzr, w16, eq);
6022*f5c631daSSadaf Ebrahimi 
6023*f5c631daSSadaf Ebrahimi   __ Csinv(x9, xzr, xzr, eq);
6024*f5c631daSSadaf Ebrahimi 
6025*f5c631daSSadaf Ebrahimi   __ Cmp(x15, 0);
6026*f5c631daSSadaf Ebrahimi   __ Csneg(x10, x16, xzr, eq);
6027*f5c631daSSadaf Ebrahimi   __ Csneg(x11, xzr, x16, eq);
6028*f5c631daSSadaf Ebrahimi   __ Cmp(x15, 1);
6029*f5c631daSSadaf Ebrahimi   __ Csneg(w12, w16, wzr, eq);
6030*f5c631daSSadaf Ebrahimi   __ Csneg(w13, wzr, w16, eq);
6031*f5c631daSSadaf Ebrahimi 
6032*f5c631daSSadaf Ebrahimi   __ Csneg(x14, xzr, xzr, eq);
6033*f5c631daSSadaf Ebrahimi 
6034*f5c631daSSadaf Ebrahimi   END();
6035*f5c631daSSadaf Ebrahimi 
6036*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6037*f5c631daSSadaf Ebrahimi     RUN();
6038*f5c631daSSadaf Ebrahimi 
6039*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000001f0000002f, x0);
6040*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x1);
6041*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1, w2);
6042*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x30, w3);
6043*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1, x4);
6044*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000001f0000002f, x5);
6045*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x6);
6046*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffff, w7);
6047*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffd0, w8);
6048*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, x9);
6049*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000001f0000002f, x10);
6050*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x11);
6051*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x0, w12);
6052*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffd1, w13);
6053*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x14);
6054*f5c631daSSadaf Ebrahimi   }
6055*f5c631daSSadaf Ebrahimi }
6056*f5c631daSSadaf Ebrahimi 
6057*f5c631daSSadaf Ebrahimi 
TEST(csel_imm)6058*f5c631daSSadaf Ebrahimi TEST(csel_imm) {
6059*f5c631daSSadaf Ebrahimi   SETUP();
6060*f5c631daSSadaf Ebrahimi 
6061*f5c631daSSadaf Ebrahimi   int values[] = {-123, -2, -1, 0, 1, 2, 123};
6062*f5c631daSSadaf Ebrahimi   int n_values = sizeof(values) / sizeof(values[0]);
6063*f5c631daSSadaf Ebrahimi 
6064*f5c631daSSadaf Ebrahimi   for (int i = 0; i < n_values; i++) {
6065*f5c631daSSadaf Ebrahimi     for (int j = 0; j < n_values; j++) {
6066*f5c631daSSadaf Ebrahimi       int left = values[i];
6067*f5c631daSSadaf Ebrahimi       int right = values[j];
6068*f5c631daSSadaf Ebrahimi 
6069*f5c631daSSadaf Ebrahimi       START();
6070*f5c631daSSadaf Ebrahimi       __ Mov(x10, 0);
6071*f5c631daSSadaf Ebrahimi       __ Cmp(x10, 0);
6072*f5c631daSSadaf Ebrahimi       __ Csel(w0, left, right, eq);
6073*f5c631daSSadaf Ebrahimi       __ Csel(w1, left, right, ne);
6074*f5c631daSSadaf Ebrahimi       __ Csel(x2, left, right, eq);
6075*f5c631daSSadaf Ebrahimi       __ Csel(x3, left, right, ne);
6076*f5c631daSSadaf Ebrahimi 
6077*f5c631daSSadaf Ebrahimi       END();
6078*f5c631daSSadaf Ebrahimi 
6079*f5c631daSSadaf Ebrahimi       if (CAN_RUN()) {
6080*f5c631daSSadaf Ebrahimi         RUN();
6081*f5c631daSSadaf Ebrahimi 
6082*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_32(left, w0);
6083*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_32(right, w1);
6084*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(left, x2);
6085*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(right, x3);
6086*f5c631daSSadaf Ebrahimi       }
6087*f5c631daSSadaf Ebrahimi     }
6088*f5c631daSSadaf Ebrahimi   }
6089*f5c631daSSadaf Ebrahimi }
6090*f5c631daSSadaf Ebrahimi 
6091*f5c631daSSadaf Ebrahimi 
TEST(csel_mixed)6092*f5c631daSSadaf Ebrahimi TEST(csel_mixed) {
6093*f5c631daSSadaf Ebrahimi   SETUP();
6094*f5c631daSSadaf Ebrahimi 
6095*f5c631daSSadaf Ebrahimi   START();
6096*f5c631daSSadaf Ebrahimi   __ Mov(x18, 0);
6097*f5c631daSSadaf Ebrahimi   __ Mov(x19, 0x80000000);
6098*f5c631daSSadaf Ebrahimi   __ Mov(x20, 0x8000000000000000);
6099*f5c631daSSadaf Ebrahimi 
6100*f5c631daSSadaf Ebrahimi   __ Cmp(x18, Operand(0));
6101*f5c631daSSadaf Ebrahimi   __ Csel(w0, w19, -2, ne);
6102*f5c631daSSadaf Ebrahimi   __ Csel(w1, w19, -1, ne);
6103*f5c631daSSadaf Ebrahimi   __ Csel(w2, w19, 0, ne);
6104*f5c631daSSadaf Ebrahimi   __ Csel(w3, w19, 1, ne);
6105*f5c631daSSadaf Ebrahimi   __ Csel(w4, w19, 2, ne);
6106*f5c631daSSadaf Ebrahimi   __ Csel(w5, w19, Operand(w19, ASR, 31), ne);
6107*f5c631daSSadaf Ebrahimi   __ Csel(w6, w19, Operand(w19, ROR, 1), ne);
6108*f5c631daSSadaf Ebrahimi   __ Csel(w7, w19, 3, eq);
6109*f5c631daSSadaf Ebrahimi 
6110*f5c631daSSadaf Ebrahimi   __ Csel(x8, x20, -2, ne);
6111*f5c631daSSadaf Ebrahimi   __ Csel(x9, x20, -1, ne);
6112*f5c631daSSadaf Ebrahimi   __ Csel(x10, x20, 0, ne);
6113*f5c631daSSadaf Ebrahimi   __ Csel(x11, x20, 1, ne);
6114*f5c631daSSadaf Ebrahimi   __ Csel(x12, x20, 2, ne);
6115*f5c631daSSadaf Ebrahimi   __ Csel(x13, x20, Operand(x20, ASR, 63), ne);
6116*f5c631daSSadaf Ebrahimi   __ Csel(x14, x20, Operand(x20, ROR, 1), ne);
6117*f5c631daSSadaf Ebrahimi   __ Csel(x15, x20, 3, eq);
6118*f5c631daSSadaf Ebrahimi 
6119*f5c631daSSadaf Ebrahimi   END();
6120*f5c631daSSadaf Ebrahimi 
6121*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6122*f5c631daSSadaf Ebrahimi     RUN();
6123*f5c631daSSadaf Ebrahimi 
6124*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(-2, w0);
6125*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(-1, w1);
6126*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w2);
6127*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(1, w3);
6128*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(2, w4);
6129*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(-1, w5);
6130*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x40000000, w6);
6131*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x80000000, w7);
6132*f5c631daSSadaf Ebrahimi 
6133*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-2, x8);
6134*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-1, x9);
6135*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x10);
6136*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x11);
6137*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x12);
6138*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(-1, x13);
6139*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4000000000000000, x14);
6140*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8000000000000000, x15);
6141*f5c631daSSadaf Ebrahimi   }
6142*f5c631daSSadaf Ebrahimi }
6143*f5c631daSSadaf Ebrahimi 
6144*f5c631daSSadaf Ebrahimi 
TEST(lslv)6145*f5c631daSSadaf Ebrahimi TEST(lslv) {
6146*f5c631daSSadaf Ebrahimi   SETUP();
6147*f5c631daSSadaf Ebrahimi 
6148*f5c631daSSadaf Ebrahimi   uint64_t value = 0x0123456789abcdef;
6149*f5c631daSSadaf Ebrahimi   int shift[] = {1, 3, 5, 9, 17, 33};
6150*f5c631daSSadaf Ebrahimi 
6151*f5c631daSSadaf Ebrahimi   START();
6152*f5c631daSSadaf Ebrahimi   __ Mov(x0, value);
6153*f5c631daSSadaf Ebrahimi   __ Mov(w1, shift[0]);
6154*f5c631daSSadaf Ebrahimi   __ Mov(w2, shift[1]);
6155*f5c631daSSadaf Ebrahimi   __ Mov(w3, shift[2]);
6156*f5c631daSSadaf Ebrahimi   __ Mov(w4, shift[3]);
6157*f5c631daSSadaf Ebrahimi   __ Mov(w5, shift[4]);
6158*f5c631daSSadaf Ebrahimi   __ Mov(w6, shift[5]);
6159*f5c631daSSadaf Ebrahimi 
6160*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow zr as an argument.
6161*f5c631daSSadaf Ebrahimi   {
6162*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
6163*f5c631daSSadaf Ebrahimi     __ lslv(x0, x0, xzr);
6164*f5c631daSSadaf Ebrahimi   }
6165*f5c631daSSadaf Ebrahimi 
6166*f5c631daSSadaf Ebrahimi   __ Lsl(x16, x0, x1);
6167*f5c631daSSadaf Ebrahimi   __ Lsl(x17, x0, x2);
6168*f5c631daSSadaf Ebrahimi   __ Lsl(x18, x0, x3);
6169*f5c631daSSadaf Ebrahimi   __ Lsl(x19, x0, x4);
6170*f5c631daSSadaf Ebrahimi   __ Lsl(x20, x0, x5);
6171*f5c631daSSadaf Ebrahimi   __ Lsl(x21, x0, x6);
6172*f5c631daSSadaf Ebrahimi 
6173*f5c631daSSadaf Ebrahimi   __ Lsl(w22, w0, w1);
6174*f5c631daSSadaf Ebrahimi   __ Lsl(w23, w0, w2);
6175*f5c631daSSadaf Ebrahimi   __ Lsl(w24, w0, w3);
6176*f5c631daSSadaf Ebrahimi   __ Lsl(w25, w0, w4);
6177*f5c631daSSadaf Ebrahimi   __ Lsl(w26, w0, w5);
6178*f5c631daSSadaf Ebrahimi   __ Lsl(w27, w0, w6);
6179*f5c631daSSadaf Ebrahimi   END();
6180*f5c631daSSadaf Ebrahimi 
6181*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6182*f5c631daSSadaf Ebrahimi     RUN();
6183*f5c631daSSadaf Ebrahimi 
6184*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value, x0);
6185*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value << (shift[0] & 63), x16);
6186*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value << (shift[1] & 63), x17);
6187*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value << (shift[2] & 63), x18);
6188*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value << (shift[3] & 63), x19);
6189*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value << (shift[4] & 63), x20);
6190*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value << (shift[5] & 63), x21);
6191*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value << (shift[0] & 31), w22);
6192*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value << (shift[1] & 31), w23);
6193*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value << (shift[2] & 31), w24);
6194*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value << (shift[3] & 31), w25);
6195*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value << (shift[4] & 31), w26);
6196*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value << (shift[5] & 31), w27);
6197*f5c631daSSadaf Ebrahimi   }
6198*f5c631daSSadaf Ebrahimi }
6199*f5c631daSSadaf Ebrahimi 
6200*f5c631daSSadaf Ebrahimi 
TEST(lsrv)6201*f5c631daSSadaf Ebrahimi TEST(lsrv) {
6202*f5c631daSSadaf Ebrahimi   SETUP();
6203*f5c631daSSadaf Ebrahimi 
6204*f5c631daSSadaf Ebrahimi   uint64_t value = 0x0123456789abcdef;
6205*f5c631daSSadaf Ebrahimi   int shift[] = {1, 3, 5, 9, 17, 33};
6206*f5c631daSSadaf Ebrahimi 
6207*f5c631daSSadaf Ebrahimi   START();
6208*f5c631daSSadaf Ebrahimi   __ Mov(x0, value);
6209*f5c631daSSadaf Ebrahimi   __ Mov(w1, shift[0]);
6210*f5c631daSSadaf Ebrahimi   __ Mov(w2, shift[1]);
6211*f5c631daSSadaf Ebrahimi   __ Mov(w3, shift[2]);
6212*f5c631daSSadaf Ebrahimi   __ Mov(w4, shift[3]);
6213*f5c631daSSadaf Ebrahimi   __ Mov(w5, shift[4]);
6214*f5c631daSSadaf Ebrahimi   __ Mov(w6, shift[5]);
6215*f5c631daSSadaf Ebrahimi 
6216*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow zr as an argument.
6217*f5c631daSSadaf Ebrahimi   {
6218*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
6219*f5c631daSSadaf Ebrahimi     __ lsrv(x0, x0, xzr);
6220*f5c631daSSadaf Ebrahimi   }
6221*f5c631daSSadaf Ebrahimi 
6222*f5c631daSSadaf Ebrahimi   __ Lsr(x16, x0, x1);
6223*f5c631daSSadaf Ebrahimi   __ Lsr(x17, x0, x2);
6224*f5c631daSSadaf Ebrahimi   __ Lsr(x18, x0, x3);
6225*f5c631daSSadaf Ebrahimi   __ Lsr(x19, x0, x4);
6226*f5c631daSSadaf Ebrahimi   __ Lsr(x20, x0, x5);
6227*f5c631daSSadaf Ebrahimi   __ Lsr(x21, x0, x6);
6228*f5c631daSSadaf Ebrahimi 
6229*f5c631daSSadaf Ebrahimi   __ Lsr(w22, w0, w1);
6230*f5c631daSSadaf Ebrahimi   __ Lsr(w23, w0, w2);
6231*f5c631daSSadaf Ebrahimi   __ Lsr(w24, w0, w3);
6232*f5c631daSSadaf Ebrahimi   __ Lsr(w25, w0, w4);
6233*f5c631daSSadaf Ebrahimi   __ Lsr(w26, w0, w5);
6234*f5c631daSSadaf Ebrahimi   __ Lsr(w27, w0, w6);
6235*f5c631daSSadaf Ebrahimi   END();
6236*f5c631daSSadaf Ebrahimi 
6237*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6238*f5c631daSSadaf Ebrahimi     RUN();
6239*f5c631daSSadaf Ebrahimi 
6240*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value, x0);
6241*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
6242*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
6243*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
6244*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
6245*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
6246*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
6247*f5c631daSSadaf Ebrahimi 
6248*f5c631daSSadaf Ebrahimi     value &= 0xffffffff;
6249*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value >> (shift[0] & 31), w22);
6250*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value >> (shift[1] & 31), w23);
6251*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value >> (shift[2] & 31), w24);
6252*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value >> (shift[3] & 31), w25);
6253*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value >> (shift[4] & 31), w26);
6254*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value >> (shift[5] & 31), w27);
6255*f5c631daSSadaf Ebrahimi   }
6256*f5c631daSSadaf Ebrahimi }
6257*f5c631daSSadaf Ebrahimi 
6258*f5c631daSSadaf Ebrahimi 
TEST(asrv)6259*f5c631daSSadaf Ebrahimi TEST(asrv) {
6260*f5c631daSSadaf Ebrahimi   SETUP();
6261*f5c631daSSadaf Ebrahimi 
6262*f5c631daSSadaf Ebrahimi   int64_t value = 0xfedcba98fedcba98;
6263*f5c631daSSadaf Ebrahimi   int shift[] = {1, 3, 5, 9, 17, 33};
6264*f5c631daSSadaf Ebrahimi 
6265*f5c631daSSadaf Ebrahimi   START();
6266*f5c631daSSadaf Ebrahimi   __ Mov(x0, value);
6267*f5c631daSSadaf Ebrahimi   __ Mov(w1, shift[0]);
6268*f5c631daSSadaf Ebrahimi   __ Mov(w2, shift[1]);
6269*f5c631daSSadaf Ebrahimi   __ Mov(w3, shift[2]);
6270*f5c631daSSadaf Ebrahimi   __ Mov(w4, shift[3]);
6271*f5c631daSSadaf Ebrahimi   __ Mov(w5, shift[4]);
6272*f5c631daSSadaf Ebrahimi   __ Mov(w6, shift[5]);
6273*f5c631daSSadaf Ebrahimi 
6274*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow zr as an argument.
6275*f5c631daSSadaf Ebrahimi   {
6276*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
6277*f5c631daSSadaf Ebrahimi     __ asrv(x0, x0, xzr);
6278*f5c631daSSadaf Ebrahimi   }
6279*f5c631daSSadaf Ebrahimi 
6280*f5c631daSSadaf Ebrahimi   __ Asr(x16, x0, x1);
6281*f5c631daSSadaf Ebrahimi   __ Asr(x17, x0, x2);
6282*f5c631daSSadaf Ebrahimi   __ Asr(x18, x0, x3);
6283*f5c631daSSadaf Ebrahimi   __ Asr(x19, x0, x4);
6284*f5c631daSSadaf Ebrahimi   __ Asr(x20, x0, x5);
6285*f5c631daSSadaf Ebrahimi   __ Asr(x21, x0, x6);
6286*f5c631daSSadaf Ebrahimi 
6287*f5c631daSSadaf Ebrahimi   __ Asr(w22, w0, w1);
6288*f5c631daSSadaf Ebrahimi   __ Asr(w23, w0, w2);
6289*f5c631daSSadaf Ebrahimi   __ Asr(w24, w0, w3);
6290*f5c631daSSadaf Ebrahimi   __ Asr(w25, w0, w4);
6291*f5c631daSSadaf Ebrahimi   __ Asr(w26, w0, w5);
6292*f5c631daSSadaf Ebrahimi   __ Asr(w27, w0, w6);
6293*f5c631daSSadaf Ebrahimi   END();
6294*f5c631daSSadaf Ebrahimi 
6295*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6296*f5c631daSSadaf Ebrahimi     RUN();
6297*f5c631daSSadaf Ebrahimi 
6298*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value, x0);
6299*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
6300*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
6301*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
6302*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
6303*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
6304*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
6305*f5c631daSSadaf Ebrahimi 
6306*f5c631daSSadaf Ebrahimi     int32_t value32 = static_cast<int32_t>(value & 0xffffffff);
6307*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value32 >> (shift[0] & 31), w22);
6308*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value32 >> (shift[1] & 31), w23);
6309*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value32 >> (shift[2] & 31), w24);
6310*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value32 >> (shift[3] & 31), w25);
6311*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value32 >> (shift[4] & 31), w26);
6312*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(value32 >> (shift[5] & 31), w27);
6313*f5c631daSSadaf Ebrahimi   }
6314*f5c631daSSadaf Ebrahimi }
6315*f5c631daSSadaf Ebrahimi 
6316*f5c631daSSadaf Ebrahimi 
TEST(rorv)6317*f5c631daSSadaf Ebrahimi TEST(rorv) {
6318*f5c631daSSadaf Ebrahimi   SETUP();
6319*f5c631daSSadaf Ebrahimi 
6320*f5c631daSSadaf Ebrahimi   uint64_t value = 0x0123456789abcdef;
6321*f5c631daSSadaf Ebrahimi   int shift[] = {4, 8, 12, 16, 24, 36};
6322*f5c631daSSadaf Ebrahimi 
6323*f5c631daSSadaf Ebrahimi   START();
6324*f5c631daSSadaf Ebrahimi   __ Mov(x0, value);
6325*f5c631daSSadaf Ebrahimi   __ Mov(w1, shift[0]);
6326*f5c631daSSadaf Ebrahimi   __ Mov(w2, shift[1]);
6327*f5c631daSSadaf Ebrahimi   __ Mov(w3, shift[2]);
6328*f5c631daSSadaf Ebrahimi   __ Mov(w4, shift[3]);
6329*f5c631daSSadaf Ebrahimi   __ Mov(w5, shift[4]);
6330*f5c631daSSadaf Ebrahimi   __ Mov(w6, shift[5]);
6331*f5c631daSSadaf Ebrahimi 
6332*f5c631daSSadaf Ebrahimi   // The MacroAssembler does not allow zr as an argument.
6333*f5c631daSSadaf Ebrahimi   {
6334*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize);
6335*f5c631daSSadaf Ebrahimi     __ rorv(x0, x0, xzr);
6336*f5c631daSSadaf Ebrahimi   }
6337*f5c631daSSadaf Ebrahimi 
6338*f5c631daSSadaf Ebrahimi   __ Ror(x16, x0, x1);
6339*f5c631daSSadaf Ebrahimi   __ Ror(x17, x0, x2);
6340*f5c631daSSadaf Ebrahimi   __ Ror(x18, x0, x3);
6341*f5c631daSSadaf Ebrahimi   __ Ror(x19, x0, x4);
6342*f5c631daSSadaf Ebrahimi   __ Ror(x20, x0, x5);
6343*f5c631daSSadaf Ebrahimi   __ Ror(x21, x0, x6);
6344*f5c631daSSadaf Ebrahimi 
6345*f5c631daSSadaf Ebrahimi   __ Ror(w22, w0, w1);
6346*f5c631daSSadaf Ebrahimi   __ Ror(w23, w0, w2);
6347*f5c631daSSadaf Ebrahimi   __ Ror(w24, w0, w3);
6348*f5c631daSSadaf Ebrahimi   __ Ror(w25, w0, w4);
6349*f5c631daSSadaf Ebrahimi   __ Ror(w26, w0, w5);
6350*f5c631daSSadaf Ebrahimi   __ Ror(w27, w0, w6);
6351*f5c631daSSadaf Ebrahimi   END();
6352*f5c631daSSadaf Ebrahimi 
6353*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6354*f5c631daSSadaf Ebrahimi     RUN();
6355*f5c631daSSadaf Ebrahimi 
6356*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(value, x0);
6357*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf0123456789abcde, x16);
6358*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xef0123456789abcd, x17);
6359*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xdef0123456789abc, x18);
6360*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xcdef0123456789ab, x19);
6361*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xabcdef0123456789, x20);
6362*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x789abcdef0123456, x21);
6363*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xf89abcde, w22);
6364*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xef89abcd, w23);
6365*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xdef89abc, w24);
6366*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xcdef89ab, w25);
6367*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xabcdef89, w26);
6368*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xf89abcde, w27);
6369*f5c631daSSadaf Ebrahimi   }
6370*f5c631daSSadaf Ebrahimi }
6371*f5c631daSSadaf Ebrahimi 
6372*f5c631daSSadaf Ebrahimi 
TEST(bfm)6373*f5c631daSSadaf Ebrahimi TEST(bfm) {
6374*f5c631daSSadaf Ebrahimi   SETUP();
6375*f5c631daSSadaf Ebrahimi 
6376*f5c631daSSadaf Ebrahimi   START();
6377*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0123456789abcdef);
6378*f5c631daSSadaf Ebrahimi 
6379*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0x8888888888888888);
6380*f5c631daSSadaf Ebrahimi   __ Mov(x11, 0x8888888888888888);
6381*f5c631daSSadaf Ebrahimi   __ Mov(x12, 0x8888888888888888);
6382*f5c631daSSadaf Ebrahimi   __ Mov(x13, 0x8888888888888888);
6383*f5c631daSSadaf Ebrahimi   __ Mov(x14, 0xffffffffffffffff);
6384*f5c631daSSadaf Ebrahimi   __ Mov(w20, 0x88888888);
6385*f5c631daSSadaf Ebrahimi   __ Mov(w21, 0x88888888);
6386*f5c631daSSadaf Ebrahimi 
6387*f5c631daSSadaf Ebrahimi   __ Bfm(x10, x1, 16, 31);
6388*f5c631daSSadaf Ebrahimi   __ Bfm(x11, x1, 32, 15);
6389*f5c631daSSadaf Ebrahimi 
6390*f5c631daSSadaf Ebrahimi   __ Bfm(w20, w1, 16, 23);
6391*f5c631daSSadaf Ebrahimi   __ Bfm(w21, w1, 24, 15);
6392*f5c631daSSadaf Ebrahimi 
6393*f5c631daSSadaf Ebrahimi   // Aliases.
6394*f5c631daSSadaf Ebrahimi   __ Bfi(x12, x1, 16, 8);
6395*f5c631daSSadaf Ebrahimi   __ Bfxil(x13, x1, 16, 8);
6396*f5c631daSSadaf Ebrahimi   __ Bfc(x14, 16, 8);
6397*f5c631daSSadaf Ebrahimi   END();
6398*f5c631daSSadaf Ebrahimi 
6399*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6400*f5c631daSSadaf Ebrahimi     RUN();
6401*f5c631daSSadaf Ebrahimi 
6402*f5c631daSSadaf Ebrahimi 
6403*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x88888888888889ab, x10);
6404*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8888cdef88888888, x11);
6405*f5c631daSSadaf Ebrahimi 
6406*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x888888ab, w20);
6407*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x88cdef88, w21);
6408*f5c631daSSadaf Ebrahimi 
6409*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8888888888ef8888, x12);
6410*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x88888888888888ab, x13);
6411*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffff00ffff, x14);
6412*f5c631daSSadaf Ebrahimi   }
6413*f5c631daSSadaf Ebrahimi }
6414*f5c631daSSadaf Ebrahimi 
6415*f5c631daSSadaf Ebrahimi 
TEST(sbfm)6416*f5c631daSSadaf Ebrahimi TEST(sbfm) {
6417*f5c631daSSadaf Ebrahimi   SETUP();
6418*f5c631daSSadaf Ebrahimi 
6419*f5c631daSSadaf Ebrahimi   START();
6420*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0123456789abcdef);
6421*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xfedcba9876543210);
6422*f5c631daSSadaf Ebrahimi 
6423*f5c631daSSadaf Ebrahimi   __ Sbfm(x10, x1, 16, 31);
6424*f5c631daSSadaf Ebrahimi   __ Sbfm(x11, x1, 32, 15);
6425*f5c631daSSadaf Ebrahimi   __ Sbfm(x12, x1, 32, 47);
6426*f5c631daSSadaf Ebrahimi   __ Sbfm(x13, x1, 48, 35);
6427*f5c631daSSadaf Ebrahimi 
6428*f5c631daSSadaf Ebrahimi   __ Sbfm(w14, w1, 16, 23);
6429*f5c631daSSadaf Ebrahimi   __ Sbfm(w15, w1, 24, 15);
6430*f5c631daSSadaf Ebrahimi   __ Sbfm(w16, w2, 16, 23);
6431*f5c631daSSadaf Ebrahimi   __ Sbfm(w17, w2, 24, 15);
6432*f5c631daSSadaf Ebrahimi 
6433*f5c631daSSadaf Ebrahimi   // Aliases.
6434*f5c631daSSadaf Ebrahimi   __ Asr(x18, x1, 32);
6435*f5c631daSSadaf Ebrahimi   __ Asr(x19, x2, 32);
6436*f5c631daSSadaf Ebrahimi   __ Sbfiz(x20, x1, 8, 16);
6437*f5c631daSSadaf Ebrahimi   __ Sbfiz(x21, x2, 8, 16);
6438*f5c631daSSadaf Ebrahimi   __ Sbfx(x22, x1, 8, 16);
6439*f5c631daSSadaf Ebrahimi   __ Sbfx(x23, x2, 8, 16);
6440*f5c631daSSadaf Ebrahimi   __ Sxtb(x24, w1);
6441*f5c631daSSadaf Ebrahimi   __ Sxtb(x25, x2);
6442*f5c631daSSadaf Ebrahimi   __ Sxth(x26, w1);
6443*f5c631daSSadaf Ebrahimi   __ Sxth(x27, x2);
6444*f5c631daSSadaf Ebrahimi   __ Sxtw(x28, w1);
6445*f5c631daSSadaf Ebrahimi   __ Sxtw(x29, x2);
6446*f5c631daSSadaf Ebrahimi   END();
6447*f5c631daSSadaf Ebrahimi 
6448*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6449*f5c631daSSadaf Ebrahimi     RUN();
6450*f5c631daSSadaf Ebrahimi 
6451*f5c631daSSadaf Ebrahimi 
6452*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffff89ab, x10);
6453*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffcdef00000000, x11);
6454*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000004567, x12);
6455*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000789abcdef0000, x13);
6456*f5c631daSSadaf Ebrahimi 
6457*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffffffab, w14);
6458*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0xffcdef00, w15);
6459*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00000054, w16);
6460*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00321000, w17);
6461*f5c631daSSadaf Ebrahimi 
6462*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000001234567, x18);
6463*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffedcba98, x19);
6464*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffcdef00, x20);
6465*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000321000, x21);
6466*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffabcd, x22);
6467*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000005432, x23);
6468*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffef, x24);
6469*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000010, x25);
6470*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffcdef, x26);
6471*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000003210, x27);
6472*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff89abcdef, x28);
6473*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000076543210, x29);
6474*f5c631daSSadaf Ebrahimi   }
6475*f5c631daSSadaf Ebrahimi }
6476*f5c631daSSadaf Ebrahimi 
6477*f5c631daSSadaf Ebrahimi 
TEST(ubfm)6478*f5c631daSSadaf Ebrahimi TEST(ubfm) {
6479*f5c631daSSadaf Ebrahimi   SETUP();
6480*f5c631daSSadaf Ebrahimi 
6481*f5c631daSSadaf Ebrahimi   START();
6482*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0123456789abcdef);
6483*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xfedcba9876543210);
6484*f5c631daSSadaf Ebrahimi 
6485*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0x8888888888888888);
6486*f5c631daSSadaf Ebrahimi   __ Mov(x11, 0x8888888888888888);
6487*f5c631daSSadaf Ebrahimi 
6488*f5c631daSSadaf Ebrahimi   __ Ubfm(x10, x1, 16, 31);
6489*f5c631daSSadaf Ebrahimi   __ Ubfm(x11, x1, 32, 15);
6490*f5c631daSSadaf Ebrahimi   __ Ubfm(x12, x1, 32, 47);
6491*f5c631daSSadaf Ebrahimi   __ Ubfm(x13, x1, 48, 35);
6492*f5c631daSSadaf Ebrahimi 
6493*f5c631daSSadaf Ebrahimi   __ Ubfm(w25, w1, 16, 23);
6494*f5c631daSSadaf Ebrahimi   __ Ubfm(w26, w1, 24, 15);
6495*f5c631daSSadaf Ebrahimi   __ Ubfm(w27, w2, 16, 23);
6496*f5c631daSSadaf Ebrahimi   __ Ubfm(w28, w2, 24, 15);
6497*f5c631daSSadaf Ebrahimi 
6498*f5c631daSSadaf Ebrahimi   // Aliases
6499*f5c631daSSadaf Ebrahimi   __ Lsl(x15, x1, 63);
6500*f5c631daSSadaf Ebrahimi   __ Lsl(x16, x1, 0);
6501*f5c631daSSadaf Ebrahimi   __ Lsr(x17, x1, 32);
6502*f5c631daSSadaf Ebrahimi   __ Ubfiz(x18, x1, 8, 16);
6503*f5c631daSSadaf Ebrahimi   __ Ubfx(x19, x1, 8, 16);
6504*f5c631daSSadaf Ebrahimi   __ Uxtb(x20, x1);
6505*f5c631daSSadaf Ebrahimi   __ Uxth(x21, x1);
6506*f5c631daSSadaf Ebrahimi   __ Uxtw(x22, x1);
6507*f5c631daSSadaf Ebrahimi   END();
6508*f5c631daSSadaf Ebrahimi 
6509*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6510*f5c631daSSadaf Ebrahimi     RUN();
6511*f5c631daSSadaf Ebrahimi 
6512*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000000089ab, x10);
6513*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000cdef00000000, x11);
6514*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000004567, x12);
6515*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000789abcdef0000, x13);
6516*f5c631daSSadaf Ebrahimi 
6517*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x000000ab, w25);
6518*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00cdef00, w26);
6519*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00000054, w27);
6520*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00321000, w28);
6521*f5c631daSSadaf Ebrahimi 
6522*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x8000000000000000, x15);
6523*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x16);
6524*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000001234567, x17);
6525*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000cdef00, x18);
6526*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000abcd, x19);
6527*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000000000000ef, x20);
6528*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000000000000cdef, x21);
6529*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000089abcdef, x22);
6530*f5c631daSSadaf Ebrahimi   }
6531*f5c631daSSadaf Ebrahimi }
6532*f5c631daSSadaf Ebrahimi 
6533*f5c631daSSadaf Ebrahimi 
TEST(extr)6534*f5c631daSSadaf Ebrahimi TEST(extr) {
6535*f5c631daSSadaf Ebrahimi   SETUP();
6536*f5c631daSSadaf Ebrahimi 
6537*f5c631daSSadaf Ebrahimi   START();
6538*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x0123456789abcdef);
6539*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xfedcba9876543210);
6540*f5c631daSSadaf Ebrahimi 
6541*f5c631daSSadaf Ebrahimi   __ Extr(w10, w1, w2, 0);
6542*f5c631daSSadaf Ebrahimi   __ Extr(w11, w1, w2, 1);
6543*f5c631daSSadaf Ebrahimi   __ Extr(x12, x2, x1, 2);
6544*f5c631daSSadaf Ebrahimi 
6545*f5c631daSSadaf Ebrahimi   __ Ror(w13, w1, 0);
6546*f5c631daSSadaf Ebrahimi   __ Ror(w14, w2, 17);
6547*f5c631daSSadaf Ebrahimi   __ Ror(w15, w1, 31);
6548*f5c631daSSadaf Ebrahimi   __ Ror(x18, x2, 0);
6549*f5c631daSSadaf Ebrahimi   __ Ror(x19, x2, 1);
6550*f5c631daSSadaf Ebrahimi   __ Ror(x20, x1, 63);
6551*f5c631daSSadaf Ebrahimi   END();
6552*f5c631daSSadaf Ebrahimi 
6553*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6554*f5c631daSSadaf Ebrahimi     RUN();
6555*f5c631daSSadaf Ebrahimi 
6556*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x76543210, x10);
6557*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbb2a1908, x11);
6558*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0048d159e26af37b, x12);
6559*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef, x13);
6560*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x19083b2a, x14);
6561*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x13579bdf, x15);
6562*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, x18);
6563*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7f6e5d4c3b2a1908, x19);
6564*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x02468acf13579bde, x20);
6565*f5c631daSSadaf Ebrahimi   }
6566*f5c631daSSadaf Ebrahimi }
6567*f5c631daSSadaf Ebrahimi 
6568*f5c631daSSadaf Ebrahimi 
TEST(system_mrs)6569*f5c631daSSadaf Ebrahimi TEST(system_mrs) {
6570*f5c631daSSadaf Ebrahimi   SETUP();
6571*f5c631daSSadaf Ebrahimi 
6572*f5c631daSSadaf Ebrahimi   START();
6573*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
6574*f5c631daSSadaf Ebrahimi   __ Mov(w1, 1);
6575*f5c631daSSadaf Ebrahimi   __ Mov(w2, 0x80000000);
6576*f5c631daSSadaf Ebrahimi 
6577*f5c631daSSadaf Ebrahimi   // Set the Z and C flags.
6578*f5c631daSSadaf Ebrahimi   __ Cmp(w0, w0);
6579*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
6580*f5c631daSSadaf Ebrahimi 
6581*f5c631daSSadaf Ebrahimi   // Set the N flag.
6582*f5c631daSSadaf Ebrahimi   __ Cmp(w0, w1);
6583*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
6584*f5c631daSSadaf Ebrahimi 
6585*f5c631daSSadaf Ebrahimi   // Set the Z, C and V flags.
6586*f5c631daSSadaf Ebrahimi   __ Adds(w0, w2, w2);
6587*f5c631daSSadaf Ebrahimi   __ Mrs(x5, NZCV);
6588*f5c631daSSadaf Ebrahimi 
6589*f5c631daSSadaf Ebrahimi   // Read the default FPCR.
6590*f5c631daSSadaf Ebrahimi   __ Mrs(x6, FPCR);
6591*f5c631daSSadaf Ebrahimi   END();
6592*f5c631daSSadaf Ebrahimi 
6593*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6594*f5c631daSSadaf Ebrahimi     RUN();
6595*f5c631daSSadaf Ebrahimi 
6596*f5c631daSSadaf Ebrahimi     // NZCV
6597*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCFlag, w3);
6598*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NFlag, w4);
6599*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(ZCVFlag, w5);
6600*f5c631daSSadaf Ebrahimi 
6601*f5c631daSSadaf Ebrahimi     // FPCR
6602*f5c631daSSadaf Ebrahimi     // The default FPCR on Linux-based platforms is 0.
6603*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w6);
6604*f5c631daSSadaf Ebrahimi   }
6605*f5c631daSSadaf Ebrahimi }
6606*f5c631daSSadaf Ebrahimi 
TEST(system_rng)6607*f5c631daSSadaf Ebrahimi TEST(system_rng) {
6608*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kRNG);
6609*f5c631daSSadaf Ebrahimi 
6610*f5c631daSSadaf Ebrahimi   START();
6611*f5c631daSSadaf Ebrahimi   // Random number.
6612*f5c631daSSadaf Ebrahimi   __ Mrs(x1, RNDR);
6613*f5c631daSSadaf Ebrahimi   // Assume that each generation is successful now.
6614*f5c631daSSadaf Ebrahimi   // TODO: Return failure occasionally.
6615*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
6616*f5c631daSSadaf Ebrahimi   __ Mrs(x3, RNDR);
6617*f5c631daSSadaf Ebrahimi   __ Mrs(x4, NZCV);
6618*f5c631daSSadaf Ebrahimi 
6619*f5c631daSSadaf Ebrahimi   // Reseeded random number.
6620*f5c631daSSadaf Ebrahimi   __ Mrs(x5, RNDRRS);
6621*f5c631daSSadaf Ebrahimi   // Assume that each generation is successful now.
6622*f5c631daSSadaf Ebrahimi   // TODO: Return failure occasionally.
6623*f5c631daSSadaf Ebrahimi   __ Mrs(x6, NZCV);
6624*f5c631daSSadaf Ebrahimi   __ Mrs(x7, RNDRRS);
6625*f5c631daSSadaf Ebrahimi   __ Mrs(x8, NZCV);
6626*f5c631daSSadaf Ebrahimi   END();
6627*f5c631daSSadaf Ebrahimi 
6628*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6629*f5c631daSSadaf Ebrahimi     RUN();
6630*f5c631daSSadaf Ebrahimi     // Random number generation series.
6631*f5c631daSSadaf Ebrahimi     // Check random numbers have been generated and aren't equal when reseed has
6632*f5c631daSSadaf Ebrahimi     // happened.
6633*f5c631daSSadaf Ebrahimi     // NOTE: With a different architectural implementation, there may be a
6634*f5c631daSSadaf Ebrahimi     // collison.
6635*f5c631daSSadaf Ebrahimi     // TODO: Return failure occasionally. Set ZFlag and return UNKNOWN value.
6636*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x1, x3);
6637*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(NoFlag, x2);
6638*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(NoFlag, x4);
6639*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x5, x7);
6640*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(NoFlag, x6);
6641*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(NoFlag, x8);
6642*f5c631daSSadaf Ebrahimi   }
6643*f5c631daSSadaf Ebrahimi }
6644*f5c631daSSadaf Ebrahimi 
TEST(cfinv)6645*f5c631daSSadaf Ebrahimi TEST(cfinv) {
6646*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFlagM);
6647*f5c631daSSadaf Ebrahimi 
6648*f5c631daSSadaf Ebrahimi   START();
6649*f5c631daSSadaf Ebrahimi   __ Mov(w0, 1);
6650*f5c631daSSadaf Ebrahimi 
6651*f5c631daSSadaf Ebrahimi   // Set the C flag.
6652*f5c631daSSadaf Ebrahimi   __ Cmp(w0, 0);
6653*f5c631daSSadaf Ebrahimi   __ Mrs(x1, NZCV);
6654*f5c631daSSadaf Ebrahimi 
6655*f5c631daSSadaf Ebrahimi   // Invert the C flag.
6656*f5c631daSSadaf Ebrahimi   __ Cfinv();
6657*f5c631daSSadaf Ebrahimi   __ Mrs(x2, NZCV);
6658*f5c631daSSadaf Ebrahimi 
6659*f5c631daSSadaf Ebrahimi   // Invert the C flag again.
6660*f5c631daSSadaf Ebrahimi   __ Cfinv();
6661*f5c631daSSadaf Ebrahimi   __ Mrs(x3, NZCV);
6662*f5c631daSSadaf Ebrahimi   END();
6663*f5c631daSSadaf Ebrahimi 
6664*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6665*f5c631daSSadaf Ebrahimi     RUN();
6666*f5c631daSSadaf Ebrahimi 
6667*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(CFlag, w1);
6668*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(NoFlag, w2);
6669*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(CFlag, w3);
6670*f5c631daSSadaf Ebrahimi   }
6671*f5c631daSSadaf Ebrahimi }
6672*f5c631daSSadaf Ebrahimi 
6673*f5c631daSSadaf Ebrahimi 
TEST(axflag_xaflag)6674*f5c631daSSadaf Ebrahimi TEST(axflag_xaflag) {
6675*f5c631daSSadaf Ebrahimi   // The AXFLAG and XAFLAG instructions are designed for converting the FP
6676*f5c631daSSadaf Ebrahimi   // conditional flags from Arm format to an alternate format efficiently.
6677*f5c631daSSadaf Ebrahimi   // There are only 4 cases which are relevant for this conversion but we test
6678*f5c631daSSadaf Ebrahimi   // the behaviour for all 16 cases anyway. The 4 important cases are labelled
6679*f5c631daSSadaf Ebrahimi   // below.
6680*f5c631daSSadaf Ebrahimi   StatusFlags expected_x[16] = {NoFlag,
6681*f5c631daSSadaf Ebrahimi                                 ZFlag,
6682*f5c631daSSadaf Ebrahimi                                 CFlag,  // Greater than
6683*f5c631daSSadaf Ebrahimi                                 ZFlag,  // Unordered
6684*f5c631daSSadaf Ebrahimi                                 ZFlag,
6685*f5c631daSSadaf Ebrahimi                                 ZFlag,
6686*f5c631daSSadaf Ebrahimi                                 ZCFlag,  // Equal to
6687*f5c631daSSadaf Ebrahimi                                 ZFlag,
6688*f5c631daSSadaf Ebrahimi                                 NoFlag,  // Less than
6689*f5c631daSSadaf Ebrahimi                                 ZFlag,
6690*f5c631daSSadaf Ebrahimi                                 CFlag,
6691*f5c631daSSadaf Ebrahimi                                 ZFlag,
6692*f5c631daSSadaf Ebrahimi                                 ZFlag,
6693*f5c631daSSadaf Ebrahimi                                 ZFlag,
6694*f5c631daSSadaf Ebrahimi                                 ZCFlag,
6695*f5c631daSSadaf Ebrahimi                                 ZFlag};
6696*f5c631daSSadaf Ebrahimi   StatusFlags expected_a[16] = {NFlag,  // Less than
6697*f5c631daSSadaf Ebrahimi                                 NFlag,
6698*f5c631daSSadaf Ebrahimi                                 CFlag,  // Greater than
6699*f5c631daSSadaf Ebrahimi                                 CFlag,
6700*f5c631daSSadaf Ebrahimi                                 CVFlag,  // Unordered
6701*f5c631daSSadaf Ebrahimi                                 CVFlag,
6702*f5c631daSSadaf Ebrahimi                                 ZCFlag,  // Equal to
6703*f5c631daSSadaf Ebrahimi                                 ZCFlag,
6704*f5c631daSSadaf Ebrahimi                                 NFlag,
6705*f5c631daSSadaf Ebrahimi                                 NFlag,
6706*f5c631daSSadaf Ebrahimi                                 CFlag,
6707*f5c631daSSadaf Ebrahimi                                 CFlag,
6708*f5c631daSSadaf Ebrahimi                                 CVFlag,
6709*f5c631daSSadaf Ebrahimi                                 CVFlag,
6710*f5c631daSSadaf Ebrahimi                                 ZCFlag,
6711*f5c631daSSadaf Ebrahimi                                 ZCFlag};
6712*f5c631daSSadaf Ebrahimi 
6713*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < 16; i++) {
6714*f5c631daSSadaf Ebrahimi     SETUP_WITH_FEATURES(CPUFeatures::kAXFlag);
6715*f5c631daSSadaf Ebrahimi 
6716*f5c631daSSadaf Ebrahimi     START();
6717*f5c631daSSadaf Ebrahimi     __ Mov(x0, i << Flags_offset);
6718*f5c631daSSadaf Ebrahimi     __ Msr(NZCV, x0);
6719*f5c631daSSadaf Ebrahimi     __ Axflag();
6720*f5c631daSSadaf Ebrahimi     __ Mrs(x1, NZCV);
6721*f5c631daSSadaf Ebrahimi     __ Msr(NZCV, x0);
6722*f5c631daSSadaf Ebrahimi     __ Xaflag();
6723*f5c631daSSadaf Ebrahimi     __ Mrs(x2, NZCV);
6724*f5c631daSSadaf Ebrahimi     END();
6725*f5c631daSSadaf Ebrahimi 
6726*f5c631daSSadaf Ebrahimi     if (CAN_RUN()) {
6727*f5c631daSSadaf Ebrahimi       RUN();
6728*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_32(expected_x[i], w1);
6729*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_32(expected_a[i], w2);
6730*f5c631daSSadaf Ebrahimi     }
6731*f5c631daSSadaf Ebrahimi   }
6732*f5c631daSSadaf Ebrahimi }
6733*f5c631daSSadaf Ebrahimi 
6734*f5c631daSSadaf Ebrahimi 
TEST(system_msr)6735*f5c631daSSadaf Ebrahimi TEST(system_msr) {
6736*f5c631daSSadaf Ebrahimi   // All FPCR fields that must be implemented: AHP, DN, FZ, RMode
6737*f5c631daSSadaf Ebrahimi   const uint64_t fpcr_core = (0b1 << 26) |  // AHP
6738*f5c631daSSadaf Ebrahimi                              (0b1 << 25) |  // DN
6739*f5c631daSSadaf Ebrahimi                              (0b1 << 24) |  // FZ
6740*f5c631daSSadaf Ebrahimi                              (0b11 << 22);  // RMode
6741*f5c631daSSadaf Ebrahimi 
6742*f5c631daSSadaf Ebrahimi   SETUP();
6743*f5c631daSSadaf Ebrahimi 
6744*f5c631daSSadaf Ebrahimi   START();
6745*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
6746*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x7fffffff);
6747*f5c631daSSadaf Ebrahimi 
6748*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0);
6749*f5c631daSSadaf Ebrahimi 
6750*f5c631daSSadaf Ebrahimi   __ Mov(x10, NVFlag);
6751*f5c631daSSadaf Ebrahimi   __ Cmp(w0, w0);     // Set Z and C.
6752*f5c631daSSadaf Ebrahimi   __ Msr(NZCV, x10);  // Set N and V.
6753*f5c631daSSadaf Ebrahimi   // The Msr should have overwritten every flag set by the Cmp.
6754*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, mi);  // N
6755*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, ne);  // !Z
6756*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, lo);  // !C
6757*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, vs);  // V
6758*f5c631daSSadaf Ebrahimi 
6759*f5c631daSSadaf Ebrahimi   __ Mov(x10, ZCFlag);
6760*f5c631daSSadaf Ebrahimi   __ Cmn(w1, w1);     // Set N and V.
6761*f5c631daSSadaf Ebrahimi   __ Msr(NZCV, x10);  // Set Z and C.
6762*f5c631daSSadaf Ebrahimi   // The Msr should have overwritten every flag set by the Cmn.
6763*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, pl);  // !N
6764*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, eq);  // Z
6765*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, hs);  // C
6766*f5c631daSSadaf Ebrahimi   __ Cinc(x7, x7, vc);  // !V
6767*f5c631daSSadaf Ebrahimi 
6768*f5c631daSSadaf Ebrahimi   // All core FPCR fields must be writable.
6769*f5c631daSSadaf Ebrahimi   __ Mov(x8, fpcr_core);
6770*f5c631daSSadaf Ebrahimi   __ Msr(FPCR, x8);
6771*f5c631daSSadaf Ebrahimi   __ Mrs(x8, FPCR);
6772*f5c631daSSadaf Ebrahimi 
6773*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
6774*f5c631daSSadaf Ebrahimi   // All FPCR fields that aren't `RES0`:
6775*f5c631daSSadaf Ebrahimi   const uint64_t fpcr_all = fpcr_core | (0b11 << 20) |  // Stride
6776*f5c631daSSadaf Ebrahimi                             (0b1 << 19) |               // FZ16
6777*f5c631daSSadaf Ebrahimi                             (0b111 << 16) |             // Len
6778*f5c631daSSadaf Ebrahimi                             (0b1 << 15) |               // IDE
6779*f5c631daSSadaf Ebrahimi                             (0b1 << 12) |               // IXE
6780*f5c631daSSadaf Ebrahimi                             (0b1 << 11) |               // UFE
6781*f5c631daSSadaf Ebrahimi                             (0b1 << 10) |               // OFE
6782*f5c631daSSadaf Ebrahimi                             (0b1 << 9) |                // DZE
6783*f5c631daSSadaf Ebrahimi                             (0b1 << 8);                 // IOE
6784*f5c631daSSadaf Ebrahimi 
6785*f5c631daSSadaf Ebrahimi   // All FPCR fields, including optional ones. This part of the test doesn't
6786*f5c631daSSadaf Ebrahimi   // achieve much other than ensuring that supported fields can be cleared by
6787*f5c631daSSadaf Ebrahimi   // the next test.
6788*f5c631daSSadaf Ebrahimi   __ Mov(x9, fpcr_all);
6789*f5c631daSSadaf Ebrahimi   __ Msr(FPCR, x9);
6790*f5c631daSSadaf Ebrahimi   __ Mrs(x9, FPCR);
6791*f5c631daSSadaf Ebrahimi   __ And(x9, x9, fpcr_core);
6792*f5c631daSSadaf Ebrahimi 
6793*f5c631daSSadaf Ebrahimi   // The undefined bits must ignore writes.
6794*f5c631daSSadaf Ebrahimi   // It's conceivable that a future version of the architecture could use these
6795*f5c631daSSadaf Ebrahimi   // fields (making this test fail), but in the meantime this is a useful test
6796*f5c631daSSadaf Ebrahimi   // for the simulator.
6797*f5c631daSSadaf Ebrahimi   __ Mov(x10, ~fpcr_all);
6798*f5c631daSSadaf Ebrahimi   __ Msr(FPCR, x10);
6799*f5c631daSSadaf Ebrahimi   __ Mrs(x10, FPCR);
6800*f5c631daSSadaf Ebrahimi #endif
6801*f5c631daSSadaf Ebrahimi 
6802*f5c631daSSadaf Ebrahimi   END();
6803*f5c631daSSadaf Ebrahimi 
6804*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6805*f5c631daSSadaf Ebrahimi     RUN();
6806*f5c631daSSadaf Ebrahimi 
6807*f5c631daSSadaf Ebrahimi     // We should have incremented x7 (from 0) exactly 8 times.
6808*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(8, x7);
6809*f5c631daSSadaf Ebrahimi 
6810*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(fpcr_core, x8);
6811*f5c631daSSadaf Ebrahimi 
6812*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
6813*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(fpcr_core, x9);
6814*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x10);
6815*f5c631daSSadaf Ebrahimi #endif
6816*f5c631daSSadaf Ebrahimi   }
6817*f5c631daSSadaf Ebrahimi }
6818*f5c631daSSadaf Ebrahimi 
6819*f5c631daSSadaf Ebrahimi 
TEST(system_pauth_a)6820*f5c631daSSadaf Ebrahimi TEST(system_pauth_a) {
6821*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
6822*f5c631daSSadaf Ebrahimi   START();
6823*f5c631daSSadaf Ebrahimi 
6824*f5c631daSSadaf Ebrahimi   // Exclude x16 and x17 from the scratch register list so we can use
6825*f5c631daSSadaf Ebrahimi   // Pac/Autia1716 safely.
6826*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
6827*f5c631daSSadaf Ebrahimi   temps.Exclude(x16, x17);
6828*f5c631daSSadaf Ebrahimi   temps.Include(x10, x11);
6829*f5c631daSSadaf Ebrahimi 
6830*f5c631daSSadaf Ebrahimi   // Backup stack pointer.
6831*f5c631daSSadaf Ebrahimi   __ Mov(x20, sp);
6832*f5c631daSSadaf Ebrahimi 
6833*f5c631daSSadaf Ebrahimi   // Modifiers
6834*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0x477d469dec0b8760);
6835*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x477d469dec0b8760);
6836*f5c631daSSadaf Ebrahimi 
6837*f5c631daSSadaf Ebrahimi   // Generate PACs using the 3 system instructions.
6838*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0x0000000012345678);
6839*f5c631daSSadaf Ebrahimi   __ Pacia1716();
6840*f5c631daSSadaf Ebrahimi   __ Mov(x0, x17);
6841*f5c631daSSadaf Ebrahimi 
6842*f5c631daSSadaf Ebrahimi   __ Mov(lr, 0x0000000012345678);
6843*f5c631daSSadaf Ebrahimi   __ Paciaz();
6844*f5c631daSSadaf Ebrahimi   __ Mov(x1, lr);
6845*f5c631daSSadaf Ebrahimi 
6846*f5c631daSSadaf Ebrahimi   __ Mov(lr, 0x0000000012345678);
6847*f5c631daSSadaf Ebrahimi   __ Paciasp();
6848*f5c631daSSadaf Ebrahimi   __ Mov(x2, lr);
6849*f5c631daSSadaf Ebrahimi 
6850*f5c631daSSadaf Ebrahimi   // Authenticate the pointers above.
6851*f5c631daSSadaf Ebrahimi   __ Mov(x17, x0);
6852*f5c631daSSadaf Ebrahimi   __ Autia1716();
6853*f5c631daSSadaf Ebrahimi   __ Mov(x3, x17);
6854*f5c631daSSadaf Ebrahimi 
6855*f5c631daSSadaf Ebrahimi   __ Mov(lr, x1);
6856*f5c631daSSadaf Ebrahimi   __ Autiaz();
6857*f5c631daSSadaf Ebrahimi   __ Mov(x4, lr);
6858*f5c631daSSadaf Ebrahimi 
6859*f5c631daSSadaf Ebrahimi   __ Mov(lr, x2);
6860*f5c631daSSadaf Ebrahimi   __ Autiasp();
6861*f5c631daSSadaf Ebrahimi   __ Mov(x5, lr);
6862*f5c631daSSadaf Ebrahimi 
6863*f5c631daSSadaf Ebrahimi   // Attempt to authenticate incorrect pointers.
6864*f5c631daSSadaf Ebrahimi   __ Mov(x17, x1);
6865*f5c631daSSadaf Ebrahimi   __ Autia1716();
6866*f5c631daSSadaf Ebrahimi   __ Mov(x6, x17);
6867*f5c631daSSadaf Ebrahimi 
6868*f5c631daSSadaf Ebrahimi   __ Mov(lr, x0);
6869*f5c631daSSadaf Ebrahimi   __ Autiaz();
6870*f5c631daSSadaf Ebrahimi   __ Mov(x7, lr);
6871*f5c631daSSadaf Ebrahimi 
6872*f5c631daSSadaf Ebrahimi   __ Mov(lr, x1);
6873*f5c631daSSadaf Ebrahimi   __ Autiasp();
6874*f5c631daSSadaf Ebrahimi   __ Mov(x8, lr);
6875*f5c631daSSadaf Ebrahimi 
6876*f5c631daSSadaf Ebrahimi   // Strip the pac code from the pointer in x0.
6877*f5c631daSSadaf Ebrahimi   __ Mov(lr, x0);
6878*f5c631daSSadaf Ebrahimi   __ Xpaclri();
6879*f5c631daSSadaf Ebrahimi   __ Mov(x9, lr);
6880*f5c631daSSadaf Ebrahimi 
6881*f5c631daSSadaf Ebrahimi   // Restore stack pointer.
6882*f5c631daSSadaf Ebrahimi   __ Mov(sp, x20);
6883*f5c631daSSadaf Ebrahimi 
6884*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
6885*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
6886*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0x007f000000000000);
6887*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
6888*f5c631daSSadaf Ebrahimi   __ And(x2, x2, 0x007f000000000000);
6889*f5c631daSSadaf Ebrahimi 
6890*f5c631daSSadaf Ebrahimi   END();
6891*f5c631daSSadaf Ebrahimi 
6892*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6893*f5c631daSSadaf Ebrahimi     RUN();
6894*f5c631daSSadaf Ebrahimi 
6895*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
6896*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
6897*f5c631daSSadaf Ebrahimi     // collision.
6898*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
6899*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
6900*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x2);
6901*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x0, x1);
6902*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x0, x2);
6903*f5c631daSSadaf Ebrahimi 
6904*f5c631daSSadaf Ebrahimi     // Pointers correctly authenticated.
6905*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x3);
6906*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x4);
6907*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x5);
6908*f5c631daSSadaf Ebrahimi 
6909*f5c631daSSadaf Ebrahimi     // Pointers corrupted after failing to authenticate.
6910*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x6);
6911*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x7);
6912*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0020000012345678, x8);
6913*f5c631daSSadaf Ebrahimi 
6914*f5c631daSSadaf Ebrahimi     // Pointer with code stripped.
6915*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x9);
6916*f5c631daSSadaf Ebrahimi   }
6917*f5c631daSSadaf Ebrahimi }
6918*f5c631daSSadaf Ebrahimi 
6919*f5c631daSSadaf Ebrahimi 
TEST(system_pauth_b)6920*f5c631daSSadaf Ebrahimi TEST(system_pauth_b) {
6921*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
6922*f5c631daSSadaf Ebrahimi   START();
6923*f5c631daSSadaf Ebrahimi 
6924*f5c631daSSadaf Ebrahimi   // Exclude x16 and x17 from the scratch register list so we can use
6925*f5c631daSSadaf Ebrahimi   // Pac/Autia1716 safely.
6926*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
6927*f5c631daSSadaf Ebrahimi   temps.Exclude(x16, x17);
6928*f5c631daSSadaf Ebrahimi   temps.Include(x10, x11);
6929*f5c631daSSadaf Ebrahimi 
6930*f5c631daSSadaf Ebrahimi   // Backup stack pointer.
6931*f5c631daSSadaf Ebrahimi   __ Mov(x20, sp);
6932*f5c631daSSadaf Ebrahimi 
6933*f5c631daSSadaf Ebrahimi   // Modifiers
6934*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0x477d469dec0b8760);
6935*f5c631daSSadaf Ebrahimi   __ Mov(sp, 0x477d469dec0b8760);
6936*f5c631daSSadaf Ebrahimi 
6937*f5c631daSSadaf Ebrahimi   // Generate PACs using the 3 system instructions.
6938*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0x0000000012345678);
6939*f5c631daSSadaf Ebrahimi   __ Pacib1716();
6940*f5c631daSSadaf Ebrahimi   __ Mov(x0, x17);
6941*f5c631daSSadaf Ebrahimi 
6942*f5c631daSSadaf Ebrahimi   __ Mov(lr, 0x0000000012345678);
6943*f5c631daSSadaf Ebrahimi   __ Pacibz();
6944*f5c631daSSadaf Ebrahimi   __ Mov(x1, lr);
6945*f5c631daSSadaf Ebrahimi 
6946*f5c631daSSadaf Ebrahimi   __ Mov(lr, 0x0000000012345678);
6947*f5c631daSSadaf Ebrahimi   __ Pacibsp();
6948*f5c631daSSadaf Ebrahimi   __ Mov(x2, lr);
6949*f5c631daSSadaf Ebrahimi 
6950*f5c631daSSadaf Ebrahimi   // Authenticate the pointers above.
6951*f5c631daSSadaf Ebrahimi   __ Mov(x17, x0);
6952*f5c631daSSadaf Ebrahimi   __ Autib1716();
6953*f5c631daSSadaf Ebrahimi   __ Mov(x3, x17);
6954*f5c631daSSadaf Ebrahimi 
6955*f5c631daSSadaf Ebrahimi   __ Mov(lr, x1);
6956*f5c631daSSadaf Ebrahimi   __ Autibz();
6957*f5c631daSSadaf Ebrahimi   __ Mov(x4, lr);
6958*f5c631daSSadaf Ebrahimi 
6959*f5c631daSSadaf Ebrahimi   __ Mov(lr, x2);
6960*f5c631daSSadaf Ebrahimi   __ Autibsp();
6961*f5c631daSSadaf Ebrahimi   __ Mov(x5, lr);
6962*f5c631daSSadaf Ebrahimi 
6963*f5c631daSSadaf Ebrahimi   // Attempt to authenticate incorrect pointers.
6964*f5c631daSSadaf Ebrahimi   __ Mov(x17, x1);
6965*f5c631daSSadaf Ebrahimi   __ Autib1716();
6966*f5c631daSSadaf Ebrahimi   __ Mov(x6, x17);
6967*f5c631daSSadaf Ebrahimi 
6968*f5c631daSSadaf Ebrahimi   __ Mov(lr, x0);
6969*f5c631daSSadaf Ebrahimi   __ Autibz();
6970*f5c631daSSadaf Ebrahimi   __ Mov(x7, lr);
6971*f5c631daSSadaf Ebrahimi 
6972*f5c631daSSadaf Ebrahimi   __ Mov(lr, x1);
6973*f5c631daSSadaf Ebrahimi   __ Autibsp();
6974*f5c631daSSadaf Ebrahimi   __ Mov(x8, lr);
6975*f5c631daSSadaf Ebrahimi 
6976*f5c631daSSadaf Ebrahimi   // Strip the pac code from the pointer in x0.
6977*f5c631daSSadaf Ebrahimi   __ Mov(lr, x0);
6978*f5c631daSSadaf Ebrahimi   __ Xpaclri();
6979*f5c631daSSadaf Ebrahimi   __ Mov(x9, lr);
6980*f5c631daSSadaf Ebrahimi 
6981*f5c631daSSadaf Ebrahimi   // Restore stack pointer.
6982*f5c631daSSadaf Ebrahimi   __ Mov(sp, x20);
6983*f5c631daSSadaf Ebrahimi 
6984*f5c631daSSadaf Ebrahimi   // Mask out just the PAC code bits.
6985*f5c631daSSadaf Ebrahimi   // TODO: use Simulator::CalculatePACMask in a nice way.
6986*f5c631daSSadaf Ebrahimi   __ And(x0, x0, 0x007f000000000000);
6987*f5c631daSSadaf Ebrahimi   __ And(x1, x1, 0x007f000000000000);
6988*f5c631daSSadaf Ebrahimi   __ And(x2, x2, 0x007f000000000000);
6989*f5c631daSSadaf Ebrahimi 
6990*f5c631daSSadaf Ebrahimi   END();
6991*f5c631daSSadaf Ebrahimi 
6992*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
6993*f5c631daSSadaf Ebrahimi     RUN();
6994*f5c631daSSadaf Ebrahimi 
6995*f5c631daSSadaf Ebrahimi     // Check PAC codes have been generated and aren't equal.
6996*f5c631daSSadaf Ebrahimi     // NOTE: with a different ComputePAC implementation, there may be a
6997*f5c631daSSadaf Ebrahimi     // collision.
6998*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x0);
6999*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x1);
7000*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(0, x2);
7001*f5c631daSSadaf Ebrahimi     ASSERT_NOT_EQUAL_64(x0, x1);
7002*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x0, x2);
7003*f5c631daSSadaf Ebrahimi 
7004*f5c631daSSadaf Ebrahimi     // Pointers correctly authenticated.
7005*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x3);
7006*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x4);
7007*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x5);
7008*f5c631daSSadaf Ebrahimi 
7009*f5c631daSSadaf Ebrahimi     // Pointers corrupted after failing to authenticate.
7010*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x6);
7011*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x7);
7012*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0040000012345678, x8);
7013*f5c631daSSadaf Ebrahimi 
7014*f5c631daSSadaf Ebrahimi     // Pointer with code stripped.
7015*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000012345678, x9);
7016*f5c631daSSadaf Ebrahimi   }
7017*f5c631daSSadaf Ebrahimi }
7018*f5c631daSSadaf Ebrahimi 
7019*f5c631daSSadaf Ebrahimi #ifdef VIXL_NEGATIVE_TESTING
TEST(system_pauth_negative_test)7020*f5c631daSSadaf Ebrahimi TEST(system_pauth_negative_test) {
7021*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
7022*f5c631daSSadaf Ebrahimi   START();
7023*f5c631daSSadaf Ebrahimi 
7024*f5c631daSSadaf Ebrahimi   // Test for an assert (independent of order).
7025*f5c631daSSadaf Ebrahimi   MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7026*f5c631daSSadaf Ebrahimi                          "Assertion failed "
7027*f5c631daSSadaf Ebrahimi                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7028*f5c631daSSadaf Ebrahimi 
7029*f5c631daSSadaf Ebrahimi   // Test for x16 assert.
7030*f5c631daSSadaf Ebrahimi   {
7031*f5c631daSSadaf Ebrahimi     UseScratchRegisterScope temps(&masm);
7032*f5c631daSSadaf Ebrahimi     temps.Exclude(x17);
7033*f5c631daSSadaf Ebrahimi     temps.Include(x16);
7034*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7035*f5c631daSSadaf Ebrahimi                            "Assertion failed "
7036*f5c631daSSadaf Ebrahimi                            "(!GetScratchRegisterList()->IncludesAliasOf(x16))");
7037*f5c631daSSadaf Ebrahimi   }
7038*f5c631daSSadaf Ebrahimi 
7039*f5c631daSSadaf Ebrahimi   // Test for x17 assert.
7040*f5c631daSSadaf Ebrahimi   {
7041*f5c631daSSadaf Ebrahimi     UseScratchRegisterScope temps(&masm);
7042*f5c631daSSadaf Ebrahimi     temps.Exclude(x16);
7043*f5c631daSSadaf Ebrahimi     temps.Include(x17);
7044*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(__ Pacia1716(),
7045*f5c631daSSadaf Ebrahimi                            "Assertion failed "
7046*f5c631daSSadaf Ebrahimi                            "(!GetScratchRegisterList()->IncludesAliasOf(x17))");
7047*f5c631daSSadaf Ebrahimi   }
7048*f5c631daSSadaf Ebrahimi 
7049*f5c631daSSadaf Ebrahimi   // Repeat first test for other 1716 instructions.
7050*f5c631daSSadaf Ebrahimi   MUST_FAIL_WITH_MESSAGE(__ Pacib1716(),
7051*f5c631daSSadaf Ebrahimi                          "Assertion failed "
7052*f5c631daSSadaf Ebrahimi                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7053*f5c631daSSadaf Ebrahimi   MUST_FAIL_WITH_MESSAGE(__ Autia1716(),
7054*f5c631daSSadaf Ebrahimi                          "Assertion failed "
7055*f5c631daSSadaf Ebrahimi                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7056*f5c631daSSadaf Ebrahimi   MUST_FAIL_WITH_MESSAGE(__ Autib1716(),
7057*f5c631daSSadaf Ebrahimi                          "Assertion failed "
7058*f5c631daSSadaf Ebrahimi                          "(!GetScratchRegisterList()->IncludesAliasOf(");
7059*f5c631daSSadaf Ebrahimi 
7060*f5c631daSSadaf Ebrahimi   END();
7061*f5c631daSSadaf Ebrahimi }
7062*f5c631daSSadaf Ebrahimi #endif  // VIXL_NEGATIVE_TESTING
7063*f5c631daSSadaf Ebrahimi 
7064*f5c631daSSadaf Ebrahimi 
TEST(system)7065*f5c631daSSadaf Ebrahimi TEST(system) {
7066*f5c631daSSadaf Ebrahimi   // RegisterDump::Dump uses NEON.
7067*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRAS);
7068*f5c631daSSadaf Ebrahimi   RegisterDump before;
7069*f5c631daSSadaf Ebrahimi 
7070*f5c631daSSadaf Ebrahimi   START();
7071*f5c631daSSadaf Ebrahimi   before.Dump(&masm);
7072*f5c631daSSadaf Ebrahimi   __ Nop();
7073*f5c631daSSadaf Ebrahimi   __ Esb();
7074*f5c631daSSadaf Ebrahimi   __ Csdb();
7075*f5c631daSSadaf Ebrahimi   END();
7076*f5c631daSSadaf Ebrahimi 
7077*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7078*f5c631daSSadaf Ebrahimi     RUN();
7079*f5c631daSSadaf Ebrahimi 
7080*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_REGISTERS(before);
7081*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(before.flags_nzcv());
7082*f5c631daSSadaf Ebrahimi   }
7083*f5c631daSSadaf Ebrahimi }
7084*f5c631daSSadaf Ebrahimi 
BtiHelper(Register ipreg)7085*f5c631daSSadaf Ebrahimi static void BtiHelper(Register ipreg) {
7086*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7087*f5c631daSSadaf Ebrahimi 
7088*f5c631daSSadaf Ebrahimi   Label jump_target, jump_call_target, call_target, done;
7089*f5c631daSSadaf Ebrahimi   START();
7090*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
7091*f5c631daSSadaf Ebrahimi   temps.Exclude(ipreg);
7092*f5c631daSSadaf Ebrahimi   __ Adr(x0, &jump_target);
7093*f5c631daSSadaf Ebrahimi   __ Br(x0);
7094*f5c631daSSadaf Ebrahimi   __ Nop();
7095*f5c631daSSadaf Ebrahimi   __ Bind(&jump_target, EmitBTI_j);
7096*f5c631daSSadaf Ebrahimi   __ Adr(x0, &call_target);
7097*f5c631daSSadaf Ebrahimi   __ Blr(x0);
7098*f5c631daSSadaf Ebrahimi   __ Adr(ipreg, &jump_call_target);
7099*f5c631daSSadaf Ebrahimi   __ Blr(ipreg);
7100*f5c631daSSadaf Ebrahimi   __ Adr(lr, &done);  // Make Ret return to done label.
7101*f5c631daSSadaf Ebrahimi   __ Br(ipreg);
7102*f5c631daSSadaf Ebrahimi   __ Bind(&call_target, EmitBTI_c);
7103*f5c631daSSadaf Ebrahimi   __ Ret();
7104*f5c631daSSadaf Ebrahimi   __ Bind(&jump_call_target, EmitBTI_jc);
7105*f5c631daSSadaf Ebrahimi   __ Ret();
7106*f5c631daSSadaf Ebrahimi   __ Bind(&done);
7107*f5c631daSSadaf Ebrahimi   END();
7108*f5c631daSSadaf Ebrahimi 
7109*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7110*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7111*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7112*f5c631daSSadaf Ebrahimi #else
7113*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7114*f5c631daSSadaf Ebrahimi #endif
7115*f5c631daSSadaf Ebrahimi     RUN();
7116*f5c631daSSadaf Ebrahimi   }
7117*f5c631daSSadaf Ebrahimi }
7118*f5c631daSSadaf Ebrahimi 
TEST(bti)7119*f5c631daSSadaf Ebrahimi TEST(bti) {
7120*f5c631daSSadaf Ebrahimi   BtiHelper(x16);
7121*f5c631daSSadaf Ebrahimi   BtiHelper(x17);
7122*f5c631daSSadaf Ebrahimi }
7123*f5c631daSSadaf Ebrahimi 
TEST(unguarded_bti_is_nop)7124*f5c631daSSadaf Ebrahimi TEST(unguarded_bti_is_nop) {
7125*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7126*f5c631daSSadaf Ebrahimi 
7127*f5c631daSSadaf Ebrahimi   Label start, none, c, j, jc;
7128*f5c631daSSadaf Ebrahimi   START();
7129*f5c631daSSadaf Ebrahimi   __ B(&start);
7130*f5c631daSSadaf Ebrahimi   __ Bind(&none, EmitBTI);
7131*f5c631daSSadaf Ebrahimi   __ Bind(&c, EmitBTI_c);
7132*f5c631daSSadaf Ebrahimi   __ Bind(&j, EmitBTI_j);
7133*f5c631daSSadaf Ebrahimi   __ Bind(&jc, EmitBTI_jc);
7134*f5c631daSSadaf Ebrahimi   VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&none) == 4 * kInstructionSize);
7135*f5c631daSSadaf Ebrahimi   __ Ret();
7136*f5c631daSSadaf Ebrahimi 
7137*f5c631daSSadaf Ebrahimi   Label jump_to_c, call_to_j;
7138*f5c631daSSadaf Ebrahimi   __ Bind(&start);
7139*f5c631daSSadaf Ebrahimi   __ Adr(x0, &none);
7140*f5c631daSSadaf Ebrahimi   __ Adr(lr, &jump_to_c);
7141*f5c631daSSadaf Ebrahimi   __ Br(x0);
7142*f5c631daSSadaf Ebrahimi 
7143*f5c631daSSadaf Ebrahimi   __ Bind(&jump_to_c);
7144*f5c631daSSadaf Ebrahimi   __ Adr(x0, &c);
7145*f5c631daSSadaf Ebrahimi   __ Adr(lr, &call_to_j);
7146*f5c631daSSadaf Ebrahimi   __ Br(x0);
7147*f5c631daSSadaf Ebrahimi 
7148*f5c631daSSadaf Ebrahimi   __ Bind(&call_to_j);
7149*f5c631daSSadaf Ebrahimi   __ Adr(x0, &j);
7150*f5c631daSSadaf Ebrahimi   __ Blr(x0);
7151*f5c631daSSadaf Ebrahimi   END();
7152*f5c631daSSadaf Ebrahimi 
7153*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7154*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7155*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(false);
7156*f5c631daSSadaf Ebrahimi #else
7157*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7158*f5c631daSSadaf Ebrahimi #endif
7159*f5c631daSSadaf Ebrahimi     RUN();
7160*f5c631daSSadaf Ebrahimi   }
7161*f5c631daSSadaf Ebrahimi }
7162*f5c631daSSadaf Ebrahimi 
7163*f5c631daSSadaf Ebrahimi #ifdef VIXL_NEGATIVE_TESTING
TEST(bti_jump_to_ip_unidentified)7164*f5c631daSSadaf Ebrahimi TEST(bti_jump_to_ip_unidentified) {
7165*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7166*f5c631daSSadaf Ebrahimi 
7167*f5c631daSSadaf Ebrahimi   START();
7168*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
7169*f5c631daSSadaf Ebrahimi   temps.Exclude(x17);
7170*f5c631daSSadaf Ebrahimi   Label l;
7171*f5c631daSSadaf Ebrahimi   __ Adr(x17, &l);
7172*f5c631daSSadaf Ebrahimi   __ Br(x17);
7173*f5c631daSSadaf Ebrahimi   __ Nop();
7174*f5c631daSSadaf Ebrahimi   __ Bind(&l);
7175*f5c631daSSadaf Ebrahimi   __ Nop();
7176*f5c631daSSadaf Ebrahimi   END();
7177*f5c631daSSadaf Ebrahimi 
7178*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7179*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7180*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7181*f5c631daSSadaf Ebrahimi #else
7182*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7183*f5c631daSSadaf Ebrahimi #endif
7184*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(),
7185*f5c631daSSadaf Ebrahimi                            "Executing non-BTI instruction with wrong "
7186*f5c631daSSadaf Ebrahimi                            "BType.");
7187*f5c631daSSadaf Ebrahimi   }
7188*f5c631daSSadaf Ebrahimi }
7189*f5c631daSSadaf Ebrahimi 
TEST(bti_jump_to_unidentified)7190*f5c631daSSadaf Ebrahimi TEST(bti_jump_to_unidentified) {
7191*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7192*f5c631daSSadaf Ebrahimi 
7193*f5c631daSSadaf Ebrahimi   START();
7194*f5c631daSSadaf Ebrahimi   Label l;
7195*f5c631daSSadaf Ebrahimi   __ Adr(x0, &l);
7196*f5c631daSSadaf Ebrahimi   __ Br(x0);
7197*f5c631daSSadaf Ebrahimi   __ Nop();
7198*f5c631daSSadaf Ebrahimi   __ Bind(&l);
7199*f5c631daSSadaf Ebrahimi   __ Nop();
7200*f5c631daSSadaf Ebrahimi   END();
7201*f5c631daSSadaf Ebrahimi 
7202*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7203*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7204*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7205*f5c631daSSadaf Ebrahimi #else
7206*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7207*f5c631daSSadaf Ebrahimi #endif
7208*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(),
7209*f5c631daSSadaf Ebrahimi                            "Executing non-BTI instruction with wrong "
7210*f5c631daSSadaf Ebrahimi                            "BType.");
7211*f5c631daSSadaf Ebrahimi   }
7212*f5c631daSSadaf Ebrahimi }
7213*f5c631daSSadaf Ebrahimi 
TEST(bti_call_to_unidentified)7214*f5c631daSSadaf Ebrahimi TEST(bti_call_to_unidentified) {
7215*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7216*f5c631daSSadaf Ebrahimi 
7217*f5c631daSSadaf Ebrahimi   START();
7218*f5c631daSSadaf Ebrahimi   Label l;
7219*f5c631daSSadaf Ebrahimi   __ Adr(x0, &l);
7220*f5c631daSSadaf Ebrahimi   __ Blr(x0);
7221*f5c631daSSadaf Ebrahimi   __ Nop();
7222*f5c631daSSadaf Ebrahimi   __ Bind(&l);
7223*f5c631daSSadaf Ebrahimi   __ Nop();
7224*f5c631daSSadaf Ebrahimi   END();
7225*f5c631daSSadaf Ebrahimi 
7226*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7227*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7228*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7229*f5c631daSSadaf Ebrahimi #else
7230*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7231*f5c631daSSadaf Ebrahimi #endif
7232*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(),
7233*f5c631daSSadaf Ebrahimi                            "Executing non-BTI instruction with wrong "
7234*f5c631daSSadaf Ebrahimi                            "BType.");
7235*f5c631daSSadaf Ebrahimi   }
7236*f5c631daSSadaf Ebrahimi }
7237*f5c631daSSadaf Ebrahimi 
TEST(bti_jump_to_c)7238*f5c631daSSadaf Ebrahimi TEST(bti_jump_to_c) {
7239*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7240*f5c631daSSadaf Ebrahimi 
7241*f5c631daSSadaf Ebrahimi   START();
7242*f5c631daSSadaf Ebrahimi   // Jumping to a "BTI c" target must fail.
7243*f5c631daSSadaf Ebrahimi   Label jump_target;
7244*f5c631daSSadaf Ebrahimi   __ Adr(x0, &jump_target);
7245*f5c631daSSadaf Ebrahimi   __ Br(x0);
7246*f5c631daSSadaf Ebrahimi   __ Nop();
7247*f5c631daSSadaf Ebrahimi   __ Bind(&jump_target, EmitBTI_c);
7248*f5c631daSSadaf Ebrahimi   __ Nop();
7249*f5c631daSSadaf Ebrahimi   END();
7250*f5c631daSSadaf Ebrahimi 
7251*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7252*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7253*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7254*f5c631daSSadaf Ebrahimi #else
7255*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7256*f5c631daSSadaf Ebrahimi #endif
7257*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI c with wrong BType.");
7258*f5c631daSSadaf Ebrahimi   }
7259*f5c631daSSadaf Ebrahimi }
7260*f5c631daSSadaf Ebrahimi 
TEST(bti_call_to_j)7261*f5c631daSSadaf Ebrahimi TEST(bti_call_to_j) {
7262*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI);
7263*f5c631daSSadaf Ebrahimi 
7264*f5c631daSSadaf Ebrahimi   START();
7265*f5c631daSSadaf Ebrahimi   // Calling a "BTI j" target must fail.
7266*f5c631daSSadaf Ebrahimi   Label call_target;
7267*f5c631daSSadaf Ebrahimi   __ Adr(x0, &call_target);
7268*f5c631daSSadaf Ebrahimi   __ Blr(x0);
7269*f5c631daSSadaf Ebrahimi   __ Nop();
7270*f5c631daSSadaf Ebrahimi   __ Bind(&call_target, EmitBTI_j);
7271*f5c631daSSadaf Ebrahimi   __ Nop();
7272*f5c631daSSadaf Ebrahimi   END();
7273*f5c631daSSadaf Ebrahimi 
7274*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7275*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7276*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7277*f5c631daSSadaf Ebrahimi #else
7278*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7279*f5c631daSSadaf Ebrahimi #endif
7280*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI j with wrong BType.");
7281*f5c631daSSadaf Ebrahimi   }
7282*f5c631daSSadaf Ebrahimi }
7283*f5c631daSSadaf Ebrahimi #endif  // VIXL_NEGATIVE_TESTING
7284*f5c631daSSadaf Ebrahimi 
TEST(fall_through_bti)7285*f5c631daSSadaf Ebrahimi TEST(fall_through_bti) {
7286*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kBTI, CPUFeatures::kPAuth);
7287*f5c631daSSadaf Ebrahimi 
7288*f5c631daSSadaf Ebrahimi   START();
7289*f5c631daSSadaf Ebrahimi   Label target, target_j, target_c, target_jc;
7290*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);  // 'Normal' instruction sets BTYPE to zero.
7291*f5c631daSSadaf Ebrahimi   __ Bind(&target, EmitBTI);
7292*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
7293*f5c631daSSadaf Ebrahimi   __ Bind(&target_j, EmitBTI_j);
7294*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
7295*f5c631daSSadaf Ebrahimi   __ Bind(&target_c, EmitBTI_c);
7296*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
7297*f5c631daSSadaf Ebrahimi   __ Bind(&target_jc, EmitBTI_jc);
7298*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
7299*f5c631daSSadaf Ebrahimi   __ Paciasp();
7300*f5c631daSSadaf Ebrahimi   END();
7301*f5c631daSSadaf Ebrahimi 
7302*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7303*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
7304*f5c631daSSadaf Ebrahimi     simulator.SetGuardedPages(true);
7305*f5c631daSSadaf Ebrahimi #else
7306*f5c631daSSadaf Ebrahimi     VIXL_UNIMPLEMENTED();
7307*f5c631daSSadaf Ebrahimi #endif
7308*f5c631daSSadaf Ebrahimi     RUN();
7309*f5c631daSSadaf Ebrahimi 
7310*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(4, x0);
7311*f5c631daSSadaf Ebrahimi   }
7312*f5c631daSSadaf Ebrahimi }
7313*f5c631daSSadaf Ebrahimi 
TEST(zero_dest)7314*f5c631daSSadaf Ebrahimi TEST(zero_dest) {
7315*f5c631daSSadaf Ebrahimi   // RegisterDump::Dump uses NEON.
7316*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
7317*f5c631daSSadaf Ebrahimi   RegisterDump before;
7318*f5c631daSSadaf Ebrahimi 
7319*f5c631daSSadaf Ebrahimi   START();
7320*f5c631daSSadaf Ebrahimi   // Preserve the stack pointer, in case we clobber it.
7321*f5c631daSSadaf Ebrahimi   __ Mov(x30, sp);
7322*f5c631daSSadaf Ebrahimi   // Initialize the other registers used in this test.
7323*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
7324*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
7325*f5c631daSSadaf Ebrahimi   __ Mov(x1, literal_base);
7326*f5c631daSSadaf Ebrahimi   for (unsigned i = 2; i < x30.GetCode(); i++) {
7327*f5c631daSSadaf Ebrahimi     __ Add(XRegister(i), XRegister(i - 1), x1);
7328*f5c631daSSadaf Ebrahimi   }
7329*f5c631daSSadaf Ebrahimi   before.Dump(&masm);
7330*f5c631daSSadaf Ebrahimi 
7331*f5c631daSSadaf Ebrahimi   // All of these instructions should be NOPs in these forms, but have
7332*f5c631daSSadaf Ebrahimi   // alternate forms which can write into the stack pointer.
7333*f5c631daSSadaf Ebrahimi   {
7334*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 3 * 7 * kInstructionSize);
7335*f5c631daSSadaf Ebrahimi     __ add(xzr, x0, x1);
7336*f5c631daSSadaf Ebrahimi     __ add(xzr, x1, xzr);
7337*f5c631daSSadaf Ebrahimi     __ add(xzr, xzr, x1);
7338*f5c631daSSadaf Ebrahimi 
7339*f5c631daSSadaf Ebrahimi     __ and_(xzr, x0, x2);
7340*f5c631daSSadaf Ebrahimi     __ and_(xzr, x2, xzr);
7341*f5c631daSSadaf Ebrahimi     __ and_(xzr, xzr, x2);
7342*f5c631daSSadaf Ebrahimi 
7343*f5c631daSSadaf Ebrahimi     __ bic(xzr, x0, x3);
7344*f5c631daSSadaf Ebrahimi     __ bic(xzr, x3, xzr);
7345*f5c631daSSadaf Ebrahimi     __ bic(xzr, xzr, x3);
7346*f5c631daSSadaf Ebrahimi 
7347*f5c631daSSadaf Ebrahimi     __ eon(xzr, x0, x4);
7348*f5c631daSSadaf Ebrahimi     __ eon(xzr, x4, xzr);
7349*f5c631daSSadaf Ebrahimi     __ eon(xzr, xzr, x4);
7350*f5c631daSSadaf Ebrahimi 
7351*f5c631daSSadaf Ebrahimi     __ eor(xzr, x0, x5);
7352*f5c631daSSadaf Ebrahimi     __ eor(xzr, x5, xzr);
7353*f5c631daSSadaf Ebrahimi     __ eor(xzr, xzr, x5);
7354*f5c631daSSadaf Ebrahimi 
7355*f5c631daSSadaf Ebrahimi     __ orr(xzr, x0, x6);
7356*f5c631daSSadaf Ebrahimi     __ orr(xzr, x6, xzr);
7357*f5c631daSSadaf Ebrahimi     __ orr(xzr, xzr, x6);
7358*f5c631daSSadaf Ebrahimi 
7359*f5c631daSSadaf Ebrahimi     __ sub(xzr, x0, x7);
7360*f5c631daSSadaf Ebrahimi     __ sub(xzr, x7, xzr);
7361*f5c631daSSadaf Ebrahimi     __ sub(xzr, xzr, x7);
7362*f5c631daSSadaf Ebrahimi   }
7363*f5c631daSSadaf Ebrahimi 
7364*f5c631daSSadaf Ebrahimi   // Swap the saved stack pointer with the real one. If sp was written
7365*f5c631daSSadaf Ebrahimi   // during the test, it will show up in x30. This is done because the test
7366*f5c631daSSadaf Ebrahimi   // framework assumes that sp will be valid at the end of the test.
7367*f5c631daSSadaf Ebrahimi   __ Mov(x29, x30);
7368*f5c631daSSadaf Ebrahimi   __ Mov(x30, sp);
7369*f5c631daSSadaf Ebrahimi   __ Mov(sp, x29);
7370*f5c631daSSadaf Ebrahimi   // We used x29 as a scratch register, so reset it to make sure it doesn't
7371*f5c631daSSadaf Ebrahimi   // trigger a test failure.
7372*f5c631daSSadaf Ebrahimi   __ Add(x29, x28, x1);
7373*f5c631daSSadaf Ebrahimi   END();
7374*f5c631daSSadaf Ebrahimi 
7375*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7376*f5c631daSSadaf Ebrahimi     RUN();
7377*f5c631daSSadaf Ebrahimi 
7378*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_REGISTERS(before);
7379*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(before.flags_nzcv());
7380*f5c631daSSadaf Ebrahimi   }
7381*f5c631daSSadaf Ebrahimi }
7382*f5c631daSSadaf Ebrahimi 
7383*f5c631daSSadaf Ebrahimi 
TEST(zero_dest_setflags)7384*f5c631daSSadaf Ebrahimi TEST(zero_dest_setflags) {
7385*f5c631daSSadaf Ebrahimi   // RegisterDump::Dump uses NEON.
7386*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON);
7387*f5c631daSSadaf Ebrahimi   RegisterDump before;
7388*f5c631daSSadaf Ebrahimi 
7389*f5c631daSSadaf Ebrahimi   START();
7390*f5c631daSSadaf Ebrahimi   // Preserve the stack pointer, in case we clobber it.
7391*f5c631daSSadaf Ebrahimi   __ Mov(x30, sp);
7392*f5c631daSSadaf Ebrahimi   // Initialize the other registers used in this test.
7393*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
7394*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
7395*f5c631daSSadaf Ebrahimi   __ Mov(x1, literal_base);
7396*f5c631daSSadaf Ebrahimi   for (int i = 2; i < 30; i++) {
7397*f5c631daSSadaf Ebrahimi     __ Add(XRegister(i), XRegister(i - 1), x1);
7398*f5c631daSSadaf Ebrahimi   }
7399*f5c631daSSadaf Ebrahimi   before.Dump(&masm);
7400*f5c631daSSadaf Ebrahimi 
7401*f5c631daSSadaf Ebrahimi   // All of these instructions should only write to the flags in these forms,
7402*f5c631daSSadaf Ebrahimi   // but have alternate forms which can write into the stack pointer.
7403*f5c631daSSadaf Ebrahimi   {
7404*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 6 * kInstructionSize);
7405*f5c631daSSadaf Ebrahimi     __ adds(xzr, x0, Operand(x1, UXTX));
7406*f5c631daSSadaf Ebrahimi     __ adds(xzr, x1, Operand(xzr, UXTX));
7407*f5c631daSSadaf Ebrahimi     __ adds(xzr, x1, 1234);
7408*f5c631daSSadaf Ebrahimi     __ adds(xzr, x0, x1);
7409*f5c631daSSadaf Ebrahimi     __ adds(xzr, x1, xzr);
7410*f5c631daSSadaf Ebrahimi     __ adds(xzr, xzr, x1);
7411*f5c631daSSadaf Ebrahimi   }
7412*f5c631daSSadaf Ebrahimi 
7413*f5c631daSSadaf Ebrahimi   {
7414*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 5 * kInstructionSize);
7415*f5c631daSSadaf Ebrahimi     __ ands(xzr, x2, ~0xf);
7416*f5c631daSSadaf Ebrahimi     __ ands(xzr, xzr, ~0xf);
7417*f5c631daSSadaf Ebrahimi     __ ands(xzr, x0, x2);
7418*f5c631daSSadaf Ebrahimi     __ ands(xzr, x2, xzr);
7419*f5c631daSSadaf Ebrahimi     __ ands(xzr, xzr, x2);
7420*f5c631daSSadaf Ebrahimi   }
7421*f5c631daSSadaf Ebrahimi 
7422*f5c631daSSadaf Ebrahimi   {
7423*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 5 * kInstructionSize);
7424*f5c631daSSadaf Ebrahimi     __ bics(xzr, x3, ~0xf);
7425*f5c631daSSadaf Ebrahimi     __ bics(xzr, xzr, ~0xf);
7426*f5c631daSSadaf Ebrahimi     __ bics(xzr, x0, x3);
7427*f5c631daSSadaf Ebrahimi     __ bics(xzr, x3, xzr);
7428*f5c631daSSadaf Ebrahimi     __ bics(xzr, xzr, x3);
7429*f5c631daSSadaf Ebrahimi   }
7430*f5c631daSSadaf Ebrahimi 
7431*f5c631daSSadaf Ebrahimi   {
7432*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, 6 * kInstructionSize);
7433*f5c631daSSadaf Ebrahimi     __ subs(xzr, x0, Operand(x3, UXTX));
7434*f5c631daSSadaf Ebrahimi     __ subs(xzr, x3, Operand(xzr, UXTX));
7435*f5c631daSSadaf Ebrahimi     __ subs(xzr, x3, 1234);
7436*f5c631daSSadaf Ebrahimi     __ subs(xzr, x0, x3);
7437*f5c631daSSadaf Ebrahimi     __ subs(xzr, x3, xzr);
7438*f5c631daSSadaf Ebrahimi     __ subs(xzr, xzr, x3);
7439*f5c631daSSadaf Ebrahimi   }
7440*f5c631daSSadaf Ebrahimi 
7441*f5c631daSSadaf Ebrahimi   // Swap the saved stack pointer with the real one. If sp was written
7442*f5c631daSSadaf Ebrahimi   // during the test, it will show up in x30. This is done because the test
7443*f5c631daSSadaf Ebrahimi   // framework assumes that sp will be valid at the end of the test.
7444*f5c631daSSadaf Ebrahimi   __ Mov(x29, x30);
7445*f5c631daSSadaf Ebrahimi   __ Mov(x30, sp);
7446*f5c631daSSadaf Ebrahimi   __ Mov(sp, x29);
7447*f5c631daSSadaf Ebrahimi   // We used x29 as a scratch register, so reset it to make sure it doesn't
7448*f5c631daSSadaf Ebrahimi   // trigger a test failure.
7449*f5c631daSSadaf Ebrahimi   __ Add(x29, x28, x1);
7450*f5c631daSSadaf Ebrahimi   END();
7451*f5c631daSSadaf Ebrahimi 
7452*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7453*f5c631daSSadaf Ebrahimi     RUN();
7454*f5c631daSSadaf Ebrahimi 
7455*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_REGISTERS(before);
7456*f5c631daSSadaf Ebrahimi   }
7457*f5c631daSSadaf Ebrahimi }
7458*f5c631daSSadaf Ebrahimi 
7459*f5c631daSSadaf Ebrahimi 
TEST(stack_pointer_override)7460*f5c631daSSadaf Ebrahimi TEST(stack_pointer_override) {
7461*f5c631daSSadaf Ebrahimi   // This test generates some stack maintenance code, but the test only checks
7462*f5c631daSSadaf Ebrahimi   // the reported state.
7463*f5c631daSSadaf Ebrahimi   SETUP();
7464*f5c631daSSadaf Ebrahimi   START();
7465*f5c631daSSadaf Ebrahimi 
7466*f5c631daSSadaf Ebrahimi   // The default stack pointer in VIXL is sp.
7467*f5c631daSSadaf Ebrahimi   VIXL_CHECK(sp.Is(__ StackPointer()));
7468*f5c631daSSadaf Ebrahimi   __ SetStackPointer(x0);
7469*f5c631daSSadaf Ebrahimi   VIXL_CHECK(x0.Is(__ StackPointer()));
7470*f5c631daSSadaf Ebrahimi   __ SetStackPointer(x28);
7471*f5c631daSSadaf Ebrahimi   VIXL_CHECK(x28.Is(__ StackPointer()));
7472*f5c631daSSadaf Ebrahimi   __ SetStackPointer(sp);
7473*f5c631daSSadaf Ebrahimi   VIXL_CHECK(sp.Is(__ StackPointer()));
7474*f5c631daSSadaf Ebrahimi 
7475*f5c631daSSadaf Ebrahimi   END();
7476*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7477*f5c631daSSadaf Ebrahimi     RUN();
7478*f5c631daSSadaf Ebrahimi   }
7479*f5c631daSSadaf Ebrahimi }
7480*f5c631daSSadaf Ebrahimi 
7481*f5c631daSSadaf Ebrahimi 
TEST(peek_poke_simple)7482*f5c631daSSadaf Ebrahimi TEST(peek_poke_simple) {
7483*f5c631daSSadaf Ebrahimi   SETUP();
7484*f5c631daSSadaf Ebrahimi   START();
7485*f5c631daSSadaf Ebrahimi 
7486*f5c631daSSadaf Ebrahimi   static const RegList x0_to_x3 =
7487*f5c631daSSadaf Ebrahimi       x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit();
7488*f5c631daSSadaf Ebrahimi   static const RegList x10_to_x13 =
7489*f5c631daSSadaf Ebrahimi       x10.GetBit() | x11.GetBit() | x12.GetBit() | x13.GetBit();
7490*f5c631daSSadaf Ebrahimi 
7491*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
7492*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
7493*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
7494*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
7495*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
7496*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
7497*f5c631daSSadaf Ebrahimi 
7498*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7499*f5c631daSSadaf Ebrahimi   __ Mov(x0, literal_base);
7500*f5c631daSSadaf Ebrahimi   __ Add(x1, x0, x0);
7501*f5c631daSSadaf Ebrahimi   __ Add(x2, x1, x0);
7502*f5c631daSSadaf Ebrahimi   __ Add(x3, x2, x0);
7503*f5c631daSSadaf Ebrahimi 
7504*f5c631daSSadaf Ebrahimi   __ Claim(32);
7505*f5c631daSSadaf Ebrahimi 
7506*f5c631daSSadaf Ebrahimi   // Simple exchange.
7507*f5c631daSSadaf Ebrahimi   //  After this test:
7508*f5c631daSSadaf Ebrahimi   //    x0-x3 should be unchanged.
7509*f5c631daSSadaf Ebrahimi   //    w10-w13 should contain the lower words of x0-x3.
7510*f5c631daSSadaf Ebrahimi   __ Poke(x0, 0);
7511*f5c631daSSadaf Ebrahimi   __ Poke(x1, 8);
7512*f5c631daSSadaf Ebrahimi   __ Poke(x2, 16);
7513*f5c631daSSadaf Ebrahimi   __ Poke(x3, 24);
7514*f5c631daSSadaf Ebrahimi   Clobber(&masm, x0_to_x3);
7515*f5c631daSSadaf Ebrahimi   __ Peek(x0, 0);
7516*f5c631daSSadaf Ebrahimi   __ Peek(x1, 8);
7517*f5c631daSSadaf Ebrahimi   __ Peek(x2, 16);
7518*f5c631daSSadaf Ebrahimi   __ Peek(x3, 24);
7519*f5c631daSSadaf Ebrahimi 
7520*f5c631daSSadaf Ebrahimi   __ Poke(w0, 0);
7521*f5c631daSSadaf Ebrahimi   __ Poke(w1, 4);
7522*f5c631daSSadaf Ebrahimi   __ Poke(w2, 8);
7523*f5c631daSSadaf Ebrahimi   __ Poke(w3, 12);
7524*f5c631daSSadaf Ebrahimi   Clobber(&masm, x10_to_x13);
7525*f5c631daSSadaf Ebrahimi   __ Peek(w10, 0);
7526*f5c631daSSadaf Ebrahimi   __ Peek(w11, 4);
7527*f5c631daSSadaf Ebrahimi   __ Peek(w12, 8);
7528*f5c631daSSadaf Ebrahimi   __ Peek(w13, 12);
7529*f5c631daSSadaf Ebrahimi 
7530*f5c631daSSadaf Ebrahimi   __ Drop(32);
7531*f5c631daSSadaf Ebrahimi 
7532*f5c631daSSadaf Ebrahimi   END();
7533*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7534*f5c631daSSadaf Ebrahimi     RUN();
7535*f5c631daSSadaf Ebrahimi 
7536*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 1, x0);
7537*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 2, x1);
7538*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 3, x2);
7539*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 4, x3);
7540*f5c631daSSadaf Ebrahimi 
7541*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
7542*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
7543*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
7544*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 4) & 0xffffffff, x13);
7545*f5c631daSSadaf Ebrahimi   }
7546*f5c631daSSadaf Ebrahimi }
7547*f5c631daSSadaf Ebrahimi 
7548*f5c631daSSadaf Ebrahimi 
TEST(peek_poke_unaligned)7549*f5c631daSSadaf Ebrahimi TEST(peek_poke_unaligned) {
7550*f5c631daSSadaf Ebrahimi   SETUP();
7551*f5c631daSSadaf Ebrahimi   START();
7552*f5c631daSSadaf Ebrahimi 
7553*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
7554*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
7555*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
7556*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
7557*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
7558*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
7559*f5c631daSSadaf Ebrahimi 
7560*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7561*f5c631daSSadaf Ebrahimi   __ Mov(x0, literal_base);
7562*f5c631daSSadaf Ebrahimi   __ Add(x1, x0, x0);
7563*f5c631daSSadaf Ebrahimi   __ Add(x2, x1, x0);
7564*f5c631daSSadaf Ebrahimi   __ Add(x3, x2, x0);
7565*f5c631daSSadaf Ebrahimi   __ Add(x4, x3, x0);
7566*f5c631daSSadaf Ebrahimi   __ Add(x5, x4, x0);
7567*f5c631daSSadaf Ebrahimi   __ Add(x6, x5, x0);
7568*f5c631daSSadaf Ebrahimi 
7569*f5c631daSSadaf Ebrahimi   __ Claim(32);
7570*f5c631daSSadaf Ebrahimi 
7571*f5c631daSSadaf Ebrahimi   // Unaligned exchanges.
7572*f5c631daSSadaf Ebrahimi   //  After this test:
7573*f5c631daSSadaf Ebrahimi   //    x0-x6 should be unchanged.
7574*f5c631daSSadaf Ebrahimi   //    w10-w12 should contain the lower words of x0-x2.
7575*f5c631daSSadaf Ebrahimi   __ Poke(x0, 1);
7576*f5c631daSSadaf Ebrahimi   Clobber(&masm, x0.GetBit());
7577*f5c631daSSadaf Ebrahimi   __ Peek(x0, 1);
7578*f5c631daSSadaf Ebrahimi   __ Poke(x1, 2);
7579*f5c631daSSadaf Ebrahimi   Clobber(&masm, x1.GetBit());
7580*f5c631daSSadaf Ebrahimi   __ Peek(x1, 2);
7581*f5c631daSSadaf Ebrahimi   __ Poke(x2, 3);
7582*f5c631daSSadaf Ebrahimi   Clobber(&masm, x2.GetBit());
7583*f5c631daSSadaf Ebrahimi   __ Peek(x2, 3);
7584*f5c631daSSadaf Ebrahimi   __ Poke(x3, 4);
7585*f5c631daSSadaf Ebrahimi   Clobber(&masm, x3.GetBit());
7586*f5c631daSSadaf Ebrahimi   __ Peek(x3, 4);
7587*f5c631daSSadaf Ebrahimi   __ Poke(x4, 5);
7588*f5c631daSSadaf Ebrahimi   Clobber(&masm, x4.GetBit());
7589*f5c631daSSadaf Ebrahimi   __ Peek(x4, 5);
7590*f5c631daSSadaf Ebrahimi   __ Poke(x5, 6);
7591*f5c631daSSadaf Ebrahimi   Clobber(&masm, x5.GetBit());
7592*f5c631daSSadaf Ebrahimi   __ Peek(x5, 6);
7593*f5c631daSSadaf Ebrahimi   __ Poke(x6, 7);
7594*f5c631daSSadaf Ebrahimi   Clobber(&masm, x6.GetBit());
7595*f5c631daSSadaf Ebrahimi   __ Peek(x6, 7);
7596*f5c631daSSadaf Ebrahimi 
7597*f5c631daSSadaf Ebrahimi   __ Poke(w0, 1);
7598*f5c631daSSadaf Ebrahimi   Clobber(&masm, w10.GetBit());
7599*f5c631daSSadaf Ebrahimi   __ Peek(w10, 1);
7600*f5c631daSSadaf Ebrahimi   __ Poke(w1, 2);
7601*f5c631daSSadaf Ebrahimi   Clobber(&masm, w11.GetBit());
7602*f5c631daSSadaf Ebrahimi   __ Peek(w11, 2);
7603*f5c631daSSadaf Ebrahimi   __ Poke(w2, 3);
7604*f5c631daSSadaf Ebrahimi   Clobber(&masm, w12.GetBit());
7605*f5c631daSSadaf Ebrahimi   __ Peek(w12, 3);
7606*f5c631daSSadaf Ebrahimi 
7607*f5c631daSSadaf Ebrahimi   __ Drop(32);
7608*f5c631daSSadaf Ebrahimi 
7609*f5c631daSSadaf Ebrahimi   END();
7610*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7611*f5c631daSSadaf Ebrahimi     RUN();
7612*f5c631daSSadaf Ebrahimi 
7613*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 1, x0);
7614*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 2, x1);
7615*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 3, x2);
7616*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 4, x3);
7617*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 5, x4);
7618*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 6, x5);
7619*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 7, x6);
7620*f5c631daSSadaf Ebrahimi 
7621*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
7622*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
7623*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
7624*f5c631daSSadaf Ebrahimi   }
7625*f5c631daSSadaf Ebrahimi }
7626*f5c631daSSadaf Ebrahimi 
7627*f5c631daSSadaf Ebrahimi 
TEST(peek_poke_endianness)7628*f5c631daSSadaf Ebrahimi TEST(peek_poke_endianness) {
7629*f5c631daSSadaf Ebrahimi   SETUP();
7630*f5c631daSSadaf Ebrahimi   START();
7631*f5c631daSSadaf Ebrahimi 
7632*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
7633*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
7634*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
7635*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
7636*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
7637*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
7638*f5c631daSSadaf Ebrahimi 
7639*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7640*f5c631daSSadaf Ebrahimi   __ Mov(x0, literal_base);
7641*f5c631daSSadaf Ebrahimi   __ Add(x1, x0, x0);
7642*f5c631daSSadaf Ebrahimi 
7643*f5c631daSSadaf Ebrahimi   __ Claim(32);
7644*f5c631daSSadaf Ebrahimi 
7645*f5c631daSSadaf Ebrahimi   // Endianness tests.
7646*f5c631daSSadaf Ebrahimi   //  After this section:
7647*f5c631daSSadaf Ebrahimi   //    x4 should match x0[31:0]:x0[63:32]
7648*f5c631daSSadaf Ebrahimi   //    w5 should match w1[15:0]:w1[31:16]
7649*f5c631daSSadaf Ebrahimi   __ Poke(x0, 0);
7650*f5c631daSSadaf Ebrahimi   __ Poke(x0, 8);
7651*f5c631daSSadaf Ebrahimi   __ Peek(x4, 4);
7652*f5c631daSSadaf Ebrahimi 
7653*f5c631daSSadaf Ebrahimi   __ Poke(w1, 0);
7654*f5c631daSSadaf Ebrahimi   __ Poke(w1, 4);
7655*f5c631daSSadaf Ebrahimi   __ Peek(w5, 2);
7656*f5c631daSSadaf Ebrahimi 
7657*f5c631daSSadaf Ebrahimi   __ Drop(32);
7658*f5c631daSSadaf Ebrahimi 
7659*f5c631daSSadaf Ebrahimi   END();
7660*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7661*f5c631daSSadaf Ebrahimi     RUN();
7662*f5c631daSSadaf Ebrahimi 
7663*f5c631daSSadaf Ebrahimi     uint64_t x0_expected = literal_base * 1;
7664*f5c631daSSadaf Ebrahimi     uint64_t x1_expected = literal_base * 2;
7665*f5c631daSSadaf Ebrahimi     uint64_t x4_expected = (x0_expected << 32) | (x0_expected >> 32);
7666*f5c631daSSadaf Ebrahimi     uint64_t x5_expected =
7667*f5c631daSSadaf Ebrahimi         ((x1_expected << 16) & 0xffff0000) | ((x1_expected >> 16) & 0x0000ffff);
7668*f5c631daSSadaf Ebrahimi 
7669*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x0_expected, x0);
7670*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x1_expected, x1);
7671*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x4_expected, x4);
7672*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x5_expected, x5);
7673*f5c631daSSadaf Ebrahimi   }
7674*f5c631daSSadaf Ebrahimi }
7675*f5c631daSSadaf Ebrahimi 
7676*f5c631daSSadaf Ebrahimi 
TEST(peek_poke_mixed)7677*f5c631daSSadaf Ebrahimi TEST(peek_poke_mixed) {
7678*f5c631daSSadaf Ebrahimi   SETUP();
7679*f5c631daSSadaf Ebrahimi   START();
7680*f5c631daSSadaf Ebrahimi 
7681*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
7682*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
7683*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
7684*f5c631daSSadaf Ebrahimi 
7685*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
7686*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
7687*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
7688*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
7689*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
7690*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
7691*f5c631daSSadaf Ebrahimi 
7692*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7693*f5c631daSSadaf Ebrahimi   __ Mov(x0, literal_base);
7694*f5c631daSSadaf Ebrahimi   __ Add(x1, x0, x0);
7695*f5c631daSSadaf Ebrahimi   __ Add(x2, x1, x0);
7696*f5c631daSSadaf Ebrahimi   __ Add(x3, x2, x0);
7697*f5c631daSSadaf Ebrahimi 
7698*f5c631daSSadaf Ebrahimi   __ Claim(32);
7699*f5c631daSSadaf Ebrahimi 
7700*f5c631daSSadaf Ebrahimi   // Mix with other stack operations.
7701*f5c631daSSadaf Ebrahimi   //  After this section:
7702*f5c631daSSadaf Ebrahimi   //    x0-x3 should be unchanged.
7703*f5c631daSSadaf Ebrahimi   //    x6 should match x1[31:0]:x0[63:32]
7704*f5c631daSSadaf Ebrahimi   //    w7 should match x1[15:0]:x0[63:48]
7705*f5c631daSSadaf Ebrahimi   __ Poke(x1, 8);
7706*f5c631daSSadaf Ebrahimi   __ Poke(x0, 0);
7707*f5c631daSSadaf Ebrahimi   {
7708*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(__ StackPointer().Is(sp));
7709*f5c631daSSadaf Ebrahimi     __ Mov(x4, __ StackPointer());
7710*f5c631daSSadaf Ebrahimi     __ SetStackPointer(x4);
7711*f5c631daSSadaf Ebrahimi 
7712*f5c631daSSadaf Ebrahimi     __ Poke(wzr, 0);  // Clobber the space we're about to drop.
7713*f5c631daSSadaf Ebrahimi     __ Drop(4);
7714*f5c631daSSadaf Ebrahimi     __ Peek(x6, 0);
7715*f5c631daSSadaf Ebrahimi     __ Claim(8);
7716*f5c631daSSadaf Ebrahimi     __ Peek(w7, 10);
7717*f5c631daSSadaf Ebrahimi     __ Poke(x3, 28);
7718*f5c631daSSadaf Ebrahimi     __ Poke(xzr, 0);  // Clobber the space we're about to drop.
7719*f5c631daSSadaf Ebrahimi     __ Drop(8);
7720*f5c631daSSadaf Ebrahimi     __ Poke(x2, 12);
7721*f5c631daSSadaf Ebrahimi     __ Push(w0);
7722*f5c631daSSadaf Ebrahimi 
7723*f5c631daSSadaf Ebrahimi     __ Mov(sp, __ StackPointer());
7724*f5c631daSSadaf Ebrahimi     __ SetStackPointer(sp);
7725*f5c631daSSadaf Ebrahimi   }
7726*f5c631daSSadaf Ebrahimi 
7727*f5c631daSSadaf Ebrahimi   __ Pop(x0, x1, x2, x3);
7728*f5c631daSSadaf Ebrahimi 
7729*f5c631daSSadaf Ebrahimi   END();
7730*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7731*f5c631daSSadaf Ebrahimi     RUN();
7732*f5c631daSSadaf Ebrahimi 
7733*f5c631daSSadaf Ebrahimi     uint64_t x0_expected = literal_base * 1;
7734*f5c631daSSadaf Ebrahimi     uint64_t x1_expected = literal_base * 2;
7735*f5c631daSSadaf Ebrahimi     uint64_t x2_expected = literal_base * 3;
7736*f5c631daSSadaf Ebrahimi     uint64_t x3_expected = literal_base * 4;
7737*f5c631daSSadaf Ebrahimi     uint64_t x6_expected = (x1_expected << 32) | (x0_expected >> 32);
7738*f5c631daSSadaf Ebrahimi     uint64_t x7_expected =
7739*f5c631daSSadaf Ebrahimi         ((x1_expected << 16) & 0xffff0000) | ((x0_expected >> 48) & 0x0000ffff);
7740*f5c631daSSadaf Ebrahimi 
7741*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x0_expected, x0);
7742*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x1_expected, x1);
7743*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x2_expected, x2);
7744*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x3_expected, x3);
7745*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x6_expected, x6);
7746*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(x7_expected, x7);
7747*f5c631daSSadaf Ebrahimi   }
7748*f5c631daSSadaf Ebrahimi }
7749*f5c631daSSadaf Ebrahimi 
7750*f5c631daSSadaf Ebrahimi 
TEST(peek_poke_reglist)7751*f5c631daSSadaf Ebrahimi TEST(peek_poke_reglist) {
7752*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
7753*f5c631daSSadaf Ebrahimi 
7754*f5c631daSSadaf Ebrahimi   START();
7755*f5c631daSSadaf Ebrahimi 
7756*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
7757*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
7758*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
7759*f5c631daSSadaf Ebrahimi 
7760*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
7761*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
7762*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
7763*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
7764*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
7765*f5c631daSSadaf Ebrahimi   uint64_t base = 0x0100001000100101;
7766*f5c631daSSadaf Ebrahimi 
7767*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7768*f5c631daSSadaf Ebrahimi   __ Mov(x1, base);
7769*f5c631daSSadaf Ebrahimi   __ Add(x2, x1, x1);
7770*f5c631daSSadaf Ebrahimi   __ Add(x3, x2, x1);
7771*f5c631daSSadaf Ebrahimi   __ Add(x4, x3, x1);
7772*f5c631daSSadaf Ebrahimi 
7773*f5c631daSSadaf Ebrahimi   CPURegList list_1(x1, x2, x3, x4);
7774*f5c631daSSadaf Ebrahimi   CPURegList list_2(x11, x12, x13, x14);
7775*f5c631daSSadaf Ebrahimi   int list_1_size = list_1.GetTotalSizeInBytes();
7776*f5c631daSSadaf Ebrahimi 
7777*f5c631daSSadaf Ebrahimi   __ Claim(2 * list_1_size);
7778*f5c631daSSadaf Ebrahimi 
7779*f5c631daSSadaf Ebrahimi   __ PokeCPURegList(list_1, 0);
7780*f5c631daSSadaf Ebrahimi   __ PokeXRegList(list_1.GetList(), list_1_size);
7781*f5c631daSSadaf Ebrahimi   __ PeekCPURegList(list_2, 2 * kXRegSizeInBytes);
7782*f5c631daSSadaf Ebrahimi   __ PeekXRegList(x15.GetBit(), kWRegSizeInBytes);
7783*f5c631daSSadaf Ebrahimi   __ PeekWRegList(w16.GetBit() | w17.GetBit(), 3 * kXRegSizeInBytes);
7784*f5c631daSSadaf Ebrahimi 
7785*f5c631daSSadaf Ebrahimi   __ Drop(2 * list_1_size);
7786*f5c631daSSadaf Ebrahimi 
7787*f5c631daSSadaf Ebrahimi 
7788*f5c631daSSadaf Ebrahimi   uint64_t base_d = 0x1010010001000010;
7789*f5c631daSSadaf Ebrahimi 
7790*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7791*f5c631daSSadaf Ebrahimi   __ Mov(x1, base_d);
7792*f5c631daSSadaf Ebrahimi   __ Add(x2, x1, x1);
7793*f5c631daSSadaf Ebrahimi   __ Add(x3, x2, x1);
7794*f5c631daSSadaf Ebrahimi   __ Add(x4, x3, x1);
7795*f5c631daSSadaf Ebrahimi   __ Fmov(d1, x1);
7796*f5c631daSSadaf Ebrahimi   __ Fmov(d2, x2);
7797*f5c631daSSadaf Ebrahimi   __ Fmov(d3, x3);
7798*f5c631daSSadaf Ebrahimi   __ Fmov(d4, x4);
7799*f5c631daSSadaf Ebrahimi 
7800*f5c631daSSadaf Ebrahimi   CPURegList list_d_1(d1, d2, d3, d4);
7801*f5c631daSSadaf Ebrahimi   CPURegList list_d_2(d11, d12, d13, d14);
7802*f5c631daSSadaf Ebrahimi   int list_d_1_size = list_d_1.GetTotalSizeInBytes();
7803*f5c631daSSadaf Ebrahimi 
7804*f5c631daSSadaf Ebrahimi   __ Claim(2 * list_d_1_size);
7805*f5c631daSSadaf Ebrahimi 
7806*f5c631daSSadaf Ebrahimi   __ PokeCPURegList(list_d_1, 0);
7807*f5c631daSSadaf Ebrahimi   __ PokeDRegList(list_d_1.GetList(), list_d_1_size);
7808*f5c631daSSadaf Ebrahimi   __ PeekCPURegList(list_d_2, 2 * kDRegSizeInBytes);
7809*f5c631daSSadaf Ebrahimi   __ PeekDRegList(d15.GetBit(), kSRegSizeInBytes);
7810*f5c631daSSadaf Ebrahimi   __ PeekSRegList(s16.GetBit() | s17.GetBit(), 3 * kDRegSizeInBytes);
7811*f5c631daSSadaf Ebrahimi 
7812*f5c631daSSadaf Ebrahimi   __ Drop(2 * list_d_1_size);
7813*f5c631daSSadaf Ebrahimi 
7814*f5c631daSSadaf Ebrahimi 
7815*f5c631daSSadaf Ebrahimi   END();
7816*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7817*f5c631daSSadaf Ebrahimi     RUN();
7818*f5c631daSSadaf Ebrahimi 
7819*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3 * base, x11);
7820*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(4 * base, x12);
7821*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1 * base, x13);
7822*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2 * base, x14);
7823*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(((1 * base) >> kWRegSize) | ((2 * base) << kWRegSize), x15);
7824*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2 * base, x14);
7825*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32((4 * base) & kWRegMask, w16);
7826*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32((4 * base) >> kWRegSize, w17);
7827*f5c631daSSadaf Ebrahimi 
7828*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base_d), d11);
7829*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base_d), d12);
7830*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base_d), d13);
7831*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14);
7832*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble((base_d >> kSRegSize) |
7833*f5c631daSSadaf Ebrahimi                                       ((2 * base_d) << kSRegSize)),
7834*f5c631daSSadaf Ebrahimi                       d15);
7835*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14);
7836*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) & kSRegMask), s16);
7837*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) >> kSRegSize), s17);
7838*f5c631daSSadaf Ebrahimi   }
7839*f5c631daSSadaf Ebrahimi }
7840*f5c631daSSadaf Ebrahimi 
7841*f5c631daSSadaf Ebrahimi 
TEST(load_store_reglist)7842*f5c631daSSadaf Ebrahimi TEST(load_store_reglist) {
7843*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
7844*f5c631daSSadaf Ebrahimi 
7845*f5c631daSSadaf Ebrahimi   START();
7846*f5c631daSSadaf Ebrahimi 
7847*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
7848*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
7849*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
7850*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
7851*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
7852*f5c631daSSadaf Ebrahimi   uint64_t high_base = UINT32_C(0x01000010);
7853*f5c631daSSadaf Ebrahimi   uint64_t low_base = UINT32_C(0x00100101);
7854*f5c631daSSadaf Ebrahimi   uint64_t base = (high_base << 32) | low_base;
7855*f5c631daSSadaf Ebrahimi   uint64_t array[21];
7856*f5c631daSSadaf Ebrahimi   memset(array, 0, sizeof(array));
7857*f5c631daSSadaf Ebrahimi 
7858*f5c631daSSadaf Ebrahimi   // Initialize the registers.
7859*f5c631daSSadaf Ebrahimi   __ Mov(x1, base);
7860*f5c631daSSadaf Ebrahimi   __ Add(x2, x1, x1);
7861*f5c631daSSadaf Ebrahimi   __ Add(x3, x2, x1);
7862*f5c631daSSadaf Ebrahimi   __ Add(x4, x3, x1);
7863*f5c631daSSadaf Ebrahimi   __ Fmov(d1, x1);
7864*f5c631daSSadaf Ebrahimi   __ Fmov(d2, x2);
7865*f5c631daSSadaf Ebrahimi   __ Fmov(d3, x3);
7866*f5c631daSSadaf Ebrahimi   __ Fmov(d4, x4);
7867*f5c631daSSadaf Ebrahimi   __ Fmov(d5, x1);
7868*f5c631daSSadaf Ebrahimi   __ Fmov(d6, x2);
7869*f5c631daSSadaf Ebrahimi   __ Fmov(d7, x3);
7870*f5c631daSSadaf Ebrahimi   __ Fmov(d8, x4);
7871*f5c631daSSadaf Ebrahimi 
7872*f5c631daSSadaf Ebrahimi   Register reg_base = x20;
7873*f5c631daSSadaf Ebrahimi   Register reg_index = x21;
7874*f5c631daSSadaf Ebrahimi   int size_stored = 0;
7875*f5c631daSSadaf Ebrahimi 
7876*f5c631daSSadaf Ebrahimi   __ Mov(reg_base, reinterpret_cast<uintptr_t>(&array));
7877*f5c631daSSadaf Ebrahimi 
7878*f5c631daSSadaf Ebrahimi   // Test aligned accesses.
7879*f5c631daSSadaf Ebrahimi   CPURegList list_src(w1, w2, w3, w4);
7880*f5c631daSSadaf Ebrahimi   CPURegList list_dst(w11, w12, w13, w14);
7881*f5c631daSSadaf Ebrahimi   CPURegList list_fp_src_1(d1, d2, d3, d4);
7882*f5c631daSSadaf Ebrahimi   CPURegList list_fp_dst_1(d11, d12, d13, d14);
7883*f5c631daSSadaf Ebrahimi 
7884*f5c631daSSadaf Ebrahimi   __ StoreCPURegList(list_src, MemOperand(reg_base, 0 * sizeof(uint64_t)));
7885*f5c631daSSadaf Ebrahimi   __ LoadCPURegList(list_dst, MemOperand(reg_base, 0 * sizeof(uint64_t)));
7886*f5c631daSSadaf Ebrahimi   size_stored += 4 * kWRegSizeInBytes;
7887*f5c631daSSadaf Ebrahimi 
7888*f5c631daSSadaf Ebrahimi   __ Mov(reg_index, size_stored);
7889*f5c631daSSadaf Ebrahimi   __ StoreCPURegList(list_src, MemOperand(reg_base, reg_index));
7890*f5c631daSSadaf Ebrahimi   __ LoadCPURegList(list_dst, MemOperand(reg_base, reg_index));
7891*f5c631daSSadaf Ebrahimi   size_stored += 4 * kWRegSizeInBytes;
7892*f5c631daSSadaf Ebrahimi 
7893*f5c631daSSadaf Ebrahimi   __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, size_stored));
7894*f5c631daSSadaf Ebrahimi   __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, size_stored));
7895*f5c631daSSadaf Ebrahimi   size_stored += 4 * kDRegSizeInBytes;
7896*f5c631daSSadaf Ebrahimi 
7897*f5c631daSSadaf Ebrahimi   __ Mov(reg_index, size_stored);
7898*f5c631daSSadaf Ebrahimi   __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, reg_index));
7899*f5c631daSSadaf Ebrahimi   __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, reg_index));
7900*f5c631daSSadaf Ebrahimi   size_stored += 4 * kDRegSizeInBytes;
7901*f5c631daSSadaf Ebrahimi 
7902*f5c631daSSadaf Ebrahimi   // Test unaligned accesses.
7903*f5c631daSSadaf Ebrahimi   CPURegList list_fp_src_2(d5, d6, d7, d8);
7904*f5c631daSSadaf Ebrahimi   CPURegList list_fp_dst_2(d15, d16, d17, d18);
7905*f5c631daSSadaf Ebrahimi 
7906*f5c631daSSadaf Ebrahimi   __ Str(wzr, MemOperand(reg_base, size_stored));
7907*f5c631daSSadaf Ebrahimi   size_stored += 1 * kWRegSizeInBytes;
7908*f5c631daSSadaf Ebrahimi   __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, size_stored));
7909*f5c631daSSadaf Ebrahimi   __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, size_stored));
7910*f5c631daSSadaf Ebrahimi   size_stored += 4 * kDRegSizeInBytes;
7911*f5c631daSSadaf Ebrahimi 
7912*f5c631daSSadaf Ebrahimi   __ Mov(reg_index, size_stored);
7913*f5c631daSSadaf Ebrahimi   __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, reg_index));
7914*f5c631daSSadaf Ebrahimi   __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, reg_index));
7915*f5c631daSSadaf Ebrahimi 
7916*f5c631daSSadaf Ebrahimi   END();
7917*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
7918*f5c631daSSadaf Ebrahimi     RUN();
7919*f5c631daSSadaf Ebrahimi 
7920*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[0] == (1 * low_base) + (2 * low_base << kWRegSize));
7921*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[1] == (3 * low_base) + (4 * low_base << kWRegSize));
7922*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[2] == (1 * low_base) + (2 * low_base << kWRegSize));
7923*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[3] == (3 * low_base) + (4 * low_base << kWRegSize));
7924*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[4] == 1 * base);
7925*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[5] == 2 * base);
7926*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[6] == 3 * base);
7927*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[7] == 4 * base);
7928*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[8] == 1 * base);
7929*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[9] == 2 * base);
7930*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[10] == 3 * base);
7931*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[11] == 4 * base);
7932*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[12] == ((1 * low_base) << kSRegSize));
7933*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[13] == (((2 * low_base) << kSRegSize) | (1 * high_base)));
7934*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[14] == (((3 * low_base) << kSRegSize) | (2 * high_base)));
7935*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[15] == (((4 * low_base) << kSRegSize) | (3 * high_base)));
7936*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[16] == (((1 * low_base) << kSRegSize) | (4 * high_base)));
7937*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[17] == (((2 * low_base) << kSRegSize) | (1 * high_base)));
7938*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[18] == (((3 * low_base) << kSRegSize) | (2 * high_base)));
7939*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[19] == (((4 * low_base) << kSRegSize) | (3 * high_base)));
7940*f5c631daSSadaf Ebrahimi     VIXL_CHECK(array[20] == (4 * high_base));
7941*f5c631daSSadaf Ebrahimi 
7942*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1 * low_base, x11);
7943*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2 * low_base, x12);
7944*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3 * low_base, x13);
7945*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(4 * low_base, x14);
7946*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d11);
7947*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d12);
7948*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d13);
7949*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d14);
7950*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d15);
7951*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d16);
7952*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d17);
7953*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d18);
7954*f5c631daSSadaf Ebrahimi   }
7955*f5c631daSSadaf Ebrahimi }
7956*f5c631daSSadaf Ebrahimi 
7957*f5c631daSSadaf Ebrahimi 
7958*f5c631daSSadaf Ebrahimi // This enum is used only as an argument to the push-pop test helpers.
7959*f5c631daSSadaf Ebrahimi enum PushPopMethod {
7960*f5c631daSSadaf Ebrahimi   // Push or Pop using the Push and Pop methods, with blocks of up to four
7961*f5c631daSSadaf Ebrahimi   // registers. (Smaller blocks will be used if necessary.)
7962*f5c631daSSadaf Ebrahimi   PushPopByFour,
7963*f5c631daSSadaf Ebrahimi 
7964*f5c631daSSadaf Ebrahimi   // Use Push<Size>RegList and Pop<Size>RegList to transfer the registers.
7965*f5c631daSSadaf Ebrahimi   PushPopRegList
7966*f5c631daSSadaf Ebrahimi };
7967*f5c631daSSadaf Ebrahimi 
7968*f5c631daSSadaf Ebrahimi 
7969*f5c631daSSadaf Ebrahimi // For the PushPop* tests, use the maximum number of registers that the test
7970*f5c631daSSadaf Ebrahimi // supports (where a reg_count argument would otherwise be provided).
7971*f5c631daSSadaf Ebrahimi static int const kPushPopUseMaxRegCount = -1;
7972*f5c631daSSadaf Ebrahimi 
7973*f5c631daSSadaf Ebrahimi // Test a simple push-pop pattern:
7974*f5c631daSSadaf Ebrahimi //  * Claim <claim> bytes to set the stack alignment.
7975*f5c631daSSadaf Ebrahimi //  * Push <reg_count> registers with size <reg_size>.
7976*f5c631daSSadaf Ebrahimi //  * Clobber the register contents.
7977*f5c631daSSadaf Ebrahimi //  * Pop <reg_count> registers to restore the original contents.
7978*f5c631daSSadaf Ebrahimi //  * Drop <claim> bytes to restore the original stack pointer.
7979*f5c631daSSadaf Ebrahimi //
7980*f5c631daSSadaf Ebrahimi // Different push and pop methods can be specified independently to test for
7981*f5c631daSSadaf Ebrahimi // proper word-endian behaviour.
PushPopSimpleHelper(int reg_count,int claim,int reg_size,PushPopMethod push_method,PushPopMethod pop_method)7982*f5c631daSSadaf Ebrahimi static void PushPopSimpleHelper(int reg_count,
7983*f5c631daSSadaf Ebrahimi                                 int claim,
7984*f5c631daSSadaf Ebrahimi                                 int reg_size,
7985*f5c631daSSadaf Ebrahimi                                 PushPopMethod push_method,
7986*f5c631daSSadaf Ebrahimi                                 PushPopMethod pop_method) {
7987*f5c631daSSadaf Ebrahimi   SETUP();
7988*f5c631daSSadaf Ebrahimi 
7989*f5c631daSSadaf Ebrahimi   START();
7990*f5c631daSSadaf Ebrahimi 
7991*f5c631daSSadaf Ebrahimi   // Arbitrarily pick a register to use as a stack pointer.
7992*f5c631daSSadaf Ebrahimi   const Register& stack_pointer = x20;
7993*f5c631daSSadaf Ebrahimi   const RegList allowed = ~stack_pointer.GetBit();
7994*f5c631daSSadaf Ebrahimi   if (reg_count == kPushPopUseMaxRegCount) {
7995*f5c631daSSadaf Ebrahimi     reg_count = CountSetBits(allowed, kNumberOfRegisters);
7996*f5c631daSSadaf Ebrahimi   }
7997*f5c631daSSadaf Ebrahimi   // Work out which registers to use, based on reg_size.
7998*f5c631daSSadaf Ebrahimi   Register r[kNumberOfRegisters];
7999*f5c631daSSadaf Ebrahimi   Register x[kNumberOfRegisters];
8000*f5c631daSSadaf Ebrahimi   RegList list =
8001*f5c631daSSadaf Ebrahimi       PopulateRegisterArray(NULL, x, r, reg_size, reg_count, allowed);
8002*f5c631daSSadaf Ebrahimi 
8003*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8004*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
8005*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
8006*f5c631daSSadaf Ebrahimi 
8007*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
8008*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
8009*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
8010*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
8011*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
8012*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
8013*f5c631daSSadaf Ebrahimi 
8014*f5c631daSSadaf Ebrahimi   {
8015*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(__ StackPointer().Is(sp));
8016*f5c631daSSadaf Ebrahimi     __ Mov(stack_pointer, __ StackPointer());
8017*f5c631daSSadaf Ebrahimi     __ SetStackPointer(stack_pointer);
8018*f5c631daSSadaf Ebrahimi 
8019*f5c631daSSadaf Ebrahimi     int i;
8020*f5c631daSSadaf Ebrahimi 
8021*f5c631daSSadaf Ebrahimi     // Initialize the registers.
8022*f5c631daSSadaf Ebrahimi     for (i = 0; i < reg_count; i++) {
8023*f5c631daSSadaf Ebrahimi       // Always write into the X register, to ensure that the upper word is
8024*f5c631daSSadaf Ebrahimi       // properly ignored by Push when testing W registers.
8025*f5c631daSSadaf Ebrahimi       __ Mov(x[i], literal_base * i);
8026*f5c631daSSadaf Ebrahimi     }
8027*f5c631daSSadaf Ebrahimi 
8028*f5c631daSSadaf Ebrahimi     // Claim memory first, as requested.
8029*f5c631daSSadaf Ebrahimi     __ Claim(claim);
8030*f5c631daSSadaf Ebrahimi 
8031*f5c631daSSadaf Ebrahimi     switch (push_method) {
8032*f5c631daSSadaf Ebrahimi       case PushPopByFour:
8033*f5c631daSSadaf Ebrahimi         // Push high-numbered registers first (to the highest addresses).
8034*f5c631daSSadaf Ebrahimi         for (i = reg_count; i >= 4; i -= 4) {
8035*f5c631daSSadaf Ebrahimi           __ Push(r[i - 1], r[i - 2], r[i - 3], r[i - 4]);
8036*f5c631daSSadaf Ebrahimi         }
8037*f5c631daSSadaf Ebrahimi         // Finish off the leftovers.
8038*f5c631daSSadaf Ebrahimi         switch (i) {
8039*f5c631daSSadaf Ebrahimi           case 3:
8040*f5c631daSSadaf Ebrahimi             __ Push(r[2], r[1], r[0]);
8041*f5c631daSSadaf Ebrahimi             break;
8042*f5c631daSSadaf Ebrahimi           case 2:
8043*f5c631daSSadaf Ebrahimi             __ Push(r[1], r[0]);
8044*f5c631daSSadaf Ebrahimi             break;
8045*f5c631daSSadaf Ebrahimi           case 1:
8046*f5c631daSSadaf Ebrahimi             __ Push(r[0]);
8047*f5c631daSSadaf Ebrahimi             break;
8048*f5c631daSSadaf Ebrahimi           default:
8049*f5c631daSSadaf Ebrahimi             VIXL_ASSERT(i == 0);
8050*f5c631daSSadaf Ebrahimi             break;
8051*f5c631daSSadaf Ebrahimi         }
8052*f5c631daSSadaf Ebrahimi         break;
8053*f5c631daSSadaf Ebrahimi       case PushPopRegList:
8054*f5c631daSSadaf Ebrahimi         __ PushSizeRegList(list, reg_size);
8055*f5c631daSSadaf Ebrahimi         break;
8056*f5c631daSSadaf Ebrahimi     }
8057*f5c631daSSadaf Ebrahimi 
8058*f5c631daSSadaf Ebrahimi     // Clobber all the registers, to ensure that they get repopulated by Pop.
8059*f5c631daSSadaf Ebrahimi     Clobber(&masm, list);
8060*f5c631daSSadaf Ebrahimi 
8061*f5c631daSSadaf Ebrahimi     switch (pop_method) {
8062*f5c631daSSadaf Ebrahimi       case PushPopByFour:
8063*f5c631daSSadaf Ebrahimi         // Pop low-numbered registers first (from the lowest addresses).
8064*f5c631daSSadaf Ebrahimi         for (i = 0; i <= (reg_count - 4); i += 4) {
8065*f5c631daSSadaf Ebrahimi           __ Pop(r[i], r[i + 1], r[i + 2], r[i + 3]);
8066*f5c631daSSadaf Ebrahimi         }
8067*f5c631daSSadaf Ebrahimi         // Finish off the leftovers.
8068*f5c631daSSadaf Ebrahimi         switch (reg_count - i) {
8069*f5c631daSSadaf Ebrahimi           case 3:
8070*f5c631daSSadaf Ebrahimi             __ Pop(r[i], r[i + 1], r[i + 2]);
8071*f5c631daSSadaf Ebrahimi             break;
8072*f5c631daSSadaf Ebrahimi           case 2:
8073*f5c631daSSadaf Ebrahimi             __ Pop(r[i], r[i + 1]);
8074*f5c631daSSadaf Ebrahimi             break;
8075*f5c631daSSadaf Ebrahimi           case 1:
8076*f5c631daSSadaf Ebrahimi             __ Pop(r[i]);
8077*f5c631daSSadaf Ebrahimi             break;
8078*f5c631daSSadaf Ebrahimi           default:
8079*f5c631daSSadaf Ebrahimi             VIXL_ASSERT(i == reg_count);
8080*f5c631daSSadaf Ebrahimi             break;
8081*f5c631daSSadaf Ebrahimi         }
8082*f5c631daSSadaf Ebrahimi         break;
8083*f5c631daSSadaf Ebrahimi       case PushPopRegList:
8084*f5c631daSSadaf Ebrahimi         __ PopSizeRegList(list, reg_size);
8085*f5c631daSSadaf Ebrahimi         break;
8086*f5c631daSSadaf Ebrahimi     }
8087*f5c631daSSadaf Ebrahimi 
8088*f5c631daSSadaf Ebrahimi     // Drop memory to restore stack_pointer.
8089*f5c631daSSadaf Ebrahimi     __ Drop(claim);
8090*f5c631daSSadaf Ebrahimi 
8091*f5c631daSSadaf Ebrahimi     __ Mov(sp, __ StackPointer());
8092*f5c631daSSadaf Ebrahimi     __ SetStackPointer(sp);
8093*f5c631daSSadaf Ebrahimi   }
8094*f5c631daSSadaf Ebrahimi 
8095*f5c631daSSadaf Ebrahimi   END();
8096*f5c631daSSadaf Ebrahimi 
8097*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
8098*f5c631daSSadaf Ebrahimi     RUN();
8099*f5c631daSSadaf Ebrahimi 
8100*f5c631daSSadaf Ebrahimi     // Check that the register contents were preserved.
8101*f5c631daSSadaf Ebrahimi     // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
8102*f5c631daSSadaf Ebrahimi     // that the upper word was properly cleared by Pop.
8103*f5c631daSSadaf Ebrahimi     literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8104*f5c631daSSadaf Ebrahimi     for (int i = 0; i < reg_count; i++) {
8105*f5c631daSSadaf Ebrahimi       if (x[i].Is(xzr)) {
8106*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(0, x[i]);
8107*f5c631daSSadaf Ebrahimi       } else {
8108*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(literal_base * i, x[i]);
8109*f5c631daSSadaf Ebrahimi       }
8110*f5c631daSSadaf Ebrahimi     }
8111*f5c631daSSadaf Ebrahimi   }
8112*f5c631daSSadaf Ebrahimi }
8113*f5c631daSSadaf Ebrahimi 
8114*f5c631daSSadaf Ebrahimi 
TEST(push_pop_xreg_simple_32)8115*f5c631daSSadaf Ebrahimi TEST(push_pop_xreg_simple_32) {
8116*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8117*f5c631daSSadaf Ebrahimi     for (int count = 0; count <= 8; count++) {
8118*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8119*f5c631daSSadaf Ebrahimi                           claim,
8120*f5c631daSSadaf Ebrahimi                           kWRegSize,
8121*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8122*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8123*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8124*f5c631daSSadaf Ebrahimi                           claim,
8125*f5c631daSSadaf Ebrahimi                           kWRegSize,
8126*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8127*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8128*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8129*f5c631daSSadaf Ebrahimi                           claim,
8130*f5c631daSSadaf Ebrahimi                           kWRegSize,
8131*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8132*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8133*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8134*f5c631daSSadaf Ebrahimi                           claim,
8135*f5c631daSSadaf Ebrahimi                           kWRegSize,
8136*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8137*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8138*f5c631daSSadaf Ebrahimi     }
8139*f5c631daSSadaf Ebrahimi     // Test with the maximum number of registers.
8140*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8141*f5c631daSSadaf Ebrahimi                         claim,
8142*f5c631daSSadaf Ebrahimi                         kWRegSize,
8143*f5c631daSSadaf Ebrahimi                         PushPopByFour,
8144*f5c631daSSadaf Ebrahimi                         PushPopByFour);
8145*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8146*f5c631daSSadaf Ebrahimi                         claim,
8147*f5c631daSSadaf Ebrahimi                         kWRegSize,
8148*f5c631daSSadaf Ebrahimi                         PushPopByFour,
8149*f5c631daSSadaf Ebrahimi                         PushPopRegList);
8150*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8151*f5c631daSSadaf Ebrahimi                         claim,
8152*f5c631daSSadaf Ebrahimi                         kWRegSize,
8153*f5c631daSSadaf Ebrahimi                         PushPopRegList,
8154*f5c631daSSadaf Ebrahimi                         PushPopByFour);
8155*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8156*f5c631daSSadaf Ebrahimi                         claim,
8157*f5c631daSSadaf Ebrahimi                         kWRegSize,
8158*f5c631daSSadaf Ebrahimi                         PushPopRegList,
8159*f5c631daSSadaf Ebrahimi                         PushPopRegList);
8160*f5c631daSSadaf Ebrahimi   }
8161*f5c631daSSadaf Ebrahimi }
8162*f5c631daSSadaf Ebrahimi 
8163*f5c631daSSadaf Ebrahimi 
TEST(push_pop_xreg_simple_64)8164*f5c631daSSadaf Ebrahimi TEST(push_pop_xreg_simple_64) {
8165*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8166*f5c631daSSadaf Ebrahimi     for (int count = 0; count <= 8; count++) {
8167*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8168*f5c631daSSadaf Ebrahimi                           claim,
8169*f5c631daSSadaf Ebrahimi                           kXRegSize,
8170*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8171*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8172*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8173*f5c631daSSadaf Ebrahimi                           claim,
8174*f5c631daSSadaf Ebrahimi                           kXRegSize,
8175*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8176*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8177*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8178*f5c631daSSadaf Ebrahimi                           claim,
8179*f5c631daSSadaf Ebrahimi                           kXRegSize,
8180*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8181*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8182*f5c631daSSadaf Ebrahimi       PushPopSimpleHelper(count,
8183*f5c631daSSadaf Ebrahimi                           claim,
8184*f5c631daSSadaf Ebrahimi                           kXRegSize,
8185*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8186*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8187*f5c631daSSadaf Ebrahimi     }
8188*f5c631daSSadaf Ebrahimi     // Test with the maximum number of registers.
8189*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8190*f5c631daSSadaf Ebrahimi                         claim,
8191*f5c631daSSadaf Ebrahimi                         kXRegSize,
8192*f5c631daSSadaf Ebrahimi                         PushPopByFour,
8193*f5c631daSSadaf Ebrahimi                         PushPopByFour);
8194*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8195*f5c631daSSadaf Ebrahimi                         claim,
8196*f5c631daSSadaf Ebrahimi                         kXRegSize,
8197*f5c631daSSadaf Ebrahimi                         PushPopByFour,
8198*f5c631daSSadaf Ebrahimi                         PushPopRegList);
8199*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8200*f5c631daSSadaf Ebrahimi                         claim,
8201*f5c631daSSadaf Ebrahimi                         kXRegSize,
8202*f5c631daSSadaf Ebrahimi                         PushPopRegList,
8203*f5c631daSSadaf Ebrahimi                         PushPopByFour);
8204*f5c631daSSadaf Ebrahimi     PushPopSimpleHelper(kPushPopUseMaxRegCount,
8205*f5c631daSSadaf Ebrahimi                         claim,
8206*f5c631daSSadaf Ebrahimi                         kXRegSize,
8207*f5c631daSSadaf Ebrahimi                         PushPopRegList,
8208*f5c631daSSadaf Ebrahimi                         PushPopRegList);
8209*f5c631daSSadaf Ebrahimi   }
8210*f5c631daSSadaf Ebrahimi }
8211*f5c631daSSadaf Ebrahimi 
8212*f5c631daSSadaf Ebrahimi // For the PushPopFP* tests, use the maximum number of registers that the test
8213*f5c631daSSadaf Ebrahimi // supports (where a reg_count argument would otherwise be provided).
8214*f5c631daSSadaf Ebrahimi static int const kPushPopFPUseMaxRegCount = -1;
8215*f5c631daSSadaf Ebrahimi 
8216*f5c631daSSadaf Ebrahimi // Test a simple push-pop pattern:
8217*f5c631daSSadaf Ebrahimi //  * Claim <claim> bytes to set the stack alignment.
8218*f5c631daSSadaf Ebrahimi //  * Push <reg_count> FP registers with size <reg_size>.
8219*f5c631daSSadaf Ebrahimi //  * Clobber the register contents.
8220*f5c631daSSadaf Ebrahimi //  * Pop <reg_count> FP registers to restore the original contents.
8221*f5c631daSSadaf Ebrahimi //  * Drop <claim> bytes to restore the original stack pointer.
8222*f5c631daSSadaf Ebrahimi //
8223*f5c631daSSadaf Ebrahimi // Different push and pop methods can be specified independently to test for
8224*f5c631daSSadaf Ebrahimi // proper word-endian behaviour.
PushPopFPSimpleHelper(int reg_count,int claim,int reg_size,PushPopMethod push_method,PushPopMethod pop_method)8225*f5c631daSSadaf Ebrahimi static void PushPopFPSimpleHelper(int reg_count,
8226*f5c631daSSadaf Ebrahimi                                   int claim,
8227*f5c631daSSadaf Ebrahimi                                   int reg_size,
8228*f5c631daSSadaf Ebrahimi                                   PushPopMethod push_method,
8229*f5c631daSSadaf Ebrahimi                                   PushPopMethod pop_method) {
8230*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES((reg_count == 0) ? CPUFeatures::kNone : CPUFeatures::kFP);
8231*f5c631daSSadaf Ebrahimi 
8232*f5c631daSSadaf Ebrahimi   START();
8233*f5c631daSSadaf Ebrahimi 
8234*f5c631daSSadaf Ebrahimi   // We can use any floating-point register. None of them are reserved for
8235*f5c631daSSadaf Ebrahimi   // debug code, for example.
8236*f5c631daSSadaf Ebrahimi   static RegList const allowed = ~0;
8237*f5c631daSSadaf Ebrahimi   if (reg_count == kPushPopFPUseMaxRegCount) {
8238*f5c631daSSadaf Ebrahimi     reg_count = CountSetBits(allowed, kNumberOfVRegisters);
8239*f5c631daSSadaf Ebrahimi   }
8240*f5c631daSSadaf Ebrahimi   // Work out which registers to use, based on reg_size.
8241*f5c631daSSadaf Ebrahimi   VRegister v[kNumberOfRegisters];
8242*f5c631daSSadaf Ebrahimi   VRegister d[kNumberOfRegisters];
8243*f5c631daSSadaf Ebrahimi   RegList list =
8244*f5c631daSSadaf Ebrahimi       PopulateVRegisterArray(NULL, d, v, reg_size, reg_count, allowed);
8245*f5c631daSSadaf Ebrahimi 
8246*f5c631daSSadaf Ebrahimi   // Arbitrarily pick a register to use as a stack pointer.
8247*f5c631daSSadaf Ebrahimi   const Register& stack_pointer = x10;
8248*f5c631daSSadaf Ebrahimi 
8249*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8250*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
8251*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
8252*f5c631daSSadaf Ebrahimi 
8253*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
8254*f5c631daSSadaf Ebrahimi   //  * When multiplied (using an integer) by small values (such as a register
8255*f5c631daSSadaf Ebrahimi   //    index), this value is clearly readable in the result.
8256*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
8257*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
8258*f5c631daSSadaf Ebrahimi   //  * It is never a floating-point NaN, and will therefore always compare
8259*f5c631daSSadaf Ebrahimi   //    equal to itself.
8260*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
8261*f5c631daSSadaf Ebrahimi 
8262*f5c631daSSadaf Ebrahimi   {
8263*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(__ StackPointer().Is(sp));
8264*f5c631daSSadaf Ebrahimi     __ Mov(stack_pointer, __ StackPointer());
8265*f5c631daSSadaf Ebrahimi     __ SetStackPointer(stack_pointer);
8266*f5c631daSSadaf Ebrahimi 
8267*f5c631daSSadaf Ebrahimi     int i;
8268*f5c631daSSadaf Ebrahimi 
8269*f5c631daSSadaf Ebrahimi     // Initialize the registers, using X registers to load the literal.
8270*f5c631daSSadaf Ebrahimi     __ Mov(x0, 0);
8271*f5c631daSSadaf Ebrahimi     __ Mov(x1, literal_base);
8272*f5c631daSSadaf Ebrahimi     for (i = 0; i < reg_count; i++) {
8273*f5c631daSSadaf Ebrahimi       // Always write into the D register, to ensure that the upper word is
8274*f5c631daSSadaf Ebrahimi       // properly ignored by Push when testing S registers.
8275*f5c631daSSadaf Ebrahimi       __ Fmov(d[i], x0);
8276*f5c631daSSadaf Ebrahimi       // Calculate the next literal.
8277*f5c631daSSadaf Ebrahimi       __ Add(x0, x0, x1);
8278*f5c631daSSadaf Ebrahimi     }
8279*f5c631daSSadaf Ebrahimi 
8280*f5c631daSSadaf Ebrahimi     // Claim memory first, as requested.
8281*f5c631daSSadaf Ebrahimi     __ Claim(claim);
8282*f5c631daSSadaf Ebrahimi 
8283*f5c631daSSadaf Ebrahimi     switch (push_method) {
8284*f5c631daSSadaf Ebrahimi       case PushPopByFour:
8285*f5c631daSSadaf Ebrahimi         // Push high-numbered registers first (to the highest addresses).
8286*f5c631daSSadaf Ebrahimi         for (i = reg_count; i >= 4; i -= 4) {
8287*f5c631daSSadaf Ebrahimi           __ Push(v[i - 1], v[i - 2], v[i - 3], v[i - 4]);
8288*f5c631daSSadaf Ebrahimi         }
8289*f5c631daSSadaf Ebrahimi         // Finish off the leftovers.
8290*f5c631daSSadaf Ebrahimi         switch (i) {
8291*f5c631daSSadaf Ebrahimi           case 3:
8292*f5c631daSSadaf Ebrahimi             __ Push(v[2], v[1], v[0]);
8293*f5c631daSSadaf Ebrahimi             break;
8294*f5c631daSSadaf Ebrahimi           case 2:
8295*f5c631daSSadaf Ebrahimi             __ Push(v[1], v[0]);
8296*f5c631daSSadaf Ebrahimi             break;
8297*f5c631daSSadaf Ebrahimi           case 1:
8298*f5c631daSSadaf Ebrahimi             __ Push(v[0]);
8299*f5c631daSSadaf Ebrahimi             break;
8300*f5c631daSSadaf Ebrahimi           default:
8301*f5c631daSSadaf Ebrahimi             VIXL_ASSERT(i == 0);
8302*f5c631daSSadaf Ebrahimi             break;
8303*f5c631daSSadaf Ebrahimi         }
8304*f5c631daSSadaf Ebrahimi         break;
8305*f5c631daSSadaf Ebrahimi       case PushPopRegList:
8306*f5c631daSSadaf Ebrahimi         __ PushSizeRegList(list, reg_size, CPURegister::kVRegister);
8307*f5c631daSSadaf Ebrahimi         break;
8308*f5c631daSSadaf Ebrahimi     }
8309*f5c631daSSadaf Ebrahimi 
8310*f5c631daSSadaf Ebrahimi     // Clobber all the registers, to ensure that they get repopulated by Pop.
8311*f5c631daSSadaf Ebrahimi     ClobberFP(&masm, list);
8312*f5c631daSSadaf Ebrahimi 
8313*f5c631daSSadaf Ebrahimi     switch (pop_method) {
8314*f5c631daSSadaf Ebrahimi       case PushPopByFour:
8315*f5c631daSSadaf Ebrahimi         // Pop low-numbered registers first (from the lowest addresses).
8316*f5c631daSSadaf Ebrahimi         for (i = 0; i <= (reg_count - 4); i += 4) {
8317*f5c631daSSadaf Ebrahimi           __ Pop(v[i], v[i + 1], v[i + 2], v[i + 3]);
8318*f5c631daSSadaf Ebrahimi         }
8319*f5c631daSSadaf Ebrahimi         // Finish off the leftovers.
8320*f5c631daSSadaf Ebrahimi         switch (reg_count - i) {
8321*f5c631daSSadaf Ebrahimi           case 3:
8322*f5c631daSSadaf Ebrahimi             __ Pop(v[i], v[i + 1], v[i + 2]);
8323*f5c631daSSadaf Ebrahimi             break;
8324*f5c631daSSadaf Ebrahimi           case 2:
8325*f5c631daSSadaf Ebrahimi             __ Pop(v[i], v[i + 1]);
8326*f5c631daSSadaf Ebrahimi             break;
8327*f5c631daSSadaf Ebrahimi           case 1:
8328*f5c631daSSadaf Ebrahimi             __ Pop(v[i]);
8329*f5c631daSSadaf Ebrahimi             break;
8330*f5c631daSSadaf Ebrahimi           default:
8331*f5c631daSSadaf Ebrahimi             VIXL_ASSERT(i == reg_count);
8332*f5c631daSSadaf Ebrahimi             break;
8333*f5c631daSSadaf Ebrahimi         }
8334*f5c631daSSadaf Ebrahimi         break;
8335*f5c631daSSadaf Ebrahimi       case PushPopRegList:
8336*f5c631daSSadaf Ebrahimi         __ PopSizeRegList(list, reg_size, CPURegister::kVRegister);
8337*f5c631daSSadaf Ebrahimi         break;
8338*f5c631daSSadaf Ebrahimi     }
8339*f5c631daSSadaf Ebrahimi 
8340*f5c631daSSadaf Ebrahimi     // Drop memory to restore the stack pointer.
8341*f5c631daSSadaf Ebrahimi     __ Drop(claim);
8342*f5c631daSSadaf Ebrahimi 
8343*f5c631daSSadaf Ebrahimi     __ Mov(sp, __ StackPointer());
8344*f5c631daSSadaf Ebrahimi     __ SetStackPointer(sp);
8345*f5c631daSSadaf Ebrahimi   }
8346*f5c631daSSadaf Ebrahimi 
8347*f5c631daSSadaf Ebrahimi   END();
8348*f5c631daSSadaf Ebrahimi 
8349*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
8350*f5c631daSSadaf Ebrahimi     RUN();
8351*f5c631daSSadaf Ebrahimi 
8352*f5c631daSSadaf Ebrahimi     // Check that the register contents were preserved.
8353*f5c631daSSadaf Ebrahimi     // Always use ASSERT_EQUAL_FP64, even when testing S registers, so we can
8354*f5c631daSSadaf Ebrahimi     // test that the upper word was properly cleared by Pop.
8355*f5c631daSSadaf Ebrahimi     literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8356*f5c631daSSadaf Ebrahimi     for (int i = 0; i < reg_count; i++) {
8357*f5c631daSSadaf Ebrahimi       uint64_t literal = literal_base * i;
8358*f5c631daSSadaf Ebrahimi       double expected;
8359*f5c631daSSadaf Ebrahimi       memcpy(&expected, &literal, sizeof(expected));
8360*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_FP64(expected, d[i]);
8361*f5c631daSSadaf Ebrahimi     }
8362*f5c631daSSadaf Ebrahimi   }
8363*f5c631daSSadaf Ebrahimi }
8364*f5c631daSSadaf Ebrahimi 
8365*f5c631daSSadaf Ebrahimi 
TEST(push_pop_fp_xreg_simple_32)8366*f5c631daSSadaf Ebrahimi TEST(push_pop_fp_xreg_simple_32) {
8367*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8368*f5c631daSSadaf Ebrahimi     for (int count = 0; count <= 8; count++) {
8369*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8370*f5c631daSSadaf Ebrahimi                             claim,
8371*f5c631daSSadaf Ebrahimi                             kSRegSize,
8372*f5c631daSSadaf Ebrahimi                             PushPopByFour,
8373*f5c631daSSadaf Ebrahimi                             PushPopByFour);
8374*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8375*f5c631daSSadaf Ebrahimi                             claim,
8376*f5c631daSSadaf Ebrahimi                             kSRegSize,
8377*f5c631daSSadaf Ebrahimi                             PushPopByFour,
8378*f5c631daSSadaf Ebrahimi                             PushPopRegList);
8379*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8380*f5c631daSSadaf Ebrahimi                             claim,
8381*f5c631daSSadaf Ebrahimi                             kSRegSize,
8382*f5c631daSSadaf Ebrahimi                             PushPopRegList,
8383*f5c631daSSadaf Ebrahimi                             PushPopByFour);
8384*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8385*f5c631daSSadaf Ebrahimi                             claim,
8386*f5c631daSSadaf Ebrahimi                             kSRegSize,
8387*f5c631daSSadaf Ebrahimi                             PushPopRegList,
8388*f5c631daSSadaf Ebrahimi                             PushPopRegList);
8389*f5c631daSSadaf Ebrahimi     }
8390*f5c631daSSadaf Ebrahimi     // Test with the maximum number of registers.
8391*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8392*f5c631daSSadaf Ebrahimi                           claim,
8393*f5c631daSSadaf Ebrahimi                           kSRegSize,
8394*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8395*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8396*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8397*f5c631daSSadaf Ebrahimi                           claim,
8398*f5c631daSSadaf Ebrahimi                           kSRegSize,
8399*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8400*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8401*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8402*f5c631daSSadaf Ebrahimi                           claim,
8403*f5c631daSSadaf Ebrahimi                           kSRegSize,
8404*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8405*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8406*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8407*f5c631daSSadaf Ebrahimi                           claim,
8408*f5c631daSSadaf Ebrahimi                           kSRegSize,
8409*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8410*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8411*f5c631daSSadaf Ebrahimi   }
8412*f5c631daSSadaf Ebrahimi }
8413*f5c631daSSadaf Ebrahimi 
8414*f5c631daSSadaf Ebrahimi 
TEST(push_pop_fp_xreg_simple_64)8415*f5c631daSSadaf Ebrahimi TEST(push_pop_fp_xreg_simple_64) {
8416*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8417*f5c631daSSadaf Ebrahimi     for (int count = 0; count <= 8; count++) {
8418*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8419*f5c631daSSadaf Ebrahimi                             claim,
8420*f5c631daSSadaf Ebrahimi                             kDRegSize,
8421*f5c631daSSadaf Ebrahimi                             PushPopByFour,
8422*f5c631daSSadaf Ebrahimi                             PushPopByFour);
8423*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8424*f5c631daSSadaf Ebrahimi                             claim,
8425*f5c631daSSadaf Ebrahimi                             kDRegSize,
8426*f5c631daSSadaf Ebrahimi                             PushPopByFour,
8427*f5c631daSSadaf Ebrahimi                             PushPopRegList);
8428*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8429*f5c631daSSadaf Ebrahimi                             claim,
8430*f5c631daSSadaf Ebrahimi                             kDRegSize,
8431*f5c631daSSadaf Ebrahimi                             PushPopRegList,
8432*f5c631daSSadaf Ebrahimi                             PushPopByFour);
8433*f5c631daSSadaf Ebrahimi       PushPopFPSimpleHelper(count,
8434*f5c631daSSadaf Ebrahimi                             claim,
8435*f5c631daSSadaf Ebrahimi                             kDRegSize,
8436*f5c631daSSadaf Ebrahimi                             PushPopRegList,
8437*f5c631daSSadaf Ebrahimi                             PushPopRegList);
8438*f5c631daSSadaf Ebrahimi     }
8439*f5c631daSSadaf Ebrahimi     // Test with the maximum number of registers.
8440*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8441*f5c631daSSadaf Ebrahimi                           claim,
8442*f5c631daSSadaf Ebrahimi                           kDRegSize,
8443*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8444*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8445*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8446*f5c631daSSadaf Ebrahimi                           claim,
8447*f5c631daSSadaf Ebrahimi                           kDRegSize,
8448*f5c631daSSadaf Ebrahimi                           PushPopByFour,
8449*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8450*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8451*f5c631daSSadaf Ebrahimi                           claim,
8452*f5c631daSSadaf Ebrahimi                           kDRegSize,
8453*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8454*f5c631daSSadaf Ebrahimi                           PushPopByFour);
8455*f5c631daSSadaf Ebrahimi     PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount,
8456*f5c631daSSadaf Ebrahimi                           claim,
8457*f5c631daSSadaf Ebrahimi                           kDRegSize,
8458*f5c631daSSadaf Ebrahimi                           PushPopRegList,
8459*f5c631daSSadaf Ebrahimi                           PushPopRegList);
8460*f5c631daSSadaf Ebrahimi   }
8461*f5c631daSSadaf Ebrahimi }
8462*f5c631daSSadaf Ebrahimi 
8463*f5c631daSSadaf Ebrahimi 
8464*f5c631daSSadaf Ebrahimi // Push and pop data using an overlapping combination of Push/Pop and
8465*f5c631daSSadaf Ebrahimi // RegList-based methods.
PushPopMixedMethodsHelper(int claim,int reg_size)8466*f5c631daSSadaf Ebrahimi static void PushPopMixedMethodsHelper(int claim, int reg_size) {
8467*f5c631daSSadaf Ebrahimi   SETUP();
8468*f5c631daSSadaf Ebrahimi 
8469*f5c631daSSadaf Ebrahimi   // Arbitrarily pick a register to use as a stack pointer.
8470*f5c631daSSadaf Ebrahimi   const Register& stack_pointer = x5;
8471*f5c631daSSadaf Ebrahimi   const RegList allowed = ~stack_pointer.GetBit();
8472*f5c631daSSadaf Ebrahimi   // Work out which registers to use, based on reg_size.
8473*f5c631daSSadaf Ebrahimi   Register r[10];
8474*f5c631daSSadaf Ebrahimi   Register x[10];
8475*f5c631daSSadaf Ebrahimi   PopulateRegisterArray(NULL, x, r, reg_size, 10, allowed);
8476*f5c631daSSadaf Ebrahimi 
8477*f5c631daSSadaf Ebrahimi   // Calculate some handy register lists.
8478*f5c631daSSadaf Ebrahimi   RegList r0_to_r3 = 0;
8479*f5c631daSSadaf Ebrahimi   for (int i = 0; i <= 3; i++) {
8480*f5c631daSSadaf Ebrahimi     r0_to_r3 |= x[i].GetBit();
8481*f5c631daSSadaf Ebrahimi   }
8482*f5c631daSSadaf Ebrahimi   RegList r4_to_r5 = 0;
8483*f5c631daSSadaf Ebrahimi   for (int i = 4; i <= 5; i++) {
8484*f5c631daSSadaf Ebrahimi     r4_to_r5 |= x[i].GetBit();
8485*f5c631daSSadaf Ebrahimi   }
8486*f5c631daSSadaf Ebrahimi   RegList r6_to_r9 = 0;
8487*f5c631daSSadaf Ebrahimi   for (int i = 6; i <= 9; i++) {
8488*f5c631daSSadaf Ebrahimi     r6_to_r9 |= x[i].GetBit();
8489*f5c631daSSadaf Ebrahimi   }
8490*f5c631daSSadaf Ebrahimi 
8491*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8492*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
8493*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
8494*f5c631daSSadaf Ebrahimi 
8495*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
8496*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
8497*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
8498*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
8499*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
8500*f5c631daSSadaf Ebrahimi   uint64_t literal_base = 0x0100001000100101;
8501*f5c631daSSadaf Ebrahimi 
8502*f5c631daSSadaf Ebrahimi   START();
8503*f5c631daSSadaf Ebrahimi   {
8504*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(__ StackPointer().Is(sp));
8505*f5c631daSSadaf Ebrahimi     __ Mov(stack_pointer, __ StackPointer());
8506*f5c631daSSadaf Ebrahimi     __ SetStackPointer(stack_pointer);
8507*f5c631daSSadaf Ebrahimi 
8508*f5c631daSSadaf Ebrahimi     // Claim memory first, as requested.
8509*f5c631daSSadaf Ebrahimi     __ Claim(claim);
8510*f5c631daSSadaf Ebrahimi 
8511*f5c631daSSadaf Ebrahimi     __ Mov(x[3], literal_base * 3);
8512*f5c631daSSadaf Ebrahimi     __ Mov(x[2], literal_base * 2);
8513*f5c631daSSadaf Ebrahimi     __ Mov(x[1], literal_base * 1);
8514*f5c631daSSadaf Ebrahimi     __ Mov(x[0], literal_base * 0);
8515*f5c631daSSadaf Ebrahimi 
8516*f5c631daSSadaf Ebrahimi     __ PushSizeRegList(r0_to_r3, reg_size);
8517*f5c631daSSadaf Ebrahimi     __ Push(r[3], r[2]);
8518*f5c631daSSadaf Ebrahimi 
8519*f5c631daSSadaf Ebrahimi     Clobber(&masm, r0_to_r3);
8520*f5c631daSSadaf Ebrahimi     __ PopSizeRegList(r0_to_r3, reg_size);
8521*f5c631daSSadaf Ebrahimi 
8522*f5c631daSSadaf Ebrahimi     __ Push(r[2], r[1], r[3], r[0]);
8523*f5c631daSSadaf Ebrahimi 
8524*f5c631daSSadaf Ebrahimi     Clobber(&masm, r4_to_r5);
8525*f5c631daSSadaf Ebrahimi     __ Pop(r[4], r[5]);
8526*f5c631daSSadaf Ebrahimi     Clobber(&masm, r6_to_r9);
8527*f5c631daSSadaf Ebrahimi     __ Pop(r[6], r[7], r[8], r[9]);
8528*f5c631daSSadaf Ebrahimi 
8529*f5c631daSSadaf Ebrahimi     // Drop memory to restore stack_pointer.
8530*f5c631daSSadaf Ebrahimi     __ Drop(claim);
8531*f5c631daSSadaf Ebrahimi 
8532*f5c631daSSadaf Ebrahimi     __ Mov(sp, __ StackPointer());
8533*f5c631daSSadaf Ebrahimi     __ SetStackPointer(sp);
8534*f5c631daSSadaf Ebrahimi   }
8535*f5c631daSSadaf Ebrahimi 
8536*f5c631daSSadaf Ebrahimi   END();
8537*f5c631daSSadaf Ebrahimi 
8538*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
8539*f5c631daSSadaf Ebrahimi     RUN();
8540*f5c631daSSadaf Ebrahimi 
8541*f5c631daSSadaf Ebrahimi     // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
8542*f5c631daSSadaf Ebrahimi     // that the upper word was properly cleared by Pop.
8543*f5c631daSSadaf Ebrahimi     literal_base &= (0xffffffffffffffff >> (64 - reg_size));
8544*f5c631daSSadaf Ebrahimi 
8545*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 3, x[9]);
8546*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 2, x[8]);
8547*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 0, x[7]);
8548*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 3, x[6]);
8549*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 1, x[5]);
8550*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(literal_base * 2, x[4]);
8551*f5c631daSSadaf Ebrahimi   }
8552*f5c631daSSadaf Ebrahimi }
8553*f5c631daSSadaf Ebrahimi 
8554*f5c631daSSadaf Ebrahimi 
TEST(push_pop_xreg_mixed_methods_64)8555*f5c631daSSadaf Ebrahimi TEST(push_pop_xreg_mixed_methods_64) {
8556*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8557*f5c631daSSadaf Ebrahimi     PushPopMixedMethodsHelper(claim, kXRegSize);
8558*f5c631daSSadaf Ebrahimi   }
8559*f5c631daSSadaf Ebrahimi }
8560*f5c631daSSadaf Ebrahimi 
8561*f5c631daSSadaf Ebrahimi 
TEST(push_pop_xreg_mixed_methods_32)8562*f5c631daSSadaf Ebrahimi TEST(push_pop_xreg_mixed_methods_32) {
8563*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8564*f5c631daSSadaf Ebrahimi     PushPopMixedMethodsHelper(claim, kWRegSize);
8565*f5c631daSSadaf Ebrahimi   }
8566*f5c631daSSadaf Ebrahimi }
8567*f5c631daSSadaf Ebrahimi 
8568*f5c631daSSadaf Ebrahimi 
8569*f5c631daSSadaf Ebrahimi // Push and pop data using overlapping X- and W-sized quantities.
PushPopWXOverlapHelper(int reg_count,int claim)8570*f5c631daSSadaf Ebrahimi static void PushPopWXOverlapHelper(int reg_count, int claim) {
8571*f5c631daSSadaf Ebrahimi   SETUP();
8572*f5c631daSSadaf Ebrahimi 
8573*f5c631daSSadaf Ebrahimi   // Arbitrarily pick a register to use as a stack pointer.
8574*f5c631daSSadaf Ebrahimi   const Register& stack_pointer = x10;
8575*f5c631daSSadaf Ebrahimi   const RegList allowed = ~stack_pointer.GetBit();
8576*f5c631daSSadaf Ebrahimi   if (reg_count == kPushPopUseMaxRegCount) {
8577*f5c631daSSadaf Ebrahimi     reg_count = CountSetBits(allowed, kNumberOfRegisters);
8578*f5c631daSSadaf Ebrahimi   }
8579*f5c631daSSadaf Ebrahimi   // Work out which registers to use, based on reg_size.
8580*f5c631daSSadaf Ebrahimi   Register w[kNumberOfRegisters];
8581*f5c631daSSadaf Ebrahimi   Register x[kNumberOfRegisters];
8582*f5c631daSSadaf Ebrahimi   RegList list = PopulateRegisterArray(w, x, NULL, 0, reg_count, allowed);
8583*f5c631daSSadaf Ebrahimi 
8584*f5c631daSSadaf Ebrahimi   // The number of W-sized slots we expect to pop. When we pop, we alternate
8585*f5c631daSSadaf Ebrahimi   // between W and X registers, so we need reg_count*1.5 W-sized slots.
8586*f5c631daSSadaf Ebrahimi   int const requested_w_slots = reg_count + reg_count / 2;
8587*f5c631daSSadaf Ebrahimi 
8588*f5c631daSSadaf Ebrahimi   // Track what _should_ be on the stack, using W-sized slots.
8589*f5c631daSSadaf Ebrahimi   static int const kMaxWSlots = kNumberOfRegisters + kNumberOfRegisters / 2;
8590*f5c631daSSadaf Ebrahimi   uint32_t stack[kMaxWSlots];
8591*f5c631daSSadaf Ebrahimi   for (int i = 0; i < kMaxWSlots; i++) {
8592*f5c631daSSadaf Ebrahimi     stack[i] = 0xdeadbeef;
8593*f5c631daSSadaf Ebrahimi   }
8594*f5c631daSSadaf Ebrahimi 
8595*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8596*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
8597*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
8598*f5c631daSSadaf Ebrahimi 
8599*f5c631daSSadaf Ebrahimi   // The literal base is chosen to have two useful properties:
8600*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
8601*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
8602*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
8603*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
8604*f5c631daSSadaf Ebrahimi   static uint64_t const literal_base = 0x0100001000100101;
8605*f5c631daSSadaf Ebrahimi   static uint64_t const literal_base_hi = literal_base >> 32;
8606*f5c631daSSadaf Ebrahimi   static uint64_t const literal_base_lo = literal_base & 0xffffffff;
8607*f5c631daSSadaf Ebrahimi   static uint64_t const literal_base_w = literal_base & 0xffffffff;
8608*f5c631daSSadaf Ebrahimi 
8609*f5c631daSSadaf Ebrahimi   START();
8610*f5c631daSSadaf Ebrahimi   {
8611*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(__ StackPointer().Is(sp));
8612*f5c631daSSadaf Ebrahimi     __ Mov(stack_pointer, __ StackPointer());
8613*f5c631daSSadaf Ebrahimi     __ SetStackPointer(stack_pointer);
8614*f5c631daSSadaf Ebrahimi 
8615*f5c631daSSadaf Ebrahimi     // Initialize the registers.
8616*f5c631daSSadaf Ebrahimi     for (int i = 0; i < reg_count; i++) {
8617*f5c631daSSadaf Ebrahimi       // Always write into the X register, to ensure that the upper word is
8618*f5c631daSSadaf Ebrahimi       // properly ignored by Push when testing W registers.
8619*f5c631daSSadaf Ebrahimi       __ Mov(x[i], literal_base * i);
8620*f5c631daSSadaf Ebrahimi     }
8621*f5c631daSSadaf Ebrahimi 
8622*f5c631daSSadaf Ebrahimi     // Claim memory first, as requested.
8623*f5c631daSSadaf Ebrahimi     __ Claim(claim);
8624*f5c631daSSadaf Ebrahimi 
8625*f5c631daSSadaf Ebrahimi     // The push-pop pattern is as follows:
8626*f5c631daSSadaf Ebrahimi     // Push:           Pop:
8627*f5c631daSSadaf Ebrahimi     //  x[0](hi)   ->   w[0]
8628*f5c631daSSadaf Ebrahimi     //  x[0](lo)   ->   x[1](hi)
8629*f5c631daSSadaf Ebrahimi     //  w[1]       ->   x[1](lo)
8630*f5c631daSSadaf Ebrahimi     //  w[1]       ->   w[2]
8631*f5c631daSSadaf Ebrahimi     //  x[2](hi)   ->   x[2](hi)
8632*f5c631daSSadaf Ebrahimi     //  x[2](lo)   ->   x[2](lo)
8633*f5c631daSSadaf Ebrahimi     //  x[2](hi)   ->   w[3]
8634*f5c631daSSadaf Ebrahimi     //  x[2](lo)   ->   x[4](hi)
8635*f5c631daSSadaf Ebrahimi     //  x[2](hi)   ->   x[4](lo)
8636*f5c631daSSadaf Ebrahimi     //  x[2](lo)   ->   w[5]
8637*f5c631daSSadaf Ebrahimi     //  w[3]       ->   x[5](hi)
8638*f5c631daSSadaf Ebrahimi     //  w[3]       ->   x[6](lo)
8639*f5c631daSSadaf Ebrahimi     //  w[3]       ->   w[7]
8640*f5c631daSSadaf Ebrahimi     //  w[3]       ->   x[8](hi)
8641*f5c631daSSadaf Ebrahimi     //  x[4](hi)   ->   x[8](lo)
8642*f5c631daSSadaf Ebrahimi     //  x[4](lo)   ->   w[9]
8643*f5c631daSSadaf Ebrahimi     // ... pattern continues ...
8644*f5c631daSSadaf Ebrahimi     //
8645*f5c631daSSadaf Ebrahimi     // That is, registers are pushed starting with the lower numbers,
8646*f5c631daSSadaf Ebrahimi     // alternating between x and w registers, and pushing i%4+1 copies of each,
8647*f5c631daSSadaf Ebrahimi     // where i is the register number.
8648*f5c631daSSadaf Ebrahimi     // Registers are popped starting with the higher numbers one-by-one,
8649*f5c631daSSadaf Ebrahimi     // alternating between x and w registers, but only popping one at a time.
8650*f5c631daSSadaf Ebrahimi     //
8651*f5c631daSSadaf Ebrahimi     // This pattern provides a wide variety of alignment effects and overlaps.
8652*f5c631daSSadaf Ebrahimi 
8653*f5c631daSSadaf Ebrahimi     // ---- Push ----
8654*f5c631daSSadaf Ebrahimi 
8655*f5c631daSSadaf Ebrahimi     int active_w_slots = 0;
8656*f5c631daSSadaf Ebrahimi     for (int i = 0; active_w_slots < requested_w_slots; i++) {
8657*f5c631daSSadaf Ebrahimi       VIXL_ASSERT(i < reg_count);
8658*f5c631daSSadaf Ebrahimi       // In order to test various arguments to PushMultipleTimes, and to try to
8659*f5c631daSSadaf Ebrahimi       // exercise different alignment and overlap effects, we push each
8660*f5c631daSSadaf Ebrahimi       // register a different number of times.
8661*f5c631daSSadaf Ebrahimi       int times = i % 4 + 1;
8662*f5c631daSSadaf Ebrahimi       if (i & 1) {
8663*f5c631daSSadaf Ebrahimi         // Push odd-numbered registers as W registers.
8664*f5c631daSSadaf Ebrahimi         __ PushMultipleTimes(times, w[i]);
8665*f5c631daSSadaf Ebrahimi         // Fill in the expected stack slots.
8666*f5c631daSSadaf Ebrahimi         for (int j = 0; j < times; j++) {
8667*f5c631daSSadaf Ebrahimi           if (w[i].Is(wzr)) {
8668*f5c631daSSadaf Ebrahimi             // The zero register always writes zeroes.
8669*f5c631daSSadaf Ebrahimi             stack[active_w_slots++] = 0;
8670*f5c631daSSadaf Ebrahimi           } else {
8671*f5c631daSSadaf Ebrahimi             stack[active_w_slots++] = literal_base_w * i;
8672*f5c631daSSadaf Ebrahimi           }
8673*f5c631daSSadaf Ebrahimi         }
8674*f5c631daSSadaf Ebrahimi       } else {
8675*f5c631daSSadaf Ebrahimi         // Push even-numbered registers as X registers.
8676*f5c631daSSadaf Ebrahimi         __ PushMultipleTimes(times, x[i]);
8677*f5c631daSSadaf Ebrahimi         // Fill in the expected stack slots.
8678*f5c631daSSadaf Ebrahimi         for (int j = 0; j < times; j++) {
8679*f5c631daSSadaf Ebrahimi           if (x[i].Is(xzr)) {
8680*f5c631daSSadaf Ebrahimi             // The zero register always writes zeroes.
8681*f5c631daSSadaf Ebrahimi             stack[active_w_slots++] = 0;
8682*f5c631daSSadaf Ebrahimi             stack[active_w_slots++] = 0;
8683*f5c631daSSadaf Ebrahimi           } else {
8684*f5c631daSSadaf Ebrahimi             stack[active_w_slots++] = literal_base_hi * i;
8685*f5c631daSSadaf Ebrahimi             stack[active_w_slots++] = literal_base_lo * i;
8686*f5c631daSSadaf Ebrahimi           }
8687*f5c631daSSadaf Ebrahimi         }
8688*f5c631daSSadaf Ebrahimi       }
8689*f5c631daSSadaf Ebrahimi     }
8690*f5c631daSSadaf Ebrahimi     // Because we were pushing several registers at a time, we probably pushed
8691*f5c631daSSadaf Ebrahimi     // more than we needed to.
8692*f5c631daSSadaf Ebrahimi     if (active_w_slots > requested_w_slots) {
8693*f5c631daSSadaf Ebrahimi       __ Drop((active_w_slots - requested_w_slots) * kWRegSizeInBytes);
8694*f5c631daSSadaf Ebrahimi       // Bump the number of active W-sized slots back to where it should be,
8695*f5c631daSSadaf Ebrahimi       // and fill the empty space with a placeholder value.
8696*f5c631daSSadaf Ebrahimi       do {
8697*f5c631daSSadaf Ebrahimi         stack[active_w_slots--] = 0xdeadbeef;
8698*f5c631daSSadaf Ebrahimi       } while (active_w_slots > requested_w_slots);
8699*f5c631daSSadaf Ebrahimi     }
8700*f5c631daSSadaf Ebrahimi 
8701*f5c631daSSadaf Ebrahimi     // ---- Pop ----
8702*f5c631daSSadaf Ebrahimi 
8703*f5c631daSSadaf Ebrahimi     Clobber(&masm, list);
8704*f5c631daSSadaf Ebrahimi 
8705*f5c631daSSadaf Ebrahimi     // If popping an even number of registers, the first one will be X-sized.
8706*f5c631daSSadaf Ebrahimi     // Otherwise, the first one will be W-sized.
8707*f5c631daSSadaf Ebrahimi     bool next_is_64 = !(reg_count & 1);
8708*f5c631daSSadaf Ebrahimi     for (int i = reg_count - 1; i >= 0; i--) {
8709*f5c631daSSadaf Ebrahimi       if (next_is_64) {
8710*f5c631daSSadaf Ebrahimi         __ Pop(x[i]);
8711*f5c631daSSadaf Ebrahimi         active_w_slots -= 2;
8712*f5c631daSSadaf Ebrahimi       } else {
8713*f5c631daSSadaf Ebrahimi         __ Pop(w[i]);
8714*f5c631daSSadaf Ebrahimi         active_w_slots -= 1;
8715*f5c631daSSadaf Ebrahimi       }
8716*f5c631daSSadaf Ebrahimi       next_is_64 = !next_is_64;
8717*f5c631daSSadaf Ebrahimi     }
8718*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(active_w_slots == 0);
8719*f5c631daSSadaf Ebrahimi 
8720*f5c631daSSadaf Ebrahimi     // Drop memory to restore stack_pointer.
8721*f5c631daSSadaf Ebrahimi     __ Drop(claim);
8722*f5c631daSSadaf Ebrahimi 
8723*f5c631daSSadaf Ebrahimi     __ Mov(sp, __ StackPointer());
8724*f5c631daSSadaf Ebrahimi     __ SetStackPointer(sp);
8725*f5c631daSSadaf Ebrahimi   }
8726*f5c631daSSadaf Ebrahimi 
8727*f5c631daSSadaf Ebrahimi   END();
8728*f5c631daSSadaf Ebrahimi 
8729*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
8730*f5c631daSSadaf Ebrahimi     RUN();
8731*f5c631daSSadaf Ebrahimi 
8732*f5c631daSSadaf Ebrahimi     int slot = 0;
8733*f5c631daSSadaf Ebrahimi     for (int i = 0; i < reg_count; i++) {
8734*f5c631daSSadaf Ebrahimi       // Even-numbered registers were written as W registers.
8735*f5c631daSSadaf Ebrahimi       // Odd-numbered registers were written as X registers.
8736*f5c631daSSadaf Ebrahimi       bool expect_64 = (i & 1);
8737*f5c631daSSadaf Ebrahimi       uint64_t expected;
8738*f5c631daSSadaf Ebrahimi 
8739*f5c631daSSadaf Ebrahimi       if (expect_64) {
8740*f5c631daSSadaf Ebrahimi         uint64_t hi = stack[slot++];
8741*f5c631daSSadaf Ebrahimi         uint64_t lo = stack[slot++];
8742*f5c631daSSadaf Ebrahimi         expected = (hi << 32) | lo;
8743*f5c631daSSadaf Ebrahimi       } else {
8744*f5c631daSSadaf Ebrahimi         expected = stack[slot++];
8745*f5c631daSSadaf Ebrahimi       }
8746*f5c631daSSadaf Ebrahimi 
8747*f5c631daSSadaf Ebrahimi       // Always use ASSERT_EQUAL_64, even when testing W registers, so we can
8748*f5c631daSSadaf Ebrahimi       // test that the upper word was properly cleared by Pop.
8749*f5c631daSSadaf Ebrahimi       if (x[i].Is(xzr)) {
8750*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(0, x[i]);
8751*f5c631daSSadaf Ebrahimi       } else {
8752*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(expected, x[i]);
8753*f5c631daSSadaf Ebrahimi       }
8754*f5c631daSSadaf Ebrahimi     }
8755*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(slot == requested_w_slots);
8756*f5c631daSSadaf Ebrahimi   }
8757*f5c631daSSadaf Ebrahimi }
8758*f5c631daSSadaf Ebrahimi 
8759*f5c631daSSadaf Ebrahimi 
TEST(push_pop_xreg_wx_overlap)8760*f5c631daSSadaf Ebrahimi TEST(push_pop_xreg_wx_overlap) {
8761*f5c631daSSadaf Ebrahimi   for (int claim = 0; claim <= 8; claim++) {
8762*f5c631daSSadaf Ebrahimi     for (int count = 1; count <= 8; count++) {
8763*f5c631daSSadaf Ebrahimi       PushPopWXOverlapHelper(count, claim);
8764*f5c631daSSadaf Ebrahimi     }
8765*f5c631daSSadaf Ebrahimi     // Test with the maximum number of registers.
8766*f5c631daSSadaf Ebrahimi     PushPopWXOverlapHelper(kPushPopUseMaxRegCount, claim);
8767*f5c631daSSadaf Ebrahimi   }
8768*f5c631daSSadaf Ebrahimi }
8769*f5c631daSSadaf Ebrahimi 
8770*f5c631daSSadaf Ebrahimi 
TEST(push_pop_sp)8771*f5c631daSSadaf Ebrahimi TEST(push_pop_sp) {
8772*f5c631daSSadaf Ebrahimi   SETUP();
8773*f5c631daSSadaf Ebrahimi 
8774*f5c631daSSadaf Ebrahimi   START();
8775*f5c631daSSadaf Ebrahimi 
8776*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(sp.Is(__ StackPointer()));
8777*f5c631daSSadaf Ebrahimi 
8778*f5c631daSSadaf Ebrahimi   // Acquire all temps from the MacroAssembler. They are used arbitrarily below.
8779*f5c631daSSadaf Ebrahimi   UseScratchRegisterScope temps(&masm);
8780*f5c631daSSadaf Ebrahimi   temps.ExcludeAll();
8781*f5c631daSSadaf Ebrahimi 
8782*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0x3333333333333333);
8783*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x2222222222222222);
8784*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1111111111111111);
8785*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0000000000000000);
8786*f5c631daSSadaf Ebrahimi   __ Claim(2 * kXRegSizeInBytes);
8787*f5c631daSSadaf Ebrahimi   __ PushXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit());
8788*f5c631daSSadaf Ebrahimi   __ Push(x3, x2);
8789*f5c631daSSadaf Ebrahimi   __ PopXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit());
8790*f5c631daSSadaf Ebrahimi   __ Push(x2, x1, x3, x0);
8791*f5c631daSSadaf Ebrahimi   __ Pop(x4, x5);
8792*f5c631daSSadaf Ebrahimi   __ Pop(x6, x7, x8, x9);
8793*f5c631daSSadaf Ebrahimi 
8794*f5c631daSSadaf Ebrahimi   __ Claim(2 * kXRegSizeInBytes);
8795*f5c631daSSadaf Ebrahimi   __ PushWRegList(w0.GetBit() | w1.GetBit() | w2.GetBit() | w3.GetBit());
8796*f5c631daSSadaf Ebrahimi   __ Push(w3, w1, w2, w0);
8797*f5c631daSSadaf Ebrahimi   __ PopWRegList(w10.GetBit() | w11.GetBit() | w12.GetBit() | w13.GetBit());
8798*f5c631daSSadaf Ebrahimi   __ Pop(w14, w15, w16, w17);
8799*f5c631daSSadaf Ebrahimi 
8800*f5c631daSSadaf Ebrahimi   __ Claim(2 * kXRegSizeInBytes);
8801*f5c631daSSadaf Ebrahimi   __ Push(w2, w2, w1, w1);
8802*f5c631daSSadaf Ebrahimi   __ Push(x3, x3);
8803*f5c631daSSadaf Ebrahimi   __ Pop(w18, w19, w20, w21);
8804*f5c631daSSadaf Ebrahimi   __ Pop(x22, x23);
8805*f5c631daSSadaf Ebrahimi 
8806*f5c631daSSadaf Ebrahimi   __ Claim(2 * kXRegSizeInBytes);
8807*f5c631daSSadaf Ebrahimi   __ PushXRegList(x1.GetBit() | x22.GetBit());
8808*f5c631daSSadaf Ebrahimi   __ PopXRegList(x24.GetBit() | x26.GetBit());
8809*f5c631daSSadaf Ebrahimi 
8810*f5c631daSSadaf Ebrahimi   __ Claim(2 * kXRegSizeInBytes);
8811*f5c631daSSadaf Ebrahimi   __ PushWRegList(w1.GetBit() | w2.GetBit() | w4.GetBit() | w22.GetBit());
8812*f5c631daSSadaf Ebrahimi   __ PopWRegList(w25.GetBit() | w27.GetBit() | w28.GetBit() | w29.GetBit());
8813*f5c631daSSadaf Ebrahimi 
8814*f5c631daSSadaf Ebrahimi   __ Claim(2 * kXRegSizeInBytes);
8815*f5c631daSSadaf Ebrahimi   __ PushXRegList(0);
8816*f5c631daSSadaf Ebrahimi   __ PopXRegList(0);
8817*f5c631daSSadaf Ebrahimi   __ PushXRegList(0xffffffff);
8818*f5c631daSSadaf Ebrahimi   __ PopXRegList(0xffffffff);
8819*f5c631daSSadaf Ebrahimi   __ Drop(12 * kXRegSizeInBytes);
8820*f5c631daSSadaf Ebrahimi   END();
8821*f5c631daSSadaf Ebrahimi 
8822*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
8823*f5c631daSSadaf Ebrahimi     RUN();
8824*f5c631daSSadaf Ebrahimi 
8825*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1111111111111111, x3);
8826*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000000, x2);
8827*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3333333333333333, x1);
8828*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x2222222222222222, x0);
8829*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3333333333333333, x9);
8830*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x2222222222222222, x8);
8831*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000000, x7);
8832*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3333333333333333, x6);
8833*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1111111111111111, x5);
8834*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x2222222222222222, x4);
8835*f5c631daSSadaf Ebrahimi 
8836*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111U, w13);
8837*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x33333333U, w12);
8838*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00000000U, w11);
8839*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x22222222U, w10);
8840*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111U, w17);
8841*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00000000U, w16);
8842*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x33333333U, w15);
8843*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x22222222U, w14);
8844*f5c631daSSadaf Ebrahimi 
8845*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111U, w18);
8846*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111U, w19);
8847*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111U, w20);
8848*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111U, w21);
8849*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3333333333333333, x22);
8850*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000000, x23);
8851*f5c631daSSadaf Ebrahimi 
8852*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3333333333333333, x24);
8853*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3333333333333333, x26);
8854*f5c631daSSadaf Ebrahimi 
8855*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x33333333U, w25);
8856*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x00000000U, w27);
8857*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x22222222U, w28);
8858*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x33333333U, w29);
8859*f5c631daSSadaf Ebrahimi   }
8860*f5c631daSSadaf Ebrahimi }
8861*f5c631daSSadaf Ebrahimi 
8862*f5c631daSSadaf Ebrahimi 
TEST(printf)8863*f5c631daSSadaf Ebrahimi TEST(printf) {
8864*f5c631daSSadaf Ebrahimi   // RegisterDump::Dump uses NEON.
8865*f5c631daSSadaf Ebrahimi   // Printf uses FP to cast FP arguments to doubles.
8866*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP);
8867*f5c631daSSadaf Ebrahimi 
8868*f5c631daSSadaf Ebrahimi   START();
8869*f5c631daSSadaf Ebrahimi 
8870*f5c631daSSadaf Ebrahimi   char const* test_plain_string = "Printf with no arguments.\n";
8871*f5c631daSSadaf Ebrahimi   char const* test_substring = "'This is a substring.'";
8872*f5c631daSSadaf Ebrahimi   RegisterDump before;
8873*f5c631daSSadaf Ebrahimi 
8874*f5c631daSSadaf Ebrahimi   // Initialize x29 to the value of the stack pointer. We will use x29 as a
8875*f5c631daSSadaf Ebrahimi   // temporary stack pointer later, and initializing it in this way allows the
8876*f5c631daSSadaf Ebrahimi   // RegisterDump check to pass.
8877*f5c631daSSadaf Ebrahimi   __ Mov(x29, __ StackPointer());
8878*f5c631daSSadaf Ebrahimi 
8879*f5c631daSSadaf Ebrahimi   // Test simple integer arguments.
8880*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1234);
8881*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1234);
8882*f5c631daSSadaf Ebrahimi 
8883*f5c631daSSadaf Ebrahimi   // Test simple floating-point arguments.
8884*f5c631daSSadaf Ebrahimi   __ Fmov(d0, 1.234);
8885*f5c631daSSadaf Ebrahimi 
8886*f5c631daSSadaf Ebrahimi   // Test pointer (string) arguments.
8887*f5c631daSSadaf Ebrahimi   __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
8888*f5c631daSSadaf Ebrahimi 
8889*f5c631daSSadaf Ebrahimi   // Test the maximum number of arguments, and sign extension.
8890*f5c631daSSadaf Ebrahimi   __ Mov(w3, 0xffffffff);
8891*f5c631daSSadaf Ebrahimi   __ Mov(w4, 0xffffffff);
8892*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xffffffffffffffff);
8893*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0xffffffffffffffff);
8894*f5c631daSSadaf Ebrahimi   __ Fmov(s1, 1.234);
8895*f5c631daSSadaf Ebrahimi   __ Fmov(s2, 2.345);
8896*f5c631daSSadaf Ebrahimi   __ Fmov(d3, 3.456);
8897*f5c631daSSadaf Ebrahimi   __ Fmov(d4, 4.567);
8898*f5c631daSSadaf Ebrahimi 
8899*f5c631daSSadaf Ebrahimi   // Test printing callee-saved registers.
8900*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x123456789abcdef);
8901*f5c631daSSadaf Ebrahimi   __ Fmov(d10, 42.0);
8902*f5c631daSSadaf Ebrahimi 
8903*f5c631daSSadaf Ebrahimi   // Test with three arguments.
8904*f5c631daSSadaf Ebrahimi   __ Mov(x10, 3);
8905*f5c631daSSadaf Ebrahimi   __ Mov(x11, 40);
8906*f5c631daSSadaf Ebrahimi   __ Mov(x12, 500);
8907*f5c631daSSadaf Ebrahimi 
8908*f5c631daSSadaf Ebrahimi   // A single character.
8909*f5c631daSSadaf Ebrahimi   __ Mov(w13, 'x');
8910*f5c631daSSadaf Ebrahimi 
8911*f5c631daSSadaf Ebrahimi   // Check that we don't clobber any registers.
8912*f5c631daSSadaf Ebrahimi   before.Dump(&masm);
8913*f5c631daSSadaf Ebrahimi 
8914*f5c631daSSadaf Ebrahimi   __ Printf(test_plain_string);  // NOLINT(runtime/printf)
8915*f5c631daSSadaf Ebrahimi   __ Printf("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
8916*f5c631daSSadaf Ebrahimi   __ Printf("w5: %" PRId32 ", x5: %" PRId64 "\n", w5, x5);
8917*f5c631daSSadaf Ebrahimi   __ Printf("d0: %f\n", d0);
8918*f5c631daSSadaf Ebrahimi   __ Printf("Test %%s: %s\n", x2);
8919*f5c631daSSadaf Ebrahimi   __ Printf("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32
8920*f5c631daSSadaf Ebrahimi             "\n"
8921*f5c631daSSadaf Ebrahimi             "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
8922*f5c631daSSadaf Ebrahimi             w3,
8923*f5c631daSSadaf Ebrahimi             w4,
8924*f5c631daSSadaf Ebrahimi             x5,
8925*f5c631daSSadaf Ebrahimi             x6);
8926*f5c631daSSadaf Ebrahimi   __ Printf("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
8927*f5c631daSSadaf Ebrahimi   __ Printf("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
8928*f5c631daSSadaf Ebrahimi   __ Printf("%g\n", d10);
8929*f5c631daSSadaf Ebrahimi   __ Printf("%%%%%s%%%c%%\n", x2, w13);
8930*f5c631daSSadaf Ebrahimi 
8931*f5c631daSSadaf Ebrahimi   // Print the stack pointer (sp).
8932*f5c631daSSadaf Ebrahimi   __ Printf("StackPointer(sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
8933*f5c631daSSadaf Ebrahimi             __ StackPointer(),
8934*f5c631daSSadaf Ebrahimi             __ StackPointer().W());
8935*f5c631daSSadaf Ebrahimi 
8936*f5c631daSSadaf Ebrahimi   // Test with a different stack pointer.
8937*f5c631daSSadaf Ebrahimi   const Register old_stack_pointer = __ StackPointer();
8938*f5c631daSSadaf Ebrahimi   __ Mov(x29, old_stack_pointer);
8939*f5c631daSSadaf Ebrahimi   __ SetStackPointer(x29);
8940*f5c631daSSadaf Ebrahimi   // Print the stack pointer (not sp).
8941*f5c631daSSadaf Ebrahimi   __ Printf("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
8942*f5c631daSSadaf Ebrahimi             __ StackPointer(),
8943*f5c631daSSadaf Ebrahimi             __ StackPointer().W());
8944*f5c631daSSadaf Ebrahimi   __ Mov(old_stack_pointer, __ StackPointer());
8945*f5c631daSSadaf Ebrahimi   __ SetStackPointer(old_stack_pointer);
8946*f5c631daSSadaf Ebrahimi 
8947*f5c631daSSadaf Ebrahimi   // Test with three arguments.
8948*f5c631daSSadaf Ebrahimi   __ Printf("3=%u, 4=%u, 5=%u\n", x10, x11, x12);
8949*f5c631daSSadaf Ebrahimi 
8950*f5c631daSSadaf Ebrahimi   // Mixed argument types.
8951*f5c631daSSadaf Ebrahimi   __ Printf("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
8952*f5c631daSSadaf Ebrahimi             w3,
8953*f5c631daSSadaf Ebrahimi             s1,
8954*f5c631daSSadaf Ebrahimi             x5,
8955*f5c631daSSadaf Ebrahimi             d3);
8956*f5c631daSSadaf Ebrahimi   __ Printf("s1: %f, d3: %f, w3: %" PRId32 ", x5: %" PRId64 "\n",
8957*f5c631daSSadaf Ebrahimi             s1,
8958*f5c631daSSadaf Ebrahimi             d3,
8959*f5c631daSSadaf Ebrahimi             w3,
8960*f5c631daSSadaf Ebrahimi             x5);
8961*f5c631daSSadaf Ebrahimi 
8962*f5c631daSSadaf Ebrahimi   END();
8963*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
8964*f5c631daSSadaf Ebrahimi     RUN();
8965*f5c631daSSadaf Ebrahimi 
8966*f5c631daSSadaf Ebrahimi     // We cannot easily test the output of the Printf sequences, and because
8967*f5c631daSSadaf Ebrahimi     // Printf preserves all registers by default, we can't look at the number of
8968*f5c631daSSadaf Ebrahimi     // bytes that were printed. However, the printf_no_preserve test should
8969*f5c631daSSadaf Ebrahimi     // check
8970*f5c631daSSadaf Ebrahimi     // that, and here we just test that we didn't clobber any registers.
8971*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_REGISTERS(before);
8972*f5c631daSSadaf Ebrahimi   }
8973*f5c631daSSadaf Ebrahimi }
8974*f5c631daSSadaf Ebrahimi 
8975*f5c631daSSadaf Ebrahimi 
TEST(printf_no_preserve)8976*f5c631daSSadaf Ebrahimi TEST(printf_no_preserve) {
8977*f5c631daSSadaf Ebrahimi   // PrintfNoPreserve uses FP to cast FP arguments to doubles.
8978*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
8979*f5c631daSSadaf Ebrahimi 
8980*f5c631daSSadaf Ebrahimi   START();
8981*f5c631daSSadaf Ebrahimi 
8982*f5c631daSSadaf Ebrahimi   char const* test_plain_string = "Printf with no arguments.\n";
8983*f5c631daSSadaf Ebrahimi   char const* test_substring = "'This is a substring.'";
8984*f5c631daSSadaf Ebrahimi 
8985*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve(test_plain_string);
8986*f5c631daSSadaf Ebrahimi   __ Mov(x19, x0);
8987*f5c631daSSadaf Ebrahimi 
8988*f5c631daSSadaf Ebrahimi   // Test simple integer arguments.
8989*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1234);
8990*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x1234);
8991*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
8992*f5c631daSSadaf Ebrahimi   __ Mov(x20, x0);
8993*f5c631daSSadaf Ebrahimi 
8994*f5c631daSSadaf Ebrahimi   // Test simple floating-point arguments.
8995*f5c631daSSadaf Ebrahimi   __ Fmov(d0, 1.234);
8996*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("d0: %f\n", d0);
8997*f5c631daSSadaf Ebrahimi   __ Mov(x21, x0);
8998*f5c631daSSadaf Ebrahimi 
8999*f5c631daSSadaf Ebrahimi   // Test pointer (string) arguments.
9000*f5c631daSSadaf Ebrahimi   __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9001*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("Test %%s: %s\n", x2);
9002*f5c631daSSadaf Ebrahimi   __ Mov(x22, x0);
9003*f5c631daSSadaf Ebrahimi 
9004*f5c631daSSadaf Ebrahimi   // Test the maximum number of arguments, and sign extension.
9005*f5c631daSSadaf Ebrahimi   __ Mov(w3, 0xffffffff);
9006*f5c631daSSadaf Ebrahimi   __ Mov(w4, 0xffffffff);
9007*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xffffffffffffffff);
9008*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0xffffffffffffffff);
9009*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32
9010*f5c631daSSadaf Ebrahimi                       "\n"
9011*f5c631daSSadaf Ebrahimi                       "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9012*f5c631daSSadaf Ebrahimi                       w3,
9013*f5c631daSSadaf Ebrahimi                       w4,
9014*f5c631daSSadaf Ebrahimi                       x5,
9015*f5c631daSSadaf Ebrahimi                       x6);
9016*f5c631daSSadaf Ebrahimi   __ Mov(x23, x0);
9017*f5c631daSSadaf Ebrahimi 
9018*f5c631daSSadaf Ebrahimi   __ Fmov(s1, 1.234);
9019*f5c631daSSadaf Ebrahimi   __ Fmov(s2, 2.345);
9020*f5c631daSSadaf Ebrahimi   __ Fmov(d3, 3.456);
9021*f5c631daSSadaf Ebrahimi   __ Fmov(d4, 4.567);
9022*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
9023*f5c631daSSadaf Ebrahimi   __ Mov(x24, x0);
9024*f5c631daSSadaf Ebrahimi 
9025*f5c631daSSadaf Ebrahimi   // Test printing callee-saved registers.
9026*f5c631daSSadaf Ebrahimi   __ Mov(x28, 0x123456789abcdef);
9027*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
9028*f5c631daSSadaf Ebrahimi   __ Mov(x25, x0);
9029*f5c631daSSadaf Ebrahimi 
9030*f5c631daSSadaf Ebrahimi   __ Fmov(d10, 42.0);
9031*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("%g\n", d10);
9032*f5c631daSSadaf Ebrahimi   __ Mov(x26, x0);
9033*f5c631daSSadaf Ebrahimi 
9034*f5c631daSSadaf Ebrahimi   // Test with a different stack pointer.
9035*f5c631daSSadaf Ebrahimi   const Register old_stack_pointer = __ StackPointer();
9036*f5c631daSSadaf Ebrahimi   __ Mov(x29, old_stack_pointer);
9037*f5c631daSSadaf Ebrahimi   __ SetStackPointer(x29);
9038*f5c631daSSadaf Ebrahimi   // Print the stack pointer (not sp).
9039*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32
9040*f5c631daSSadaf Ebrahimi                       "\n",
9041*f5c631daSSadaf Ebrahimi                       __ StackPointer(),
9042*f5c631daSSadaf Ebrahimi                       __ StackPointer().W());
9043*f5c631daSSadaf Ebrahimi   __ Mov(x27, x0);
9044*f5c631daSSadaf Ebrahimi   __ Mov(old_stack_pointer, __ StackPointer());
9045*f5c631daSSadaf Ebrahimi   __ SetStackPointer(old_stack_pointer);
9046*f5c631daSSadaf Ebrahimi 
9047*f5c631daSSadaf Ebrahimi   // Test with three arguments.
9048*f5c631daSSadaf Ebrahimi   __ Mov(x3, 3);
9049*f5c631daSSadaf Ebrahimi   __ Mov(x4, 40);
9050*f5c631daSSadaf Ebrahimi   __ Mov(x5, 500);
9051*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("3=%u, 4=%u, 5=%u\n", x3, x4, x5);
9052*f5c631daSSadaf Ebrahimi   __ Mov(x28, x0);
9053*f5c631daSSadaf Ebrahimi 
9054*f5c631daSSadaf Ebrahimi   // Mixed argument types.
9055*f5c631daSSadaf Ebrahimi   __ Mov(w3, 0xffffffff);
9056*f5c631daSSadaf Ebrahimi   __ Fmov(s1, 1.234);
9057*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xffffffffffffffff);
9058*f5c631daSSadaf Ebrahimi   __ Fmov(d3, 3.456);
9059*f5c631daSSadaf Ebrahimi   __ PrintfNoPreserve("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
9060*f5c631daSSadaf Ebrahimi                       w3,
9061*f5c631daSSadaf Ebrahimi                       s1,
9062*f5c631daSSadaf Ebrahimi                       x5,
9063*f5c631daSSadaf Ebrahimi                       d3);
9064*f5c631daSSadaf Ebrahimi   __ Mov(x29, x0);
9065*f5c631daSSadaf Ebrahimi 
9066*f5c631daSSadaf Ebrahimi   END();
9067*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9068*f5c631daSSadaf Ebrahimi     RUN();
9069*f5c631daSSadaf Ebrahimi 
9070*f5c631daSSadaf Ebrahimi     // We cannot easily test the exact output of the Printf sequences, but we
9071*f5c631daSSadaf Ebrahimi     // can
9072*f5c631daSSadaf Ebrahimi     // use the return code to check that the string length was correct.
9073*f5c631daSSadaf Ebrahimi 
9074*f5c631daSSadaf Ebrahimi     // Printf with no arguments.
9075*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(strlen(test_plain_string), x19);
9076*f5c631daSSadaf Ebrahimi     // x0: 1234, x1: 0x00001234
9077*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(25, x20);
9078*f5c631daSSadaf Ebrahimi     // d0: 1.234000
9079*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(13, x21);
9080*f5c631daSSadaf Ebrahimi     // Test %s: 'This is a substring.'
9081*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(32, x22);
9082*f5c631daSSadaf Ebrahimi     // w3(uint32): 4294967295
9083*f5c631daSSadaf Ebrahimi     // w4(int32): -1
9084*f5c631daSSadaf Ebrahimi     // x5(uint64): 18446744073709551615
9085*f5c631daSSadaf Ebrahimi     // x6(int64): -1
9086*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(23 + 14 + 33 + 14, x23);
9087*f5c631daSSadaf Ebrahimi     // %f: 1.234000
9088*f5c631daSSadaf Ebrahimi     // %g: 2.345
9089*f5c631daSSadaf Ebrahimi     // %e: 3.456000e+00
9090*f5c631daSSadaf Ebrahimi     // %E: 4.567000E+00
9091*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(13 + 10 + 17 + 17, x24);
9092*f5c631daSSadaf Ebrahimi     // 0x89abcdef, 0x123456789abcdef
9093*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(30, x25);
9094*f5c631daSSadaf Ebrahimi     // 42
9095*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x26);
9096*f5c631daSSadaf Ebrahimi     // StackPointer(not sp): 0x00007fb037ae2370, 0x37ae2370
9097*f5c631daSSadaf Ebrahimi     // Note: This is an example value, but the field width is fixed here so the
9098*f5c631daSSadaf Ebrahimi     // string length is still predictable.
9099*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(53, x27);
9100*f5c631daSSadaf Ebrahimi     // 3=3, 4=40, 5=500
9101*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(17, x28);
9102*f5c631daSSadaf Ebrahimi     // w3: 4294967295, s1: 1.234000, x5: 18446744073709551615, d3: 3.456000
9103*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(69, x29);
9104*f5c631daSSadaf Ebrahimi   }
9105*f5c631daSSadaf Ebrahimi }
9106*f5c631daSSadaf Ebrahimi 
9107*f5c631daSSadaf Ebrahimi 
TEST(trace)9108*f5c631daSSadaf Ebrahimi TEST(trace) {
9109*f5c631daSSadaf Ebrahimi   // The Trace helper should not generate any code unless the simulator is being
9110*f5c631daSSadaf Ebrahimi   // used.
9111*f5c631daSSadaf Ebrahimi   SETUP();
9112*f5c631daSSadaf Ebrahimi   START();
9113*f5c631daSSadaf Ebrahimi 
9114*f5c631daSSadaf Ebrahimi   Label start;
9115*f5c631daSSadaf Ebrahimi   __ Bind(&start);
9116*f5c631daSSadaf Ebrahimi   __ Trace(LOG_ALL, TRACE_ENABLE);
9117*f5c631daSSadaf Ebrahimi   __ Trace(LOG_ALL, TRACE_DISABLE);
9118*f5c631daSSadaf Ebrahimi   if (masm.GenerateSimulatorCode()) {
9119*f5c631daSSadaf Ebrahimi     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0);
9120*f5c631daSSadaf Ebrahimi   } else {
9121*f5c631daSSadaf Ebrahimi     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
9122*f5c631daSSadaf Ebrahimi   }
9123*f5c631daSSadaf Ebrahimi 
9124*f5c631daSSadaf Ebrahimi   END();
9125*f5c631daSSadaf Ebrahimi }
9126*f5c631daSSadaf Ebrahimi 
9127*f5c631daSSadaf Ebrahimi 
TEST(log)9128*f5c631daSSadaf Ebrahimi TEST(log) {
9129*f5c631daSSadaf Ebrahimi   // The Log helper should not generate any code unless the simulator is being
9130*f5c631daSSadaf Ebrahimi   // used.
9131*f5c631daSSadaf Ebrahimi   SETUP();
9132*f5c631daSSadaf Ebrahimi   START();
9133*f5c631daSSadaf Ebrahimi 
9134*f5c631daSSadaf Ebrahimi   Label start;
9135*f5c631daSSadaf Ebrahimi   __ Bind(&start);
9136*f5c631daSSadaf Ebrahimi   __ Log(LOG_ALL);
9137*f5c631daSSadaf Ebrahimi   if (masm.GenerateSimulatorCode()) {
9138*f5c631daSSadaf Ebrahimi     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0);
9139*f5c631daSSadaf Ebrahimi   } else {
9140*f5c631daSSadaf Ebrahimi     VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0);
9141*f5c631daSSadaf Ebrahimi   }
9142*f5c631daSSadaf Ebrahimi 
9143*f5c631daSSadaf Ebrahimi   END();
9144*f5c631daSSadaf Ebrahimi }
9145*f5c631daSSadaf Ebrahimi 
9146*f5c631daSSadaf Ebrahimi 
TEST(blr_lr)9147*f5c631daSSadaf Ebrahimi TEST(blr_lr) {
9148*f5c631daSSadaf Ebrahimi   // A simple test to check that the simulator correcty handle "blr lr".
9149*f5c631daSSadaf Ebrahimi   SETUP();
9150*f5c631daSSadaf Ebrahimi 
9151*f5c631daSSadaf Ebrahimi   START();
9152*f5c631daSSadaf Ebrahimi   Label target;
9153*f5c631daSSadaf Ebrahimi   Label end;
9154*f5c631daSSadaf Ebrahimi 
9155*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0);
9156*f5c631daSSadaf Ebrahimi   __ Adr(lr, &target);
9157*f5c631daSSadaf Ebrahimi 
9158*f5c631daSSadaf Ebrahimi   __ Blr(lr);
9159*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xdeadbeef);
9160*f5c631daSSadaf Ebrahimi   __ B(&end);
9161*f5c631daSSadaf Ebrahimi 
9162*f5c631daSSadaf Ebrahimi   __ Bind(&target);
9163*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xc001c0de);
9164*f5c631daSSadaf Ebrahimi 
9165*f5c631daSSadaf Ebrahimi   __ Bind(&end);
9166*f5c631daSSadaf Ebrahimi   END();
9167*f5c631daSSadaf Ebrahimi 
9168*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9169*f5c631daSSadaf Ebrahimi     RUN();
9170*f5c631daSSadaf Ebrahimi 
9171*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xc001c0de, x0);
9172*f5c631daSSadaf Ebrahimi   }
9173*f5c631daSSadaf Ebrahimi }
9174*f5c631daSSadaf Ebrahimi 
9175*f5c631daSSadaf Ebrahimi 
TEST(barriers)9176*f5c631daSSadaf Ebrahimi TEST(barriers) {
9177*f5c631daSSadaf Ebrahimi   // Generate all supported barriers, this is just a smoke test
9178*f5c631daSSadaf Ebrahimi   SETUP();
9179*f5c631daSSadaf Ebrahimi 
9180*f5c631daSSadaf Ebrahimi   START();
9181*f5c631daSSadaf Ebrahimi 
9182*f5c631daSSadaf Ebrahimi   // DMB
9183*f5c631daSSadaf Ebrahimi   __ Dmb(FullSystem, BarrierAll);
9184*f5c631daSSadaf Ebrahimi   __ Dmb(FullSystem, BarrierReads);
9185*f5c631daSSadaf Ebrahimi   __ Dmb(FullSystem, BarrierWrites);
9186*f5c631daSSadaf Ebrahimi   __ Dmb(FullSystem, BarrierOther);
9187*f5c631daSSadaf Ebrahimi 
9188*f5c631daSSadaf Ebrahimi   __ Dmb(InnerShareable, BarrierAll);
9189*f5c631daSSadaf Ebrahimi   __ Dmb(InnerShareable, BarrierReads);
9190*f5c631daSSadaf Ebrahimi   __ Dmb(InnerShareable, BarrierWrites);
9191*f5c631daSSadaf Ebrahimi   __ Dmb(InnerShareable, BarrierOther);
9192*f5c631daSSadaf Ebrahimi 
9193*f5c631daSSadaf Ebrahimi   __ Dmb(NonShareable, BarrierAll);
9194*f5c631daSSadaf Ebrahimi   __ Dmb(NonShareable, BarrierReads);
9195*f5c631daSSadaf Ebrahimi   __ Dmb(NonShareable, BarrierWrites);
9196*f5c631daSSadaf Ebrahimi   __ Dmb(NonShareable, BarrierOther);
9197*f5c631daSSadaf Ebrahimi 
9198*f5c631daSSadaf Ebrahimi   __ Dmb(OuterShareable, BarrierAll);
9199*f5c631daSSadaf Ebrahimi   __ Dmb(OuterShareable, BarrierReads);
9200*f5c631daSSadaf Ebrahimi   __ Dmb(OuterShareable, BarrierWrites);
9201*f5c631daSSadaf Ebrahimi   __ Dmb(OuterShareable, BarrierOther);
9202*f5c631daSSadaf Ebrahimi 
9203*f5c631daSSadaf Ebrahimi   // DSB
9204*f5c631daSSadaf Ebrahimi   __ Dsb(FullSystem, BarrierAll);
9205*f5c631daSSadaf Ebrahimi   __ Dsb(FullSystem, BarrierReads);
9206*f5c631daSSadaf Ebrahimi   __ Dsb(FullSystem, BarrierWrites);
9207*f5c631daSSadaf Ebrahimi   __ Dsb(FullSystem, BarrierOther);
9208*f5c631daSSadaf Ebrahimi 
9209*f5c631daSSadaf Ebrahimi   __ Dsb(InnerShareable, BarrierAll);
9210*f5c631daSSadaf Ebrahimi   __ Dsb(InnerShareable, BarrierReads);
9211*f5c631daSSadaf Ebrahimi   __ Dsb(InnerShareable, BarrierWrites);
9212*f5c631daSSadaf Ebrahimi   __ Dsb(InnerShareable, BarrierOther);
9213*f5c631daSSadaf Ebrahimi 
9214*f5c631daSSadaf Ebrahimi   __ Dsb(NonShareable, BarrierAll);
9215*f5c631daSSadaf Ebrahimi   __ Dsb(NonShareable, BarrierReads);
9216*f5c631daSSadaf Ebrahimi   __ Dsb(NonShareable, BarrierWrites);
9217*f5c631daSSadaf Ebrahimi   __ Dsb(NonShareable, BarrierOther);
9218*f5c631daSSadaf Ebrahimi 
9219*f5c631daSSadaf Ebrahimi   __ Dsb(OuterShareable, BarrierAll);
9220*f5c631daSSadaf Ebrahimi   __ Dsb(OuterShareable, BarrierReads);
9221*f5c631daSSadaf Ebrahimi   __ Dsb(OuterShareable, BarrierWrites);
9222*f5c631daSSadaf Ebrahimi   __ Dsb(OuterShareable, BarrierOther);
9223*f5c631daSSadaf Ebrahimi 
9224*f5c631daSSadaf Ebrahimi   // ISB
9225*f5c631daSSadaf Ebrahimi   __ Isb();
9226*f5c631daSSadaf Ebrahimi 
9227*f5c631daSSadaf Ebrahimi   END();
9228*f5c631daSSadaf Ebrahimi 
9229*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9230*f5c631daSSadaf Ebrahimi     RUN();
9231*f5c631daSSadaf Ebrahimi   }
9232*f5c631daSSadaf Ebrahimi }
9233*f5c631daSSadaf Ebrahimi 
9234*f5c631daSSadaf Ebrahimi 
TEST(ldar_stlr)9235*f5c631daSSadaf Ebrahimi TEST(ldar_stlr) {
9236*f5c631daSSadaf Ebrahimi   // The middle value is read, modified, and written. The padding exists only to
9237*f5c631daSSadaf Ebrahimi   // check for over-write.
9238*f5c631daSSadaf Ebrahimi   uint8_t b[] = {0, 0x12, 0};
9239*f5c631daSSadaf Ebrahimi   uint16_t h[] = {0, 0x1234, 0};
9240*f5c631daSSadaf Ebrahimi   uint32_t w[] = {0, 0x12345678, 0};
9241*f5c631daSSadaf Ebrahimi   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9242*f5c631daSSadaf Ebrahimi 
9243*f5c631daSSadaf Ebrahimi   SETUP();
9244*f5c631daSSadaf Ebrahimi   START();
9245*f5c631daSSadaf Ebrahimi 
9246*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9247*f5c631daSSadaf Ebrahimi   __ Ldarb(w0, MemOperand(x10));
9248*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9249*f5c631daSSadaf Ebrahimi   __ Stlrb(w0, MemOperand(x10));
9250*f5c631daSSadaf Ebrahimi 
9251*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9252*f5c631daSSadaf Ebrahimi   __ Ldarh(w0, MemOperand(x10));
9253*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9254*f5c631daSSadaf Ebrahimi   __ Stlrh(w0, MemOperand(x10));
9255*f5c631daSSadaf Ebrahimi 
9256*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9257*f5c631daSSadaf Ebrahimi   __ Ldar(w0, MemOperand(x10));
9258*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9259*f5c631daSSadaf Ebrahimi   __ Stlr(w0, MemOperand(x10));
9260*f5c631daSSadaf Ebrahimi 
9261*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9262*f5c631daSSadaf Ebrahimi   __ Ldar(x0, MemOperand(x10));
9263*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9264*f5c631daSSadaf Ebrahimi   __ Stlr(x0, MemOperand(x10));
9265*f5c631daSSadaf Ebrahimi 
9266*f5c631daSSadaf Ebrahimi   END();
9267*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9268*f5c631daSSadaf Ebrahimi     RUN();
9269*f5c631daSSadaf Ebrahimi 
9270*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x13, b[1]);
9271*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1235, h[1]);
9272*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345679, w[1]);
9273*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9274*f5c631daSSadaf Ebrahimi 
9275*f5c631daSSadaf Ebrahimi     // Check for over-write.
9276*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[0]);
9277*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[2]);
9278*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[0]);
9279*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[2]);
9280*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[0]);
9281*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[2]);
9282*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[0]);
9283*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[2]);
9284*f5c631daSSadaf Ebrahimi   }
9285*f5c631daSSadaf Ebrahimi }
9286*f5c631daSSadaf Ebrahimi 
9287*f5c631daSSadaf Ebrahimi 
TEST(ldlar_stllr)9288*f5c631daSSadaf Ebrahimi TEST(ldlar_stllr) {
9289*f5c631daSSadaf Ebrahimi   // The middle value is read, modified, and written. The padding exists only to
9290*f5c631daSSadaf Ebrahimi   // check for over-write.
9291*f5c631daSSadaf Ebrahimi   uint8_t b[] = {0, 0x12, 0};
9292*f5c631daSSadaf Ebrahimi   uint16_t h[] = {0, 0x1234, 0};
9293*f5c631daSSadaf Ebrahimi   uint32_t w[] = {0, 0x12345678, 0};
9294*f5c631daSSadaf Ebrahimi   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9295*f5c631daSSadaf Ebrahimi 
9296*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kLORegions);
9297*f5c631daSSadaf Ebrahimi 
9298*f5c631daSSadaf Ebrahimi   START();
9299*f5c631daSSadaf Ebrahimi 
9300*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9301*f5c631daSSadaf Ebrahimi   __ Ldlarb(w0, MemOperand(x10));
9302*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9303*f5c631daSSadaf Ebrahimi   __ Stllrb(w0, MemOperand(x10));
9304*f5c631daSSadaf Ebrahimi 
9305*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9306*f5c631daSSadaf Ebrahimi   __ Ldlarh(w0, MemOperand(x10));
9307*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9308*f5c631daSSadaf Ebrahimi   __ Stllrh(w0, MemOperand(x10));
9309*f5c631daSSadaf Ebrahimi 
9310*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9311*f5c631daSSadaf Ebrahimi   __ Ldlar(w0, MemOperand(x10));
9312*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9313*f5c631daSSadaf Ebrahimi   __ Stllr(w0, MemOperand(x10));
9314*f5c631daSSadaf Ebrahimi 
9315*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9316*f5c631daSSadaf Ebrahimi   __ Ldlar(x0, MemOperand(x10));
9317*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9318*f5c631daSSadaf Ebrahimi   __ Stllr(x0, MemOperand(x10));
9319*f5c631daSSadaf Ebrahimi 
9320*f5c631daSSadaf Ebrahimi   END();
9321*f5c631daSSadaf Ebrahimi 
9322*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9323*f5c631daSSadaf Ebrahimi     RUN();
9324*f5c631daSSadaf Ebrahimi 
9325*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x13, b[1]);
9326*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1235, h[1]);
9327*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345679, w[1]);
9328*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9329*f5c631daSSadaf Ebrahimi 
9330*f5c631daSSadaf Ebrahimi     // Check for over-write.
9331*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[0]);
9332*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[2]);
9333*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[0]);
9334*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[2]);
9335*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[0]);
9336*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[2]);
9337*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[0]);
9338*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[2]);
9339*f5c631daSSadaf Ebrahimi   }
9340*f5c631daSSadaf Ebrahimi }
9341*f5c631daSSadaf Ebrahimi 
9342*f5c631daSSadaf Ebrahimi 
TEST(ldxr_stxr)9343*f5c631daSSadaf Ebrahimi TEST(ldxr_stxr) {
9344*f5c631daSSadaf Ebrahimi   // The middle value is read, modified, and written. The padding exists only to
9345*f5c631daSSadaf Ebrahimi   // check for over-write.
9346*f5c631daSSadaf Ebrahimi   uint8_t b[] = {0, 0x12, 0};
9347*f5c631daSSadaf Ebrahimi   uint16_t h[] = {0, 0x1234, 0};
9348*f5c631daSSadaf Ebrahimi   uint32_t w[] = {0, 0x12345678, 0};
9349*f5c631daSSadaf Ebrahimi   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9350*f5c631daSSadaf Ebrahimi 
9351*f5c631daSSadaf Ebrahimi   // As above, but get suitably-aligned values for ldxp and stxp.
9352*f5c631daSSadaf Ebrahimi   uint32_t wp_data[] = {0, 0, 0, 0, 0};
9353*f5c631daSSadaf Ebrahimi   uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
9354*f5c631daSSadaf Ebrahimi   wp[1] = 0x12345678;  // wp[1] is 64-bit-aligned.
9355*f5c631daSSadaf Ebrahimi   wp[2] = 0x87654321;
9356*f5c631daSSadaf Ebrahimi   uint64_t xp_data[] = {0, 0, 0, 0, 0};
9357*f5c631daSSadaf Ebrahimi   uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
9358*f5c631daSSadaf Ebrahimi   xp[1] = 0x123456789abcdef0;  // xp[1] is 128-bit-aligned.
9359*f5c631daSSadaf Ebrahimi   xp[2] = 0x0fedcba987654321;
9360*f5c631daSSadaf Ebrahimi 
9361*f5c631daSSadaf Ebrahimi   SETUP();
9362*f5c631daSSadaf Ebrahimi   START();
9363*f5c631daSSadaf Ebrahimi 
9364*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9365*f5c631daSSadaf Ebrahimi   Label try_b;
9366*f5c631daSSadaf Ebrahimi   __ Bind(&try_b);
9367*f5c631daSSadaf Ebrahimi   __ Ldxrb(w0, MemOperand(x10));
9368*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9369*f5c631daSSadaf Ebrahimi   __ Stxrb(w5, w0, MemOperand(x10));
9370*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_b);
9371*f5c631daSSadaf Ebrahimi 
9372*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9373*f5c631daSSadaf Ebrahimi   Label try_h;
9374*f5c631daSSadaf Ebrahimi   __ Bind(&try_h);
9375*f5c631daSSadaf Ebrahimi   __ Ldxrh(w0, MemOperand(x10));
9376*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9377*f5c631daSSadaf Ebrahimi   __ Stxrh(w5, w0, MemOperand(x10));
9378*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_h);
9379*f5c631daSSadaf Ebrahimi 
9380*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9381*f5c631daSSadaf Ebrahimi   Label try_w;
9382*f5c631daSSadaf Ebrahimi   __ Bind(&try_w);
9383*f5c631daSSadaf Ebrahimi   __ Ldxr(w0, MemOperand(x10));
9384*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9385*f5c631daSSadaf Ebrahimi   __ Stxr(w5, w0, MemOperand(x10));
9386*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_w);
9387*f5c631daSSadaf Ebrahimi 
9388*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9389*f5c631daSSadaf Ebrahimi   Label try_x;
9390*f5c631daSSadaf Ebrahimi   __ Bind(&try_x);
9391*f5c631daSSadaf Ebrahimi   __ Ldxr(x0, MemOperand(x10));
9392*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9393*f5c631daSSadaf Ebrahimi   __ Stxr(w5, x0, MemOperand(x10));
9394*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_x);
9395*f5c631daSSadaf Ebrahimi 
9396*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
9397*f5c631daSSadaf Ebrahimi   Label try_wp;
9398*f5c631daSSadaf Ebrahimi   __ Bind(&try_wp);
9399*f5c631daSSadaf Ebrahimi   __ Ldxp(w0, w1, MemOperand(x10));
9400*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9401*f5c631daSSadaf Ebrahimi   __ Add(w1, w1, 1);
9402*f5c631daSSadaf Ebrahimi   __ Stxp(w5, w0, w1, MemOperand(x10));
9403*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_wp);
9404*f5c631daSSadaf Ebrahimi 
9405*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
9406*f5c631daSSadaf Ebrahimi   Label try_xp;
9407*f5c631daSSadaf Ebrahimi   __ Bind(&try_xp);
9408*f5c631daSSadaf Ebrahimi   __ Ldxp(x0, x1, MemOperand(x10));
9409*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9410*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);
9411*f5c631daSSadaf Ebrahimi   __ Stxp(w5, x0, x1, MemOperand(x10));
9412*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_xp);
9413*f5c631daSSadaf Ebrahimi 
9414*f5c631daSSadaf Ebrahimi   END();
9415*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9416*f5c631daSSadaf Ebrahimi     RUN();
9417*f5c631daSSadaf Ebrahimi 
9418*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x13, b[1]);
9419*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1235, h[1]);
9420*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345679, w[1]);
9421*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9422*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345679, wp[1]);
9423*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x87654322, wp[2]);
9424*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
9425*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
9426*f5c631daSSadaf Ebrahimi 
9427*f5c631daSSadaf Ebrahimi     // Check for over-write.
9428*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[0]);
9429*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[2]);
9430*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[0]);
9431*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[2]);
9432*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[0]);
9433*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[2]);
9434*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[0]);
9435*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[2]);
9436*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, wp[0]);
9437*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, wp[3]);
9438*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, xp[0]);
9439*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, xp[3]);
9440*f5c631daSSadaf Ebrahimi   }
9441*f5c631daSSadaf Ebrahimi }
9442*f5c631daSSadaf Ebrahimi 
9443*f5c631daSSadaf Ebrahimi 
TEST(ldaxr_stlxr)9444*f5c631daSSadaf Ebrahimi TEST(ldaxr_stlxr) {
9445*f5c631daSSadaf Ebrahimi   // The middle value is read, modified, and written. The padding exists only to
9446*f5c631daSSadaf Ebrahimi   // check for over-write.
9447*f5c631daSSadaf Ebrahimi   uint8_t b[] = {0, 0x12, 0};
9448*f5c631daSSadaf Ebrahimi   uint16_t h[] = {0, 0x1234, 0};
9449*f5c631daSSadaf Ebrahimi   uint32_t w[] = {0, 0x12345678, 0};
9450*f5c631daSSadaf Ebrahimi   uint64_t x[] = {0, 0x123456789abcdef0, 0};
9451*f5c631daSSadaf Ebrahimi 
9452*f5c631daSSadaf Ebrahimi   // As above, but get suitably-aligned values for ldxp and stxp.
9453*f5c631daSSadaf Ebrahimi   uint32_t wp_data[] = {0, 0, 0, 0, 0};
9454*f5c631daSSadaf Ebrahimi   uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
9455*f5c631daSSadaf Ebrahimi   wp[1] = 0x12345678;  // wp[1] is 64-bit-aligned.
9456*f5c631daSSadaf Ebrahimi   wp[2] = 0x87654321;
9457*f5c631daSSadaf Ebrahimi   uint64_t xp_data[] = {0, 0, 0, 0, 0};
9458*f5c631daSSadaf Ebrahimi   uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
9459*f5c631daSSadaf Ebrahimi   xp[1] = 0x123456789abcdef0;  // xp[1] is 128-bit-aligned.
9460*f5c631daSSadaf Ebrahimi   xp[2] = 0x0fedcba987654321;
9461*f5c631daSSadaf Ebrahimi 
9462*f5c631daSSadaf Ebrahimi   SETUP();
9463*f5c631daSSadaf Ebrahimi   START();
9464*f5c631daSSadaf Ebrahimi 
9465*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
9466*f5c631daSSadaf Ebrahimi   Label try_b;
9467*f5c631daSSadaf Ebrahimi   __ Bind(&try_b);
9468*f5c631daSSadaf Ebrahimi   __ Ldaxrb(w0, MemOperand(x10));
9469*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9470*f5c631daSSadaf Ebrahimi   __ Stlxrb(w5, w0, MemOperand(x10));
9471*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_b);
9472*f5c631daSSadaf Ebrahimi 
9473*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
9474*f5c631daSSadaf Ebrahimi   Label try_h;
9475*f5c631daSSadaf Ebrahimi   __ Bind(&try_h);
9476*f5c631daSSadaf Ebrahimi   __ Ldaxrh(w0, MemOperand(x10));
9477*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9478*f5c631daSSadaf Ebrahimi   __ Stlxrh(w5, w0, MemOperand(x10));
9479*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_h);
9480*f5c631daSSadaf Ebrahimi 
9481*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
9482*f5c631daSSadaf Ebrahimi   Label try_w;
9483*f5c631daSSadaf Ebrahimi   __ Bind(&try_w);
9484*f5c631daSSadaf Ebrahimi   __ Ldaxr(w0, MemOperand(x10));
9485*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9486*f5c631daSSadaf Ebrahimi   __ Stlxr(w5, w0, MemOperand(x10));
9487*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_w);
9488*f5c631daSSadaf Ebrahimi 
9489*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
9490*f5c631daSSadaf Ebrahimi   Label try_x;
9491*f5c631daSSadaf Ebrahimi   __ Bind(&try_x);
9492*f5c631daSSadaf Ebrahimi   __ Ldaxr(x0, MemOperand(x10));
9493*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9494*f5c631daSSadaf Ebrahimi   __ Stlxr(w5, x0, MemOperand(x10));
9495*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_x);
9496*f5c631daSSadaf Ebrahimi 
9497*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
9498*f5c631daSSadaf Ebrahimi   Label try_wp;
9499*f5c631daSSadaf Ebrahimi   __ Bind(&try_wp);
9500*f5c631daSSadaf Ebrahimi   __ Ldaxp(w0, w1, MemOperand(x10));
9501*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9502*f5c631daSSadaf Ebrahimi   __ Add(w1, w1, 1);
9503*f5c631daSSadaf Ebrahimi   __ Stlxp(w5, w0, w1, MemOperand(x10));
9504*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_wp);
9505*f5c631daSSadaf Ebrahimi 
9506*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
9507*f5c631daSSadaf Ebrahimi   Label try_xp;
9508*f5c631daSSadaf Ebrahimi   __ Bind(&try_xp);
9509*f5c631daSSadaf Ebrahimi   __ Ldaxp(x0, x1, MemOperand(x10));
9510*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9511*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);
9512*f5c631daSSadaf Ebrahimi   __ Stlxp(w5, x0, x1, MemOperand(x10));
9513*f5c631daSSadaf Ebrahimi   __ Cbnz(w5, &try_xp);
9514*f5c631daSSadaf Ebrahimi 
9515*f5c631daSSadaf Ebrahimi   END();
9516*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9517*f5c631daSSadaf Ebrahimi     RUN();
9518*f5c631daSSadaf Ebrahimi 
9519*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x13, b[1]);
9520*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x1235, h[1]);
9521*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345679, w[1]);
9522*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
9523*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x12345679, wp[1]);
9524*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x87654322, wp[2]);
9525*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
9526*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
9527*f5c631daSSadaf Ebrahimi 
9528*f5c631daSSadaf Ebrahimi     // Check for over-write.
9529*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[0]);
9530*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, b[2]);
9531*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[0]);
9532*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, h[2]);
9533*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[0]);
9534*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, w[2]);
9535*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[0]);
9536*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x[2]);
9537*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, wp[0]);
9538*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0, wp[3]);
9539*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, xp[0]);
9540*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, xp[3]);
9541*f5c631daSSadaf Ebrahimi   }
9542*f5c631daSSadaf Ebrahimi }
9543*f5c631daSSadaf Ebrahimi 
9544*f5c631daSSadaf Ebrahimi 
TEST(clrex)9545*f5c631daSSadaf Ebrahimi TEST(clrex) {
9546*f5c631daSSadaf Ebrahimi   // This data should never be written.
9547*f5c631daSSadaf Ebrahimi   uint64_t data[] = {0, 0, 0};
9548*f5c631daSSadaf Ebrahimi   uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
9549*f5c631daSSadaf Ebrahimi 
9550*f5c631daSSadaf Ebrahimi   SETUP();
9551*f5c631daSSadaf Ebrahimi   START();
9552*f5c631daSSadaf Ebrahimi 
9553*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
9554*f5c631daSSadaf Ebrahimi   __ Mov(w6, 0);
9555*f5c631daSSadaf Ebrahimi 
9556*f5c631daSSadaf Ebrahimi   __ Ldxrb(w0, MemOperand(x10));
9557*f5c631daSSadaf Ebrahimi   __ Clrex();
9558*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9559*f5c631daSSadaf Ebrahimi   __ Stxrb(w5, w0, MemOperand(x10));
9560*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9561*f5c631daSSadaf Ebrahimi 
9562*f5c631daSSadaf Ebrahimi   __ Ldxrh(w0, MemOperand(x10));
9563*f5c631daSSadaf Ebrahimi   __ Clrex();
9564*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9565*f5c631daSSadaf Ebrahimi   __ Stxrh(w5, w0, MemOperand(x10));
9566*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9567*f5c631daSSadaf Ebrahimi 
9568*f5c631daSSadaf Ebrahimi   __ Ldxr(w0, MemOperand(x10));
9569*f5c631daSSadaf Ebrahimi   __ Clrex();
9570*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9571*f5c631daSSadaf Ebrahimi   __ Stxr(w5, w0, MemOperand(x10));
9572*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9573*f5c631daSSadaf Ebrahimi 
9574*f5c631daSSadaf Ebrahimi   __ Ldxr(x0, MemOperand(x10));
9575*f5c631daSSadaf Ebrahimi   __ Clrex();
9576*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9577*f5c631daSSadaf Ebrahimi   __ Stxr(w5, x0, MemOperand(x10));
9578*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9579*f5c631daSSadaf Ebrahimi 
9580*f5c631daSSadaf Ebrahimi   __ Ldxp(w0, w1, MemOperand(x10));
9581*f5c631daSSadaf Ebrahimi   __ Clrex();
9582*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9583*f5c631daSSadaf Ebrahimi   __ Add(w1, w1, 1);
9584*f5c631daSSadaf Ebrahimi   __ Stxp(w5, w0, w1, MemOperand(x10));
9585*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9586*f5c631daSSadaf Ebrahimi 
9587*f5c631daSSadaf Ebrahimi   __ Ldxp(x0, x1, MemOperand(x10));
9588*f5c631daSSadaf Ebrahimi   __ Clrex();
9589*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9590*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);
9591*f5c631daSSadaf Ebrahimi   __ Stxp(w5, x0, x1, MemOperand(x10));
9592*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9593*f5c631daSSadaf Ebrahimi 
9594*f5c631daSSadaf Ebrahimi   // Acquire-release variants.
9595*f5c631daSSadaf Ebrahimi 
9596*f5c631daSSadaf Ebrahimi   __ Ldaxrb(w0, MemOperand(x10));
9597*f5c631daSSadaf Ebrahimi   __ Clrex();
9598*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9599*f5c631daSSadaf Ebrahimi   __ Stlxrb(w5, w0, MemOperand(x10));
9600*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9601*f5c631daSSadaf Ebrahimi 
9602*f5c631daSSadaf Ebrahimi   __ Ldaxrh(w0, MemOperand(x10));
9603*f5c631daSSadaf Ebrahimi   __ Clrex();
9604*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9605*f5c631daSSadaf Ebrahimi   __ Stlxrh(w5, w0, MemOperand(x10));
9606*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9607*f5c631daSSadaf Ebrahimi 
9608*f5c631daSSadaf Ebrahimi   __ Ldaxr(w0, MemOperand(x10));
9609*f5c631daSSadaf Ebrahimi   __ Clrex();
9610*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9611*f5c631daSSadaf Ebrahimi   __ Stlxr(w5, w0, MemOperand(x10));
9612*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9613*f5c631daSSadaf Ebrahimi 
9614*f5c631daSSadaf Ebrahimi   __ Ldaxr(x0, MemOperand(x10));
9615*f5c631daSSadaf Ebrahimi   __ Clrex();
9616*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9617*f5c631daSSadaf Ebrahimi   __ Stlxr(w5, x0, MemOperand(x10));
9618*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9619*f5c631daSSadaf Ebrahimi 
9620*f5c631daSSadaf Ebrahimi   __ Ldaxp(w0, w1, MemOperand(x10));
9621*f5c631daSSadaf Ebrahimi   __ Clrex();
9622*f5c631daSSadaf Ebrahimi   __ Add(w0, w0, 1);
9623*f5c631daSSadaf Ebrahimi   __ Add(w1, w1, 1);
9624*f5c631daSSadaf Ebrahimi   __ Stlxp(w5, w0, w1, MemOperand(x10));
9625*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9626*f5c631daSSadaf Ebrahimi 
9627*f5c631daSSadaf Ebrahimi   __ Ldaxp(x0, x1, MemOperand(x10));
9628*f5c631daSSadaf Ebrahimi   __ Clrex();
9629*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, 1);
9630*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);
9631*f5c631daSSadaf Ebrahimi   __ Stlxp(w5, x0, x1, MemOperand(x10));
9632*f5c631daSSadaf Ebrahimi   __ Add(w6, w6, w5);
9633*f5c631daSSadaf Ebrahimi 
9634*f5c631daSSadaf Ebrahimi   END();
9635*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9636*f5c631daSSadaf Ebrahimi     RUN();
9637*f5c631daSSadaf Ebrahimi 
9638*f5c631daSSadaf Ebrahimi     // None of the 12 store-exclusives should have succeeded.
9639*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(12, w6);
9640*f5c631daSSadaf Ebrahimi 
9641*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, data[0]);
9642*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, data[1]);
9643*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, data[2]);
9644*f5c631daSSadaf Ebrahimi   }
9645*f5c631daSSadaf Ebrahimi }
9646*f5c631daSSadaf Ebrahimi 
9647*f5c631daSSadaf Ebrahimi 
9648*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
9649*f5c631daSSadaf Ebrahimi // Check that the simulator occasionally makes store-exclusive fail.
TEST(ldxr_stxr_fail)9650*f5c631daSSadaf Ebrahimi TEST(ldxr_stxr_fail) {
9651*f5c631daSSadaf Ebrahimi   uint64_t data[] = {0, 0, 0};
9652*f5c631daSSadaf Ebrahimi   uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
9653*f5c631daSSadaf Ebrahimi 
9654*f5c631daSSadaf Ebrahimi   // Impose a hard limit on the number of attempts, so the test cannot hang.
9655*f5c631daSSadaf Ebrahimi   static const uint64_t kWatchdog = 10000;
9656*f5c631daSSadaf Ebrahimi   Label done;
9657*f5c631daSSadaf Ebrahimi 
9658*f5c631daSSadaf Ebrahimi   SETUP();
9659*f5c631daSSadaf Ebrahimi   START();
9660*f5c631daSSadaf Ebrahimi 
9661*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
9662*f5c631daSSadaf Ebrahimi   __ Mov(x11, kWatchdog);
9663*f5c631daSSadaf Ebrahimi 
9664*f5c631daSSadaf Ebrahimi   // This loop is the opposite of what we normally do with ldxr and stxr; we
9665*f5c631daSSadaf Ebrahimi   // keep trying until we fail (or the watchdog counter runs out).
9666*f5c631daSSadaf Ebrahimi   Label try_b;
9667*f5c631daSSadaf Ebrahimi   __ Bind(&try_b);
9668*f5c631daSSadaf Ebrahimi   __ Ldxrb(w0, MemOperand(x10));
9669*f5c631daSSadaf Ebrahimi   __ Stxrb(w5, w0, MemOperand(x10));
9670*f5c631daSSadaf Ebrahimi   // Check the watchdog counter.
9671*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9672*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9673*f5c631daSSadaf Ebrahimi   // Check the exclusive-store result.
9674*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_b);
9675*f5c631daSSadaf Ebrahimi 
9676*f5c631daSSadaf Ebrahimi   Label try_h;
9677*f5c631daSSadaf Ebrahimi   __ Bind(&try_h);
9678*f5c631daSSadaf Ebrahimi   __ Ldxrh(w0, MemOperand(x10));
9679*f5c631daSSadaf Ebrahimi   __ Stxrh(w5, w0, MemOperand(x10));
9680*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9681*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9682*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_h);
9683*f5c631daSSadaf Ebrahimi 
9684*f5c631daSSadaf Ebrahimi   Label try_w;
9685*f5c631daSSadaf Ebrahimi   __ Bind(&try_w);
9686*f5c631daSSadaf Ebrahimi   __ Ldxr(w0, MemOperand(x10));
9687*f5c631daSSadaf Ebrahimi   __ Stxr(w5, w0, MemOperand(x10));
9688*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9689*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9690*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_w);
9691*f5c631daSSadaf Ebrahimi 
9692*f5c631daSSadaf Ebrahimi   Label try_x;
9693*f5c631daSSadaf Ebrahimi   __ Bind(&try_x);
9694*f5c631daSSadaf Ebrahimi   __ Ldxr(x0, MemOperand(x10));
9695*f5c631daSSadaf Ebrahimi   __ Stxr(w5, x0, MemOperand(x10));
9696*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9697*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9698*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_x);
9699*f5c631daSSadaf Ebrahimi 
9700*f5c631daSSadaf Ebrahimi   Label try_wp;
9701*f5c631daSSadaf Ebrahimi   __ Bind(&try_wp);
9702*f5c631daSSadaf Ebrahimi   __ Ldxp(w0, w1, MemOperand(x10));
9703*f5c631daSSadaf Ebrahimi   __ Stxp(w5, w0, w1, MemOperand(x10));
9704*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9705*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9706*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_wp);
9707*f5c631daSSadaf Ebrahimi 
9708*f5c631daSSadaf Ebrahimi   Label try_xp;
9709*f5c631daSSadaf Ebrahimi   __ Bind(&try_xp);
9710*f5c631daSSadaf Ebrahimi   __ Ldxp(x0, x1, MemOperand(x10));
9711*f5c631daSSadaf Ebrahimi   __ Stxp(w5, x0, x1, MemOperand(x10));
9712*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9713*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9714*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_xp);
9715*f5c631daSSadaf Ebrahimi 
9716*f5c631daSSadaf Ebrahimi   __ Bind(&done);
9717*f5c631daSSadaf Ebrahimi   // Trigger an error if x11 (watchdog) is zero.
9718*f5c631daSSadaf Ebrahimi   __ Cmp(x11, 0);
9719*f5c631daSSadaf Ebrahimi   __ Cset(x12, eq);
9720*f5c631daSSadaf Ebrahimi 
9721*f5c631daSSadaf Ebrahimi   END();
9722*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9723*f5c631daSSadaf Ebrahimi     RUN();
9724*f5c631daSSadaf Ebrahimi 
9725*f5c631daSSadaf Ebrahimi     // Check that the watchdog counter didn't run out.
9726*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x12);
9727*f5c631daSSadaf Ebrahimi   }
9728*f5c631daSSadaf Ebrahimi }
9729*f5c631daSSadaf Ebrahimi #endif
9730*f5c631daSSadaf Ebrahimi 
9731*f5c631daSSadaf Ebrahimi 
9732*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
9733*f5c631daSSadaf Ebrahimi // Check that the simulator occasionally makes store-exclusive fail.
TEST(ldaxr_stlxr_fail)9734*f5c631daSSadaf Ebrahimi TEST(ldaxr_stlxr_fail) {
9735*f5c631daSSadaf Ebrahimi   uint64_t data[] = {0, 0, 0};
9736*f5c631daSSadaf Ebrahimi   uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
9737*f5c631daSSadaf Ebrahimi 
9738*f5c631daSSadaf Ebrahimi   // Impose a hard limit on the number of attempts, so the test cannot hang.
9739*f5c631daSSadaf Ebrahimi   static const uint64_t kWatchdog = 10000;
9740*f5c631daSSadaf Ebrahimi   Label done;
9741*f5c631daSSadaf Ebrahimi 
9742*f5c631daSSadaf Ebrahimi   SETUP();
9743*f5c631daSSadaf Ebrahimi   START();
9744*f5c631daSSadaf Ebrahimi 
9745*f5c631daSSadaf Ebrahimi   __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
9746*f5c631daSSadaf Ebrahimi   __ Mov(x11, kWatchdog);
9747*f5c631daSSadaf Ebrahimi 
9748*f5c631daSSadaf Ebrahimi   // This loop is the opposite of what we normally do with ldxr and stxr; we
9749*f5c631daSSadaf Ebrahimi   // keep trying until we fail (or the watchdog counter runs out).
9750*f5c631daSSadaf Ebrahimi   Label try_b;
9751*f5c631daSSadaf Ebrahimi   __ Bind(&try_b);
9752*f5c631daSSadaf Ebrahimi   __ Ldxrb(w0, MemOperand(x10));
9753*f5c631daSSadaf Ebrahimi   __ Stxrb(w5, w0, MemOperand(x10));
9754*f5c631daSSadaf Ebrahimi   // Check the watchdog counter.
9755*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9756*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9757*f5c631daSSadaf Ebrahimi   // Check the exclusive-store result.
9758*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_b);
9759*f5c631daSSadaf Ebrahimi 
9760*f5c631daSSadaf Ebrahimi   Label try_h;
9761*f5c631daSSadaf Ebrahimi   __ Bind(&try_h);
9762*f5c631daSSadaf Ebrahimi   __ Ldaxrh(w0, MemOperand(x10));
9763*f5c631daSSadaf Ebrahimi   __ Stlxrh(w5, w0, MemOperand(x10));
9764*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9765*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9766*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_h);
9767*f5c631daSSadaf Ebrahimi 
9768*f5c631daSSadaf Ebrahimi   Label try_w;
9769*f5c631daSSadaf Ebrahimi   __ Bind(&try_w);
9770*f5c631daSSadaf Ebrahimi   __ Ldaxr(w0, MemOperand(x10));
9771*f5c631daSSadaf Ebrahimi   __ Stlxr(w5, w0, MemOperand(x10));
9772*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9773*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9774*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_w);
9775*f5c631daSSadaf Ebrahimi 
9776*f5c631daSSadaf Ebrahimi   Label try_x;
9777*f5c631daSSadaf Ebrahimi   __ Bind(&try_x);
9778*f5c631daSSadaf Ebrahimi   __ Ldaxr(x0, MemOperand(x10));
9779*f5c631daSSadaf Ebrahimi   __ Stlxr(w5, x0, MemOperand(x10));
9780*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9781*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9782*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_x);
9783*f5c631daSSadaf Ebrahimi 
9784*f5c631daSSadaf Ebrahimi   Label try_wp;
9785*f5c631daSSadaf Ebrahimi   __ Bind(&try_wp);
9786*f5c631daSSadaf Ebrahimi   __ Ldaxp(w0, w1, MemOperand(x10));
9787*f5c631daSSadaf Ebrahimi   __ Stlxp(w5, w0, w1, MemOperand(x10));
9788*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9789*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9790*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_wp);
9791*f5c631daSSadaf Ebrahimi 
9792*f5c631daSSadaf Ebrahimi   Label try_xp;
9793*f5c631daSSadaf Ebrahimi   __ Bind(&try_xp);
9794*f5c631daSSadaf Ebrahimi   __ Ldaxp(x0, x1, MemOperand(x10));
9795*f5c631daSSadaf Ebrahimi   __ Stlxp(w5, x0, x1, MemOperand(x10));
9796*f5c631daSSadaf Ebrahimi   __ Sub(x11, x11, 1);
9797*f5c631daSSadaf Ebrahimi   __ Cbz(x11, &done);
9798*f5c631daSSadaf Ebrahimi   __ Cbz(w5, &try_xp);
9799*f5c631daSSadaf Ebrahimi 
9800*f5c631daSSadaf Ebrahimi   __ Bind(&done);
9801*f5c631daSSadaf Ebrahimi   // Trigger an error if x11 (watchdog) is zero.
9802*f5c631daSSadaf Ebrahimi   __ Cmp(x11, 0);
9803*f5c631daSSadaf Ebrahimi   __ Cset(x12, eq);
9804*f5c631daSSadaf Ebrahimi 
9805*f5c631daSSadaf Ebrahimi   END();
9806*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9807*f5c631daSSadaf Ebrahimi     RUN();
9808*f5c631daSSadaf Ebrahimi 
9809*f5c631daSSadaf Ebrahimi     // Check that the watchdog counter didn't run out.
9810*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x12);
9811*f5c631daSSadaf Ebrahimi   }
9812*f5c631daSSadaf Ebrahimi }
9813*f5c631daSSadaf Ebrahimi #endif
9814*f5c631daSSadaf Ebrahimi 
TEST(cas_casa_casl_casal_w)9815*f5c631daSSadaf Ebrahimi TEST(cas_casa_casl_casal_w) {
9816*f5c631daSSadaf Ebrahimi   uint64_t data1 = 0x0123456789abcdef;
9817*f5c631daSSadaf Ebrahimi   uint64_t data2 = 0x0123456789abcdef;
9818*f5c631daSSadaf Ebrahimi   uint64_t data3 = 0x0123456789abcdef;
9819*f5c631daSSadaf Ebrahimi   uint64_t data4 = 0x0123456789abcdef;
9820*f5c631daSSadaf Ebrahimi   uint64_t data5 = 0x0123456789abcdef;
9821*f5c631daSSadaf Ebrahimi   uint64_t data6 = 0x0123456789abcdef;
9822*f5c631daSSadaf Ebrahimi   uint64_t data7 = 0x0123456789abcdef;
9823*f5c631daSSadaf Ebrahimi   uint64_t data8 = 0x0123456789abcdef;
9824*f5c631daSSadaf Ebrahimi 
9825*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
9826*f5c631daSSadaf Ebrahimi 
9827*f5c631daSSadaf Ebrahimi   START();
9828*f5c631daSSadaf Ebrahimi 
9829*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
9830*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
9831*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 4);
9832*f5c631daSSadaf Ebrahimi   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 4);
9833*f5c631daSSadaf Ebrahimi   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 0);
9834*f5c631daSSadaf Ebrahimi   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 0);
9835*f5c631daSSadaf Ebrahimi   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 4);
9836*f5c631daSSadaf Ebrahimi   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 4);
9837*f5c631daSSadaf Ebrahimi 
9838*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffff);
9839*f5c631daSSadaf Ebrahimi 
9840*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xfedcba9876543210);
9841*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x0123456789abcdef);
9842*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xfedcba9876543210);
9843*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x89abcdef01234567);
9844*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xfedcba9876543210);
9845*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x0123456789abcdef);
9846*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0xfedcba9876543210);
9847*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0x89abcdef01234567);
9848*f5c631daSSadaf Ebrahimi 
9849*f5c631daSSadaf Ebrahimi   __ Cas(w1, w0, MemOperand(x21));
9850*f5c631daSSadaf Ebrahimi   __ Cas(w2, w0, MemOperand(x22));
9851*f5c631daSSadaf Ebrahimi   __ Casa(w3, w0, MemOperand(x23));
9852*f5c631daSSadaf Ebrahimi   __ Casa(w4, w0, MemOperand(x24));
9853*f5c631daSSadaf Ebrahimi   __ Casl(w5, w0, MemOperand(x25));
9854*f5c631daSSadaf Ebrahimi   __ Casl(w6, w0, MemOperand(x26));
9855*f5c631daSSadaf Ebrahimi   __ Casal(w7, w0, MemOperand(x27));
9856*f5c631daSSadaf Ebrahimi   __ Casal(w8, w0, MemOperand(x28));
9857*f5c631daSSadaf Ebrahimi 
9858*f5c631daSSadaf Ebrahimi   END();
9859*f5c631daSSadaf Ebrahimi 
9860*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9861*f5c631daSSadaf Ebrahimi     RUN();
9862*f5c631daSSadaf Ebrahimi 
9863*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef, x1);
9864*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef, x2);
9865*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, x3);
9866*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, x4);
9867*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef, x5);
9868*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef, x6);
9869*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, x7);
9870*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, x8);
9871*f5c631daSSadaf Ebrahimi 
9872*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data1);
9873*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567ffffffff, data2);
9874*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data3);
9875*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff89abcdef, data4);
9876*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data5);
9877*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567ffffffff, data6);
9878*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data7);
9879*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff89abcdef, data8);
9880*f5c631daSSadaf Ebrahimi   }
9881*f5c631daSSadaf Ebrahimi }
9882*f5c631daSSadaf Ebrahimi 
TEST(cas_casa_casl_casal_x)9883*f5c631daSSadaf Ebrahimi TEST(cas_casa_casl_casal_x) {
9884*f5c631daSSadaf Ebrahimi   uint64_t data1 = 0x0123456789abcdef;
9885*f5c631daSSadaf Ebrahimi   uint64_t data2 = 0x0123456789abcdef;
9886*f5c631daSSadaf Ebrahimi   uint64_t data3 = 0x0123456789abcdef;
9887*f5c631daSSadaf Ebrahimi   uint64_t data4 = 0x0123456789abcdef;
9888*f5c631daSSadaf Ebrahimi   uint64_t data5 = 0x0123456789abcdef;
9889*f5c631daSSadaf Ebrahimi   uint64_t data6 = 0x0123456789abcdef;
9890*f5c631daSSadaf Ebrahimi   uint64_t data7 = 0x0123456789abcdef;
9891*f5c631daSSadaf Ebrahimi   uint64_t data8 = 0x0123456789abcdef;
9892*f5c631daSSadaf Ebrahimi 
9893*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
9894*f5c631daSSadaf Ebrahimi 
9895*f5c631daSSadaf Ebrahimi   START();
9896*f5c631daSSadaf Ebrahimi 
9897*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1));
9898*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2));
9899*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3));
9900*f5c631daSSadaf Ebrahimi   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4));
9901*f5c631daSSadaf Ebrahimi   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5));
9902*f5c631daSSadaf Ebrahimi   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6));
9903*f5c631daSSadaf Ebrahimi   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7));
9904*f5c631daSSadaf Ebrahimi   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8));
9905*f5c631daSSadaf Ebrahimi 
9906*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffffffffffffffff);
9907*f5c631daSSadaf Ebrahimi 
9908*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xfedcba9876543210);
9909*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x0123456789abcdef);
9910*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xfedcba9876543210);
9911*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x0123456789abcdef);
9912*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xfedcba9876543210);
9913*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x0123456789abcdef);
9914*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0xfedcba9876543210);
9915*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0x0123456789abcdef);
9916*f5c631daSSadaf Ebrahimi 
9917*f5c631daSSadaf Ebrahimi   __ Cas(x1, x0, MemOperand(x21));
9918*f5c631daSSadaf Ebrahimi   __ Cas(x2, x0, MemOperand(x22));
9919*f5c631daSSadaf Ebrahimi   __ Casa(x3, x0, MemOperand(x23));
9920*f5c631daSSadaf Ebrahimi   __ Casa(x4, x0, MemOperand(x24));
9921*f5c631daSSadaf Ebrahimi   __ Casl(x5, x0, MemOperand(x25));
9922*f5c631daSSadaf Ebrahimi   __ Casl(x6, x0, MemOperand(x26));
9923*f5c631daSSadaf Ebrahimi   __ Casal(x7, x0, MemOperand(x27));
9924*f5c631daSSadaf Ebrahimi   __ Casal(x8, x0, MemOperand(x28));
9925*f5c631daSSadaf Ebrahimi 
9926*f5c631daSSadaf Ebrahimi   END();
9927*f5c631daSSadaf Ebrahimi 
9928*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9929*f5c631daSSadaf Ebrahimi     RUN();
9930*f5c631daSSadaf Ebrahimi 
9931*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x1);
9932*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x2);
9933*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x3);
9934*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x4);
9935*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x5);
9936*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x6);
9937*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x7);
9938*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x8);
9939*f5c631daSSadaf Ebrahimi 
9940*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data1);
9941*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, data2);
9942*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data3);
9943*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, data4);
9944*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data5);
9945*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, data6);
9946*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data7);
9947*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffff, data8);
9948*f5c631daSSadaf Ebrahimi   }
9949*f5c631daSSadaf Ebrahimi }
9950*f5c631daSSadaf Ebrahimi 
TEST(casb_casab_caslb_casalb)9951*f5c631daSSadaf Ebrahimi TEST(casb_casab_caslb_casalb) {
9952*f5c631daSSadaf Ebrahimi   uint32_t data1 = 0x01234567;
9953*f5c631daSSadaf Ebrahimi   uint32_t data2 = 0x01234567;
9954*f5c631daSSadaf Ebrahimi   uint32_t data3 = 0x01234567;
9955*f5c631daSSadaf Ebrahimi   uint32_t data4 = 0x01234567;
9956*f5c631daSSadaf Ebrahimi   uint32_t data5 = 0x01234567;
9957*f5c631daSSadaf Ebrahimi   uint32_t data6 = 0x01234567;
9958*f5c631daSSadaf Ebrahimi   uint32_t data7 = 0x01234567;
9959*f5c631daSSadaf Ebrahimi   uint32_t data8 = 0x01234567;
9960*f5c631daSSadaf Ebrahimi 
9961*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
9962*f5c631daSSadaf Ebrahimi 
9963*f5c631daSSadaf Ebrahimi   START();
9964*f5c631daSSadaf Ebrahimi 
9965*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
9966*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
9967*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 1);
9968*f5c631daSSadaf Ebrahimi   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 1);
9969*f5c631daSSadaf Ebrahimi   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 2);
9970*f5c631daSSadaf Ebrahimi   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 2);
9971*f5c631daSSadaf Ebrahimi   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 3);
9972*f5c631daSSadaf Ebrahimi   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 3);
9973*f5c631daSSadaf Ebrahimi 
9974*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xff);
9975*f5c631daSSadaf Ebrahimi 
9976*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x76543210);
9977*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x01234567);
9978*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0x76543210);
9979*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x67012345);
9980*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0x76543210);
9981*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x45670123);
9982*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0x76543210);
9983*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0x23456701);
9984*f5c631daSSadaf Ebrahimi 
9985*f5c631daSSadaf Ebrahimi   __ Casb(w1, w0, MemOperand(x21));
9986*f5c631daSSadaf Ebrahimi   __ Casb(w2, w0, MemOperand(x22));
9987*f5c631daSSadaf Ebrahimi   __ Casab(w3, w0, MemOperand(x23));
9988*f5c631daSSadaf Ebrahimi   __ Casab(w4, w0, MemOperand(x24));
9989*f5c631daSSadaf Ebrahimi   __ Caslb(w5, w0, MemOperand(x25));
9990*f5c631daSSadaf Ebrahimi   __ Caslb(w6, w0, MemOperand(x26));
9991*f5c631daSSadaf Ebrahimi   __ Casalb(w7, w0, MemOperand(x27));
9992*f5c631daSSadaf Ebrahimi   __ Casalb(w8, w0, MemOperand(x28));
9993*f5c631daSSadaf Ebrahimi 
9994*f5c631daSSadaf Ebrahimi   END();
9995*f5c631daSSadaf Ebrahimi 
9996*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
9997*f5c631daSSadaf Ebrahimi     RUN();
9998*f5c631daSSadaf Ebrahimi 
9999*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000067, x1);
10000*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000067, x2);
10001*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000045, x3);
10002*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000045, x4);
10003*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000023, x5);
10004*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000023, x6);
10005*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001, x7);
10006*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000001, x8);
10007*f5c631daSSadaf Ebrahimi 
10008*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, data1);
10009*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x012345ff, data2);
10010*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, data3);
10011*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123ff67, data4);
10012*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, data5);
10013*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01ff4567, data6);
10014*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567, data7);
10015*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xff234567, data8);
10016*f5c631daSSadaf Ebrahimi   }
10017*f5c631daSSadaf Ebrahimi }
10018*f5c631daSSadaf Ebrahimi 
TEST(cash_casah_caslh_casalh)10019*f5c631daSSadaf Ebrahimi TEST(cash_casah_caslh_casalh) {
10020*f5c631daSSadaf Ebrahimi   uint64_t data1 = 0x0123456789abcdef;
10021*f5c631daSSadaf Ebrahimi   uint64_t data2 = 0x0123456789abcdef;
10022*f5c631daSSadaf Ebrahimi   uint64_t data3 = 0x0123456789abcdef;
10023*f5c631daSSadaf Ebrahimi   uint64_t data4 = 0x0123456789abcdef;
10024*f5c631daSSadaf Ebrahimi   uint64_t data5 = 0x0123456789abcdef;
10025*f5c631daSSadaf Ebrahimi   uint64_t data6 = 0x0123456789abcdef;
10026*f5c631daSSadaf Ebrahimi   uint64_t data7 = 0x0123456789abcdef;
10027*f5c631daSSadaf Ebrahimi   uint64_t data8 = 0x0123456789abcdef;
10028*f5c631daSSadaf Ebrahimi 
10029*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10030*f5c631daSSadaf Ebrahimi 
10031*f5c631daSSadaf Ebrahimi   START();
10032*f5c631daSSadaf Ebrahimi 
10033*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0);
10034*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0);
10035*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 2);
10036*f5c631daSSadaf Ebrahimi   __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 2);
10037*f5c631daSSadaf Ebrahimi   __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 4);
10038*f5c631daSSadaf Ebrahimi   __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 4);
10039*f5c631daSSadaf Ebrahimi   __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 6);
10040*f5c631daSSadaf Ebrahimi   __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 6);
10041*f5c631daSSadaf Ebrahimi 
10042*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xffff);
10043*f5c631daSSadaf Ebrahimi 
10044*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xfedcba9876543210);
10045*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x0123456789abcdef);
10046*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xfedcba9876543210);
10047*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0xcdef0123456789ab);
10048*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xfedcba9876543210);
10049*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x89abcdef01234567);
10050*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0xfedcba9876543210);
10051*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0x456789abcdef0123);
10052*f5c631daSSadaf Ebrahimi 
10053*f5c631daSSadaf Ebrahimi   __ Cash(w1, w0, MemOperand(x21));
10054*f5c631daSSadaf Ebrahimi   __ Cash(w2, w0, MemOperand(x22));
10055*f5c631daSSadaf Ebrahimi   __ Casah(w3, w0, MemOperand(x23));
10056*f5c631daSSadaf Ebrahimi   __ Casah(w4, w0, MemOperand(x24));
10057*f5c631daSSadaf Ebrahimi   __ Caslh(w5, w0, MemOperand(x25));
10058*f5c631daSSadaf Ebrahimi   __ Caslh(w6, w0, MemOperand(x26));
10059*f5c631daSSadaf Ebrahimi   __ Casalh(w7, w0, MemOperand(x27));
10060*f5c631daSSadaf Ebrahimi   __ Casalh(w8, w0, MemOperand(x28));
10061*f5c631daSSadaf Ebrahimi 
10062*f5c631daSSadaf Ebrahimi   END();
10063*f5c631daSSadaf Ebrahimi 
10064*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10065*f5c631daSSadaf Ebrahimi     RUN();
10066*f5c631daSSadaf Ebrahimi 
10067*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000cdef, x1);
10068*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000cdef, x2);
10069*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000089ab, x3);
10070*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x000089ab, x4);
10071*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00004567, x5);
10072*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00004567, x6);
10073*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000123, x7);
10074*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00000123, x8);
10075*f5c631daSSadaf Ebrahimi 
10076*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data1);
10077*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abffff, data2);
10078*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data3);
10079*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x01234567ffffcdef, data4);
10080*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data5);
10081*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123ffff89abcdef, data6);
10082*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data7);
10083*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffff456789abcdef, data8);
10084*f5c631daSSadaf Ebrahimi   }
10085*f5c631daSSadaf Ebrahimi }
10086*f5c631daSSadaf Ebrahimi 
TEST(casp_caspa_caspl_caspal_w)10087*f5c631daSSadaf Ebrahimi TEST(casp_caspa_caspl_caspal_w) {
10088*f5c631daSSadaf Ebrahimi   uint64_t data1[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10089*f5c631daSSadaf Ebrahimi   uint64_t data2[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10090*f5c631daSSadaf Ebrahimi   uint64_t data3[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10091*f5c631daSSadaf Ebrahimi   uint64_t data4[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10092*f5c631daSSadaf Ebrahimi   uint64_t data5[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10093*f5c631daSSadaf Ebrahimi   uint64_t data6[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10094*f5c631daSSadaf Ebrahimi   uint64_t data7[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10095*f5c631daSSadaf Ebrahimi   uint64_t data8[] = {0x7766554433221100, 0xffeeddccbbaa9988};
10096*f5c631daSSadaf Ebrahimi 
10097*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10098*f5c631daSSadaf Ebrahimi 
10099*f5c631daSSadaf Ebrahimi   START();
10100*f5c631daSSadaf Ebrahimi 
10101*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0);
10102*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0);
10103*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 8);
10104*f5c631daSSadaf Ebrahimi   __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 8);
10105*f5c631daSSadaf Ebrahimi   __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 8);
10106*f5c631daSSadaf Ebrahimi   __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 8);
10107*f5c631daSSadaf Ebrahimi   __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0);
10108*f5c631daSSadaf Ebrahimi   __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0);
10109*f5c631daSSadaf Ebrahimi 
10110*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfff00fff);
10111*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xfff11fff);
10112*f5c631daSSadaf Ebrahimi 
10113*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x77665544);
10114*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0x33221100);
10115*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x33221100);
10116*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0x77665544);
10117*f5c631daSSadaf Ebrahimi 
10118*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0xffeeddcc);
10119*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0xbbaa9988);
10120*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0xbbaa9988);
10121*f5c631daSSadaf Ebrahimi   __ Mov(x9, 0xffeeddcc);
10122*f5c631daSSadaf Ebrahimi 
10123*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0xffeeddcc);
10124*f5c631daSSadaf Ebrahimi   __ Mov(x11, 0xbbaa9988);
10125*f5c631daSSadaf Ebrahimi   __ Mov(x12, 0xbbaa9988);
10126*f5c631daSSadaf Ebrahimi   __ Mov(x13, 0xffeeddcc);
10127*f5c631daSSadaf Ebrahimi 
10128*f5c631daSSadaf Ebrahimi   __ Mov(x14, 0x77665544);
10129*f5c631daSSadaf Ebrahimi   __ Mov(x15, 0x33221100);
10130*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0x33221100);
10131*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0x77665544);
10132*f5c631daSSadaf Ebrahimi 
10133*f5c631daSSadaf Ebrahimi   __ Casp(w2, w3, w0, w1, MemOperand(x21));
10134*f5c631daSSadaf Ebrahimi   __ Casp(w4, w5, w0, w1, MemOperand(x22));
10135*f5c631daSSadaf Ebrahimi   __ Caspa(w6, w7, w0, w1, MemOperand(x23));
10136*f5c631daSSadaf Ebrahimi   __ Caspa(w8, w9, w0, w1, MemOperand(x24));
10137*f5c631daSSadaf Ebrahimi   __ Caspl(w10, w11, w0, w1, MemOperand(x25));
10138*f5c631daSSadaf Ebrahimi   __ Caspl(w12, w13, w0, w1, MemOperand(x26));
10139*f5c631daSSadaf Ebrahimi   __ Caspal(w14, w15, w0, w1, MemOperand(x27));
10140*f5c631daSSadaf Ebrahimi   __ Caspal(w16, w17, w0, w1, MemOperand(x28));
10141*f5c631daSSadaf Ebrahimi 
10142*f5c631daSSadaf Ebrahimi   END();
10143*f5c631daSSadaf Ebrahimi 
10144*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10145*f5c631daSSadaf Ebrahimi     RUN();
10146*f5c631daSSadaf Ebrahimi 
10147*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x33221100, x2);
10148*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x77665544, x3);
10149*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x33221100, x4);
10150*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x77665544, x5);
10151*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x6);
10152*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddcc, x7);
10153*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x8);
10154*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddcc, x9);
10155*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x10);
10156*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddcc, x11);
10157*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbbaa9988, x12);
10158*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddcc, x13);
10159*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x33221100, x14);
10160*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x77665544, x15);
10161*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x33221100, x16);
10162*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x77665544, x17);
10163*f5c631daSSadaf Ebrahimi 
10164*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data1[0]);
10165*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]);
10166*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfff11ffffff00fff, data2[0]);
10167*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data2[1]);
10168*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data3[0]);
10169*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]);
10170*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data4[0]);
10171*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfff11ffffff00fff, data4[1]);
10172*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data5[0]);
10173*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]);
10174*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data6[0]);
10175*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfff11ffffff00fff, data6[1]);
10176*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data7[0]);
10177*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]);
10178*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfff11ffffff00fff, data8[0]);
10179*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data8[1]);
10180*f5c631daSSadaf Ebrahimi   }
10181*f5c631daSSadaf Ebrahimi }
10182*f5c631daSSadaf Ebrahimi 
TEST(casp_caspa_caspl_caspal_x)10183*f5c631daSSadaf Ebrahimi TEST(casp_caspa_caspl_caspal_x) {
10184*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data1[] = {0x7766554433221100,
10185*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10186*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10187*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10188*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data2[] = {0x7766554433221100,
10189*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10190*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10191*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10192*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data3[] = {0x7766554433221100,
10193*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10194*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10195*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10196*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data4[] = {0x7766554433221100,
10197*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10198*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10199*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10200*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data5[] = {0x7766554433221100,
10201*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10202*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10203*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10204*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data6[] = {0x7766554433221100,
10205*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10206*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10207*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10208*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data7[] = {0x7766554433221100,
10209*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10210*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10211*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10212*f5c631daSSadaf Ebrahimi   alignas(kXRegSizeInBytes * 2) uint64_t data8[] = {0x7766554433221100,
10213*f5c631daSSadaf Ebrahimi                                                     0xffeeddccbbaa9988,
10214*f5c631daSSadaf Ebrahimi                                                     0xfedcba9876543210,
10215*f5c631daSSadaf Ebrahimi                                                     0x0123456789abcdef};
10216*f5c631daSSadaf Ebrahimi 
10217*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10218*f5c631daSSadaf Ebrahimi 
10219*f5c631daSSadaf Ebrahimi   START();
10220*f5c631daSSadaf Ebrahimi 
10221*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0);
10222*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0);
10223*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 16);
10224*f5c631daSSadaf Ebrahimi   __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 16);
10225*f5c631daSSadaf Ebrahimi   __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 16);
10226*f5c631daSSadaf Ebrahimi   __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 16);
10227*f5c631daSSadaf Ebrahimi   __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0);
10228*f5c631daSSadaf Ebrahimi   __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0);
10229*f5c631daSSadaf Ebrahimi 
10230*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0xfffffff00fffffff);
10231*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0xfffffff11fffffff);
10232*f5c631daSSadaf Ebrahimi 
10233*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0xffeeddccbbaa9988);
10234*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0x7766554433221100);
10235*f5c631daSSadaf Ebrahimi   __ Mov(x4, 0x7766554433221100);
10236*f5c631daSSadaf Ebrahimi   __ Mov(x5, 0xffeeddccbbaa9988);
10237*f5c631daSSadaf Ebrahimi 
10238*f5c631daSSadaf Ebrahimi   __ Mov(x6, 0x0123456789abcdef);
10239*f5c631daSSadaf Ebrahimi   __ Mov(x7, 0xfedcba9876543210);
10240*f5c631daSSadaf Ebrahimi   __ Mov(x8, 0xfedcba9876543210);
10241*f5c631daSSadaf Ebrahimi   __ Mov(x9, 0x0123456789abcdef);
10242*f5c631daSSadaf Ebrahimi 
10243*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0x0123456789abcdef);
10244*f5c631daSSadaf Ebrahimi   __ Mov(x11, 0xfedcba9876543210);
10245*f5c631daSSadaf Ebrahimi   __ Mov(x12, 0xfedcba9876543210);
10246*f5c631daSSadaf Ebrahimi   __ Mov(x13, 0x0123456789abcdef);
10247*f5c631daSSadaf Ebrahimi 
10248*f5c631daSSadaf Ebrahimi   __ Mov(x14, 0xffeeddccbbaa9988);
10249*f5c631daSSadaf Ebrahimi   __ Mov(x15, 0x7766554433221100);
10250*f5c631daSSadaf Ebrahimi   __ Mov(x16, 0x7766554433221100);
10251*f5c631daSSadaf Ebrahimi   __ Mov(x17, 0xffeeddccbbaa9988);
10252*f5c631daSSadaf Ebrahimi 
10253*f5c631daSSadaf Ebrahimi   __ Casp(x2, x3, x0, x1, MemOperand(x21));
10254*f5c631daSSadaf Ebrahimi   __ Casp(x4, x5, x0, x1, MemOperand(x22));
10255*f5c631daSSadaf Ebrahimi   __ Caspa(x6, x7, x0, x1, MemOperand(x23));
10256*f5c631daSSadaf Ebrahimi   __ Caspa(x8, x9, x0, x1, MemOperand(x24));
10257*f5c631daSSadaf Ebrahimi   __ Caspl(x10, x11, x0, x1, MemOperand(x25));
10258*f5c631daSSadaf Ebrahimi   __ Caspl(x12, x13, x0, x1, MemOperand(x26));
10259*f5c631daSSadaf Ebrahimi   __ Caspal(x14, x15, x0, x1, MemOperand(x27));
10260*f5c631daSSadaf Ebrahimi   __ Caspal(x16, x17, x0, x1, MemOperand(x28));
10261*f5c631daSSadaf Ebrahimi 
10262*f5c631daSSadaf Ebrahimi   END();
10263*f5c631daSSadaf Ebrahimi 
10264*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10265*f5c631daSSadaf Ebrahimi     RUN();
10266*f5c631daSSadaf Ebrahimi 
10267*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, x2);
10268*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x3);
10269*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, x4);
10270*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
10271*f5c631daSSadaf Ebrahimi 
10272*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, x6);
10273*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x7);
10274*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, x8);
10275*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x9);
10276*f5c631daSSadaf Ebrahimi 
10277*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, x10);
10278*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x11);
10279*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, x12);
10280*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x13);
10281*f5c631daSSadaf Ebrahimi 
10282*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, x14);
10283*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x15);
10284*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, x16);
10285*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, x17);
10286*f5c631daSSadaf Ebrahimi 
10287*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data1[0]);
10288*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]);
10289*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, data1[2]);
10290*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data1[3]);
10291*f5c631daSSadaf Ebrahimi 
10292*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff00fffffff, data2[0]);
10293*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff11fffffff, data2[1]);
10294*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, data2[2]);
10295*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data2[3]);
10296*f5c631daSSadaf Ebrahimi 
10297*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data3[0]);
10298*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]);
10299*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, data3[2]);
10300*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data3[3]);
10301*f5c631daSSadaf Ebrahimi 
10302*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data4[0]);
10303*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data4[1]);
10304*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff00fffffff, data4[2]);
10305*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff11fffffff, data4[3]);
10306*f5c631daSSadaf Ebrahimi 
10307*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data5[0]);
10308*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]);
10309*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, data5[2]);
10310*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data5[3]);
10311*f5c631daSSadaf Ebrahimi 
10312*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data6[0]);
10313*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data6[1]);
10314*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff00fffffff, data6[2]);
10315*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff11fffffff, data6[3]);
10316*f5c631daSSadaf Ebrahimi 
10317*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7766554433221100, data7[0]);
10318*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]);
10319*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, data7[2]);
10320*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data7[3]);
10321*f5c631daSSadaf Ebrahimi 
10322*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff00fffffff, data8[0]);
10323*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffff11fffffff, data8[1]);
10324*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfedcba9876543210, data8[2]);
10325*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, data8[3]);
10326*f5c631daSSadaf Ebrahimi   }
10327*f5c631daSSadaf Ebrahimi }
10328*f5c631daSSadaf Ebrahimi 
10329*f5c631daSSadaf Ebrahimi 
10330*f5c631daSSadaf Ebrahimi typedef void (MacroAssembler::*AtomicMemoryLoadSignature)(
10331*f5c631daSSadaf Ebrahimi     const Register& rs, const Register& rt, const MemOperand& src);
10332*f5c631daSSadaf Ebrahimi typedef void (MacroAssembler::*AtomicMemoryStoreSignature)(
10333*f5c631daSSadaf Ebrahimi     const Register& rs, const MemOperand& src);
10334*f5c631daSSadaf Ebrahimi 
AtomicMemoryWHelper(AtomicMemoryLoadSignature * load_funcs,AtomicMemoryStoreSignature * store_funcs,uint64_t arg1,uint64_t arg2,uint64_t expected,uint64_t result_mask)10335*f5c631daSSadaf Ebrahimi void AtomicMemoryWHelper(AtomicMemoryLoadSignature* load_funcs,
10336*f5c631daSSadaf Ebrahimi                          AtomicMemoryStoreSignature* store_funcs,
10337*f5c631daSSadaf Ebrahimi                          uint64_t arg1,
10338*f5c631daSSadaf Ebrahimi                          uint64_t arg2,
10339*f5c631daSSadaf Ebrahimi                          uint64_t expected,
10340*f5c631daSSadaf Ebrahimi                          uint64_t result_mask) {
10341*f5c631daSSadaf Ebrahimi   uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10342*f5c631daSSadaf Ebrahimi   uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10343*f5c631daSSadaf Ebrahimi   uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10344*f5c631daSSadaf Ebrahimi   uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10345*f5c631daSSadaf Ebrahimi   uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10346*f5c631daSSadaf Ebrahimi   uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10347*f5c631daSSadaf Ebrahimi 
10348*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10349*f5c631daSSadaf Ebrahimi   START();
10350*f5c631daSSadaf Ebrahimi 
10351*f5c631daSSadaf Ebrahimi   __ Mov(x20, reinterpret_cast<uintptr_t>(data0));
10352*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(data1));
10353*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(data2));
10354*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(data3));
10355*f5c631daSSadaf Ebrahimi 
10356*f5c631daSSadaf Ebrahimi   __ Mov(x0, arg1);
10357*f5c631daSSadaf Ebrahimi   __ Mov(x1, arg1);
10358*f5c631daSSadaf Ebrahimi   __ Mov(x2, arg1);
10359*f5c631daSSadaf Ebrahimi   __ Mov(x3, arg1);
10360*f5c631daSSadaf Ebrahimi 
10361*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[0]))(w0, w10, MemOperand(x20));
10362*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[1]))(w1, w11, MemOperand(x21));
10363*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[2]))(w2, w12, MemOperand(x22));
10364*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[3]))(w3, w13, MemOperand(x23));
10365*f5c631daSSadaf Ebrahimi 
10366*f5c631daSSadaf Ebrahimi   if (store_funcs != NULL) {
10367*f5c631daSSadaf Ebrahimi     __ Mov(x24, reinterpret_cast<uintptr_t>(data4));
10368*f5c631daSSadaf Ebrahimi     __ Mov(x25, reinterpret_cast<uintptr_t>(data5));
10369*f5c631daSSadaf Ebrahimi     __ Mov(x4, arg1);
10370*f5c631daSSadaf Ebrahimi     __ Mov(x5, arg1);
10371*f5c631daSSadaf Ebrahimi 
10372*f5c631daSSadaf Ebrahimi     (masm.*(store_funcs[0]))(w4, MemOperand(x24));
10373*f5c631daSSadaf Ebrahimi     (masm.*(store_funcs[1]))(w5, MemOperand(x25));
10374*f5c631daSSadaf Ebrahimi   }
10375*f5c631daSSadaf Ebrahimi 
10376*f5c631daSSadaf Ebrahimi   END();
10377*f5c631daSSadaf Ebrahimi 
10378*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10379*f5c631daSSadaf Ebrahimi     RUN();
10380*f5c631daSSadaf Ebrahimi 
10381*f5c631daSSadaf Ebrahimi     uint64_t stored_value = arg2 & result_mask;
10382*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(stored_value, x10);
10383*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(stored_value, x11);
10384*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(stored_value, x12);
10385*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(stored_value, x13);
10386*f5c631daSSadaf Ebrahimi 
10387*f5c631daSSadaf Ebrahimi     // The data fields contain arg2 already then only the bits masked by
10388*f5c631daSSadaf Ebrahimi     // result_mask are overwritten.
10389*f5c631daSSadaf Ebrahimi     uint64_t final_expected = (arg2 & ~result_mask) | (expected & result_mask);
10390*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(final_expected, data0[0]);
10391*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(final_expected, data1[0]);
10392*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(final_expected, data2[0]);
10393*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(final_expected, data3[0]);
10394*f5c631daSSadaf Ebrahimi 
10395*f5c631daSSadaf Ebrahimi     if (store_funcs != NULL) {
10396*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_64(final_expected, data4[0]);
10397*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_64(final_expected, data5[0]);
10398*f5c631daSSadaf Ebrahimi     }
10399*f5c631daSSadaf Ebrahimi   }
10400*f5c631daSSadaf Ebrahimi }
10401*f5c631daSSadaf Ebrahimi 
AtomicMemoryXHelper(AtomicMemoryLoadSignature * load_funcs,AtomicMemoryStoreSignature * store_funcs,uint64_t arg1,uint64_t arg2,uint64_t expected)10402*f5c631daSSadaf Ebrahimi void AtomicMemoryXHelper(AtomicMemoryLoadSignature* load_funcs,
10403*f5c631daSSadaf Ebrahimi                          AtomicMemoryStoreSignature* store_funcs,
10404*f5c631daSSadaf Ebrahimi                          uint64_t arg1,
10405*f5c631daSSadaf Ebrahimi                          uint64_t arg2,
10406*f5c631daSSadaf Ebrahimi                          uint64_t expected) {
10407*f5c631daSSadaf Ebrahimi   uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10408*f5c631daSSadaf Ebrahimi   uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10409*f5c631daSSadaf Ebrahimi   uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10410*f5c631daSSadaf Ebrahimi   uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10411*f5c631daSSadaf Ebrahimi   uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10412*f5c631daSSadaf Ebrahimi   uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0};
10413*f5c631daSSadaf Ebrahimi 
10414*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kAtomics);
10415*f5c631daSSadaf Ebrahimi   START();
10416*f5c631daSSadaf Ebrahimi 
10417*f5c631daSSadaf Ebrahimi   __ Mov(x20, reinterpret_cast<uintptr_t>(data0));
10418*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(data1));
10419*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(data2));
10420*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(data3));
10421*f5c631daSSadaf Ebrahimi 
10422*f5c631daSSadaf Ebrahimi   __ Mov(x0, arg1);
10423*f5c631daSSadaf Ebrahimi   __ Mov(x1, arg1);
10424*f5c631daSSadaf Ebrahimi   __ Mov(x2, arg1);
10425*f5c631daSSadaf Ebrahimi   __ Mov(x3, arg1);
10426*f5c631daSSadaf Ebrahimi 
10427*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[0]))(x0, x10, MemOperand(x20));
10428*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[1]))(x1, x11, MemOperand(x21));
10429*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[2]))(x2, x12, MemOperand(x22));
10430*f5c631daSSadaf Ebrahimi   (masm.*(load_funcs[3]))(x3, x13, MemOperand(x23));
10431*f5c631daSSadaf Ebrahimi 
10432*f5c631daSSadaf Ebrahimi   if (store_funcs != NULL) {
10433*f5c631daSSadaf Ebrahimi     __ Mov(x24, reinterpret_cast<uintptr_t>(data4));
10434*f5c631daSSadaf Ebrahimi     __ Mov(x25, reinterpret_cast<uintptr_t>(data5));
10435*f5c631daSSadaf Ebrahimi     __ Mov(x4, arg1);
10436*f5c631daSSadaf Ebrahimi     __ Mov(x5, arg1);
10437*f5c631daSSadaf Ebrahimi 
10438*f5c631daSSadaf Ebrahimi     (masm.*(store_funcs[0]))(x4, MemOperand(x24));
10439*f5c631daSSadaf Ebrahimi     (masm.*(store_funcs[1]))(x5, MemOperand(x25));
10440*f5c631daSSadaf Ebrahimi   }
10441*f5c631daSSadaf Ebrahimi 
10442*f5c631daSSadaf Ebrahimi   END();
10443*f5c631daSSadaf Ebrahimi 
10444*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10445*f5c631daSSadaf Ebrahimi     RUN();
10446*f5c631daSSadaf Ebrahimi 
10447*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(arg2, x10);
10448*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(arg2, x11);
10449*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(arg2, x12);
10450*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(arg2, x13);
10451*f5c631daSSadaf Ebrahimi 
10452*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, data0[0]);
10453*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, data1[0]);
10454*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, data2[0]);
10455*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(expected, data3[0]);
10456*f5c631daSSadaf Ebrahimi 
10457*f5c631daSSadaf Ebrahimi     if (store_funcs != NULL) {
10458*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_64(expected, data4[0]);
10459*f5c631daSSadaf Ebrahimi       ASSERT_EQUAL_64(expected, data5[0]);
10460*f5c631daSSadaf Ebrahimi     }
10461*f5c631daSSadaf Ebrahimi   }
10462*f5c631daSSadaf Ebrahimi }
10463*f5c631daSSadaf Ebrahimi 
10464*f5c631daSSadaf Ebrahimi // clang-format off
10465*f5c631daSSadaf Ebrahimi #define MAKE_LOADS(NAME)           \
10466*f5c631daSSadaf Ebrahimi     {&MacroAssembler::Ld##NAME,    \
10467*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##a, \
10468*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##l, \
10469*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##al}
10470*f5c631daSSadaf Ebrahimi #define MAKE_STORES(NAME) \
10471*f5c631daSSadaf Ebrahimi     {&MacroAssembler::St##NAME, &MacroAssembler::St##NAME##l}
10472*f5c631daSSadaf Ebrahimi 
10473*f5c631daSSadaf Ebrahimi #define MAKE_B_LOADS(NAME)          \
10474*f5c631daSSadaf Ebrahimi     {&MacroAssembler::Ld##NAME##b,  \
10475*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##ab, \
10476*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##lb, \
10477*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##alb}
10478*f5c631daSSadaf Ebrahimi #define MAKE_B_STORES(NAME) \
10479*f5c631daSSadaf Ebrahimi     {&MacroAssembler::St##NAME##b, &MacroAssembler::St##NAME##lb}
10480*f5c631daSSadaf Ebrahimi 
10481*f5c631daSSadaf Ebrahimi #define MAKE_H_LOADS(NAME)          \
10482*f5c631daSSadaf Ebrahimi     {&MacroAssembler::Ld##NAME##h,  \
10483*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##ah, \
10484*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##lh, \
10485*f5c631daSSadaf Ebrahimi      &MacroAssembler::Ld##NAME##alh}
10486*f5c631daSSadaf Ebrahimi #define MAKE_H_STORES(NAME) \
10487*f5c631daSSadaf Ebrahimi     {&MacroAssembler::St##NAME##h, &MacroAssembler::St##NAME##lh}
10488*f5c631daSSadaf Ebrahimi // clang-format on
10489*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_add)10490*f5c631daSSadaf Ebrahimi TEST(atomic_memory_add) {
10491*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(add);
10492*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(add);
10493*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(add);
10494*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(add);
10495*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(add);
10496*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(add);
10497*f5c631daSSadaf Ebrahimi 
10498*f5c631daSSadaf Ebrahimi   // The arguments are chosen to have two useful properties:
10499*f5c631daSSadaf Ebrahimi   //  * When multiplied by small values (such as a register index), this value
10500*f5c631daSSadaf Ebrahimi   //    is clearly readable in the result.
10501*f5c631daSSadaf Ebrahimi   //  * The value is not formed from repeating fixed-size smaller values, so it
10502*f5c631daSSadaf Ebrahimi   //    can be used to detect endianness-related errors.
10503*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x0100001000100101;
10504*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0200002000200202;
10505*f5c631daSSadaf Ebrahimi   uint64_t expected = arg1 + arg2;
10506*f5c631daSSadaf Ebrahimi 
10507*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10508*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10509*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10510*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10511*f5c631daSSadaf Ebrahimi }
10512*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_clr)10513*f5c631daSSadaf Ebrahimi TEST(atomic_memory_clr) {
10514*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(clr);
10515*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(clr);
10516*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(clr);
10517*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(clr);
10518*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(clr);
10519*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(clr);
10520*f5c631daSSadaf Ebrahimi 
10521*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x0300003000300303;
10522*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0500005000500505;
10523*f5c631daSSadaf Ebrahimi   uint64_t expected = arg2 & ~arg1;
10524*f5c631daSSadaf Ebrahimi 
10525*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10526*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10527*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10528*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10529*f5c631daSSadaf Ebrahimi }
10530*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_eor)10531*f5c631daSSadaf Ebrahimi TEST(atomic_memory_eor) {
10532*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(eor);
10533*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(eor);
10534*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(eor);
10535*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(eor);
10536*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(eor);
10537*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(eor);
10538*f5c631daSSadaf Ebrahimi 
10539*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x0300003000300303;
10540*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0500005000500505;
10541*f5c631daSSadaf Ebrahimi   uint64_t expected = arg1 ^ arg2;
10542*f5c631daSSadaf Ebrahimi 
10543*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10544*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10545*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10546*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10547*f5c631daSSadaf Ebrahimi }
10548*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_set)10549*f5c631daSSadaf Ebrahimi TEST(atomic_memory_set) {
10550*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(set);
10551*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(set);
10552*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(set);
10553*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(set);
10554*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(set);
10555*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(set);
10556*f5c631daSSadaf Ebrahimi 
10557*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x0300003000300303;
10558*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0500005000500505;
10559*f5c631daSSadaf Ebrahimi   uint64_t expected = arg1 | arg2;
10560*f5c631daSSadaf Ebrahimi 
10561*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10562*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10563*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10564*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10565*f5c631daSSadaf Ebrahimi }
10566*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_smax)10567*f5c631daSSadaf Ebrahimi TEST(atomic_memory_smax) {
10568*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smax);
10569*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(smax);
10570*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smax);
10571*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smax);
10572*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smax);
10573*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smax);
10574*f5c631daSSadaf Ebrahimi 
10575*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x8100000080108181;
10576*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0100001000100101;
10577*f5c631daSSadaf Ebrahimi   uint64_t expected = 0x0100001000100101;
10578*f5c631daSSadaf Ebrahimi 
10579*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10580*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10581*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10582*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10583*f5c631daSSadaf Ebrahimi }
10584*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_smin)10585*f5c631daSSadaf Ebrahimi TEST(atomic_memory_smin) {
10586*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smin);
10587*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(smin);
10588*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smin);
10589*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smin);
10590*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smin);
10591*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smin);
10592*f5c631daSSadaf Ebrahimi 
10593*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x8100000080108181;
10594*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0100001000100101;
10595*f5c631daSSadaf Ebrahimi   uint64_t expected = 0x8100000080108181;
10596*f5c631daSSadaf Ebrahimi 
10597*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10598*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10599*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10600*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10601*f5c631daSSadaf Ebrahimi }
10602*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_umax)10603*f5c631daSSadaf Ebrahimi TEST(atomic_memory_umax) {
10604*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umax);
10605*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(umax);
10606*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umax);
10607*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umax);
10608*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umax);
10609*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umax);
10610*f5c631daSSadaf Ebrahimi 
10611*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x8100000080108181;
10612*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0100001000100101;
10613*f5c631daSSadaf Ebrahimi   uint64_t expected = 0x8100000080108181;
10614*f5c631daSSadaf Ebrahimi 
10615*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10616*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10617*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10618*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10619*f5c631daSSadaf Ebrahimi }
10620*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_umin)10621*f5c631daSSadaf Ebrahimi TEST(atomic_memory_umin) {
10622*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umin);
10623*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature stores[] = MAKE_STORES(umin);
10624*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umin);
10625*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umin);
10626*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umin);
10627*f5c631daSSadaf Ebrahimi   AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umin);
10628*f5c631daSSadaf Ebrahimi 
10629*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x8100000080108181;
10630*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0100001000100101;
10631*f5c631daSSadaf Ebrahimi   uint64_t expected = 0x0100001000100101;
10632*f5c631daSSadaf Ebrahimi 
10633*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask);
10634*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask);
10635*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask);
10636*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, stores, arg1, arg2, expected);
10637*f5c631daSSadaf Ebrahimi }
10638*f5c631daSSadaf Ebrahimi 
TEST(atomic_memory_swp)10639*f5c631daSSadaf Ebrahimi TEST(atomic_memory_swp) {
10640*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature loads[] = {&MacroAssembler::Swp,
10641*f5c631daSSadaf Ebrahimi                                        &MacroAssembler::Swpa,
10642*f5c631daSSadaf Ebrahimi                                        &MacroAssembler::Swpl,
10643*f5c631daSSadaf Ebrahimi                                        &MacroAssembler::Swpal};
10644*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature b_loads[] = {&MacroAssembler::Swpb,
10645*f5c631daSSadaf Ebrahimi                                          &MacroAssembler::Swpab,
10646*f5c631daSSadaf Ebrahimi                                          &MacroAssembler::Swplb,
10647*f5c631daSSadaf Ebrahimi                                          &MacroAssembler::Swpalb};
10648*f5c631daSSadaf Ebrahimi   AtomicMemoryLoadSignature h_loads[] = {&MacroAssembler::Swph,
10649*f5c631daSSadaf Ebrahimi                                          &MacroAssembler::Swpah,
10650*f5c631daSSadaf Ebrahimi                                          &MacroAssembler::Swplh,
10651*f5c631daSSadaf Ebrahimi                                          &MacroAssembler::Swpalh};
10652*f5c631daSSadaf Ebrahimi 
10653*f5c631daSSadaf Ebrahimi   uint64_t arg1 = 0x0100001000100101;
10654*f5c631daSSadaf Ebrahimi   uint64_t arg2 = 0x0200002000200202;
10655*f5c631daSSadaf Ebrahimi   uint64_t expected = 0x0100001000100101;
10656*f5c631daSSadaf Ebrahimi 
10657*f5c631daSSadaf Ebrahimi   // SWP functions have equivalent signatures to the Atomic Memory LD functions
10658*f5c631daSSadaf Ebrahimi   // so we can use the same helper but without the ST aliases.
10659*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(b_loads, NULL, arg1, arg2, expected, kByteMask);
10660*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(h_loads, NULL, arg1, arg2, expected, kHalfWordMask);
10661*f5c631daSSadaf Ebrahimi   AtomicMemoryWHelper(loads, NULL, arg1, arg2, expected, kWordMask);
10662*f5c631daSSadaf Ebrahimi   AtomicMemoryXHelper(loads, NULL, arg1, arg2, expected);
10663*f5c631daSSadaf Ebrahimi }
10664*f5c631daSSadaf Ebrahimi 
10665*f5c631daSSadaf Ebrahimi 
TEST(ldaprb_ldaprh_ldapr)10666*f5c631daSSadaf Ebrahimi TEST(ldaprb_ldaprh_ldapr) {
10667*f5c631daSSadaf Ebrahimi   uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
10668*f5c631daSSadaf Ebrahimi   uint64_t data1[] = {0x1010101010101010, 0x1010101010101010};
10669*f5c631daSSadaf Ebrahimi   uint64_t data2[] = {0x1010101010101010, 0x1010101010101010};
10670*f5c631daSSadaf Ebrahimi   uint64_t data3[] = {0x1010101010101010, 0x1010101010101010};
10671*f5c631daSSadaf Ebrahimi 
10672*f5c631daSSadaf Ebrahimi   uint64_t* data0_aligned = AlignUp(data0, kXRegSizeInBytes * 2);
10673*f5c631daSSadaf Ebrahimi   uint64_t* data1_aligned = AlignUp(data1, kXRegSizeInBytes * 2);
10674*f5c631daSSadaf Ebrahimi   uint64_t* data2_aligned = AlignUp(data2, kXRegSizeInBytes * 2);
10675*f5c631daSSadaf Ebrahimi   uint64_t* data3_aligned = AlignUp(data3, kXRegSizeInBytes * 2);
10676*f5c631daSSadaf Ebrahimi 
10677*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kRCpc);
10678*f5c631daSSadaf Ebrahimi   START();
10679*f5c631daSSadaf Ebrahimi 
10680*f5c631daSSadaf Ebrahimi   __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned));
10681*f5c631daSSadaf Ebrahimi   __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned));
10682*f5c631daSSadaf Ebrahimi   __ Mov(x22, reinterpret_cast<uintptr_t>(data2_aligned));
10683*f5c631daSSadaf Ebrahimi   __ Mov(x23, reinterpret_cast<uintptr_t>(data3_aligned));
10684*f5c631daSSadaf Ebrahimi 
10685*f5c631daSSadaf Ebrahimi   __ Ldaprb(w0, MemOperand(x20));
10686*f5c631daSSadaf Ebrahimi   __ Ldaprh(w1, MemOperand(x21));
10687*f5c631daSSadaf Ebrahimi   __ Ldapr(w2, MemOperand(x22));
10688*f5c631daSSadaf Ebrahimi   __ Ldapr(x3, MemOperand(x23));
10689*f5c631daSSadaf Ebrahimi 
10690*f5c631daSSadaf Ebrahimi   END();
10691*f5c631daSSadaf Ebrahimi 
10692*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10693*f5c631daSSadaf Ebrahimi     RUN();
10694*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10, x0);
10695*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1010, x1);
10696*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x10101010, x2);
10697*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1010101010101010, x3);
10698*f5c631daSSadaf Ebrahimi   }
10699*f5c631daSSadaf Ebrahimi }
10700*f5c631daSSadaf Ebrahimi 
10701*f5c631daSSadaf Ebrahimi 
TEST(ldapurb_ldapurh_ldapur)10702*f5c631daSSadaf Ebrahimi TEST(ldapurb_ldapurh_ldapur) {
10703*f5c631daSSadaf Ebrahimi   uint64_t data[]
10704*f5c631daSSadaf Ebrahimi       __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef,
10705*f5c631daSSadaf Ebrahimi                                                         0xfedcba9876543210};
10706*f5c631daSSadaf Ebrahimi 
10707*f5c631daSSadaf Ebrahimi   uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
10708*f5c631daSSadaf Ebrahimi 
10709*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
10710*f5c631daSSadaf Ebrahimi   START();
10711*f5c631daSSadaf Ebrahimi 
10712*f5c631daSSadaf Ebrahimi   __ Mov(x20, data_base);
10713*f5c631daSSadaf Ebrahimi   __ Mov(x21, data_base + 2 * sizeof(data[0]));
10714*f5c631daSSadaf Ebrahimi 
10715*f5c631daSSadaf Ebrahimi   __ Ldaprb(w0, MemOperand(x20));
10716*f5c631daSSadaf Ebrahimi   __ Ldaprh(w1, MemOperand(x20));
10717*f5c631daSSadaf Ebrahimi   __ Ldapr(w2, MemOperand(x20));
10718*f5c631daSSadaf Ebrahimi   __ Ldapr(x3, MemOperand(x20));
10719*f5c631daSSadaf Ebrahimi   __ Ldaprb(w4, MemOperand(x20, 12));
10720*f5c631daSSadaf Ebrahimi   __ Ldaprh(w5, MemOperand(x20, 8));
10721*f5c631daSSadaf Ebrahimi   __ Ldapr(w6, MemOperand(x20, 10));
10722*f5c631daSSadaf Ebrahimi   __ Ldapr(x7, MemOperand(x20, 7));
10723*f5c631daSSadaf Ebrahimi   __ Ldaprb(w8, MemOperand(x21, -1));
10724*f5c631daSSadaf Ebrahimi   __ Ldaprh(w9, MemOperand(x21, -3));
10725*f5c631daSSadaf Ebrahimi   __ Ldapr(w10, MemOperand(x21, -9));
10726*f5c631daSSadaf Ebrahimi   __ Ldapr(x11, MemOperand(x21, -12));
10727*f5c631daSSadaf Ebrahimi 
10728*f5c631daSSadaf Ebrahimi   END();
10729*f5c631daSSadaf Ebrahimi 
10730*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10731*f5c631daSSadaf Ebrahimi     RUN();
10732*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xef, x0);
10733*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xcdef, x1);
10734*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x89abcdef, x2);
10735*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0123456789abcdef, x3);
10736*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x98, x4);
10737*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3210, x5);
10738*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xba987654, x6);
10739*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xdcba987654321001, x7);
10740*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfe, x8);
10741*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xdcba, x9);
10742*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x54321001, x10);
10743*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7654321001234567, x11);
10744*f5c631daSSadaf Ebrahimi   }
10745*f5c631daSSadaf Ebrahimi }
10746*f5c631daSSadaf Ebrahimi 
10747*f5c631daSSadaf Ebrahimi 
TEST(ldapursb_ldapursh_ldapursw)10748*f5c631daSSadaf Ebrahimi TEST(ldapursb_ldapursh_ldapursw) {
10749*f5c631daSSadaf Ebrahimi   uint64_t data[]
10750*f5c631daSSadaf Ebrahimi       __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef,
10751*f5c631daSSadaf Ebrahimi                                                         0xfedcba9876543210};
10752*f5c631daSSadaf Ebrahimi 
10753*f5c631daSSadaf Ebrahimi   uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
10754*f5c631daSSadaf Ebrahimi 
10755*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
10756*f5c631daSSadaf Ebrahimi   START();
10757*f5c631daSSadaf Ebrahimi 
10758*f5c631daSSadaf Ebrahimi   __ Mov(x20, data_base);
10759*f5c631daSSadaf Ebrahimi   __ Mov(x21, data_base + 2 * sizeof(data[0]));
10760*f5c631daSSadaf Ebrahimi 
10761*f5c631daSSadaf Ebrahimi   __ Ldapursb(w0, MemOperand(x20));
10762*f5c631daSSadaf Ebrahimi   __ Ldapursb(x1, MemOperand(x20));
10763*f5c631daSSadaf Ebrahimi   __ Ldapursh(w2, MemOperand(x20));
10764*f5c631daSSadaf Ebrahimi   __ Ldapursh(x3, MemOperand(x20));
10765*f5c631daSSadaf Ebrahimi   __ Ldapursw(x4, MemOperand(x20));
10766*f5c631daSSadaf Ebrahimi   __ Ldapursb(w5, MemOperand(x20, 12));
10767*f5c631daSSadaf Ebrahimi   __ Ldapursb(x6, MemOperand(x20, 12));
10768*f5c631daSSadaf Ebrahimi   __ Ldapursh(w7, MemOperand(x20, 13));
10769*f5c631daSSadaf Ebrahimi   __ Ldapursh(x8, MemOperand(x20, 13));
10770*f5c631daSSadaf Ebrahimi   __ Ldapursw(x9, MemOperand(x20, 10));
10771*f5c631daSSadaf Ebrahimi   __ Ldapursb(w10, MemOperand(x21, -1));
10772*f5c631daSSadaf Ebrahimi   __ Ldapursb(x11, MemOperand(x21, -1));
10773*f5c631daSSadaf Ebrahimi   __ Ldapursh(w12, MemOperand(x21, -4));
10774*f5c631daSSadaf Ebrahimi   __ Ldapursh(x13, MemOperand(x21, -4));
10775*f5c631daSSadaf Ebrahimi   __ Ldapursw(x14, MemOperand(x21, -5));
10776*f5c631daSSadaf Ebrahimi 
10777*f5c631daSSadaf Ebrahimi   __ Ldapursb(x15, MemOperand(x20, 8));
10778*f5c631daSSadaf Ebrahimi   __ Ldapursh(x16, MemOperand(x20, 8));
10779*f5c631daSSadaf Ebrahimi   __ Ldapursw(x17, MemOperand(x20, 8));
10780*f5c631daSSadaf Ebrahimi 
10781*f5c631daSSadaf Ebrahimi   END();
10782*f5c631daSSadaf Ebrahimi 
10783*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10784*f5c631daSSadaf Ebrahimi     RUN();
10785*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffef, x0);
10786*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffffef, x1);
10787*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffcdef, x2);
10788*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffcdef, x3);
10789*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffff89abcdef, x4);
10790*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffff98, x5);
10791*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffff98, x6);
10792*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffdcba, x7);
10793*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffdcba, x8);
10794*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffba987654, x9);
10795*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffe, x10);
10796*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfffffffffffffffe, x11);
10797*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffba98, x12);
10798*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffffffba98, x13);
10799*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xffffffffdcba9876, x14);
10800*f5c631daSSadaf Ebrahimi 
10801*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000000010, x15);
10802*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000000003210, x16);
10803*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0000000076543210, x17);
10804*f5c631daSSadaf Ebrahimi   }
10805*f5c631daSSadaf Ebrahimi }
10806*f5c631daSSadaf Ebrahimi 
10807*f5c631daSSadaf Ebrahimi 
TEST(stlurb_stlurh_strlur)10808*f5c631daSSadaf Ebrahimi TEST(stlurb_stlurh_strlur) {
10809*f5c631daSSadaf Ebrahimi   uint64_t data[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0, 0x0};
10810*f5c631daSSadaf Ebrahimi 
10811*f5c631daSSadaf Ebrahimi   uintptr_t data_base = reinterpret_cast<uintptr_t>(data);
10812*f5c631daSSadaf Ebrahimi 
10813*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
10814*f5c631daSSadaf Ebrahimi   START();
10815*f5c631daSSadaf Ebrahimi 
10816*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0011223344556677);
10817*f5c631daSSadaf Ebrahimi   __ Mov(x20, data_base);
10818*f5c631daSSadaf Ebrahimi   __ Mov(x21, data_base + 2 * sizeof(data[0]));
10819*f5c631daSSadaf Ebrahimi 
10820*f5c631daSSadaf Ebrahimi   __ Stlrb(w0, MemOperand(x20));
10821*f5c631daSSadaf Ebrahimi   __ Stlrh(w0, MemOperand(x20, 1));
10822*f5c631daSSadaf Ebrahimi   __ Stlr(w0, MemOperand(x20, 3));
10823*f5c631daSSadaf Ebrahimi   __ Stlr(x0, MemOperand(x21, -8));
10824*f5c631daSSadaf Ebrahimi 
10825*f5c631daSSadaf Ebrahimi   END();
10826*f5c631daSSadaf Ebrahimi 
10827*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
10828*f5c631daSSadaf Ebrahimi     RUN();
10829*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0044556677667777, data[0]);
10830*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0011223344556677, data[1]);
10831*f5c631daSSadaf Ebrahimi   }
10832*f5c631daSSadaf Ebrahimi }
10833*f5c631daSSadaf Ebrahimi 
10834*f5c631daSSadaf Ebrahimi 
10835*f5c631daSSadaf Ebrahimi #define SIMPLE_ATOMIC_OPS(V, DEF) \
10836*f5c631daSSadaf Ebrahimi   V(DEF, add)                     \
10837*f5c631daSSadaf Ebrahimi   V(DEF, clr)                     \
10838*f5c631daSSadaf Ebrahimi   V(DEF, eor)                     \
10839*f5c631daSSadaf Ebrahimi   V(DEF, set)                     \
10840*f5c631daSSadaf Ebrahimi   V(DEF, smax)                    \
10841*f5c631daSSadaf Ebrahimi   V(DEF, smin)                    \
10842*f5c631daSSadaf Ebrahimi   V(DEF, umax)                    \
10843*f5c631daSSadaf Ebrahimi   V(DEF, umin)
10844*f5c631daSSadaf Ebrahimi 
10845*f5c631daSSadaf Ebrahimi #define SIMPLE_ATOMIC_STORE_MODES(V, NAME) \
10846*f5c631daSSadaf Ebrahimi   V(NAME)                                  \
10847*f5c631daSSadaf Ebrahimi   V(NAME##l)
10848*f5c631daSSadaf Ebrahimi 
10849*f5c631daSSadaf Ebrahimi #define SIMPLE_ATOMIC_LOAD_MODES(V, NAME) \
10850*f5c631daSSadaf Ebrahimi   SIMPLE_ATOMIC_STORE_MODES(V, NAME)      \
10851*f5c631daSSadaf Ebrahimi   V(NAME##a)                              \
10852*f5c631daSSadaf Ebrahimi   V(NAME##al)
10853*f5c631daSSadaf Ebrahimi 
10854*f5c631daSSadaf Ebrahimi 
TEST(unaligned_single_copy_atomicity)10855*f5c631daSSadaf Ebrahimi TEST(unaligned_single_copy_atomicity) {
10856*f5c631daSSadaf Ebrahimi   uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
10857*f5c631daSSadaf Ebrahimi   uint64_t dst[] = {0x0000000000000000, 0x0000000000000000};
10858*f5c631daSSadaf Ebrahimi 
10859*f5c631daSSadaf Ebrahimi   uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule);
10860*f5c631daSSadaf Ebrahimi   uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule);
10861*f5c631daSSadaf Ebrahimi 
10862*f5c631daSSadaf Ebrahimi   CPUFeatures features(CPUFeatures::kAtomics,
10863*f5c631daSSadaf Ebrahimi                        CPUFeatures::kLORegions,
10864*f5c631daSSadaf Ebrahimi                        CPUFeatures::kRCpc,
10865*f5c631daSSadaf Ebrahimi                        CPUFeatures::kRCpcImm);
10866*f5c631daSSadaf Ebrahimi   features.Combine(CPUFeatures::kUSCAT);
10867*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(features);
10868*f5c631daSSadaf Ebrahimi   START();
10869*f5c631daSSadaf Ebrahimi 
10870*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x0123456789abcdef);
10871*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0x456789abcdef0123);
10872*f5c631daSSadaf Ebrahimi   __ Mov(x2, 0x89abcdef01234567);
10873*f5c631daSSadaf Ebrahimi   __ Mov(x3, 0xcdef0123456789ab);
10874*f5c631daSSadaf Ebrahimi   __ Mov(x18, reinterpret_cast<uintptr_t>(data0_aligned));
10875*f5c631daSSadaf Ebrahimi   __ Mov(x19, reinterpret_cast<uintptr_t>(dst_aligned));
10876*f5c631daSSadaf Ebrahimi   __ Mov(x20, x18);
10877*f5c631daSSadaf Ebrahimi   __ Mov(x21, x19);
10878*f5c631daSSadaf Ebrahimi 
10879*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < kAtomicAccessGranule; i++) {
10880*f5c631daSSadaf Ebrahimi     __ Stxrb(w0, w1, MemOperand(x20));
10881*f5c631daSSadaf Ebrahimi     __ Stlxrb(w0, w1, MemOperand(x20));
10882*f5c631daSSadaf Ebrahimi     __ Ldxrb(w0, MemOperand(x20));
10883*f5c631daSSadaf Ebrahimi     __ Ldaxrb(w0, MemOperand(x20));
10884*f5c631daSSadaf Ebrahimi     __ Stllrb(w0, MemOperand(x20));
10885*f5c631daSSadaf Ebrahimi     __ Stlrb(w0, MemOperand(x20));
10886*f5c631daSSadaf Ebrahimi     __ Casb(w0, w1, MemOperand(x20));
10887*f5c631daSSadaf Ebrahimi     __ Caslb(w0, w1, MemOperand(x20));
10888*f5c631daSSadaf Ebrahimi     __ Ldlarb(w0, MemOperand(x20));
10889*f5c631daSSadaf Ebrahimi     __ Ldarb(w0, MemOperand(x20));
10890*f5c631daSSadaf Ebrahimi     __ Casab(w0, w1, MemOperand(x20));
10891*f5c631daSSadaf Ebrahimi     __ Casalb(w0, w1, MemOperand(x20));
10892*f5c631daSSadaf Ebrahimi 
10893*f5c631daSSadaf Ebrahimi     __ Swpb(w0, w1, MemOperand(x20));
10894*f5c631daSSadaf Ebrahimi     __ Swplb(w0, w1, MemOperand(x20));
10895*f5c631daSSadaf Ebrahimi     __ Swpab(w0, w1, MemOperand(x20));
10896*f5c631daSSadaf Ebrahimi     __ Swpalb(w0, w1, MemOperand(x20));
10897*f5c631daSSadaf Ebrahimi     __ Ldaprb(w0, MemOperand(x20));
10898*f5c631daSSadaf Ebrahimi     // Use offset instead of Add to test Stlurb and Ldapurb.
10899*f5c631daSSadaf Ebrahimi     __ Stlrb(w0, MemOperand(x19, i));
10900*f5c631daSSadaf Ebrahimi     __ Ldaprb(w0, MemOperand(x19, i));
10901*f5c631daSSadaf Ebrahimi     __ Ldapursb(w0, MemOperand(x20));
10902*f5c631daSSadaf Ebrahimi     __ Ldapursb(x0, MemOperand(x20));
10903*f5c631daSSadaf Ebrahimi 
10904*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_B(NAME) __ Ld##NAME##b(w0, w1, MemOperand(x20));
10905*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_B(NAME) __ St##NAME##b(w0, MemOperand(x20));
10906*f5c631daSSadaf Ebrahimi     SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_B)
10907*f5c631daSSadaf Ebrahimi     SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_B)
10908*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_B
10909*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_B
10910*f5c631daSSadaf Ebrahimi 
10911*f5c631daSSadaf Ebrahimi     if (i <= (kAtomicAccessGranule - kHRegSizeInBytes)) {
10912*f5c631daSSadaf Ebrahimi       __ Stxrh(w0, w1, MemOperand(x20));
10913*f5c631daSSadaf Ebrahimi       __ Stlxrh(w0, w1, MemOperand(x20));
10914*f5c631daSSadaf Ebrahimi       __ Ldxrh(w0, MemOperand(x20));
10915*f5c631daSSadaf Ebrahimi       __ Ldaxrh(w0, MemOperand(x20));
10916*f5c631daSSadaf Ebrahimi       __ Stllrh(w0, MemOperand(x20));
10917*f5c631daSSadaf Ebrahimi       __ Stlrh(w0, MemOperand(x20));
10918*f5c631daSSadaf Ebrahimi       __ Cash(w0, w1, MemOperand(x20));
10919*f5c631daSSadaf Ebrahimi       __ Caslh(w0, w1, MemOperand(x20));
10920*f5c631daSSadaf Ebrahimi       __ Ldlarh(w0, MemOperand(x20));
10921*f5c631daSSadaf Ebrahimi       __ Ldarh(w0, MemOperand(x20));
10922*f5c631daSSadaf Ebrahimi       __ Casah(w0, w1, MemOperand(x20));
10923*f5c631daSSadaf Ebrahimi       __ Casalh(w0, w1, MemOperand(x20));
10924*f5c631daSSadaf Ebrahimi 
10925*f5c631daSSadaf Ebrahimi       __ Swph(w0, w1, MemOperand(x20));
10926*f5c631daSSadaf Ebrahimi       __ Swplh(w0, w1, MemOperand(x20));
10927*f5c631daSSadaf Ebrahimi       __ Swpah(w0, w1, MemOperand(x20));
10928*f5c631daSSadaf Ebrahimi       __ Swpalh(w0, w1, MemOperand(x20));
10929*f5c631daSSadaf Ebrahimi       __ Ldaprh(w0, MemOperand(x20));
10930*f5c631daSSadaf Ebrahimi       // Use offset instead of Add to test Stlurh and Ldapurh.
10931*f5c631daSSadaf Ebrahimi       __ Stlrh(w0, MemOperand(x19, i));
10932*f5c631daSSadaf Ebrahimi       __ Ldaprh(w0, MemOperand(x19, i));
10933*f5c631daSSadaf Ebrahimi       __ Ldapursh(w0, MemOperand(x20));
10934*f5c631daSSadaf Ebrahimi       __ Ldapursh(x0, MemOperand(x20));
10935*f5c631daSSadaf Ebrahimi 
10936*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_H(NAME) __ Ld##NAME##h(w0, w1, MemOperand(x20));
10937*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_H(NAME) __ St##NAME##h(w0, MemOperand(x20));
10938*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H)
10939*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H)
10940*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_H
10941*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_H
10942*f5c631daSSadaf Ebrahimi     }
10943*f5c631daSSadaf Ebrahimi 
10944*f5c631daSSadaf Ebrahimi     if (i <= (kAtomicAccessGranule - kWRegSizeInBytes)) {
10945*f5c631daSSadaf Ebrahimi       __ Stxr(w0, w1, MemOperand(x20));
10946*f5c631daSSadaf Ebrahimi       __ Stlxr(w0, w1, MemOperand(x20));
10947*f5c631daSSadaf Ebrahimi       __ Ldxr(w0, MemOperand(x20));
10948*f5c631daSSadaf Ebrahimi       __ Ldaxr(w0, MemOperand(x20));
10949*f5c631daSSadaf Ebrahimi       __ Stllr(w0, MemOperand(x20));
10950*f5c631daSSadaf Ebrahimi       __ Stlr(w0, MemOperand(x20));
10951*f5c631daSSadaf Ebrahimi       __ Cas(w0, w1, MemOperand(x20));
10952*f5c631daSSadaf Ebrahimi       __ Casl(w0, w1, MemOperand(x20));
10953*f5c631daSSadaf Ebrahimi       __ Ldlar(w0, MemOperand(x20));
10954*f5c631daSSadaf Ebrahimi       __ Ldar(w0, MemOperand(x20));
10955*f5c631daSSadaf Ebrahimi       __ Casa(w0, w1, MemOperand(x20));
10956*f5c631daSSadaf Ebrahimi       __ Casal(w0, w1, MemOperand(x20));
10957*f5c631daSSadaf Ebrahimi 
10958*f5c631daSSadaf Ebrahimi       __ Swp(w0, w1, MemOperand(x20));
10959*f5c631daSSadaf Ebrahimi       __ Swpl(w0, w1, MemOperand(x20));
10960*f5c631daSSadaf Ebrahimi       __ Swpa(w0, w1, MemOperand(x20));
10961*f5c631daSSadaf Ebrahimi       __ Swpal(w0, w1, MemOperand(x20));
10962*f5c631daSSadaf Ebrahimi       __ Ldapr(w0, MemOperand(x20));
10963*f5c631daSSadaf Ebrahimi       // Use offset instead of Add to test Stlur and Ldapur.
10964*f5c631daSSadaf Ebrahimi       __ Stlr(w0, MemOperand(x19, i));
10965*f5c631daSSadaf Ebrahimi       __ Ldapr(w0, MemOperand(x19, i));
10966*f5c631daSSadaf Ebrahimi       __ Ldapursw(x0, MemOperand(x20));
10967*f5c631daSSadaf Ebrahimi 
10968*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_W(NAME) __ Ld##NAME(w0, w1, MemOperand(x20));
10969*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_W(NAME) __ St##NAME(w0, MemOperand(x20));
10970*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W)
10971*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W)
10972*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_W
10973*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_W
10974*f5c631daSSadaf Ebrahimi     }
10975*f5c631daSSadaf Ebrahimi 
10976*f5c631daSSadaf Ebrahimi     if (i <= (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) {
10977*f5c631daSSadaf Ebrahimi       __ Casp(w0, w1, w2, w3, MemOperand(x20));
10978*f5c631daSSadaf Ebrahimi       __ Caspl(w0, w1, w2, w3, MemOperand(x20));
10979*f5c631daSSadaf Ebrahimi       __ Caspa(w0, w1, w2, w3, MemOperand(x20));
10980*f5c631daSSadaf Ebrahimi       __ Caspal(w0, w1, w2, w3, MemOperand(x20));
10981*f5c631daSSadaf Ebrahimi       __ Stxp(w0, w1, w2, MemOperand(x20));
10982*f5c631daSSadaf Ebrahimi       __ Stlxp(w0, w1, w2, MemOperand(x20));
10983*f5c631daSSadaf Ebrahimi       __ Ldxp(w0, w1, MemOperand(x20));
10984*f5c631daSSadaf Ebrahimi       __ Ldaxp(w0, w1, MemOperand(x20));
10985*f5c631daSSadaf Ebrahimi     }
10986*f5c631daSSadaf Ebrahimi 
10987*f5c631daSSadaf Ebrahimi     if (i <= (kAtomicAccessGranule - kXRegSizeInBytes)) {
10988*f5c631daSSadaf Ebrahimi       __ Stxr(x0, x1, MemOperand(x20));
10989*f5c631daSSadaf Ebrahimi       __ Stlxr(x0, x1, MemOperand(x20));
10990*f5c631daSSadaf Ebrahimi       __ Ldxr(x0, MemOperand(x20));
10991*f5c631daSSadaf Ebrahimi       __ Ldaxr(x0, MemOperand(x20));
10992*f5c631daSSadaf Ebrahimi       __ Stllr(x0, MemOperand(x20));
10993*f5c631daSSadaf Ebrahimi       __ Stlr(x0, MemOperand(x20));
10994*f5c631daSSadaf Ebrahimi       __ Cas(x0, x1, MemOperand(x20));
10995*f5c631daSSadaf Ebrahimi       __ Casl(x0, x1, MemOperand(x20));
10996*f5c631daSSadaf Ebrahimi       __ Ldlar(x0, MemOperand(x20));
10997*f5c631daSSadaf Ebrahimi       __ Ldar(x0, MemOperand(x20));
10998*f5c631daSSadaf Ebrahimi       __ Casa(x0, x1, MemOperand(x20));
10999*f5c631daSSadaf Ebrahimi       __ Casal(x0, x1, MemOperand(x20));
11000*f5c631daSSadaf Ebrahimi 
11001*f5c631daSSadaf Ebrahimi       __ Swp(x0, x1, MemOperand(x20));
11002*f5c631daSSadaf Ebrahimi       __ Swpl(x0, x1, MemOperand(x20));
11003*f5c631daSSadaf Ebrahimi       __ Swpa(x0, x1, MemOperand(x20));
11004*f5c631daSSadaf Ebrahimi       __ Swpal(x0, x1, MemOperand(x20));
11005*f5c631daSSadaf Ebrahimi       __ Ldapr(x0, MemOperand(x20));
11006*f5c631daSSadaf Ebrahimi       // Use offset instead of Add to test Stlur and Ldapur.
11007*f5c631daSSadaf Ebrahimi       __ Stlr(x0, MemOperand(x19, i));
11008*f5c631daSSadaf Ebrahimi       __ Ldapr(x0, MemOperand(x19, i));
11009*f5c631daSSadaf Ebrahimi 
11010*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_X(NAME) __ Ld##NAME(x0, x1, MemOperand(x20));
11011*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_X(NAME) __ St##NAME(x0, MemOperand(x20));
11012*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X)
11013*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X)
11014*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_X
11015*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_X
11016*f5c631daSSadaf Ebrahimi     }
11017*f5c631daSSadaf Ebrahimi 
11018*f5c631daSSadaf Ebrahimi     if (i <= (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) {
11019*f5c631daSSadaf Ebrahimi       __ Casp(x0, x1, x2, x3, MemOperand(x20));
11020*f5c631daSSadaf Ebrahimi       __ Caspl(x0, x1, x2, x3, MemOperand(x20));
11021*f5c631daSSadaf Ebrahimi       __ Caspa(x0, x1, x2, x3, MemOperand(x20));
11022*f5c631daSSadaf Ebrahimi       __ Caspal(x0, x1, x2, x3, MemOperand(x20));
11023*f5c631daSSadaf Ebrahimi       __ Stxp(x0, x1, x2, MemOperand(x20));
11024*f5c631daSSadaf Ebrahimi       __ Stlxp(x0, x1, x2, MemOperand(x20));
11025*f5c631daSSadaf Ebrahimi       __ Ldxp(x0, x1, MemOperand(x20));
11026*f5c631daSSadaf Ebrahimi       __ Ldaxp(x0, x1, MemOperand(x20));
11027*f5c631daSSadaf Ebrahimi     }
11028*f5c631daSSadaf Ebrahimi 
11029*f5c631daSSadaf Ebrahimi     __ Add(x20, x20, 1);
11030*f5c631daSSadaf Ebrahimi     __ Add(x21, x21, 1);
11031*f5c631daSSadaf Ebrahimi   }
11032*f5c631daSSadaf Ebrahimi   END();
11033*f5c631daSSadaf Ebrahimi 
11034*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
11035*f5c631daSSadaf Ebrahimi     // We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the seen
11036*f5c631daSSadaf Ebrahimi     // check.
11037*f5c631daSSadaf Ebrahimi     RUN_WITHOUT_SEEN_FEATURE_CHECK();
11038*f5c631daSSadaf Ebrahimi   }
11039*f5c631daSSadaf Ebrahimi }
11040*f5c631daSSadaf Ebrahimi 
11041*f5c631daSSadaf Ebrahimi 
11042*f5c631daSSadaf Ebrahimi #if defined(VIXL_NEGATIVE_TESTING) && defined(VIXL_INCLUDE_SIMULATOR_AARCH64)
11043*f5c631daSSadaf Ebrahimi 
11044*f5c631daSSadaf Ebrahimi #define CHECK_ALIGN_FAIL(i, expr)                                              \
11045*f5c631daSSadaf Ebrahimi   {                                                                            \
11046*f5c631daSSadaf Ebrahimi     CPUFeatures features(CPUFeatures::kAtomics,                                \
11047*f5c631daSSadaf Ebrahimi                          CPUFeatures::kLORegions,                              \
11048*f5c631daSSadaf Ebrahimi                          CPUFeatures::kRCpc,                                   \
11049*f5c631daSSadaf Ebrahimi                          CPUFeatures::kRCpcImm);                               \
11050*f5c631daSSadaf Ebrahimi     features.Combine(CPUFeatures::kUSCAT);                                     \
11051*f5c631daSSadaf Ebrahimi     SETUP_WITH_FEATURES(features);                                             \
11052*f5c631daSSadaf Ebrahimi     START();                                                                   \
11053*f5c631daSSadaf Ebrahimi     __ Mov(x0, 0x0123456789abcdef);                                            \
11054*f5c631daSSadaf Ebrahimi     __ Mov(x1, 0x456789abcdef0123);                                            \
11055*f5c631daSSadaf Ebrahimi     __ Mov(x2, 0x89abcdef01234567);                                            \
11056*f5c631daSSadaf Ebrahimi     __ Mov(x3, 0xcdef0123456789ab);                                            \
11057*f5c631daSSadaf Ebrahimi     __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned));                   \
11058*f5c631daSSadaf Ebrahimi     __ Mov(x21, reinterpret_cast<uintptr_t>(dst_aligned));                     \
11059*f5c631daSSadaf Ebrahimi     __ Add(x20, x20, i);                                                       \
11060*f5c631daSSadaf Ebrahimi     __ Add(x21, x21, i);                                                       \
11061*f5c631daSSadaf Ebrahimi     expr;                                                                      \
11062*f5c631daSSadaf Ebrahimi     END();                                                                     \
11063*f5c631daSSadaf Ebrahimi     if (CAN_RUN()) {                                                           \
11064*f5c631daSSadaf Ebrahimi       /* We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the */ \
11065*f5c631daSSadaf Ebrahimi       /* seen check. */                                                        \
11066*f5c631daSSadaf Ebrahimi       MUST_FAIL_WITH_MESSAGE(RUN_WITHOUT_SEEN_FEATURE_CHECK(),                 \
11067*f5c631daSSadaf Ebrahimi                              "ALIGNMENT EXCEPTION");                           \
11068*f5c631daSSadaf Ebrahimi     }                                                                          \
11069*f5c631daSSadaf Ebrahimi   }
11070*f5c631daSSadaf Ebrahimi 
TEST(unaligned_single_copy_atomicity_negative_test)11071*f5c631daSSadaf Ebrahimi TEST(unaligned_single_copy_atomicity_negative_test) {
11072*f5c631daSSadaf Ebrahimi   uint64_t data0[] = {0x1010101010101010, 0x1010101010101010};
11073*f5c631daSSadaf Ebrahimi   uint64_t dst[] = {0x0000000000000000, 0x0000000000000000};
11074*f5c631daSSadaf Ebrahimi 
11075*f5c631daSSadaf Ebrahimi   uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule);
11076*f5c631daSSadaf Ebrahimi   uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule);
11077*f5c631daSSadaf Ebrahimi 
11078*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < kAtomicAccessGranule; i++) {
11079*f5c631daSSadaf Ebrahimi     if (i > (kAtomicAccessGranule - kHRegSizeInBytes)) {
11080*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stxrh(w0, w1, MemOperand(x20)));
11081*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlxrh(w0, w1, MemOperand(x20)));
11082*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldxrh(w0, MemOperand(x20)));
11083*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldaxrh(w0, MemOperand(x20)));
11084*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stllrh(w0, MemOperand(x20)));
11085*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlrh(w0, MemOperand(x20)));
11086*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Cash(w0, w1, MemOperand(x20)));
11087*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caslh(w0, w1, MemOperand(x20)));
11088*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldlarh(w0, MemOperand(x20)));
11089*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldarh(w0, MemOperand(x20)));
11090*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casah(w0, w1, MemOperand(x20)));
11091*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casalh(w0, w1, MemOperand(x20)));
11092*f5c631daSSadaf Ebrahimi 
11093*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swph(w0, w1, MemOperand(x20)));
11094*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swplh(w0, w1, MemOperand(x20)));
11095*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpah(w0, w1, MemOperand(x20)));
11096*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpalh(w0, w1, MemOperand(x20)));
11097*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldaprh(w0, MemOperand(x20)));
11098*f5c631daSSadaf Ebrahimi       // Use offset instead of Add to test Stlurh and Ldapurh.
11099*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(0, __ Stlrh(w0, MemOperand(x20, i)));
11100*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(0, __ Ldaprh(w0, MemOperand(x20, i)));
11101*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldapursh(w0, MemOperand(x20)));
11102*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldapursh(x0, MemOperand(x20)));
11103*f5c631daSSadaf Ebrahimi 
11104*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_H(NAME) \
11105*f5c631daSSadaf Ebrahimi   CHECK_ALIGN_FAIL(i, __ Ld##NAME##h(w0, w1, MemOperand(x20)));
11106*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_H(NAME) \
11107*f5c631daSSadaf Ebrahimi   CHECK_ALIGN_FAIL(i, __ St##NAME##h(w0, MemOperand(x20)));
11108*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H)
11109*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H)
11110*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_H
11111*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_H
11112*f5c631daSSadaf Ebrahimi     }
11113*f5c631daSSadaf Ebrahimi 
11114*f5c631daSSadaf Ebrahimi     if (i > (kAtomicAccessGranule - kWRegSizeInBytes)) {
11115*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stxr(w0, w1, MemOperand(x20)));
11116*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlxr(w0, w1, MemOperand(x20)));
11117*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldxr(w0, MemOperand(x20)));
11118*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldaxr(w0, MemOperand(x20)));
11119*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stllr(w0, MemOperand(x20)));
11120*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlr(w0, MemOperand(x20)));
11121*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Cas(w0, w1, MemOperand(x20)));
11122*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casl(w0, w1, MemOperand(x20)));
11123*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldlar(w0, MemOperand(x20)));
11124*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldar(w0, MemOperand(x20)));
11125*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casa(w0, w1, MemOperand(x20)));
11126*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casal(w0, w1, MemOperand(x20)));
11127*f5c631daSSadaf Ebrahimi 
11128*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swp(w0, w1, MemOperand(x20)));
11129*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpl(w0, w1, MemOperand(x20)));
11130*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpa(w0, w1, MemOperand(x20)));
11131*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpal(w0, w1, MemOperand(x20)));
11132*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldapr(w0, MemOperand(x20)));
11133*f5c631daSSadaf Ebrahimi       // Use offset instead of add to test Stlur and Ldapur.
11134*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(0, __ Stlr(w0, MemOperand(x20, i)));
11135*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(0, __ Ldapr(w0, MemOperand(x20, i)));
11136*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldapursw(x0, MemOperand(x20)));
11137*f5c631daSSadaf Ebrahimi 
11138*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_W(NAME) \
11139*f5c631daSSadaf Ebrahimi   CHECK_ALIGN_FAIL(i, __ Ld##NAME(w0, w1, MemOperand(x20)));
11140*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_W(NAME) \
11141*f5c631daSSadaf Ebrahimi   CHECK_ALIGN_FAIL(i, __ St##NAME(w0, MemOperand(x20)));
11142*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W)
11143*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W)
11144*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_W
11145*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_W
11146*f5c631daSSadaf Ebrahimi     }
11147*f5c631daSSadaf Ebrahimi 
11148*f5c631daSSadaf Ebrahimi     if (i > (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) {
11149*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casp(w0, w1, w2, w3, MemOperand(x20)));
11150*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caspl(w0, w1, w2, w3, MemOperand(x20)));
11151*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caspa(w0, w1, w2, w3, MemOperand(x20)));
11152*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caspal(w0, w1, w2, w3, MemOperand(x20)));
11153*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stxp(w0, w1, w2, MemOperand(x20)));
11154*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlxp(w0, w1, w2, MemOperand(x20)));
11155*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldxp(w0, w1, MemOperand(x20)));
11156*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldaxp(w0, w1, MemOperand(x20)));
11157*f5c631daSSadaf Ebrahimi     }
11158*f5c631daSSadaf Ebrahimi 
11159*f5c631daSSadaf Ebrahimi     if (i > (kAtomicAccessGranule - kXRegSizeInBytes)) {
11160*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stxr(x0, x1, MemOperand(x20)));
11161*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlxr(x0, x1, MemOperand(x20)));
11162*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldxr(x0, MemOperand(x20)));
11163*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldaxr(x0, MemOperand(x20)));
11164*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stllr(x0, MemOperand(x20)));
11165*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlr(x0, MemOperand(x20)));
11166*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Cas(x0, x1, MemOperand(x20)));
11167*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casl(x0, x1, MemOperand(x20)));
11168*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldlar(x0, MemOperand(x20)));
11169*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldar(x0, MemOperand(x20)));
11170*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casa(x0, x1, MemOperand(x20)));
11171*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casal(x0, x1, MemOperand(x20)));
11172*f5c631daSSadaf Ebrahimi 
11173*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swp(x0, x1, MemOperand(x20)));
11174*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpl(x0, x1, MemOperand(x20)));
11175*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpa(x0, x1, MemOperand(x20)));
11176*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Swpal(x0, x1, MemOperand(x20)));
11177*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldapr(x0, MemOperand(x20)));
11178*f5c631daSSadaf Ebrahimi       // Use offset instead of add to test Stlur and Ldapur.
11179*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(0, __ Stlr(x0, MemOperand(x20, i)));
11180*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(0, __ Ldapr(x0, MemOperand(x20, i)));
11181*f5c631daSSadaf Ebrahimi 
11182*f5c631daSSadaf Ebrahimi #define ATOMIC_LOAD_X(NAME) \
11183*f5c631daSSadaf Ebrahimi   CHECK_ALIGN_FAIL(i, __ Ld##NAME(x0, x1, MemOperand(x20)));
11184*f5c631daSSadaf Ebrahimi #define ATOMIC_STORE_X(NAME) \
11185*f5c631daSSadaf Ebrahimi   CHECK_ALIGN_FAIL(i, __ St##NAME(x0, MemOperand(x20)));
11186*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X)
11187*f5c631daSSadaf Ebrahimi       SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X)
11188*f5c631daSSadaf Ebrahimi #undef ATOMIC_LOAD_X
11189*f5c631daSSadaf Ebrahimi #undef ATOMIC_STORE_X
11190*f5c631daSSadaf Ebrahimi     }
11191*f5c631daSSadaf Ebrahimi 
11192*f5c631daSSadaf Ebrahimi     if (i > (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) {
11193*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Casp(x0, x1, x2, x3, MemOperand(x20)));
11194*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caspl(x0, x1, x2, x3, MemOperand(x20)));
11195*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caspa(x0, x1, x2, x3, MemOperand(x20)));
11196*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Caspal(x0, x1, x2, x3, MemOperand(x20)));
11197*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stxp(x0, x1, x2, MemOperand(x20)));
11198*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Stlxp(x0, x1, x2, MemOperand(x20)));
11199*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldxp(x0, x1, MemOperand(x20)));
11200*f5c631daSSadaf Ebrahimi       CHECK_ALIGN_FAIL(i, __ Ldaxp(x0, x1, MemOperand(x20)));
11201*f5c631daSSadaf Ebrahimi     }
11202*f5c631daSSadaf Ebrahimi   }
11203*f5c631daSSadaf Ebrahimi }
11204*f5c631daSSadaf Ebrahimi 
TEST(unaligned_single_copy_atomicity_negative_test_2)11205*f5c631daSSadaf Ebrahimi TEST(unaligned_single_copy_atomicity_negative_test_2) {
11206*f5c631daSSadaf Ebrahimi   uint64_t data[] = {0x1010101010101010, 0x1010101010101010};
11207*f5c631daSSadaf Ebrahimi 
11208*f5c631daSSadaf Ebrahimi   uint64_t* data_aligned = AlignUp(data, kAtomicAccessGranule);
11209*f5c631daSSadaf Ebrahimi 
11210*f5c631daSSadaf Ebrahimi   // Check that the same code doesn't fail with USCAT enabled but does
11211*f5c631daSSadaf Ebrahimi   // fail when not enabled.
11212*f5c631daSSadaf Ebrahimi   {
11213*f5c631daSSadaf Ebrahimi     SETUP_WITH_FEATURES(CPUFeatures::kUSCAT);
11214*f5c631daSSadaf Ebrahimi     START();
11215*f5c631daSSadaf Ebrahimi     __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned));
11216*f5c631daSSadaf Ebrahimi     __ Add(x0, x0, 1);
11217*f5c631daSSadaf Ebrahimi     __ Ldxrh(w1, MemOperand(x0));
11218*f5c631daSSadaf Ebrahimi     END();
11219*f5c631daSSadaf Ebrahimi     if (CAN_RUN()) {
11220*f5c631daSSadaf Ebrahimi       RUN_WITHOUT_SEEN_FEATURE_CHECK();
11221*f5c631daSSadaf Ebrahimi     }
11222*f5c631daSSadaf Ebrahimi   }
11223*f5c631daSSadaf Ebrahimi   {
11224*f5c631daSSadaf Ebrahimi     SETUP();
11225*f5c631daSSadaf Ebrahimi     START();
11226*f5c631daSSadaf Ebrahimi     __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned));
11227*f5c631daSSadaf Ebrahimi     __ Add(x0, x0, 1);
11228*f5c631daSSadaf Ebrahimi     __ Ldxrh(w1, MemOperand(x0));
11229*f5c631daSSadaf Ebrahimi     END();
11230*f5c631daSSadaf Ebrahimi     if (CAN_RUN()) {
11231*f5c631daSSadaf Ebrahimi       MUST_FAIL_WITH_MESSAGE(RUN(), "ALIGNMENT EXCEPTION");
11232*f5c631daSSadaf Ebrahimi     }
11233*f5c631daSSadaf Ebrahimi   }
11234*f5c631daSSadaf Ebrahimi }
11235*f5c631daSSadaf Ebrahimi #endif  // VIXL_NEGATIVE_TESTING && VIXL_INCLUDE_SIMULATOR_AARCH64
11236*f5c631daSSadaf Ebrahimi 
11237*f5c631daSSadaf Ebrahimi 
TEST(load_store_tagged_immediate_offset)11238*f5c631daSSadaf Ebrahimi TEST(load_store_tagged_immediate_offset) {
11239*f5c631daSSadaf Ebrahimi   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11240*f5c631daSSadaf Ebrahimi   int tag_count = sizeof(tags) / sizeof(tags[0]);
11241*f5c631daSSadaf Ebrahimi 
11242*f5c631daSSadaf Ebrahimi   const int kMaxDataLength = 160;
11243*f5c631daSSadaf Ebrahimi 
11244*f5c631daSSadaf Ebrahimi   for (int i = 0; i < tag_count; i++) {
11245*f5c631daSSadaf Ebrahimi     unsigned char src[kMaxDataLength];
11246*f5c631daSSadaf Ebrahimi     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11247*f5c631daSSadaf Ebrahimi     uint64_t src_tag = tags[i];
11248*f5c631daSSadaf Ebrahimi     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11249*f5c631daSSadaf Ebrahimi 
11250*f5c631daSSadaf Ebrahimi     for (int k = 0; k < kMaxDataLength; k++) {
11251*f5c631daSSadaf Ebrahimi       src[k] = k + 1;
11252*f5c631daSSadaf Ebrahimi     }
11253*f5c631daSSadaf Ebrahimi 
11254*f5c631daSSadaf Ebrahimi     for (int j = 0; j < tag_count; j++) {
11255*f5c631daSSadaf Ebrahimi       unsigned char dst[kMaxDataLength];
11256*f5c631daSSadaf Ebrahimi       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11257*f5c631daSSadaf Ebrahimi       uint64_t dst_tag = tags[j];
11258*f5c631daSSadaf Ebrahimi       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11259*f5c631daSSadaf Ebrahimi 
11260*f5c631daSSadaf Ebrahimi       memset(dst, 0, kMaxDataLength);
11261*f5c631daSSadaf Ebrahimi 
11262*f5c631daSSadaf Ebrahimi       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11263*f5c631daSSadaf Ebrahimi       START();
11264*f5c631daSSadaf Ebrahimi 
11265*f5c631daSSadaf Ebrahimi       __ Mov(x0, src_tagged);
11266*f5c631daSSadaf Ebrahimi       __ Mov(x1, dst_tagged);
11267*f5c631daSSadaf Ebrahimi 
11268*f5c631daSSadaf Ebrahimi       int offset = 0;
11269*f5c631daSSadaf Ebrahimi 
11270*f5c631daSSadaf Ebrahimi       // Scaled-immediate offsets.
11271*f5c631daSSadaf Ebrahimi       {
11272*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11273*f5c631daSSadaf Ebrahimi         __ ldp(q0, q1, MemOperand(x0, offset));
11274*f5c631daSSadaf Ebrahimi         __ stp(q0, q1, MemOperand(x1, offset));
11275*f5c631daSSadaf Ebrahimi       }
11276*f5c631daSSadaf Ebrahimi       offset += 2 * kQRegSizeInBytes;
11277*f5c631daSSadaf Ebrahimi 
11278*f5c631daSSadaf Ebrahimi       {
11279*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11280*f5c631daSSadaf Ebrahimi         __ ldp(x2, x3, MemOperand(x0, offset));
11281*f5c631daSSadaf Ebrahimi         __ stp(x2, x3, MemOperand(x1, offset));
11282*f5c631daSSadaf Ebrahimi       }
11283*f5c631daSSadaf Ebrahimi       offset += 2 * kXRegSizeInBytes;
11284*f5c631daSSadaf Ebrahimi 
11285*f5c631daSSadaf Ebrahimi       {
11286*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11287*f5c631daSSadaf Ebrahimi         __ ldpsw(x2, x3, MemOperand(x0, offset));
11288*f5c631daSSadaf Ebrahimi         __ stp(w2, w3, MemOperand(x1, offset));
11289*f5c631daSSadaf Ebrahimi       }
11290*f5c631daSSadaf Ebrahimi       offset += 2 * kWRegSizeInBytes;
11291*f5c631daSSadaf Ebrahimi 
11292*f5c631daSSadaf Ebrahimi       {
11293*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11294*f5c631daSSadaf Ebrahimi         __ ldp(d0, d1, MemOperand(x0, offset));
11295*f5c631daSSadaf Ebrahimi         __ stp(d0, d1, MemOperand(x1, offset));
11296*f5c631daSSadaf Ebrahimi       }
11297*f5c631daSSadaf Ebrahimi       offset += 2 * kDRegSizeInBytes;
11298*f5c631daSSadaf Ebrahimi 
11299*f5c631daSSadaf Ebrahimi       {
11300*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11301*f5c631daSSadaf Ebrahimi         __ ldp(w2, w3, MemOperand(x0, offset));
11302*f5c631daSSadaf Ebrahimi         __ stp(w2, w3, MemOperand(x1, offset));
11303*f5c631daSSadaf Ebrahimi       }
11304*f5c631daSSadaf Ebrahimi       offset += 2 * kWRegSizeInBytes;
11305*f5c631daSSadaf Ebrahimi 
11306*f5c631daSSadaf Ebrahimi       {
11307*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11308*f5c631daSSadaf Ebrahimi         __ ldp(s0, s1, MemOperand(x0, offset));
11309*f5c631daSSadaf Ebrahimi         __ stp(s0, s1, MemOperand(x1, offset));
11310*f5c631daSSadaf Ebrahimi       }
11311*f5c631daSSadaf Ebrahimi       offset += 2 * kSRegSizeInBytes;
11312*f5c631daSSadaf Ebrahimi 
11313*f5c631daSSadaf Ebrahimi       {
11314*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11315*f5c631daSSadaf Ebrahimi         __ ldr(x2, MemOperand(x0, offset), RequireScaledOffset);
11316*f5c631daSSadaf Ebrahimi         __ str(x2, MemOperand(x1, offset), RequireScaledOffset);
11317*f5c631daSSadaf Ebrahimi       }
11318*f5c631daSSadaf Ebrahimi       offset += kXRegSizeInBytes;
11319*f5c631daSSadaf Ebrahimi 
11320*f5c631daSSadaf Ebrahimi       {
11321*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11322*f5c631daSSadaf Ebrahimi         __ ldr(d0, MemOperand(x0, offset), RequireScaledOffset);
11323*f5c631daSSadaf Ebrahimi         __ str(d0, MemOperand(x1, offset), RequireScaledOffset);
11324*f5c631daSSadaf Ebrahimi       }
11325*f5c631daSSadaf Ebrahimi       offset += kDRegSizeInBytes;
11326*f5c631daSSadaf Ebrahimi 
11327*f5c631daSSadaf Ebrahimi       {
11328*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11329*f5c631daSSadaf Ebrahimi         __ ldr(w2, MemOperand(x0, offset), RequireScaledOffset);
11330*f5c631daSSadaf Ebrahimi         __ str(w2, MemOperand(x1, offset), RequireScaledOffset);
11331*f5c631daSSadaf Ebrahimi       }
11332*f5c631daSSadaf Ebrahimi       offset += kWRegSizeInBytes;
11333*f5c631daSSadaf Ebrahimi 
11334*f5c631daSSadaf Ebrahimi       {
11335*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11336*f5c631daSSadaf Ebrahimi         __ ldr(s0, MemOperand(x0, offset), RequireScaledOffset);
11337*f5c631daSSadaf Ebrahimi         __ str(s0, MemOperand(x1, offset), RequireScaledOffset);
11338*f5c631daSSadaf Ebrahimi       }
11339*f5c631daSSadaf Ebrahimi       offset += kSRegSizeInBytes;
11340*f5c631daSSadaf Ebrahimi 
11341*f5c631daSSadaf Ebrahimi       {
11342*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11343*f5c631daSSadaf Ebrahimi         __ ldrh(w2, MemOperand(x0, offset), RequireScaledOffset);
11344*f5c631daSSadaf Ebrahimi         __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11345*f5c631daSSadaf Ebrahimi       }
11346*f5c631daSSadaf Ebrahimi       offset += 2;
11347*f5c631daSSadaf Ebrahimi 
11348*f5c631daSSadaf Ebrahimi       {
11349*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11350*f5c631daSSadaf Ebrahimi         __ ldrsh(w2, MemOperand(x0, offset), RequireScaledOffset);
11351*f5c631daSSadaf Ebrahimi         __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11352*f5c631daSSadaf Ebrahimi       }
11353*f5c631daSSadaf Ebrahimi       offset += 2;
11354*f5c631daSSadaf Ebrahimi 
11355*f5c631daSSadaf Ebrahimi       {
11356*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11357*f5c631daSSadaf Ebrahimi         __ ldrb(w2, MemOperand(x0, offset), RequireScaledOffset);
11358*f5c631daSSadaf Ebrahimi         __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11359*f5c631daSSadaf Ebrahimi       }
11360*f5c631daSSadaf Ebrahimi       offset += 1;
11361*f5c631daSSadaf Ebrahimi 
11362*f5c631daSSadaf Ebrahimi       {
11363*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11364*f5c631daSSadaf Ebrahimi         __ ldrsb(w2, MemOperand(x0, offset), RequireScaledOffset);
11365*f5c631daSSadaf Ebrahimi         __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11366*f5c631daSSadaf Ebrahimi       }
11367*f5c631daSSadaf Ebrahimi       offset += 1;
11368*f5c631daSSadaf Ebrahimi 
11369*f5c631daSSadaf Ebrahimi       // Unscaled-immediate offsets.
11370*f5c631daSSadaf Ebrahimi 
11371*f5c631daSSadaf Ebrahimi       {
11372*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11373*f5c631daSSadaf Ebrahimi         __ ldur(x2, MemOperand(x0, offset), RequireUnscaledOffset);
11374*f5c631daSSadaf Ebrahimi         __ stur(x2, MemOperand(x1, offset), RequireUnscaledOffset);
11375*f5c631daSSadaf Ebrahimi       }
11376*f5c631daSSadaf Ebrahimi       offset += kXRegSizeInBytes;
11377*f5c631daSSadaf Ebrahimi 
11378*f5c631daSSadaf Ebrahimi       {
11379*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11380*f5c631daSSadaf Ebrahimi         __ ldur(d0, MemOperand(x0, offset), RequireUnscaledOffset);
11381*f5c631daSSadaf Ebrahimi         __ stur(d0, MemOperand(x1, offset), RequireUnscaledOffset);
11382*f5c631daSSadaf Ebrahimi       }
11383*f5c631daSSadaf Ebrahimi       offset += kDRegSizeInBytes;
11384*f5c631daSSadaf Ebrahimi 
11385*f5c631daSSadaf Ebrahimi       {
11386*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11387*f5c631daSSadaf Ebrahimi         __ ldur(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11388*f5c631daSSadaf Ebrahimi         __ stur(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11389*f5c631daSSadaf Ebrahimi       }
11390*f5c631daSSadaf Ebrahimi       offset += kWRegSizeInBytes;
11391*f5c631daSSadaf Ebrahimi 
11392*f5c631daSSadaf Ebrahimi       {
11393*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11394*f5c631daSSadaf Ebrahimi         __ ldur(s0, MemOperand(x0, offset), RequireUnscaledOffset);
11395*f5c631daSSadaf Ebrahimi         __ stur(s0, MemOperand(x1, offset), RequireUnscaledOffset);
11396*f5c631daSSadaf Ebrahimi       }
11397*f5c631daSSadaf Ebrahimi       offset += kSRegSizeInBytes;
11398*f5c631daSSadaf Ebrahimi 
11399*f5c631daSSadaf Ebrahimi       {
11400*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11401*f5c631daSSadaf Ebrahimi         __ ldurh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11402*f5c631daSSadaf Ebrahimi         __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11403*f5c631daSSadaf Ebrahimi       }
11404*f5c631daSSadaf Ebrahimi       offset += 2;
11405*f5c631daSSadaf Ebrahimi 
11406*f5c631daSSadaf Ebrahimi       {
11407*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11408*f5c631daSSadaf Ebrahimi         __ ldursh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11409*f5c631daSSadaf Ebrahimi         __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11410*f5c631daSSadaf Ebrahimi       }
11411*f5c631daSSadaf Ebrahimi       offset += 2;
11412*f5c631daSSadaf Ebrahimi 
11413*f5c631daSSadaf Ebrahimi       {
11414*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11415*f5c631daSSadaf Ebrahimi         __ ldurb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11416*f5c631daSSadaf Ebrahimi         __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11417*f5c631daSSadaf Ebrahimi       }
11418*f5c631daSSadaf Ebrahimi       offset += 1;
11419*f5c631daSSadaf Ebrahimi 
11420*f5c631daSSadaf Ebrahimi       {
11421*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11422*f5c631daSSadaf Ebrahimi         __ ldursb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11423*f5c631daSSadaf Ebrahimi         __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11424*f5c631daSSadaf Ebrahimi       }
11425*f5c631daSSadaf Ebrahimi       offset += 1;
11426*f5c631daSSadaf Ebrahimi 
11427*f5c631daSSadaf Ebrahimi       // Extract the tag (so we can test that it was preserved correctly).
11428*f5c631daSSadaf Ebrahimi       __ Ubfx(x0, x0, kAddressTagOffset, kAddressTagWidth);
11429*f5c631daSSadaf Ebrahimi       __ Ubfx(x1, x1, kAddressTagOffset, kAddressTagWidth);
11430*f5c631daSSadaf Ebrahimi 
11431*f5c631daSSadaf Ebrahimi       VIXL_ASSERT(kMaxDataLength >= offset);
11432*f5c631daSSadaf Ebrahimi 
11433*f5c631daSSadaf Ebrahimi       END();
11434*f5c631daSSadaf Ebrahimi       if (CAN_RUN()) {
11435*f5c631daSSadaf Ebrahimi         RUN();
11436*f5c631daSSadaf Ebrahimi 
11437*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(src_tag, x0);
11438*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(dst_tag, x1);
11439*f5c631daSSadaf Ebrahimi 
11440*f5c631daSSadaf Ebrahimi         for (int k = 0; k < offset; k++) {
11441*f5c631daSSadaf Ebrahimi           VIXL_CHECK(src[k] == dst[k]);
11442*f5c631daSSadaf Ebrahimi         }
11443*f5c631daSSadaf Ebrahimi       }
11444*f5c631daSSadaf Ebrahimi     }
11445*f5c631daSSadaf Ebrahimi   }
11446*f5c631daSSadaf Ebrahimi }
11447*f5c631daSSadaf Ebrahimi 
11448*f5c631daSSadaf Ebrahimi 
TEST(load_store_tagged_immediate_preindex)11449*f5c631daSSadaf Ebrahimi TEST(load_store_tagged_immediate_preindex) {
11450*f5c631daSSadaf Ebrahimi   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11451*f5c631daSSadaf Ebrahimi   int tag_count = sizeof(tags) / sizeof(tags[0]);
11452*f5c631daSSadaf Ebrahimi 
11453*f5c631daSSadaf Ebrahimi   const int kMaxDataLength = 128;
11454*f5c631daSSadaf Ebrahimi 
11455*f5c631daSSadaf Ebrahimi   for (int i = 0; i < tag_count; i++) {
11456*f5c631daSSadaf Ebrahimi     unsigned char src[kMaxDataLength];
11457*f5c631daSSadaf Ebrahimi     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11458*f5c631daSSadaf Ebrahimi     uint64_t src_tag = tags[i];
11459*f5c631daSSadaf Ebrahimi     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11460*f5c631daSSadaf Ebrahimi 
11461*f5c631daSSadaf Ebrahimi     for (int k = 0; k < kMaxDataLength; k++) {
11462*f5c631daSSadaf Ebrahimi       src[k] = k + 1;
11463*f5c631daSSadaf Ebrahimi     }
11464*f5c631daSSadaf Ebrahimi 
11465*f5c631daSSadaf Ebrahimi     for (int j = 0; j < tag_count; j++) {
11466*f5c631daSSadaf Ebrahimi       unsigned char dst[kMaxDataLength];
11467*f5c631daSSadaf Ebrahimi       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11468*f5c631daSSadaf Ebrahimi       uint64_t dst_tag = tags[j];
11469*f5c631daSSadaf Ebrahimi       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11470*f5c631daSSadaf Ebrahimi 
11471*f5c631daSSadaf Ebrahimi       for (int k = 0; k < kMaxDataLength; k++) {
11472*f5c631daSSadaf Ebrahimi         dst[k] = 0;
11473*f5c631daSSadaf Ebrahimi       }
11474*f5c631daSSadaf Ebrahimi 
11475*f5c631daSSadaf Ebrahimi       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11476*f5c631daSSadaf Ebrahimi       START();
11477*f5c631daSSadaf Ebrahimi 
11478*f5c631daSSadaf Ebrahimi       // Each MemOperand must apply a pre-index equal to the size of the
11479*f5c631daSSadaf Ebrahimi       // previous access.
11480*f5c631daSSadaf Ebrahimi 
11481*f5c631daSSadaf Ebrahimi       // Start with a non-zero preindex.
11482*f5c631daSSadaf Ebrahimi       int preindex = 62 * kXRegSizeInBytes;
11483*f5c631daSSadaf Ebrahimi       int data_length = 0;
11484*f5c631daSSadaf Ebrahimi 
11485*f5c631daSSadaf Ebrahimi       __ Mov(x0, src_tagged - preindex);
11486*f5c631daSSadaf Ebrahimi       __ Mov(x1, dst_tagged - preindex);
11487*f5c631daSSadaf Ebrahimi 
11488*f5c631daSSadaf Ebrahimi       {
11489*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11490*f5c631daSSadaf Ebrahimi         __ ldp(q0, q1, MemOperand(x0, preindex, PreIndex));
11491*f5c631daSSadaf Ebrahimi         __ stp(q0, q1, MemOperand(x1, preindex, PreIndex));
11492*f5c631daSSadaf Ebrahimi       }
11493*f5c631daSSadaf Ebrahimi       preindex = 2 * kQRegSizeInBytes;
11494*f5c631daSSadaf Ebrahimi       data_length = preindex;
11495*f5c631daSSadaf Ebrahimi 
11496*f5c631daSSadaf Ebrahimi       {
11497*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11498*f5c631daSSadaf Ebrahimi         __ ldp(x2, x3, MemOperand(x0, preindex, PreIndex));
11499*f5c631daSSadaf Ebrahimi         __ stp(x2, x3, MemOperand(x1, preindex, PreIndex));
11500*f5c631daSSadaf Ebrahimi       }
11501*f5c631daSSadaf Ebrahimi       preindex = 2 * kXRegSizeInBytes;
11502*f5c631daSSadaf Ebrahimi       data_length += preindex;
11503*f5c631daSSadaf Ebrahimi 
11504*f5c631daSSadaf Ebrahimi       {
11505*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11506*f5c631daSSadaf Ebrahimi         __ ldpsw(x2, x3, MemOperand(x0, preindex, PreIndex));
11507*f5c631daSSadaf Ebrahimi         __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
11508*f5c631daSSadaf Ebrahimi       }
11509*f5c631daSSadaf Ebrahimi       preindex = 2 * kWRegSizeInBytes;
11510*f5c631daSSadaf Ebrahimi       data_length += preindex;
11511*f5c631daSSadaf Ebrahimi 
11512*f5c631daSSadaf Ebrahimi       {
11513*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11514*f5c631daSSadaf Ebrahimi         __ ldp(d0, d1, MemOperand(x0, preindex, PreIndex));
11515*f5c631daSSadaf Ebrahimi         __ stp(d0, d1, MemOperand(x1, preindex, PreIndex));
11516*f5c631daSSadaf Ebrahimi       }
11517*f5c631daSSadaf Ebrahimi       preindex = 2 * kDRegSizeInBytes;
11518*f5c631daSSadaf Ebrahimi       data_length += preindex;
11519*f5c631daSSadaf Ebrahimi 
11520*f5c631daSSadaf Ebrahimi       {
11521*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11522*f5c631daSSadaf Ebrahimi         __ ldp(w2, w3, MemOperand(x0, preindex, PreIndex));
11523*f5c631daSSadaf Ebrahimi         __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
11524*f5c631daSSadaf Ebrahimi       }
11525*f5c631daSSadaf Ebrahimi       preindex = 2 * kWRegSizeInBytes;
11526*f5c631daSSadaf Ebrahimi       data_length += preindex;
11527*f5c631daSSadaf Ebrahimi 
11528*f5c631daSSadaf Ebrahimi       {
11529*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11530*f5c631daSSadaf Ebrahimi         __ ldp(s0, s1, MemOperand(x0, preindex, PreIndex));
11531*f5c631daSSadaf Ebrahimi         __ stp(s0, s1, MemOperand(x1, preindex, PreIndex));
11532*f5c631daSSadaf Ebrahimi       }
11533*f5c631daSSadaf Ebrahimi       preindex = 2 * kSRegSizeInBytes;
11534*f5c631daSSadaf Ebrahimi       data_length += preindex;
11535*f5c631daSSadaf Ebrahimi 
11536*f5c631daSSadaf Ebrahimi       {
11537*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11538*f5c631daSSadaf Ebrahimi         __ ldr(x2, MemOperand(x0, preindex, PreIndex));
11539*f5c631daSSadaf Ebrahimi         __ str(x2, MemOperand(x1, preindex, PreIndex));
11540*f5c631daSSadaf Ebrahimi       }
11541*f5c631daSSadaf Ebrahimi       preindex = kXRegSizeInBytes;
11542*f5c631daSSadaf Ebrahimi       data_length += preindex;
11543*f5c631daSSadaf Ebrahimi 
11544*f5c631daSSadaf Ebrahimi       {
11545*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11546*f5c631daSSadaf Ebrahimi         __ ldr(d0, MemOperand(x0, preindex, PreIndex));
11547*f5c631daSSadaf Ebrahimi         __ str(d0, MemOperand(x1, preindex, PreIndex));
11548*f5c631daSSadaf Ebrahimi       }
11549*f5c631daSSadaf Ebrahimi       preindex = kDRegSizeInBytes;
11550*f5c631daSSadaf Ebrahimi       data_length += preindex;
11551*f5c631daSSadaf Ebrahimi 
11552*f5c631daSSadaf Ebrahimi       {
11553*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11554*f5c631daSSadaf Ebrahimi         __ ldr(w2, MemOperand(x0, preindex, PreIndex));
11555*f5c631daSSadaf Ebrahimi         __ str(w2, MemOperand(x1, preindex, PreIndex));
11556*f5c631daSSadaf Ebrahimi       }
11557*f5c631daSSadaf Ebrahimi       preindex = kWRegSizeInBytes;
11558*f5c631daSSadaf Ebrahimi       data_length += preindex;
11559*f5c631daSSadaf Ebrahimi 
11560*f5c631daSSadaf Ebrahimi       {
11561*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11562*f5c631daSSadaf Ebrahimi         __ ldr(s0, MemOperand(x0, preindex, PreIndex));
11563*f5c631daSSadaf Ebrahimi         __ str(s0, MemOperand(x1, preindex, PreIndex));
11564*f5c631daSSadaf Ebrahimi       }
11565*f5c631daSSadaf Ebrahimi       preindex = kSRegSizeInBytes;
11566*f5c631daSSadaf Ebrahimi       data_length += preindex;
11567*f5c631daSSadaf Ebrahimi 
11568*f5c631daSSadaf Ebrahimi       {
11569*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11570*f5c631daSSadaf Ebrahimi         __ ldrh(w2, MemOperand(x0, preindex, PreIndex));
11571*f5c631daSSadaf Ebrahimi         __ strh(w2, MemOperand(x1, preindex, PreIndex));
11572*f5c631daSSadaf Ebrahimi       }
11573*f5c631daSSadaf Ebrahimi       preindex = 2;
11574*f5c631daSSadaf Ebrahimi       data_length += preindex;
11575*f5c631daSSadaf Ebrahimi 
11576*f5c631daSSadaf Ebrahimi       {
11577*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11578*f5c631daSSadaf Ebrahimi         __ ldrsh(w2, MemOperand(x0, preindex, PreIndex));
11579*f5c631daSSadaf Ebrahimi         __ strh(w2, MemOperand(x1, preindex, PreIndex));
11580*f5c631daSSadaf Ebrahimi       }
11581*f5c631daSSadaf Ebrahimi       preindex = 2;
11582*f5c631daSSadaf Ebrahimi       data_length += preindex;
11583*f5c631daSSadaf Ebrahimi 
11584*f5c631daSSadaf Ebrahimi       {
11585*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11586*f5c631daSSadaf Ebrahimi         __ ldrb(w2, MemOperand(x0, preindex, PreIndex));
11587*f5c631daSSadaf Ebrahimi         __ strb(w2, MemOperand(x1, preindex, PreIndex));
11588*f5c631daSSadaf Ebrahimi       }
11589*f5c631daSSadaf Ebrahimi       preindex = 1;
11590*f5c631daSSadaf Ebrahimi       data_length += preindex;
11591*f5c631daSSadaf Ebrahimi 
11592*f5c631daSSadaf Ebrahimi       {
11593*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11594*f5c631daSSadaf Ebrahimi         __ ldrsb(w2, MemOperand(x0, preindex, PreIndex));
11595*f5c631daSSadaf Ebrahimi         __ strb(w2, MemOperand(x1, preindex, PreIndex));
11596*f5c631daSSadaf Ebrahimi       }
11597*f5c631daSSadaf Ebrahimi       preindex = 1;
11598*f5c631daSSadaf Ebrahimi       data_length += preindex;
11599*f5c631daSSadaf Ebrahimi 
11600*f5c631daSSadaf Ebrahimi       VIXL_ASSERT(kMaxDataLength >= data_length);
11601*f5c631daSSadaf Ebrahimi 
11602*f5c631daSSadaf Ebrahimi       END();
11603*f5c631daSSadaf Ebrahimi       if (CAN_RUN()) {
11604*f5c631daSSadaf Ebrahimi         RUN();
11605*f5c631daSSadaf Ebrahimi 
11606*f5c631daSSadaf Ebrahimi         // Check that the preindex was correctly applied in each operation, and
11607*f5c631daSSadaf Ebrahimi         // that the tag was preserved.
11608*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(src_tagged + data_length - preindex, x0);
11609*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(dst_tagged + data_length - preindex, x1);
11610*f5c631daSSadaf Ebrahimi 
11611*f5c631daSSadaf Ebrahimi         for (int k = 0; k < data_length; k++) {
11612*f5c631daSSadaf Ebrahimi           VIXL_CHECK(src[k] == dst[k]);
11613*f5c631daSSadaf Ebrahimi         }
11614*f5c631daSSadaf Ebrahimi       }
11615*f5c631daSSadaf Ebrahimi     }
11616*f5c631daSSadaf Ebrahimi   }
11617*f5c631daSSadaf Ebrahimi }
11618*f5c631daSSadaf Ebrahimi 
11619*f5c631daSSadaf Ebrahimi 
TEST(load_store_tagged_immediate_postindex)11620*f5c631daSSadaf Ebrahimi TEST(load_store_tagged_immediate_postindex) {
11621*f5c631daSSadaf Ebrahimi   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11622*f5c631daSSadaf Ebrahimi   int tag_count = sizeof(tags) / sizeof(tags[0]);
11623*f5c631daSSadaf Ebrahimi 
11624*f5c631daSSadaf Ebrahimi   const int kMaxDataLength = 128;
11625*f5c631daSSadaf Ebrahimi 
11626*f5c631daSSadaf Ebrahimi   for (int i = 0; i < tag_count; i++) {
11627*f5c631daSSadaf Ebrahimi     unsigned char src[kMaxDataLength];
11628*f5c631daSSadaf Ebrahimi     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11629*f5c631daSSadaf Ebrahimi     uint64_t src_tag = tags[i];
11630*f5c631daSSadaf Ebrahimi     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11631*f5c631daSSadaf Ebrahimi 
11632*f5c631daSSadaf Ebrahimi     for (int k = 0; k < kMaxDataLength; k++) {
11633*f5c631daSSadaf Ebrahimi       src[k] = k + 1;
11634*f5c631daSSadaf Ebrahimi     }
11635*f5c631daSSadaf Ebrahimi 
11636*f5c631daSSadaf Ebrahimi     for (int j = 0; j < tag_count; j++) {
11637*f5c631daSSadaf Ebrahimi       unsigned char dst[kMaxDataLength];
11638*f5c631daSSadaf Ebrahimi       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11639*f5c631daSSadaf Ebrahimi       uint64_t dst_tag = tags[j];
11640*f5c631daSSadaf Ebrahimi       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11641*f5c631daSSadaf Ebrahimi 
11642*f5c631daSSadaf Ebrahimi       for (int k = 0; k < kMaxDataLength; k++) {
11643*f5c631daSSadaf Ebrahimi         dst[k] = 0;
11644*f5c631daSSadaf Ebrahimi       }
11645*f5c631daSSadaf Ebrahimi 
11646*f5c631daSSadaf Ebrahimi       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11647*f5c631daSSadaf Ebrahimi       START();
11648*f5c631daSSadaf Ebrahimi 
11649*f5c631daSSadaf Ebrahimi       int postindex = 2 * kXRegSizeInBytes;
11650*f5c631daSSadaf Ebrahimi       int data_length = 0;
11651*f5c631daSSadaf Ebrahimi 
11652*f5c631daSSadaf Ebrahimi       __ Mov(x0, src_tagged);
11653*f5c631daSSadaf Ebrahimi       __ Mov(x1, dst_tagged);
11654*f5c631daSSadaf Ebrahimi 
11655*f5c631daSSadaf Ebrahimi       {
11656*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11657*f5c631daSSadaf Ebrahimi         __ ldp(x2, x3, MemOperand(x0, postindex, PostIndex));
11658*f5c631daSSadaf Ebrahimi         __ stp(x2, x3, MemOperand(x1, postindex, PostIndex));
11659*f5c631daSSadaf Ebrahimi       }
11660*f5c631daSSadaf Ebrahimi       data_length = postindex;
11661*f5c631daSSadaf Ebrahimi 
11662*f5c631daSSadaf Ebrahimi       postindex = 2 * kQRegSizeInBytes;
11663*f5c631daSSadaf Ebrahimi       {
11664*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11665*f5c631daSSadaf Ebrahimi         __ ldp(q0, q1, MemOperand(x0, postindex, PostIndex));
11666*f5c631daSSadaf Ebrahimi         __ stp(q0, q1, MemOperand(x1, postindex, PostIndex));
11667*f5c631daSSadaf Ebrahimi       }
11668*f5c631daSSadaf Ebrahimi       data_length += postindex;
11669*f5c631daSSadaf Ebrahimi 
11670*f5c631daSSadaf Ebrahimi       postindex = 2 * kWRegSizeInBytes;
11671*f5c631daSSadaf Ebrahimi       {
11672*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11673*f5c631daSSadaf Ebrahimi         __ ldpsw(x2, x3, MemOperand(x0, postindex, PostIndex));
11674*f5c631daSSadaf Ebrahimi         __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
11675*f5c631daSSadaf Ebrahimi       }
11676*f5c631daSSadaf Ebrahimi       data_length += postindex;
11677*f5c631daSSadaf Ebrahimi 
11678*f5c631daSSadaf Ebrahimi       postindex = 2 * kDRegSizeInBytes;
11679*f5c631daSSadaf Ebrahimi       {
11680*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11681*f5c631daSSadaf Ebrahimi         __ ldp(d0, d1, MemOperand(x0, postindex, PostIndex));
11682*f5c631daSSadaf Ebrahimi         __ stp(d0, d1, MemOperand(x1, postindex, PostIndex));
11683*f5c631daSSadaf Ebrahimi       }
11684*f5c631daSSadaf Ebrahimi       data_length += postindex;
11685*f5c631daSSadaf Ebrahimi 
11686*f5c631daSSadaf Ebrahimi       postindex = 2 * kWRegSizeInBytes;
11687*f5c631daSSadaf Ebrahimi       {
11688*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11689*f5c631daSSadaf Ebrahimi         __ ldp(w2, w3, MemOperand(x0, postindex, PostIndex));
11690*f5c631daSSadaf Ebrahimi         __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
11691*f5c631daSSadaf Ebrahimi       }
11692*f5c631daSSadaf Ebrahimi       data_length += postindex;
11693*f5c631daSSadaf Ebrahimi 
11694*f5c631daSSadaf Ebrahimi       postindex = 2 * kSRegSizeInBytes;
11695*f5c631daSSadaf Ebrahimi       {
11696*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11697*f5c631daSSadaf Ebrahimi         __ ldp(s0, s1, MemOperand(x0, postindex, PostIndex));
11698*f5c631daSSadaf Ebrahimi         __ stp(s0, s1, MemOperand(x1, postindex, PostIndex));
11699*f5c631daSSadaf Ebrahimi       }
11700*f5c631daSSadaf Ebrahimi       data_length += postindex;
11701*f5c631daSSadaf Ebrahimi 
11702*f5c631daSSadaf Ebrahimi       postindex = kXRegSizeInBytes;
11703*f5c631daSSadaf Ebrahimi       {
11704*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11705*f5c631daSSadaf Ebrahimi         __ ldr(x2, MemOperand(x0, postindex, PostIndex));
11706*f5c631daSSadaf Ebrahimi         __ str(x2, MemOperand(x1, postindex, PostIndex));
11707*f5c631daSSadaf Ebrahimi       }
11708*f5c631daSSadaf Ebrahimi       data_length += postindex;
11709*f5c631daSSadaf Ebrahimi 
11710*f5c631daSSadaf Ebrahimi       postindex = kDRegSizeInBytes;
11711*f5c631daSSadaf Ebrahimi       {
11712*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11713*f5c631daSSadaf Ebrahimi         __ ldr(d0, MemOperand(x0, postindex, PostIndex));
11714*f5c631daSSadaf Ebrahimi         __ str(d0, MemOperand(x1, postindex, PostIndex));
11715*f5c631daSSadaf Ebrahimi       }
11716*f5c631daSSadaf Ebrahimi       data_length += postindex;
11717*f5c631daSSadaf Ebrahimi 
11718*f5c631daSSadaf Ebrahimi       postindex = kWRegSizeInBytes;
11719*f5c631daSSadaf Ebrahimi       {
11720*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11721*f5c631daSSadaf Ebrahimi         __ ldr(w2, MemOperand(x0, postindex, PostIndex));
11722*f5c631daSSadaf Ebrahimi         __ str(w2, MemOperand(x1, postindex, PostIndex));
11723*f5c631daSSadaf Ebrahimi       }
11724*f5c631daSSadaf Ebrahimi       data_length += postindex;
11725*f5c631daSSadaf Ebrahimi 
11726*f5c631daSSadaf Ebrahimi       postindex = kSRegSizeInBytes;
11727*f5c631daSSadaf Ebrahimi       {
11728*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11729*f5c631daSSadaf Ebrahimi         __ ldr(s0, MemOperand(x0, postindex, PostIndex));
11730*f5c631daSSadaf Ebrahimi         __ str(s0, MemOperand(x1, postindex, PostIndex));
11731*f5c631daSSadaf Ebrahimi       }
11732*f5c631daSSadaf Ebrahimi       data_length += postindex;
11733*f5c631daSSadaf Ebrahimi 
11734*f5c631daSSadaf Ebrahimi       postindex = 2;
11735*f5c631daSSadaf Ebrahimi       {
11736*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11737*f5c631daSSadaf Ebrahimi         __ ldrh(w2, MemOperand(x0, postindex, PostIndex));
11738*f5c631daSSadaf Ebrahimi         __ strh(w2, MemOperand(x1, postindex, PostIndex));
11739*f5c631daSSadaf Ebrahimi       }
11740*f5c631daSSadaf Ebrahimi       data_length += postindex;
11741*f5c631daSSadaf Ebrahimi 
11742*f5c631daSSadaf Ebrahimi       postindex = 2;
11743*f5c631daSSadaf Ebrahimi       {
11744*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11745*f5c631daSSadaf Ebrahimi         __ ldrsh(w2, MemOperand(x0, postindex, PostIndex));
11746*f5c631daSSadaf Ebrahimi         __ strh(w2, MemOperand(x1, postindex, PostIndex));
11747*f5c631daSSadaf Ebrahimi       }
11748*f5c631daSSadaf Ebrahimi       data_length += postindex;
11749*f5c631daSSadaf Ebrahimi 
11750*f5c631daSSadaf Ebrahimi       postindex = 1;
11751*f5c631daSSadaf Ebrahimi       {
11752*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11753*f5c631daSSadaf Ebrahimi         __ ldrb(w2, MemOperand(x0, postindex, PostIndex));
11754*f5c631daSSadaf Ebrahimi         __ strb(w2, MemOperand(x1, postindex, PostIndex));
11755*f5c631daSSadaf Ebrahimi       }
11756*f5c631daSSadaf Ebrahimi       data_length += postindex;
11757*f5c631daSSadaf Ebrahimi 
11758*f5c631daSSadaf Ebrahimi       postindex = 1;
11759*f5c631daSSadaf Ebrahimi       {
11760*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11761*f5c631daSSadaf Ebrahimi         __ ldrsb(w2, MemOperand(x0, postindex, PostIndex));
11762*f5c631daSSadaf Ebrahimi         __ strb(w2, MemOperand(x1, postindex, PostIndex));
11763*f5c631daSSadaf Ebrahimi       }
11764*f5c631daSSadaf Ebrahimi       data_length += postindex;
11765*f5c631daSSadaf Ebrahimi 
11766*f5c631daSSadaf Ebrahimi       VIXL_ASSERT(kMaxDataLength >= data_length);
11767*f5c631daSSadaf Ebrahimi 
11768*f5c631daSSadaf Ebrahimi       END();
11769*f5c631daSSadaf Ebrahimi       if (CAN_RUN()) {
11770*f5c631daSSadaf Ebrahimi         RUN();
11771*f5c631daSSadaf Ebrahimi 
11772*f5c631daSSadaf Ebrahimi         // Check that the postindex was correctly applied in each operation, and
11773*f5c631daSSadaf Ebrahimi         // that the tag was preserved.
11774*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(src_tagged + data_length, x0);
11775*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(dst_tagged + data_length, x1);
11776*f5c631daSSadaf Ebrahimi 
11777*f5c631daSSadaf Ebrahimi         for (int k = 0; k < data_length; k++) {
11778*f5c631daSSadaf Ebrahimi           VIXL_CHECK(src[k] == dst[k]);
11779*f5c631daSSadaf Ebrahimi         }
11780*f5c631daSSadaf Ebrahimi       }
11781*f5c631daSSadaf Ebrahimi     }
11782*f5c631daSSadaf Ebrahimi   }
11783*f5c631daSSadaf Ebrahimi }
11784*f5c631daSSadaf Ebrahimi 
11785*f5c631daSSadaf Ebrahimi 
TEST(load_store_tagged_register_offset)11786*f5c631daSSadaf Ebrahimi TEST(load_store_tagged_register_offset) {
11787*f5c631daSSadaf Ebrahimi   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11788*f5c631daSSadaf Ebrahimi   int tag_count = sizeof(tags) / sizeof(tags[0]);
11789*f5c631daSSadaf Ebrahimi 
11790*f5c631daSSadaf Ebrahimi   const int kMaxDataLength = 128;
11791*f5c631daSSadaf Ebrahimi 
11792*f5c631daSSadaf Ebrahimi   for (int i = 0; i < tag_count; i++) {
11793*f5c631daSSadaf Ebrahimi     unsigned char src[kMaxDataLength];
11794*f5c631daSSadaf Ebrahimi     uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11795*f5c631daSSadaf Ebrahimi     uint64_t src_tag = tags[i];
11796*f5c631daSSadaf Ebrahimi     uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11797*f5c631daSSadaf Ebrahimi 
11798*f5c631daSSadaf Ebrahimi     for (int k = 0; k < kMaxDataLength; k++) {
11799*f5c631daSSadaf Ebrahimi       src[k] = k + 1;
11800*f5c631daSSadaf Ebrahimi     }
11801*f5c631daSSadaf Ebrahimi 
11802*f5c631daSSadaf Ebrahimi     for (int j = 0; j < tag_count; j++) {
11803*f5c631daSSadaf Ebrahimi       unsigned char dst[kMaxDataLength];
11804*f5c631daSSadaf Ebrahimi       uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11805*f5c631daSSadaf Ebrahimi       uint64_t dst_tag = tags[j];
11806*f5c631daSSadaf Ebrahimi       uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11807*f5c631daSSadaf Ebrahimi 
11808*f5c631daSSadaf Ebrahimi       // Also tag the offset register; the operation should still succeed.
11809*f5c631daSSadaf Ebrahimi       for (int o = 0; o < tag_count; o++) {
11810*f5c631daSSadaf Ebrahimi         uint64_t offset_base = CPU::SetPointerTag(UINT64_C(0), tags[o]);
11811*f5c631daSSadaf Ebrahimi         int data_length = 0;
11812*f5c631daSSadaf Ebrahimi 
11813*f5c631daSSadaf Ebrahimi         for (int k = 0; k < kMaxDataLength; k++) {
11814*f5c631daSSadaf Ebrahimi           dst[k] = 0;
11815*f5c631daSSadaf Ebrahimi         }
11816*f5c631daSSadaf Ebrahimi 
11817*f5c631daSSadaf Ebrahimi         SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11818*f5c631daSSadaf Ebrahimi         START();
11819*f5c631daSSadaf Ebrahimi 
11820*f5c631daSSadaf Ebrahimi         __ Mov(x0, src_tagged);
11821*f5c631daSSadaf Ebrahimi         __ Mov(x1, dst_tagged);
11822*f5c631daSSadaf Ebrahimi 
11823*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11824*f5c631daSSadaf Ebrahimi         {
11825*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11826*f5c631daSSadaf Ebrahimi           __ ldr(x2, MemOperand(x0, x10));
11827*f5c631daSSadaf Ebrahimi           __ str(x2, MemOperand(x1, x10));
11828*f5c631daSSadaf Ebrahimi         }
11829*f5c631daSSadaf Ebrahimi         data_length += kXRegSizeInBytes;
11830*f5c631daSSadaf Ebrahimi 
11831*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11832*f5c631daSSadaf Ebrahimi         {
11833*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11834*f5c631daSSadaf Ebrahimi           __ ldr(d0, MemOperand(x0, x10));
11835*f5c631daSSadaf Ebrahimi           __ str(d0, MemOperand(x1, x10));
11836*f5c631daSSadaf Ebrahimi         }
11837*f5c631daSSadaf Ebrahimi         data_length += kDRegSizeInBytes;
11838*f5c631daSSadaf Ebrahimi 
11839*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11840*f5c631daSSadaf Ebrahimi         {
11841*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11842*f5c631daSSadaf Ebrahimi           __ ldr(w2, MemOperand(x0, x10));
11843*f5c631daSSadaf Ebrahimi           __ str(w2, MemOperand(x1, x10));
11844*f5c631daSSadaf Ebrahimi         }
11845*f5c631daSSadaf Ebrahimi         data_length += kWRegSizeInBytes;
11846*f5c631daSSadaf Ebrahimi 
11847*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11848*f5c631daSSadaf Ebrahimi         {
11849*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11850*f5c631daSSadaf Ebrahimi           __ ldr(s0, MemOperand(x0, x10));
11851*f5c631daSSadaf Ebrahimi           __ str(s0, MemOperand(x1, x10));
11852*f5c631daSSadaf Ebrahimi         }
11853*f5c631daSSadaf Ebrahimi         data_length += kSRegSizeInBytes;
11854*f5c631daSSadaf Ebrahimi 
11855*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11856*f5c631daSSadaf Ebrahimi         {
11857*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11858*f5c631daSSadaf Ebrahimi           __ ldrh(w2, MemOperand(x0, x10));
11859*f5c631daSSadaf Ebrahimi           __ strh(w2, MemOperand(x1, x10));
11860*f5c631daSSadaf Ebrahimi         }
11861*f5c631daSSadaf Ebrahimi         data_length += 2;
11862*f5c631daSSadaf Ebrahimi 
11863*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11864*f5c631daSSadaf Ebrahimi         {
11865*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11866*f5c631daSSadaf Ebrahimi           __ ldrsh(w2, MemOperand(x0, x10));
11867*f5c631daSSadaf Ebrahimi           __ strh(w2, MemOperand(x1, x10));
11868*f5c631daSSadaf Ebrahimi         }
11869*f5c631daSSadaf Ebrahimi         data_length += 2;
11870*f5c631daSSadaf Ebrahimi 
11871*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11872*f5c631daSSadaf Ebrahimi         {
11873*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11874*f5c631daSSadaf Ebrahimi           __ ldrb(w2, MemOperand(x0, x10));
11875*f5c631daSSadaf Ebrahimi           __ strb(w2, MemOperand(x1, x10));
11876*f5c631daSSadaf Ebrahimi         }
11877*f5c631daSSadaf Ebrahimi         data_length += 1;
11878*f5c631daSSadaf Ebrahimi 
11879*f5c631daSSadaf Ebrahimi         __ Mov(x10, offset_base + data_length);
11880*f5c631daSSadaf Ebrahimi         {
11881*f5c631daSSadaf Ebrahimi           ExactAssemblyScope scope(&masm, 2 * kInstructionSize);
11882*f5c631daSSadaf Ebrahimi           __ ldrsb(w2, MemOperand(x0, x10));
11883*f5c631daSSadaf Ebrahimi           __ strb(w2, MemOperand(x1, x10));
11884*f5c631daSSadaf Ebrahimi         }
11885*f5c631daSSadaf Ebrahimi         data_length += 1;
11886*f5c631daSSadaf Ebrahimi 
11887*f5c631daSSadaf Ebrahimi         VIXL_ASSERT(kMaxDataLength >= data_length);
11888*f5c631daSSadaf Ebrahimi 
11889*f5c631daSSadaf Ebrahimi         END();
11890*f5c631daSSadaf Ebrahimi         if (CAN_RUN()) {
11891*f5c631daSSadaf Ebrahimi           RUN();
11892*f5c631daSSadaf Ebrahimi 
11893*f5c631daSSadaf Ebrahimi           // Check that the postindex was correctly applied in each operation,
11894*f5c631daSSadaf Ebrahimi           // and that the tag was preserved.
11895*f5c631daSSadaf Ebrahimi           ASSERT_EQUAL_64(src_tagged, x0);
11896*f5c631daSSadaf Ebrahimi           ASSERT_EQUAL_64(dst_tagged, x1);
11897*f5c631daSSadaf Ebrahimi           ASSERT_EQUAL_64(offset_base + data_length - 1, x10);
11898*f5c631daSSadaf Ebrahimi 
11899*f5c631daSSadaf Ebrahimi           for (int k = 0; k < data_length; k++) {
11900*f5c631daSSadaf Ebrahimi             VIXL_CHECK(src[k] == dst[k]);
11901*f5c631daSSadaf Ebrahimi           }
11902*f5c631daSSadaf Ebrahimi         }
11903*f5c631daSSadaf Ebrahimi       }
11904*f5c631daSSadaf Ebrahimi     }
11905*f5c631daSSadaf Ebrahimi   }
11906*f5c631daSSadaf Ebrahimi }
11907*f5c631daSSadaf Ebrahimi 
11908*f5c631daSSadaf Ebrahimi 
TEST(load_store_tagged_register_postindex)11909*f5c631daSSadaf Ebrahimi TEST(load_store_tagged_register_postindex) {
11910*f5c631daSSadaf Ebrahimi   uint64_t src[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
11911*f5c631daSSadaf Ebrahimi   uint64_t tags[] = {0x00, 0x1, 0x55, 0xff};
11912*f5c631daSSadaf Ebrahimi   int tag_count = sizeof(tags) / sizeof(tags[0]);
11913*f5c631daSSadaf Ebrahimi 
11914*f5c631daSSadaf Ebrahimi   for (int j = 0; j < tag_count; j++) {
11915*f5c631daSSadaf Ebrahimi     for (int i = 0; i < tag_count; i++) {
11916*f5c631daSSadaf Ebrahimi       SETUP_WITH_FEATURES(CPUFeatures::kNEON);
11917*f5c631daSSadaf Ebrahimi 
11918*f5c631daSSadaf Ebrahimi       uint64_t src_base = reinterpret_cast<uint64_t>(src);
11919*f5c631daSSadaf Ebrahimi       uint64_t src_tagged = CPU::SetPointerTag(src_base, tags[i]);
11920*f5c631daSSadaf Ebrahimi       uint64_t offset_tagged = CPU::SetPointerTag(UINT64_C(0), tags[j]);
11921*f5c631daSSadaf Ebrahimi 
11922*f5c631daSSadaf Ebrahimi       START();
11923*f5c631daSSadaf Ebrahimi       __ Mov(x10, src_tagged);
11924*f5c631daSSadaf Ebrahimi       __ Mov(x11, offset_tagged);
11925*f5c631daSSadaf Ebrahimi       __ Ld1(v0.V16B(), MemOperand(x10, x11, PostIndex));
11926*f5c631daSSadaf Ebrahimi       // TODO: add other instructions (ld2-4, st1-4) as they become available.
11927*f5c631daSSadaf Ebrahimi       END();
11928*f5c631daSSadaf Ebrahimi 
11929*f5c631daSSadaf Ebrahimi       if (CAN_RUN()) {
11930*f5c631daSSadaf Ebrahimi         RUN();
11931*f5c631daSSadaf Ebrahimi 
11932*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_128(0x0f0e0d0c0b0a0908, 0x0706050403020100, q0);
11933*f5c631daSSadaf Ebrahimi         ASSERT_EQUAL_64(src_tagged + offset_tagged, x10);
11934*f5c631daSSadaf Ebrahimi       }
11935*f5c631daSSadaf Ebrahimi     }
11936*f5c631daSSadaf Ebrahimi   }
11937*f5c631daSSadaf Ebrahimi }
11938*f5c631daSSadaf Ebrahimi 
11939*f5c631daSSadaf Ebrahimi 
TEST(branch_tagged)11940*f5c631daSSadaf Ebrahimi TEST(branch_tagged) {
11941*f5c631daSSadaf Ebrahimi   SETUP();
11942*f5c631daSSadaf Ebrahimi   START();
11943*f5c631daSSadaf Ebrahimi 
11944*f5c631daSSadaf Ebrahimi   Label loop, loop_entry, done;
11945*f5c631daSSadaf Ebrahimi   __ Adr(x0, &loop);
11946*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
11947*f5c631daSSadaf Ebrahimi   __ B(&loop_entry);
11948*f5c631daSSadaf Ebrahimi 
11949*f5c631daSSadaf Ebrahimi   __ Bind(&loop);
11950*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);  // Count successful jumps.
11951*f5c631daSSadaf Ebrahimi 
11952*f5c631daSSadaf Ebrahimi   // Advance to the next tag, then bail out if we've come back around to tag 0.
11953*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
11954*f5c631daSSadaf Ebrahimi   __ Tst(x0, kAddressTagMask);
11955*f5c631daSSadaf Ebrahimi   __ B(eq, &done);
11956*f5c631daSSadaf Ebrahimi 
11957*f5c631daSSadaf Ebrahimi   __ Bind(&loop_entry);
11958*f5c631daSSadaf Ebrahimi   __ Br(x0);
11959*f5c631daSSadaf Ebrahimi 
11960*f5c631daSSadaf Ebrahimi   __ Bind(&done);
11961*f5c631daSSadaf Ebrahimi 
11962*f5c631daSSadaf Ebrahimi   END();
11963*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
11964*f5c631daSSadaf Ebrahimi     RUN();
11965*f5c631daSSadaf Ebrahimi 
11966*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
11967*f5c631daSSadaf Ebrahimi   }
11968*f5c631daSSadaf Ebrahimi }
11969*f5c631daSSadaf Ebrahimi 
11970*f5c631daSSadaf Ebrahimi 
TEST(branch_and_link_tagged)11971*f5c631daSSadaf Ebrahimi TEST(branch_and_link_tagged) {
11972*f5c631daSSadaf Ebrahimi   SETUP();
11973*f5c631daSSadaf Ebrahimi   START();
11974*f5c631daSSadaf Ebrahimi 
11975*f5c631daSSadaf Ebrahimi   Label loop, loop_entry, done;
11976*f5c631daSSadaf Ebrahimi   __ Adr(x0, &loop);
11977*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
11978*f5c631daSSadaf Ebrahimi   __ B(&loop_entry);
11979*f5c631daSSadaf Ebrahimi 
11980*f5c631daSSadaf Ebrahimi   __ Bind(&loop);
11981*f5c631daSSadaf Ebrahimi 
11982*f5c631daSSadaf Ebrahimi   // Bail out (before counting a successful jump) if lr appears to be tagged.
11983*f5c631daSSadaf Ebrahimi   __ Tst(lr, kAddressTagMask);
11984*f5c631daSSadaf Ebrahimi   __ B(ne, &done);
11985*f5c631daSSadaf Ebrahimi 
11986*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);  // Count successful jumps.
11987*f5c631daSSadaf Ebrahimi 
11988*f5c631daSSadaf Ebrahimi   // Advance to the next tag, then bail out if we've come back around to tag 0.
11989*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
11990*f5c631daSSadaf Ebrahimi   __ Tst(x0, kAddressTagMask);
11991*f5c631daSSadaf Ebrahimi   __ B(eq, &done);
11992*f5c631daSSadaf Ebrahimi 
11993*f5c631daSSadaf Ebrahimi   __ Bind(&loop_entry);
11994*f5c631daSSadaf Ebrahimi   __ Blr(x0);
11995*f5c631daSSadaf Ebrahimi 
11996*f5c631daSSadaf Ebrahimi   __ Bind(&done);
11997*f5c631daSSadaf Ebrahimi 
11998*f5c631daSSadaf Ebrahimi   END();
11999*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12000*f5c631daSSadaf Ebrahimi     RUN();
12001*f5c631daSSadaf Ebrahimi 
12002*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12003*f5c631daSSadaf Ebrahimi   }
12004*f5c631daSSadaf Ebrahimi }
12005*f5c631daSSadaf Ebrahimi 
12006*f5c631daSSadaf Ebrahimi 
TEST(branch_tagged_and_adr_adrp)12007*f5c631daSSadaf Ebrahimi TEST(branch_tagged_and_adr_adrp) {
12008*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM(kPageSize, PageOffsetDependentCode);
12009*f5c631daSSadaf Ebrahimi   START();
12010*f5c631daSSadaf Ebrahimi 
12011*f5c631daSSadaf Ebrahimi   Label loop, loop_entry, done;
12012*f5c631daSSadaf Ebrahimi   __ Adr(x0, &loop);
12013*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
12014*f5c631daSSadaf Ebrahimi   __ B(&loop_entry);
12015*f5c631daSSadaf Ebrahimi 
12016*f5c631daSSadaf Ebrahimi   __ Bind(&loop);
12017*f5c631daSSadaf Ebrahimi 
12018*f5c631daSSadaf Ebrahimi   // Bail out (before counting a successful jump) if `adr x10, ...` is tagged.
12019*f5c631daSSadaf Ebrahimi   __ Adr(x10, &done);
12020*f5c631daSSadaf Ebrahimi   __ Tst(x10, kAddressTagMask);
12021*f5c631daSSadaf Ebrahimi   __ B(ne, &done);
12022*f5c631daSSadaf Ebrahimi 
12023*f5c631daSSadaf Ebrahimi   // Bail out (before counting a successful jump) if `adrp x11, ...` is tagged.
12024*f5c631daSSadaf Ebrahimi   __ Adrp(x11, &done);
12025*f5c631daSSadaf Ebrahimi   __ Tst(x11, kAddressTagMask);
12026*f5c631daSSadaf Ebrahimi   __ B(ne, &done);
12027*f5c631daSSadaf Ebrahimi 
12028*f5c631daSSadaf Ebrahimi   __ Add(x1, x1, 1);  // Count successful iterations.
12029*f5c631daSSadaf Ebrahimi 
12030*f5c631daSSadaf Ebrahimi   // Advance to the next tag, then bail out if we've come back around to tag 0.
12031*f5c631daSSadaf Ebrahimi   __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
12032*f5c631daSSadaf Ebrahimi   __ Tst(x0, kAddressTagMask);
12033*f5c631daSSadaf Ebrahimi   __ B(eq, &done);
12034*f5c631daSSadaf Ebrahimi 
12035*f5c631daSSadaf Ebrahimi   __ Bind(&loop_entry);
12036*f5c631daSSadaf Ebrahimi   __ Br(x0);
12037*f5c631daSSadaf Ebrahimi 
12038*f5c631daSSadaf Ebrahimi   __ Bind(&done);
12039*f5c631daSSadaf Ebrahimi 
12040*f5c631daSSadaf Ebrahimi   END();
12041*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12042*f5c631daSSadaf Ebrahimi     RUN();
12043*f5c631daSSadaf Ebrahimi 
12044*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
12045*f5c631daSSadaf Ebrahimi   }
12046*f5c631daSSadaf Ebrahimi }
12047*f5c631daSSadaf Ebrahimi 
TEST(system_sys)12048*f5c631daSSadaf Ebrahimi TEST(system_sys) {
12049*f5c631daSSadaf Ebrahimi   SETUP();
12050*f5c631daSSadaf Ebrahimi   const char* msg = "SYS test!";
12051*f5c631daSSadaf Ebrahimi   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12052*f5c631daSSadaf Ebrahimi 
12053*f5c631daSSadaf Ebrahimi   START();
12054*f5c631daSSadaf Ebrahimi   __ Mov(x4, msg_addr);
12055*f5c631daSSadaf Ebrahimi   __ Sys(3, 0x7, 0x5, 1, x4);
12056*f5c631daSSadaf Ebrahimi   __ Mov(x3, x4);
12057*f5c631daSSadaf Ebrahimi   __ Sys(3, 0x7, 0xa, 1, x3);
12058*f5c631daSSadaf Ebrahimi   __ Mov(x2, x3);
12059*f5c631daSSadaf Ebrahimi   __ Sys(3, 0x7, 0xb, 1, x2);
12060*f5c631daSSadaf Ebrahimi   __ Mov(x1, x2);
12061*f5c631daSSadaf Ebrahimi   __ Sys(3, 0x7, 0xe, 1, x1);
12062*f5c631daSSadaf Ebrahimi   // TODO: Add tests to check ZVA equivalent.
12063*f5c631daSSadaf Ebrahimi   END();
12064*f5c631daSSadaf Ebrahimi 
12065*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12066*f5c631daSSadaf Ebrahimi     RUN();
12067*f5c631daSSadaf Ebrahimi   }
12068*f5c631daSSadaf Ebrahimi }
12069*f5c631daSSadaf Ebrahimi 
12070*f5c631daSSadaf Ebrahimi 
TEST(system_ic)12071*f5c631daSSadaf Ebrahimi TEST(system_ic) {
12072*f5c631daSSadaf Ebrahimi   SETUP();
12073*f5c631daSSadaf Ebrahimi   const char* msg = "IC test!";
12074*f5c631daSSadaf Ebrahimi   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12075*f5c631daSSadaf Ebrahimi 
12076*f5c631daSSadaf Ebrahimi   START();
12077*f5c631daSSadaf Ebrahimi   __ Mov(x11, msg_addr);
12078*f5c631daSSadaf Ebrahimi   __ Ic(IVAU, x11);
12079*f5c631daSSadaf Ebrahimi   END();
12080*f5c631daSSadaf Ebrahimi 
12081*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12082*f5c631daSSadaf Ebrahimi     RUN();
12083*f5c631daSSadaf Ebrahimi   }
12084*f5c631daSSadaf Ebrahimi }
12085*f5c631daSSadaf Ebrahimi 
12086*f5c631daSSadaf Ebrahimi 
TEST(system_dc)12087*f5c631daSSadaf Ebrahimi TEST(system_dc) {
12088*f5c631daSSadaf Ebrahimi   SETUP();
12089*f5c631daSSadaf Ebrahimi   const char* msg = "DC test!";
12090*f5c631daSSadaf Ebrahimi   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12091*f5c631daSSadaf Ebrahimi 
12092*f5c631daSSadaf Ebrahimi   START();
12093*f5c631daSSadaf Ebrahimi   __ Mov(x20, msg_addr);
12094*f5c631daSSadaf Ebrahimi   __ Dc(CVAC, x20);
12095*f5c631daSSadaf Ebrahimi   __ Mov(x21, msg_addr);
12096*f5c631daSSadaf Ebrahimi   __ Dc(CVAU, x21);
12097*f5c631daSSadaf Ebrahimi   __ Mov(x22, msg_addr);
12098*f5c631daSSadaf Ebrahimi   __ Dc(CIVAC, x22);
12099*f5c631daSSadaf Ebrahimi   // TODO: Add tests to check ZVA.
12100*f5c631daSSadaf Ebrahimi   END();
12101*f5c631daSSadaf Ebrahimi 
12102*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12103*f5c631daSSadaf Ebrahimi     RUN();
12104*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(msg_addr, x20);
12105*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(msg_addr, x21);
12106*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(msg_addr, x22);
12107*f5c631daSSadaf Ebrahimi   }
12108*f5c631daSSadaf Ebrahimi }
12109*f5c631daSSadaf Ebrahimi 
12110*f5c631daSSadaf Ebrahimi 
TEST(system_dcpop)12111*f5c631daSSadaf Ebrahimi TEST(system_dcpop) {
12112*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kDCPoP);
12113*f5c631daSSadaf Ebrahimi   const char* msg = "DCPoP test!";
12114*f5c631daSSadaf Ebrahimi   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12115*f5c631daSSadaf Ebrahimi 
12116*f5c631daSSadaf Ebrahimi   START();
12117*f5c631daSSadaf Ebrahimi   __ Mov(x20, msg_addr);
12118*f5c631daSSadaf Ebrahimi   __ Dc(CVAP, x20);
12119*f5c631daSSadaf Ebrahimi   END();
12120*f5c631daSSadaf Ebrahimi 
12121*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12122*f5c631daSSadaf Ebrahimi     RUN();
12123*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(msg_addr, x20);
12124*f5c631daSSadaf Ebrahimi   }
12125*f5c631daSSadaf Ebrahimi }
12126*f5c631daSSadaf Ebrahimi 
TEST(system_dccvadp)12127*f5c631daSSadaf Ebrahimi TEST(system_dccvadp) {
12128*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kDCCVADP);
12129*f5c631daSSadaf Ebrahimi   const char* msg = "DCCVADP test!";
12130*f5c631daSSadaf Ebrahimi   uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg);
12131*f5c631daSSadaf Ebrahimi 
12132*f5c631daSSadaf Ebrahimi   START();
12133*f5c631daSSadaf Ebrahimi   __ Mov(x20, msg_addr);
12134*f5c631daSSadaf Ebrahimi   __ Dc(CVADP, x20);
12135*f5c631daSSadaf Ebrahimi   END();
12136*f5c631daSSadaf Ebrahimi 
12137*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12138*f5c631daSSadaf Ebrahimi     RUN();
12139*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(msg_addr, x20);
12140*f5c631daSSadaf Ebrahimi   }
12141*f5c631daSSadaf Ebrahimi }
12142*f5c631daSSadaf Ebrahimi 
12143*f5c631daSSadaf Ebrahimi 
12144*f5c631daSSadaf Ebrahimi // We currently disable tests for CRC32 instructions when running natively.
12145*f5c631daSSadaf Ebrahimi // Support for this family of instruction is optional, and so native platforms
12146*f5c631daSSadaf Ebrahimi // may simply fail to execute the test.
TEST(crc32b)12147*f5c631daSSadaf Ebrahimi TEST(crc32b) {
12148*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12149*f5c631daSSadaf Ebrahimi 
12150*f5c631daSSadaf Ebrahimi   START();
12151*f5c631daSSadaf Ebrahimi 
12152*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12153*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
12154*f5c631daSSadaf Ebrahimi   __ Crc32b(w10, w0, w1);
12155*f5c631daSSadaf Ebrahimi 
12156*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12157*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x138);
12158*f5c631daSSadaf Ebrahimi   __ Crc32b(w11, w0, w1);
12159*f5c631daSSadaf Ebrahimi 
12160*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12161*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x38);
12162*f5c631daSSadaf Ebrahimi   __ Crc32b(w12, w0, w1);
12163*f5c631daSSadaf Ebrahimi 
12164*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12165*f5c631daSSadaf Ebrahimi   __ Mov(w1, 128);
12166*f5c631daSSadaf Ebrahimi   __ Crc32b(w13, w0, w1);
12167*f5c631daSSadaf Ebrahimi 
12168*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12169*f5c631daSSadaf Ebrahimi   __ Mov(w1, 255);
12170*f5c631daSSadaf Ebrahimi   __ Crc32b(w14, w0, w1);
12171*f5c631daSSadaf Ebrahimi 
12172*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12173*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10001000);
12174*f5c631daSSadaf Ebrahimi   __ Crc32b(w15, w0, w1);
12175*f5c631daSSadaf Ebrahimi 
12176*f5c631daSSadaf Ebrahimi   END();
12177*f5c631daSSadaf Ebrahimi 
12178*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12179*f5c631daSSadaf Ebrahimi     RUN();
12180*f5c631daSSadaf Ebrahimi 
12181*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12182*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x5f058808, x11);
12183*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x5f058808, x12);
12184*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xedb88320, x13);
12185*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00ffffff, x14);
12186*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x77073196, x15);
12187*f5c631daSSadaf Ebrahimi   }
12188*f5c631daSSadaf Ebrahimi }
12189*f5c631daSSadaf Ebrahimi 
12190*f5c631daSSadaf Ebrahimi 
TEST(crc32h)12191*f5c631daSSadaf Ebrahimi TEST(crc32h) {
12192*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12193*f5c631daSSadaf Ebrahimi 
12194*f5c631daSSadaf Ebrahimi   START();
12195*f5c631daSSadaf Ebrahimi 
12196*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12197*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
12198*f5c631daSSadaf Ebrahimi   __ Crc32h(w10, w0, w1);
12199*f5c631daSSadaf Ebrahimi 
12200*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12201*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10038);
12202*f5c631daSSadaf Ebrahimi   __ Crc32h(w11, w0, w1);
12203*f5c631daSSadaf Ebrahimi 
12204*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12205*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x38);
12206*f5c631daSSadaf Ebrahimi   __ Crc32h(w12, w0, w1);
12207*f5c631daSSadaf Ebrahimi 
12208*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12209*f5c631daSSadaf Ebrahimi   __ Mov(w1, 128);
12210*f5c631daSSadaf Ebrahimi   __ Crc32h(w13, w0, w1);
12211*f5c631daSSadaf Ebrahimi 
12212*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12213*f5c631daSSadaf Ebrahimi   __ Mov(w1, 255);
12214*f5c631daSSadaf Ebrahimi   __ Crc32h(w14, w0, w1);
12215*f5c631daSSadaf Ebrahimi 
12216*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12217*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10001000);
12218*f5c631daSSadaf Ebrahimi   __ Crc32h(w15, w0, w1);
12219*f5c631daSSadaf Ebrahimi 
12220*f5c631daSSadaf Ebrahimi   END();
12221*f5c631daSSadaf Ebrahimi 
12222*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12223*f5c631daSSadaf Ebrahimi     RUN();
12224*f5c631daSSadaf Ebrahimi 
12225*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12226*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0e848dba, x11);
12227*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0e848dba, x12);
12228*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x3b83984b, x13);
12229*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x2d021072, x14);
12230*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x04ac2124, x15);
12231*f5c631daSSadaf Ebrahimi   }
12232*f5c631daSSadaf Ebrahimi }
12233*f5c631daSSadaf Ebrahimi 
12234*f5c631daSSadaf Ebrahimi 
TEST(crc32w)12235*f5c631daSSadaf Ebrahimi TEST(crc32w) {
12236*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12237*f5c631daSSadaf Ebrahimi 
12238*f5c631daSSadaf Ebrahimi   START();
12239*f5c631daSSadaf Ebrahimi 
12240*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12241*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
12242*f5c631daSSadaf Ebrahimi   __ Crc32w(w10, w0, w1);
12243*f5c631daSSadaf Ebrahimi 
12244*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12245*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x80000031);
12246*f5c631daSSadaf Ebrahimi   __ Crc32w(w11, w0, w1);
12247*f5c631daSSadaf Ebrahimi 
12248*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12249*f5c631daSSadaf Ebrahimi   __ Mov(w1, 128);
12250*f5c631daSSadaf Ebrahimi   __ Crc32w(w13, w0, w1);
12251*f5c631daSSadaf Ebrahimi 
12252*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12253*f5c631daSSadaf Ebrahimi   __ Mov(w1, 255);
12254*f5c631daSSadaf Ebrahimi   __ Crc32w(w14, w0, w1);
12255*f5c631daSSadaf Ebrahimi 
12256*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12257*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10001000);
12258*f5c631daSSadaf Ebrahimi   __ Crc32w(w15, w0, w1);
12259*f5c631daSSadaf Ebrahimi 
12260*f5c631daSSadaf Ebrahimi   END();
12261*f5c631daSSadaf Ebrahimi 
12262*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12263*f5c631daSSadaf Ebrahimi     RUN();
12264*f5c631daSSadaf Ebrahimi 
12265*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12266*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1d937b81, x11);
12267*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xed59b63b, x13);
12268*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00be2612, x14);
12269*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xa036e530, x15);
12270*f5c631daSSadaf Ebrahimi   }
12271*f5c631daSSadaf Ebrahimi }
12272*f5c631daSSadaf Ebrahimi 
12273*f5c631daSSadaf Ebrahimi 
TEST(crc32x)12274*f5c631daSSadaf Ebrahimi TEST(crc32x) {
12275*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12276*f5c631daSSadaf Ebrahimi 
12277*f5c631daSSadaf Ebrahimi   START();
12278*f5c631daSSadaf Ebrahimi 
12279*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12280*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
12281*f5c631daSSadaf Ebrahimi   __ Crc32x(w10, w0, x1);
12282*f5c631daSSadaf Ebrahimi 
12283*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12284*f5c631daSSadaf Ebrahimi   __ Mov(x1, UINT64_C(0x0000000800000031));
12285*f5c631daSSadaf Ebrahimi   __ Crc32x(w11, w0, x1);
12286*f5c631daSSadaf Ebrahimi 
12287*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12288*f5c631daSSadaf Ebrahimi   __ Mov(x1, 128);
12289*f5c631daSSadaf Ebrahimi   __ Crc32x(w13, w0, x1);
12290*f5c631daSSadaf Ebrahimi 
12291*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12292*f5c631daSSadaf Ebrahimi   __ Mov(x1, 255);
12293*f5c631daSSadaf Ebrahimi   __ Crc32x(w14, w0, x1);
12294*f5c631daSSadaf Ebrahimi 
12295*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12296*f5c631daSSadaf Ebrahimi   __ Mov(x1, UINT64_C(0x1000100000000000));
12297*f5c631daSSadaf Ebrahimi   __ Crc32x(w15, w0, x1);
12298*f5c631daSSadaf Ebrahimi 
12299*f5c631daSSadaf Ebrahimi   END();
12300*f5c631daSSadaf Ebrahimi 
12301*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12302*f5c631daSSadaf Ebrahimi     RUN();
12303*f5c631daSSadaf Ebrahimi 
12304*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12305*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x40797b92, x11);
12306*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x533b85da, x13);
12307*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbc962670, x14);
12308*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0667602f, x15);
12309*f5c631daSSadaf Ebrahimi   }
12310*f5c631daSSadaf Ebrahimi }
12311*f5c631daSSadaf Ebrahimi 
12312*f5c631daSSadaf Ebrahimi 
TEST(crc32cb)12313*f5c631daSSadaf Ebrahimi TEST(crc32cb) {
12314*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12315*f5c631daSSadaf Ebrahimi 
12316*f5c631daSSadaf Ebrahimi   START();
12317*f5c631daSSadaf Ebrahimi 
12318*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12319*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
12320*f5c631daSSadaf Ebrahimi   __ Crc32cb(w10, w0, w1);
12321*f5c631daSSadaf Ebrahimi 
12322*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12323*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x138);
12324*f5c631daSSadaf Ebrahimi   __ Crc32cb(w11, w0, w1);
12325*f5c631daSSadaf Ebrahimi 
12326*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12327*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x38);
12328*f5c631daSSadaf Ebrahimi   __ Crc32cb(w12, w0, w1);
12329*f5c631daSSadaf Ebrahimi 
12330*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12331*f5c631daSSadaf Ebrahimi   __ Mov(w1, 128);
12332*f5c631daSSadaf Ebrahimi   __ Crc32cb(w13, w0, w1);
12333*f5c631daSSadaf Ebrahimi 
12334*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12335*f5c631daSSadaf Ebrahimi   __ Mov(w1, 255);
12336*f5c631daSSadaf Ebrahimi   __ Crc32cb(w14, w0, w1);
12337*f5c631daSSadaf Ebrahimi 
12338*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12339*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10001000);
12340*f5c631daSSadaf Ebrahimi   __ Crc32cb(w15, w0, w1);
12341*f5c631daSSadaf Ebrahimi 
12342*f5c631daSSadaf Ebrahimi   END();
12343*f5c631daSSadaf Ebrahimi 
12344*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12345*f5c631daSSadaf Ebrahimi     RUN();
12346*f5c631daSSadaf Ebrahimi 
12347*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12348*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4851927d, x11);
12349*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x4851927d, x12);
12350*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x82f63b78, x13);
12351*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x00ffffff, x14);
12352*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xf26b8203, x15);
12353*f5c631daSSadaf Ebrahimi   }
12354*f5c631daSSadaf Ebrahimi }
12355*f5c631daSSadaf Ebrahimi 
12356*f5c631daSSadaf Ebrahimi 
TEST(crc32ch)12357*f5c631daSSadaf Ebrahimi TEST(crc32ch) {
12358*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12359*f5c631daSSadaf Ebrahimi 
12360*f5c631daSSadaf Ebrahimi   START();
12361*f5c631daSSadaf Ebrahimi 
12362*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12363*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
12364*f5c631daSSadaf Ebrahimi   __ Crc32ch(w10, w0, w1);
12365*f5c631daSSadaf Ebrahimi 
12366*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12367*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10038);
12368*f5c631daSSadaf Ebrahimi   __ Crc32ch(w11, w0, w1);
12369*f5c631daSSadaf Ebrahimi 
12370*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12371*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x38);
12372*f5c631daSSadaf Ebrahimi   __ Crc32ch(w12, w0, w1);
12373*f5c631daSSadaf Ebrahimi 
12374*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12375*f5c631daSSadaf Ebrahimi   __ Mov(w1, 128);
12376*f5c631daSSadaf Ebrahimi   __ Crc32ch(w13, w0, w1);
12377*f5c631daSSadaf Ebrahimi 
12378*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12379*f5c631daSSadaf Ebrahimi   __ Mov(w1, 255);
12380*f5c631daSSadaf Ebrahimi   __ Crc32ch(w14, w0, w1);
12381*f5c631daSSadaf Ebrahimi 
12382*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12383*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10001000);
12384*f5c631daSSadaf Ebrahimi   __ Crc32ch(w15, w0, w1);
12385*f5c631daSSadaf Ebrahimi 
12386*f5c631daSSadaf Ebrahimi   END();
12387*f5c631daSSadaf Ebrahimi 
12388*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12389*f5c631daSSadaf Ebrahimi     RUN();
12390*f5c631daSSadaf Ebrahimi 
12391*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12392*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xcef8494c, x11);
12393*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xcef8494c, x12);
12394*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xfbc3faf9, x13);
12395*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xad7dacae, x14);
12396*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x03fc5f19, x15);
12397*f5c631daSSadaf Ebrahimi   }
12398*f5c631daSSadaf Ebrahimi }
12399*f5c631daSSadaf Ebrahimi 
12400*f5c631daSSadaf Ebrahimi 
TEST(crc32cw)12401*f5c631daSSadaf Ebrahimi TEST(crc32cw) {
12402*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12403*f5c631daSSadaf Ebrahimi 
12404*f5c631daSSadaf Ebrahimi   START();
12405*f5c631daSSadaf Ebrahimi 
12406*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12407*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0);
12408*f5c631daSSadaf Ebrahimi   __ Crc32cw(w10, w0, w1);
12409*f5c631daSSadaf Ebrahimi 
12410*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12411*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x80000031);
12412*f5c631daSSadaf Ebrahimi   __ Crc32cw(w11, w0, w1);
12413*f5c631daSSadaf Ebrahimi 
12414*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12415*f5c631daSSadaf Ebrahimi   __ Mov(w1, 128);
12416*f5c631daSSadaf Ebrahimi   __ Crc32cw(w13, w0, w1);
12417*f5c631daSSadaf Ebrahimi 
12418*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12419*f5c631daSSadaf Ebrahimi   __ Mov(w1, 255);
12420*f5c631daSSadaf Ebrahimi   __ Crc32cw(w14, w0, w1);
12421*f5c631daSSadaf Ebrahimi 
12422*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12423*f5c631daSSadaf Ebrahimi   __ Mov(w1, 0x10001000);
12424*f5c631daSSadaf Ebrahimi   __ Crc32cw(w15, w0, w1);
12425*f5c631daSSadaf Ebrahimi 
12426*f5c631daSSadaf Ebrahimi   END();
12427*f5c631daSSadaf Ebrahimi 
12428*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12429*f5c631daSSadaf Ebrahimi     RUN();
12430*f5c631daSSadaf Ebrahimi 
12431*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12432*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xbcb79ece, x11);
12433*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x52a0c93f, x13);
12434*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x9f9b5c7a, x14);
12435*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xae1b882a, x15);
12436*f5c631daSSadaf Ebrahimi   }
12437*f5c631daSSadaf Ebrahimi }
12438*f5c631daSSadaf Ebrahimi 
12439*f5c631daSSadaf Ebrahimi 
TEST(crc32cx)12440*f5c631daSSadaf Ebrahimi TEST(crc32cx) {
12441*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kCRC32);
12442*f5c631daSSadaf Ebrahimi 
12443*f5c631daSSadaf Ebrahimi   START();
12444*f5c631daSSadaf Ebrahimi 
12445*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12446*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
12447*f5c631daSSadaf Ebrahimi   __ Crc32cx(w10, w0, x1);
12448*f5c631daSSadaf Ebrahimi 
12449*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x1);
12450*f5c631daSSadaf Ebrahimi   __ Mov(x1, UINT64_C(0x0000000800000031));
12451*f5c631daSSadaf Ebrahimi   __ Crc32cx(w11, w0, x1);
12452*f5c631daSSadaf Ebrahimi 
12453*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
12454*f5c631daSSadaf Ebrahimi   __ Mov(x1, 128);
12455*f5c631daSSadaf Ebrahimi   __ Crc32cx(w13, w0, x1);
12456*f5c631daSSadaf Ebrahimi 
12457*f5c631daSSadaf Ebrahimi   __ Mov(w0, UINT32_MAX);
12458*f5c631daSSadaf Ebrahimi   __ Mov(x1, 255);
12459*f5c631daSSadaf Ebrahimi   __ Crc32cx(w14, w0, x1);
12460*f5c631daSSadaf Ebrahimi 
12461*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0x00010001);
12462*f5c631daSSadaf Ebrahimi   __ Mov(x1, UINT64_C(0x1000100000000000));
12463*f5c631daSSadaf Ebrahimi   __ Crc32cx(w15, w0, x1);
12464*f5c631daSSadaf Ebrahimi 
12465*f5c631daSSadaf Ebrahimi   END();
12466*f5c631daSSadaf Ebrahimi 
12467*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12468*f5c631daSSadaf Ebrahimi     RUN();
12469*f5c631daSSadaf Ebrahimi 
12470*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x0, x10);
12471*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7f320fcb, x11);
12472*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x34019664, x13);
12473*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x6cc27dd0, x14);
12474*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0xc6f0acdb, x15);
12475*f5c631daSSadaf Ebrahimi   }
12476*f5c631daSSadaf Ebrahimi }
12477*f5c631daSSadaf Ebrahimi 
TEST(regress_cmp_shift_imm)12478*f5c631daSSadaf Ebrahimi TEST(regress_cmp_shift_imm) {
12479*f5c631daSSadaf Ebrahimi   SETUP();
12480*f5c631daSSadaf Ebrahimi 
12481*f5c631daSSadaf Ebrahimi   START();
12482*f5c631daSSadaf Ebrahimi 
12483*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x3d720c8d);
12484*f5c631daSSadaf Ebrahimi   __ Cmp(x0, Operand(0x3d720c8d));
12485*f5c631daSSadaf Ebrahimi 
12486*f5c631daSSadaf Ebrahimi   END();
12487*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12488*f5c631daSSadaf Ebrahimi     RUN();
12489*f5c631daSSadaf Ebrahimi 
12490*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_NZCV(ZCFlag);
12491*f5c631daSSadaf Ebrahimi   }
12492*f5c631daSSadaf Ebrahimi }
12493*f5c631daSSadaf Ebrahimi 
12494*f5c631daSSadaf Ebrahimi 
TEST(compute_address)12495*f5c631daSSadaf Ebrahimi TEST(compute_address) {
12496*f5c631daSSadaf Ebrahimi   SETUP();
12497*f5c631daSSadaf Ebrahimi 
12498*f5c631daSSadaf Ebrahimi   START();
12499*f5c631daSSadaf Ebrahimi   int64_t base_address = INT64_C(0x123000000abc);
12500*f5c631daSSadaf Ebrahimi   int64_t reg_offset = INT64_C(0x1087654321);
12501*f5c631daSSadaf Ebrahimi   Register base = x0;
12502*f5c631daSSadaf Ebrahimi   Register offset = x1;
12503*f5c631daSSadaf Ebrahimi 
12504*f5c631daSSadaf Ebrahimi   __ Mov(base, base_address);
12505*f5c631daSSadaf Ebrahimi   __ Mov(offset, reg_offset);
12506*f5c631daSSadaf Ebrahimi 
12507*f5c631daSSadaf Ebrahimi 
12508*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x2, MemOperand(base, 0));
12509*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x3, MemOperand(base, 8));
12510*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x4, MemOperand(base, -100));
12511*f5c631daSSadaf Ebrahimi 
12512*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x5, MemOperand(base, offset));
12513*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x6, MemOperand(base, offset, LSL, 2));
12514*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x7, MemOperand(base, offset, LSL, 4));
12515*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x8, MemOperand(base, offset, LSL, 8));
12516*f5c631daSSadaf Ebrahimi 
12517*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x9, MemOperand(base, offset, SXTW));
12518*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x10, MemOperand(base, offset, UXTW, 1));
12519*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x11, MemOperand(base, offset, SXTW, 2));
12520*f5c631daSSadaf Ebrahimi   __ ComputeAddress(x12, MemOperand(base, offset, UXTW, 3));
12521*f5c631daSSadaf Ebrahimi 
12522*f5c631daSSadaf Ebrahimi   END();
12523*f5c631daSSadaf Ebrahimi 
12524*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12525*f5c631daSSadaf Ebrahimi     RUN();
12526*f5c631daSSadaf Ebrahimi 
12527*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(base_address, base);
12528*f5c631daSSadaf Ebrahimi 
12529*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x123000000abc), x2);
12530*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x123000000ac4), x3);
12531*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x123000000a58), x4);
12532*f5c631daSSadaf Ebrahimi 
12533*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x124087654ddd), x5);
12534*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x12721d951740), x6);
12535*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x133876543ccc), x7);
12536*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x22b765432bbc), x8);
12537*f5c631daSSadaf Ebrahimi 
12538*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x122f87654ddd), x9);
12539*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x12310eca90fe), x10);
12540*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x122e1d951740), x11);
12541*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x12343b2a23c4), x12);
12542*f5c631daSSadaf Ebrahimi   }
12543*f5c631daSSadaf Ebrahimi }
12544*f5c631daSSadaf Ebrahimi 
12545*f5c631daSSadaf Ebrahimi 
TEST(far_branch_backward)12546*f5c631daSSadaf Ebrahimi TEST(far_branch_backward) {
12547*f5c631daSSadaf Ebrahimi   // Test that the MacroAssembler correctly resolves backward branches to labels
12548*f5c631daSSadaf Ebrahimi   // that are outside the immediate range of branch instructions.
12549*f5c631daSSadaf Ebrahimi   // Take into account that backward branches can reach one instruction further
12550*f5c631daSSadaf Ebrahimi   // than forward branches.
12551*f5c631daSSadaf Ebrahimi   const int overflow_size =
12552*f5c631daSSadaf Ebrahimi       kInstructionSize +
12553*f5c631daSSadaf Ebrahimi       std::max(Instruction::GetImmBranchForwardRange(TestBranchType),
12554*f5c631daSSadaf Ebrahimi                std::max(Instruction::GetImmBranchForwardRange(
12555*f5c631daSSadaf Ebrahimi                             CompareBranchType),
12556*f5c631daSSadaf Ebrahimi                         Instruction::GetImmBranchForwardRange(CondBranchType)));
12557*f5c631daSSadaf Ebrahimi 
12558*f5c631daSSadaf Ebrahimi   SETUP();
12559*f5c631daSSadaf Ebrahimi   START();
12560*f5c631daSSadaf Ebrahimi 
12561*f5c631daSSadaf Ebrahimi   Label done, fail;
12562*f5c631daSSadaf Ebrahimi   Label test_tbz, test_cbz, test_bcond;
12563*f5c631daSSadaf Ebrahimi   Label success_tbz, success_cbz, success_bcond;
12564*f5c631daSSadaf Ebrahimi 
12565*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
12566*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
12567*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0);
12568*f5c631daSSadaf Ebrahimi 
12569*f5c631daSSadaf Ebrahimi   __ B(&test_tbz);
12570*f5c631daSSadaf Ebrahimi   __ Bind(&success_tbz);
12571*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 0);
12572*f5c631daSSadaf Ebrahimi   __ B(&test_cbz);
12573*f5c631daSSadaf Ebrahimi   __ Bind(&success_cbz);
12574*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 1);
12575*f5c631daSSadaf Ebrahimi   __ B(&test_bcond);
12576*f5c631daSSadaf Ebrahimi   __ Bind(&success_bcond);
12577*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 2);
12578*f5c631daSSadaf Ebrahimi 
12579*f5c631daSSadaf Ebrahimi   __ B(&done);
12580*f5c631daSSadaf Ebrahimi 
12581*f5c631daSSadaf Ebrahimi   // Generate enough code to overflow the immediate range of the three types of
12582*f5c631daSSadaf Ebrahimi   // branches below.
12583*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < overflow_size / kInstructionSize; ++i) {
12584*f5c631daSSadaf Ebrahimi     if (i % 100 == 0) {
12585*f5c631daSSadaf Ebrahimi       // If we do land in this code, we do not want to execute so many nops
12586*f5c631daSSadaf Ebrahimi       // before reaching the end of test (especially if tracing is activated).
12587*f5c631daSSadaf Ebrahimi       __ B(&fail);
12588*f5c631daSSadaf Ebrahimi     } else {
12589*f5c631daSSadaf Ebrahimi       __ Nop();
12590*f5c631daSSadaf Ebrahimi     }
12591*f5c631daSSadaf Ebrahimi   }
12592*f5c631daSSadaf Ebrahimi   __ B(&fail);
12593*f5c631daSSadaf Ebrahimi 
12594*f5c631daSSadaf Ebrahimi   __ Bind(&test_tbz);
12595*f5c631daSSadaf Ebrahimi   __ Tbz(x10, 7, &success_tbz);
12596*f5c631daSSadaf Ebrahimi   __ Bind(&test_cbz);
12597*f5c631daSSadaf Ebrahimi   __ Cbz(x10, &success_cbz);
12598*f5c631daSSadaf Ebrahimi   __ Bind(&test_bcond);
12599*f5c631daSSadaf Ebrahimi   __ Cmp(x10, 0);
12600*f5c631daSSadaf Ebrahimi   __ B(eq, &success_bcond);
12601*f5c631daSSadaf Ebrahimi 
12602*f5c631daSSadaf Ebrahimi   // For each out-of-range branch instructions, at least two instructions should
12603*f5c631daSSadaf Ebrahimi   // have been generated.
12604*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&test_tbz) >=
12605*f5c631daSSadaf Ebrahimi              7 * kInstructionSize);
12606*f5c631daSSadaf Ebrahimi 
12607*f5c631daSSadaf Ebrahimi   __ Bind(&fail);
12608*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
12609*f5c631daSSadaf Ebrahimi   __ Bind(&done);
12610*f5c631daSSadaf Ebrahimi 
12611*f5c631daSSadaf Ebrahimi   END();
12612*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12613*f5c631daSSadaf Ebrahimi     RUN();
12614*f5c631daSSadaf Ebrahimi 
12615*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7, x0);
12616*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1, x1);
12617*f5c631daSSadaf Ebrahimi   }
12618*f5c631daSSadaf Ebrahimi }
12619*f5c631daSSadaf Ebrahimi 
12620*f5c631daSSadaf Ebrahimi 
TEST(single_veneer)12621*f5c631daSSadaf Ebrahimi TEST(single_veneer) {
12622*f5c631daSSadaf Ebrahimi   SETUP();
12623*f5c631daSSadaf Ebrahimi   START();
12624*f5c631daSSadaf Ebrahimi 
12625*f5c631daSSadaf Ebrahimi   const int max_range = Instruction::GetImmBranchForwardRange(TestBranchType);
12626*f5c631daSSadaf Ebrahimi 
12627*f5c631daSSadaf Ebrahimi   Label success, fail, done;
12628*f5c631daSSadaf Ebrahimi 
12629*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
12630*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
12631*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0);
12632*f5c631daSSadaf Ebrahimi 
12633*f5c631daSSadaf Ebrahimi   __ Tbz(x10, 7, &success);
12634*f5c631daSSadaf Ebrahimi 
12635*f5c631daSSadaf Ebrahimi   // Generate enough code to overflow the immediate range of the `tbz`.
12636*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) {
12637*f5c631daSSadaf Ebrahimi     if (i % 100 == 0) {
12638*f5c631daSSadaf Ebrahimi       // If we do land in this code, we do not want to execute so many nops
12639*f5c631daSSadaf Ebrahimi       // before reaching the end of test (especially if tracing is activated).
12640*f5c631daSSadaf Ebrahimi       __ B(&fail);
12641*f5c631daSSadaf Ebrahimi     } else {
12642*f5c631daSSadaf Ebrahimi       __ Nop();
12643*f5c631daSSadaf Ebrahimi     }
12644*f5c631daSSadaf Ebrahimi   }
12645*f5c631daSSadaf Ebrahimi   __ B(&fail);
12646*f5c631daSSadaf Ebrahimi 
12647*f5c631daSSadaf Ebrahimi   __ Bind(&success);
12648*f5c631daSSadaf Ebrahimi   __ Mov(x0, 1);
12649*f5c631daSSadaf Ebrahimi 
12650*f5c631daSSadaf Ebrahimi   __ B(&done);
12651*f5c631daSSadaf Ebrahimi   __ Bind(&fail);
12652*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
12653*f5c631daSSadaf Ebrahimi   __ Bind(&done);
12654*f5c631daSSadaf Ebrahimi 
12655*f5c631daSSadaf Ebrahimi   END();
12656*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12657*f5c631daSSadaf Ebrahimi     RUN();
12658*f5c631daSSadaf Ebrahimi 
12659*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x0);
12660*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(1, x1);
12661*f5c631daSSadaf Ebrahimi   }
12662*f5c631daSSadaf Ebrahimi }
12663*f5c631daSSadaf Ebrahimi 
12664*f5c631daSSadaf Ebrahimi 
TEST(simple_veneers)12665*f5c631daSSadaf Ebrahimi TEST(simple_veneers) {
12666*f5c631daSSadaf Ebrahimi   // Test that the MacroAssembler correctly emits veneers for forward branches
12667*f5c631daSSadaf Ebrahimi   // to labels that are outside the immediate range of branch instructions.
12668*f5c631daSSadaf Ebrahimi   const int max_range =
12669*f5c631daSSadaf Ebrahimi       std::max(Instruction::GetImmBranchForwardRange(TestBranchType),
12670*f5c631daSSadaf Ebrahimi                std::max(Instruction::GetImmBranchForwardRange(
12671*f5c631daSSadaf Ebrahimi                             CompareBranchType),
12672*f5c631daSSadaf Ebrahimi                         Instruction::GetImmBranchForwardRange(CondBranchType)));
12673*f5c631daSSadaf Ebrahimi 
12674*f5c631daSSadaf Ebrahimi   SETUP();
12675*f5c631daSSadaf Ebrahimi   START();
12676*f5c631daSSadaf Ebrahimi 
12677*f5c631daSSadaf Ebrahimi   Label done, fail;
12678*f5c631daSSadaf Ebrahimi   Label test_tbz, test_cbz, test_bcond;
12679*f5c631daSSadaf Ebrahimi   Label success_tbz, success_cbz, success_bcond;
12680*f5c631daSSadaf Ebrahimi 
12681*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0);
12682*f5c631daSSadaf Ebrahimi   __ Mov(x1, 1);
12683*f5c631daSSadaf Ebrahimi   __ Mov(x10, 0);
12684*f5c631daSSadaf Ebrahimi 
12685*f5c631daSSadaf Ebrahimi   __ Bind(&test_tbz);
12686*f5c631daSSadaf Ebrahimi   __ Tbz(x10, 7, &success_tbz);
12687*f5c631daSSadaf Ebrahimi   __ Bind(&test_cbz);
12688*f5c631daSSadaf Ebrahimi   __ Cbz(x10, &success_cbz);
12689*f5c631daSSadaf Ebrahimi   __ Bind(&test_bcond);
12690*f5c631daSSadaf Ebrahimi   __ Cmp(x10, 0);
12691*f5c631daSSadaf Ebrahimi   __ B(eq, &success_bcond);
12692*f5c631daSSadaf Ebrahimi 
12693*f5c631daSSadaf Ebrahimi   // Generate enough code to overflow the immediate range of the three types of
12694*f5c631daSSadaf Ebrahimi   // branches below.
12695*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) {
12696*f5c631daSSadaf Ebrahimi     if (i % 100 == 0) {
12697*f5c631daSSadaf Ebrahimi       // If we do land in this code, we do not want to execute so many nops
12698*f5c631daSSadaf Ebrahimi       // before reaching the end of test (especially if tracing is activated).
12699*f5c631daSSadaf Ebrahimi       __ B(&fail);
12700*f5c631daSSadaf Ebrahimi     } else {
12701*f5c631daSSadaf Ebrahimi       __ Nop();
12702*f5c631daSSadaf Ebrahimi     }
12703*f5c631daSSadaf Ebrahimi   }
12704*f5c631daSSadaf Ebrahimi   __ B(&fail);
12705*f5c631daSSadaf Ebrahimi 
12706*f5c631daSSadaf Ebrahimi   __ Bind(&success_tbz);
12707*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 0);
12708*f5c631daSSadaf Ebrahimi   __ B(&test_cbz);
12709*f5c631daSSadaf Ebrahimi   __ Bind(&success_cbz);
12710*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 1);
12711*f5c631daSSadaf Ebrahimi   __ B(&test_bcond);
12712*f5c631daSSadaf Ebrahimi   __ Bind(&success_bcond);
12713*f5c631daSSadaf Ebrahimi   __ Orr(x0, x0, 1 << 2);
12714*f5c631daSSadaf Ebrahimi 
12715*f5c631daSSadaf Ebrahimi   __ B(&done);
12716*f5c631daSSadaf Ebrahimi   __ Bind(&fail);
12717*f5c631daSSadaf Ebrahimi   __ Mov(x1, 0);
12718*f5c631daSSadaf Ebrahimi   __ Bind(&done);
12719*f5c631daSSadaf Ebrahimi 
12720*f5c631daSSadaf Ebrahimi   END();
12721*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12722*f5c631daSSadaf Ebrahimi     RUN();
12723*f5c631daSSadaf Ebrahimi 
12724*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x7, x0);
12725*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x1, x1);
12726*f5c631daSSadaf Ebrahimi   }
12727*f5c631daSSadaf Ebrahimi }
12728*f5c631daSSadaf Ebrahimi 
12729*f5c631daSSadaf Ebrahimi 
TEST(veneers_stress)12730*f5c631daSSadaf Ebrahimi TEST(veneers_stress) {
12731*f5c631daSSadaf Ebrahimi   SETUP();
12732*f5c631daSSadaf Ebrahimi   START();
12733*f5c631daSSadaf Ebrahimi 
12734*f5c631daSSadaf Ebrahimi   // This is a code generation test stressing the emission of veneers. The code
12735*f5c631daSSadaf Ebrahimi   // generated is not executed.
12736*f5c631daSSadaf Ebrahimi 
12737*f5c631daSSadaf Ebrahimi   Label target;
12738*f5c631daSSadaf Ebrahimi   const unsigned max_range =
12739*f5c631daSSadaf Ebrahimi       Instruction::GetImmBranchForwardRange(CondBranchType);
12740*f5c631daSSadaf Ebrahimi   const unsigned iterations =
12741*f5c631daSSadaf Ebrahimi       (max_range + max_range / 4) / (4 * kInstructionSize);
12742*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < iterations; i++) {
12743*f5c631daSSadaf Ebrahimi     __ B(&target);
12744*f5c631daSSadaf Ebrahimi     __ B(eq, &target);
12745*f5c631daSSadaf Ebrahimi     __ Cbz(x0, &target);
12746*f5c631daSSadaf Ebrahimi     __ Tbz(x0, 0, &target);
12747*f5c631daSSadaf Ebrahimi   }
12748*f5c631daSSadaf Ebrahimi   __ Bind(&target);
12749*f5c631daSSadaf Ebrahimi 
12750*f5c631daSSadaf Ebrahimi   END();
12751*f5c631daSSadaf Ebrahimi }
12752*f5c631daSSadaf Ebrahimi 
12753*f5c631daSSadaf Ebrahimi 
TEST(veneers_two_out_of_range)12754*f5c631daSSadaf Ebrahimi TEST(veneers_two_out_of_range) {
12755*f5c631daSSadaf Ebrahimi   SETUP();
12756*f5c631daSSadaf Ebrahimi   START();
12757*f5c631daSSadaf Ebrahimi 
12758*f5c631daSSadaf Ebrahimi   // This is a code generation test. The code generated is not executed.
12759*f5c631daSSadaf Ebrahimi   // Ensure that the MacroAssembler considers unresolved branches to chose when
12760*f5c631daSSadaf Ebrahimi   // a veneer pool should be emitted. We generate two branches that go out of
12761*f5c631daSSadaf Ebrahimi   // range at the same offset. When the MacroAssembler decides to emit the
12762*f5c631daSSadaf Ebrahimi   // veneer pool, the emission of a first veneer should not cause the other
12763*f5c631daSSadaf Ebrahimi   // branch to go out of range.
12764*f5c631daSSadaf Ebrahimi 
12765*f5c631daSSadaf Ebrahimi   int range_cbz = Instruction::GetImmBranchForwardRange(CompareBranchType);
12766*f5c631daSSadaf Ebrahimi   int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
12767*f5c631daSSadaf Ebrahimi   int max_target = static_cast<int>(masm.GetCursorOffset()) + range_cbz;
12768*f5c631daSSadaf Ebrahimi 
12769*f5c631daSSadaf Ebrahimi   Label done;
12770*f5c631daSSadaf Ebrahimi 
12771*f5c631daSSadaf Ebrahimi   // We use different labels to prevent the MacroAssembler from sharing veneers.
12772*f5c631daSSadaf Ebrahimi   Label target_cbz, target_tbz;
12773*f5c631daSSadaf Ebrahimi 
12774*f5c631daSSadaf Ebrahimi   __ Cbz(x0, &target_cbz);
12775*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < max_target - range_tbz) {
12776*f5c631daSSadaf Ebrahimi     __ Nop();
12777*f5c631daSSadaf Ebrahimi   }
12778*f5c631daSSadaf Ebrahimi   __ Tbz(x0, 0, &target_tbz);
12779*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < max_target) {
12780*f5c631daSSadaf Ebrahimi     __ Nop();
12781*f5c631daSSadaf Ebrahimi   }
12782*f5c631daSSadaf Ebrahimi 
12783*f5c631daSSadaf Ebrahimi   // This additional nop makes the branches go out of range.
12784*f5c631daSSadaf Ebrahimi   __ Nop();
12785*f5c631daSSadaf Ebrahimi 
12786*f5c631daSSadaf Ebrahimi   __ Bind(&target_cbz);
12787*f5c631daSSadaf Ebrahimi   __ Bind(&target_tbz);
12788*f5c631daSSadaf Ebrahimi 
12789*f5c631daSSadaf Ebrahimi   END();
12790*f5c631daSSadaf Ebrahimi }
12791*f5c631daSSadaf Ebrahimi 
12792*f5c631daSSadaf Ebrahimi 
TEST(veneers_hanging)12793*f5c631daSSadaf Ebrahimi TEST(veneers_hanging) {
12794*f5c631daSSadaf Ebrahimi   SETUP();
12795*f5c631daSSadaf Ebrahimi   START();
12796*f5c631daSSadaf Ebrahimi 
12797*f5c631daSSadaf Ebrahimi   // This is a code generation test. The code generated is not executed.
12798*f5c631daSSadaf Ebrahimi   // Ensure that the MacroAssembler considers unresolved branches to chose when
12799*f5c631daSSadaf Ebrahimi   // a veneer pool should be emitted. This is similar to the
12800*f5c631daSSadaf Ebrahimi   // 'veneers_two_out_of_range' test. We try to trigger the following situation:
12801*f5c631daSSadaf Ebrahimi   //   b.eq label
12802*f5c631daSSadaf Ebrahimi   //   b.eq label
12803*f5c631daSSadaf Ebrahimi   //   ...
12804*f5c631daSSadaf Ebrahimi   //   nop
12805*f5c631daSSadaf Ebrahimi   //   ...
12806*f5c631daSSadaf Ebrahimi   //   cbz x0, label
12807*f5c631daSSadaf Ebrahimi   //   cbz x0, label
12808*f5c631daSSadaf Ebrahimi   //   ...
12809*f5c631daSSadaf Ebrahimi   //   tbz x0, 0 label
12810*f5c631daSSadaf Ebrahimi   //   nop
12811*f5c631daSSadaf Ebrahimi   //   ...
12812*f5c631daSSadaf Ebrahimi   //   nop    <- From here the `b.eq` and `cbz` instructions run out of range,
12813*f5c631daSSadaf Ebrahimi   //             so a literal pool is required.
12814*f5c631daSSadaf Ebrahimi   //   veneer
12815*f5c631daSSadaf Ebrahimi   //   veneer
12816*f5c631daSSadaf Ebrahimi   //   veneer <- The `tbz` runs out of range somewhere in the middle of the
12817*f5c631daSSadaf Ebrahimi   //   veneer    veneer pool.
12818*f5c631daSSadaf Ebrahimi   //   veneer
12819*f5c631daSSadaf Ebrahimi 
12820*f5c631daSSadaf Ebrahimi   const int range_bcond = Instruction::GetImmBranchForwardRange(CondBranchType);
12821*f5c631daSSadaf Ebrahimi   const int range_cbz =
12822*f5c631daSSadaf Ebrahimi       Instruction::GetImmBranchForwardRange(CompareBranchType);
12823*f5c631daSSadaf Ebrahimi   const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
12824*f5c631daSSadaf Ebrahimi   const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_bcond;
12825*f5c631daSSadaf Ebrahimi 
12826*f5c631daSSadaf Ebrahimi   Label done;
12827*f5c631daSSadaf Ebrahimi   const int n_bcond = 100;
12828*f5c631daSSadaf Ebrahimi   const int n_cbz = 100;
12829*f5c631daSSadaf Ebrahimi   const int n_tbz = 1;
12830*f5c631daSSadaf Ebrahimi   const int kNTotalBranches = n_bcond + n_cbz + n_tbz;
12831*f5c631daSSadaf Ebrahimi 
12832*f5c631daSSadaf Ebrahimi   // We use different labels to prevent the MacroAssembler from sharing veneers.
12833*f5c631daSSadaf Ebrahimi   Label labels[kNTotalBranches];
12834*f5c631daSSadaf Ebrahimi   for (int i = 0; i < kNTotalBranches; i++) {
12835*f5c631daSSadaf Ebrahimi     new (&labels[i]) Label();
12836*f5c631daSSadaf Ebrahimi   }
12837*f5c631daSSadaf Ebrahimi 
12838*f5c631daSSadaf Ebrahimi   for (int i = 0; i < n_bcond; i++) {
12839*f5c631daSSadaf Ebrahimi     __ B(eq, &labels[i]);
12840*f5c631daSSadaf Ebrahimi   }
12841*f5c631daSSadaf Ebrahimi 
12842*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < max_target - range_cbz) {
12843*f5c631daSSadaf Ebrahimi     __ Nop();
12844*f5c631daSSadaf Ebrahimi   }
12845*f5c631daSSadaf Ebrahimi 
12846*f5c631daSSadaf Ebrahimi   for (int i = 0; i < n_cbz; i++) {
12847*f5c631daSSadaf Ebrahimi     __ Cbz(x0, &labels[n_bcond + i]);
12848*f5c631daSSadaf Ebrahimi   }
12849*f5c631daSSadaf Ebrahimi 
12850*f5c631daSSadaf Ebrahimi   // Ensure the 'tbz' will go out of range after some of the previously
12851*f5c631daSSadaf Ebrahimi   // generated branches.
12852*f5c631daSSadaf Ebrahimi   int margin = (n_bcond / 2) * kInstructionSize;
12853*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < max_target - range_tbz + margin) {
12854*f5c631daSSadaf Ebrahimi     __ Nop();
12855*f5c631daSSadaf Ebrahimi   }
12856*f5c631daSSadaf Ebrahimi 
12857*f5c631daSSadaf Ebrahimi   __ Tbz(x0, 0, &labels[n_bcond + n_cbz]);
12858*f5c631daSSadaf Ebrahimi 
12859*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < max_target) {
12860*f5c631daSSadaf Ebrahimi     __ Nop();
12861*f5c631daSSadaf Ebrahimi   }
12862*f5c631daSSadaf Ebrahimi 
12863*f5c631daSSadaf Ebrahimi   // This additional nop makes the 'b.eq' and 'cbz' instructions go out of range
12864*f5c631daSSadaf Ebrahimi   // and forces the emission of a veneer pool. The 'tbz' is not yet out of
12865*f5c631daSSadaf Ebrahimi   // range, but will go out of range while veneers are emitted for the other
12866*f5c631daSSadaf Ebrahimi   // branches.
12867*f5c631daSSadaf Ebrahimi   // The MacroAssembler should ensure that veneers are correctly emitted for all
12868*f5c631daSSadaf Ebrahimi   // the branches, including the 'tbz'. Checks will fail if the target of a
12869*f5c631daSSadaf Ebrahimi   // branch is out of range.
12870*f5c631daSSadaf Ebrahimi   __ Nop();
12871*f5c631daSSadaf Ebrahimi 
12872*f5c631daSSadaf Ebrahimi   for (int i = 0; i < kNTotalBranches; i++) {
12873*f5c631daSSadaf Ebrahimi     __ Bind(&labels[i]);
12874*f5c631daSSadaf Ebrahimi   }
12875*f5c631daSSadaf Ebrahimi 
12876*f5c631daSSadaf Ebrahimi   END();
12877*f5c631daSSadaf Ebrahimi }
12878*f5c631daSSadaf Ebrahimi 
12879*f5c631daSSadaf Ebrahimi 
TEST(collision_literal_veneer_pools)12880*f5c631daSSadaf Ebrahimi TEST(collision_literal_veneer_pools) {
12881*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
12882*f5c631daSSadaf Ebrahimi   START();
12883*f5c631daSSadaf Ebrahimi 
12884*f5c631daSSadaf Ebrahimi   // This is a code generation test. The code generated is not executed.
12885*f5c631daSSadaf Ebrahimi 
12886*f5c631daSSadaf Ebrahimi   // Make sure the literal pool is empty;
12887*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
12888*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12889*f5c631daSSadaf Ebrahimi 
12890*f5c631daSSadaf Ebrahimi   // We chose the offsets below to (try to) trigger the following situation:
12891*f5c631daSSadaf Ebrahimi   // buffer offset
12892*f5c631daSSadaf Ebrahimi   //              0:   tbz x0, 0, target_tbz ----------------------------------.
12893*f5c631daSSadaf Ebrahimi   //              4:   nop                                                     |
12894*f5c631daSSadaf Ebrahimi   //                   ...                                                     |
12895*f5c631daSSadaf Ebrahimi   //                   nop                                                     |
12896*f5c631daSSadaf Ebrahimi   //    literal gen:   ldr s0, [pc + ...]   ; load from `pool start + 0`       |
12897*f5c631daSSadaf Ebrahimi   //                   ldr s0, [pc + ...]   ; load from `pool start + 4`       |
12898*f5c631daSSadaf Ebrahimi   //                   ...                                                     |
12899*f5c631daSSadaf Ebrahimi   //                   ldr s0, [pc + ...]                                      |
12900*f5c631daSSadaf Ebrahimi   //     pool start:   floating-point literal (0.1)                            |
12901*f5c631daSSadaf Ebrahimi   //                   floating-point literal (1.1)                            |
12902*f5c631daSSadaf Ebrahimi   //                   ...                                                     |
12903*f5c631daSSadaf Ebrahimi   //                   floating-point literal (<n>.1)     <-----tbz-max-range--'
12904*f5c631daSSadaf Ebrahimi   //                   floating-point literal (<n+1>.1)
12905*f5c631daSSadaf Ebrahimi   //                   ...
12906*f5c631daSSadaf Ebrahimi 
12907*f5c631daSSadaf Ebrahimi   const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType);
12908*f5c631daSSadaf Ebrahimi   const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_tbz;
12909*f5c631daSSadaf Ebrahimi 
12910*f5c631daSSadaf Ebrahimi   const size_t target_literal_pool_size = 100 * kInstructionSize;
12911*f5c631daSSadaf Ebrahimi   const int offset_start_literal_gen =
12912*f5c631daSSadaf Ebrahimi       target_literal_pool_size + target_literal_pool_size / 2;
12913*f5c631daSSadaf Ebrahimi 
12914*f5c631daSSadaf Ebrahimi 
12915*f5c631daSSadaf Ebrahimi   Label target_tbz;
12916*f5c631daSSadaf Ebrahimi 
12917*f5c631daSSadaf Ebrahimi   __ Tbz(x0, 0, &target_tbz);
12918*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1);
12919*f5c631daSSadaf Ebrahimi   while (masm.GetCursorOffset() < max_target - offset_start_literal_gen) {
12920*f5c631daSSadaf Ebrahimi     __ Nop();
12921*f5c631daSSadaf Ebrahimi   }
12922*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1);
12923*f5c631daSSadaf Ebrahimi 
12924*f5c631daSSadaf Ebrahimi   for (int i = 0; i < 100; i++) {
12925*f5c631daSSadaf Ebrahimi     // Use a different value to force one literal pool entry per iteration.
12926*f5c631daSSadaf Ebrahimi     __ Ldr(s0, i + 0.1);
12927*f5c631daSSadaf Ebrahimi   }
12928*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetLiteralPoolSize() >= target_literal_pool_size);
12929*f5c631daSSadaf Ebrahimi 
12930*f5c631daSSadaf Ebrahimi   // Force emission of a literal pool.
12931*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
12932*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12933*f5c631daSSadaf Ebrahimi 
12934*f5c631daSSadaf Ebrahimi   // The branch should not have gone out of range during the emission of the
12935*f5c631daSSadaf Ebrahimi   // literal pool.
12936*f5c631daSSadaf Ebrahimi   __ Bind(&target_tbz);
12937*f5c631daSSadaf Ebrahimi 
12938*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 0);
12939*f5c631daSSadaf Ebrahimi 
12940*f5c631daSSadaf Ebrahimi   END();
12941*f5c631daSSadaf Ebrahimi }
12942*f5c631daSSadaf Ebrahimi 
12943*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_explicit)12944*f5c631daSSadaf Ebrahimi TEST(ldr_literal_explicit) {
12945*f5c631daSSadaf Ebrahimi   SETUP();
12946*f5c631daSSadaf Ebrahimi 
12947*f5c631daSSadaf Ebrahimi   START();
12948*f5c631daSSadaf Ebrahimi   Literal<int64_t> automatically_placed_literal(1, masm.GetLiteralPool());
12949*f5c631daSSadaf Ebrahimi   Literal<int64_t> manually_placed_literal(2);
12950*f5c631daSSadaf Ebrahimi   {
12951*f5c631daSSadaf Ebrahimi     ExactAssemblyScope scope(&masm, kInstructionSize + sizeof(int64_t));
12952*f5c631daSSadaf Ebrahimi     Label over_literal;
12953*f5c631daSSadaf Ebrahimi     __ b(&over_literal);
12954*f5c631daSSadaf Ebrahimi     __ place(&manually_placed_literal);
12955*f5c631daSSadaf Ebrahimi     __ bind(&over_literal);
12956*f5c631daSSadaf Ebrahimi   }
12957*f5c631daSSadaf Ebrahimi   __ Ldr(x1, &manually_placed_literal);
12958*f5c631daSSadaf Ebrahimi   __ Ldr(x2, &automatically_placed_literal);
12959*f5c631daSSadaf Ebrahimi   __ Add(x0, x1, x2);
12960*f5c631daSSadaf Ebrahimi   END();
12961*f5c631daSSadaf Ebrahimi 
12962*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
12963*f5c631daSSadaf Ebrahimi     RUN();
12964*f5c631daSSadaf Ebrahimi 
12965*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(3, x0);
12966*f5c631daSSadaf Ebrahimi   }
12967*f5c631daSSadaf Ebrahimi }
12968*f5c631daSSadaf Ebrahimi 
12969*f5c631daSSadaf Ebrahimi 
TEST(ldr_literal_automatically_placed)12970*f5c631daSSadaf Ebrahimi TEST(ldr_literal_automatically_placed) {
12971*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
12972*f5c631daSSadaf Ebrahimi 
12973*f5c631daSSadaf Ebrahimi   START();
12974*f5c631daSSadaf Ebrahimi 
12975*f5c631daSSadaf Ebrahimi   // We start with an empty literal pool.
12976*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12977*f5c631daSSadaf Ebrahimi 
12978*f5c631daSSadaf Ebrahimi   // Create a literal that should be placed by the literal pool.
12979*f5c631daSSadaf Ebrahimi   Literal<int64_t> explicit_literal(2, masm.GetLiteralPool());
12980*f5c631daSSadaf Ebrahimi   // It should not appear in the literal pool until its first use.
12981*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12982*f5c631daSSadaf Ebrahimi 
12983*f5c631daSSadaf Ebrahimi   // Check that using standard literals does not break the use of explicitly
12984*f5c631daSSadaf Ebrahimi   // created literals.
12985*f5c631daSSadaf Ebrahimi   __ Ldr(d1, 1.1);
12986*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(8);
12987*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
12988*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12989*f5c631daSSadaf Ebrahimi 
12990*f5c631daSSadaf Ebrahimi   __ Ldr(x2, &explicit_literal);
12991*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(8);
12992*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
12993*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12994*f5c631daSSadaf Ebrahimi 
12995*f5c631daSSadaf Ebrahimi   __ Ldr(d3, 3.3);
12996*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(8);
12997*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
12998*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
12999*f5c631daSSadaf Ebrahimi 
13000*f5c631daSSadaf Ebrahimi   // Re-use our explicitly created literal. It has already been placed, so it
13001*f5c631daSSadaf Ebrahimi   // should not impact the literal pool.
13002*f5c631daSSadaf Ebrahimi   __ Ldr(x4, &explicit_literal);
13003*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
13004*f5c631daSSadaf Ebrahimi 
13005*f5c631daSSadaf Ebrahimi   END();
13006*f5c631daSSadaf Ebrahimi 
13007*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13008*f5c631daSSadaf Ebrahimi     RUN();
13009*f5c631daSSadaf Ebrahimi 
13010*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(1.1, d1);
13011*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x2);
13012*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(3.3, d3);
13013*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(2, x4);
13014*f5c631daSSadaf Ebrahimi   }
13015*f5c631daSSadaf Ebrahimi }
13016*f5c631daSSadaf Ebrahimi 
13017*f5c631daSSadaf Ebrahimi 
TEST(literal_update_overwrite)13018*f5c631daSSadaf Ebrahimi TEST(literal_update_overwrite) {
13019*f5c631daSSadaf Ebrahimi   SETUP();
13020*f5c631daSSadaf Ebrahimi 
13021*f5c631daSSadaf Ebrahimi   START();
13022*f5c631daSSadaf Ebrahimi 
13023*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
13024*f5c631daSSadaf Ebrahimi   LiteralPool* literal_pool = masm.GetLiteralPool();
13025*f5c631daSSadaf Ebrahimi 
13026*f5c631daSSadaf Ebrahimi   Literal<int32_t> lit_32_update_before_pool(0xbad, literal_pool);
13027*f5c631daSSadaf Ebrahimi   Literal<int32_t> lit_32_update_after_pool(0xbad, literal_pool);
13028*f5c631daSSadaf Ebrahimi   Literal<int64_t> lit_64_update_before_pool(0xbad, literal_pool);
13029*f5c631daSSadaf Ebrahimi   Literal<int64_t> lit_64_update_after_pool(0xbad, literal_pool);
13030*f5c631daSSadaf Ebrahimi 
13031*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
13032*f5c631daSSadaf Ebrahimi 
13033*f5c631daSSadaf Ebrahimi   lit_32_update_before_pool.UpdateValue(32);
13034*f5c631daSSadaf Ebrahimi   lit_64_update_before_pool.UpdateValue(64);
13035*f5c631daSSadaf Ebrahimi 
13036*f5c631daSSadaf Ebrahimi   __ Ldr(w1, &lit_32_update_before_pool);
13037*f5c631daSSadaf Ebrahimi   __ Ldr(x2, &lit_64_update_before_pool);
13038*f5c631daSSadaf Ebrahimi   __ Ldr(w3, &lit_32_update_after_pool);
13039*f5c631daSSadaf Ebrahimi   __ Ldr(x4, &lit_64_update_after_pool);
13040*f5c631daSSadaf Ebrahimi 
13041*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13042*f5c631daSSadaf Ebrahimi 
13043*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(lit_32_update_after_pool.IsPlaced());
13044*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(lit_64_update_after_pool.IsPlaced());
13045*f5c631daSSadaf Ebrahimi   lit_32_update_after_pool.UpdateValue(128, &masm);
13046*f5c631daSSadaf Ebrahimi   lit_64_update_after_pool.UpdateValue(256, &masm);
13047*f5c631daSSadaf Ebrahimi 
13048*f5c631daSSadaf Ebrahimi   END();
13049*f5c631daSSadaf Ebrahimi 
13050*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13051*f5c631daSSadaf Ebrahimi     RUN();
13052*f5c631daSSadaf Ebrahimi 
13053*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(32, x1);
13054*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(64, x2);
13055*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(128, x3);
13056*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(256, x4);
13057*f5c631daSSadaf Ebrahimi   }
13058*f5c631daSSadaf Ebrahimi }
13059*f5c631daSSadaf Ebrahimi 
13060*f5c631daSSadaf Ebrahimi 
TEST(literal_deletion_policies)13061*f5c631daSSadaf Ebrahimi TEST(literal_deletion_policies) {
13062*f5c631daSSadaf Ebrahimi   SETUP();
13063*f5c631daSSadaf Ebrahimi 
13064*f5c631daSSadaf Ebrahimi   START();
13065*f5c631daSSadaf Ebrahimi 
13066*f5c631daSSadaf Ebrahimi   // We cannot check exactly when the deletion of the literals occur, but we
13067*f5c631daSSadaf Ebrahimi   // check that usage of the deletion policies is not broken.
13068*f5c631daSSadaf Ebrahimi 
13069*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
13070*f5c631daSSadaf Ebrahimi   LiteralPool* literal_pool = masm.GetLiteralPool();
13071*f5c631daSSadaf Ebrahimi 
13072*f5c631daSSadaf Ebrahimi   Literal<int32_t> lit_manual(0xbad, literal_pool);
13073*f5c631daSSadaf Ebrahimi   Literal<int32_t>* lit_deleted_on_placement =
13074*f5c631daSSadaf Ebrahimi       new Literal<int32_t>(0xbad,
13075*f5c631daSSadaf Ebrahimi                            literal_pool,
13076*f5c631daSSadaf Ebrahimi                            RawLiteral::kDeletedOnPlacementByPool);
13077*f5c631daSSadaf Ebrahimi   Literal<int32_t>* lit_deleted_on_pool_destruction =
13078*f5c631daSSadaf Ebrahimi       new Literal<int32_t>(0xbad,
13079*f5c631daSSadaf Ebrahimi                            literal_pool,
13080*f5c631daSSadaf Ebrahimi                            RawLiteral::kDeletedOnPoolDestruction);
13081*f5c631daSSadaf Ebrahimi 
13082*f5c631daSSadaf Ebrahimi   ASSERT_LITERAL_POOL_SIZE(0);
13083*f5c631daSSadaf Ebrahimi 
13084*f5c631daSSadaf Ebrahimi   lit_manual.UpdateValue(32);
13085*f5c631daSSadaf Ebrahimi   lit_deleted_on_placement->UpdateValue(64);
13086*f5c631daSSadaf Ebrahimi 
13087*f5c631daSSadaf Ebrahimi   __ Ldr(w1, &lit_manual);
13088*f5c631daSSadaf Ebrahimi   __ Ldr(w2, lit_deleted_on_placement);
13089*f5c631daSSadaf Ebrahimi   __ Ldr(w3, lit_deleted_on_pool_destruction);
13090*f5c631daSSadaf Ebrahimi 
13091*f5c631daSSadaf Ebrahimi   masm.EmitLiteralPool(LiteralPool::kBranchRequired);
13092*f5c631daSSadaf Ebrahimi 
13093*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(lit_manual.IsPlaced());
13094*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(lit_deleted_on_pool_destruction->IsPlaced());
13095*f5c631daSSadaf Ebrahimi   lit_deleted_on_pool_destruction->UpdateValue(128, &masm);
13096*f5c631daSSadaf Ebrahimi 
13097*f5c631daSSadaf Ebrahimi   END();
13098*f5c631daSSadaf Ebrahimi 
13099*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13100*f5c631daSSadaf Ebrahimi     RUN();
13101*f5c631daSSadaf Ebrahimi 
13102*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(32, x1);
13103*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(64, x2);
13104*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(128, x3);
13105*f5c631daSSadaf Ebrahimi   }
13106*f5c631daSSadaf Ebrahimi }
13107*f5c631daSSadaf Ebrahimi 
13108*f5c631daSSadaf Ebrahimi 
TEST(generic_operand)13109*f5c631daSSadaf Ebrahimi TEST(generic_operand) {
13110*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
13111*f5c631daSSadaf Ebrahimi 
13112*f5c631daSSadaf Ebrahimi   int32_t data_32_array[5] = {0xbadbeef,
13113*f5c631daSSadaf Ebrahimi                               0x11111111,
13114*f5c631daSSadaf Ebrahimi                               0xbadbeef,
13115*f5c631daSSadaf Ebrahimi                               0x33333333,
13116*f5c631daSSadaf Ebrahimi                               0xbadbeef};
13117*f5c631daSSadaf Ebrahimi   int64_t data_64_array[5] = {INT64_C(0xbadbadbadbeef),
13118*f5c631daSSadaf Ebrahimi                               INT64_C(0x1111111111111111),
13119*f5c631daSSadaf Ebrahimi                               INT64_C(0xbadbadbadbeef),
13120*f5c631daSSadaf Ebrahimi                               INT64_C(0x3333333333333333),
13121*f5c631daSSadaf Ebrahimi                               INT64_C(0xbadbadbadbeef)};
13122*f5c631daSSadaf Ebrahimi   size_t size_32 = sizeof(data_32_array[0]);
13123*f5c631daSSadaf Ebrahimi   size_t size_64 = sizeof(data_64_array[0]);
13124*f5c631daSSadaf Ebrahimi 
13125*f5c631daSSadaf Ebrahimi   START();
13126*f5c631daSSadaf Ebrahimi 
13127*f5c631daSSadaf Ebrahimi   intptr_t data_32_address = reinterpret_cast<intptr_t>(&data_32_array[0]);
13128*f5c631daSSadaf Ebrahimi   intptr_t data_64_address = reinterpret_cast<intptr_t>(&data_64_array[0]);
13129*f5c631daSSadaf Ebrahimi   Register data_32 = x27;
13130*f5c631daSSadaf Ebrahimi   Register data_64 = x28;
13131*f5c631daSSadaf Ebrahimi   __ Mov(data_32, data_32_address);
13132*f5c631daSSadaf Ebrahimi   __ Mov(data_64, data_64_address);
13133*f5c631daSSadaf Ebrahimi 
13134*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(w0),
13135*f5c631daSSadaf Ebrahimi           GenericOperand(MemOperand(data_32, 1 * size_32), size_32));
13136*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(s0),
13137*f5c631daSSadaf Ebrahimi           GenericOperand(MemOperand(data_32, 3 * size_32), size_32));
13138*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(x10),
13139*f5c631daSSadaf Ebrahimi           GenericOperand(MemOperand(data_64, 1 * size_64), size_64));
13140*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(d10),
13141*f5c631daSSadaf Ebrahimi           GenericOperand(MemOperand(data_64, 3 * size_64), size_64));
13142*f5c631daSSadaf Ebrahimi 
13143*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(w1), GenericOperand(w0));
13144*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(s1), GenericOperand(s0));
13145*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(x11), GenericOperand(x10));
13146*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(d11), GenericOperand(d10));
13147*f5c631daSSadaf Ebrahimi 
13148*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(MemOperand(data_32, 0 * size_32), size_32),
13149*f5c631daSSadaf Ebrahimi           GenericOperand(w1));
13150*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(MemOperand(data_32, 2 * size_32), size_32),
13151*f5c631daSSadaf Ebrahimi           GenericOperand(s1));
13152*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(MemOperand(data_64, 0 * size_64), size_64),
13153*f5c631daSSadaf Ebrahimi           GenericOperand(x11));
13154*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(MemOperand(data_64, 2 * size_64), size_64),
13155*f5c631daSSadaf Ebrahimi           GenericOperand(d11));
13156*f5c631daSSadaf Ebrahimi 
13157*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(MemOperand(data_32, 4 * size_32), size_32),
13158*f5c631daSSadaf Ebrahimi           GenericOperand(MemOperand(data_32, 0 * size_32), size_32));
13159*f5c631daSSadaf Ebrahimi   __ Move(GenericOperand(MemOperand(data_64, 4 * size_64), size_64),
13160*f5c631daSSadaf Ebrahimi           GenericOperand(MemOperand(data_64, 0 * size_64), size_64));
13161*f5c631daSSadaf Ebrahimi   END();
13162*f5c631daSSadaf Ebrahimi 
13163*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13164*f5c631daSSadaf Ebrahimi     RUN();
13165*f5c631daSSadaf Ebrahimi 
13166*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(data_32_address, data_32);
13167*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(data_64_address, data_64);
13168*f5c631daSSadaf Ebrahimi 
13169*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111, w0);
13170*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x33333333, core.sreg_bits(0));
13171*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x10);
13172*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(10));
13173*f5c631daSSadaf Ebrahimi 
13174*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x11111111, w1);
13175*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(0x33333333, core.sreg_bits(1));
13176*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x11);
13177*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(11));
13178*f5c631daSSadaf Ebrahimi 
13179*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_32_array[0] == 0x11111111);
13180*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_32_array[1] == 0x11111111);
13181*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_32_array[2] == 0x33333333);
13182*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_32_array[3] == 0x33333333);
13183*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_32_array[4] == 0x11111111);
13184*f5c631daSSadaf Ebrahimi 
13185*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_64_array[0] == INT64_C(0x1111111111111111));
13186*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_64_array[1] == INT64_C(0x1111111111111111));
13187*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_64_array[2] == INT64_C(0x3333333333333333));
13188*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_64_array[3] == INT64_C(0x3333333333333333));
13189*f5c631daSSadaf Ebrahimi     VIXL_CHECK(data_64_array[4] == INT64_C(0x1111111111111111));
13190*f5c631daSSadaf Ebrahimi   }
13191*f5c631daSSadaf Ebrahimi }
13192*f5c631daSSadaf Ebrahimi 
13193*f5c631daSSadaf Ebrahimi 
13194*f5c631daSSadaf Ebrahimi // Test feature detection of calls to runtime functions.
13195*f5c631daSSadaf Ebrahimi 
13196*f5c631daSSadaf Ebrahimi // C++11 should be sufficient to provide simulated runtime calls, except for a
13197*f5c631daSSadaf Ebrahimi // GCC bug before 4.9.1.
13198*f5c631daSSadaf Ebrahimi #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && (__cplusplus >= 201103L) && \
13199*f5c631daSSadaf Ebrahimi     (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1)) &&               \
13200*f5c631daSSadaf Ebrahimi     !defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT)
13201*f5c631daSSadaf Ebrahimi #error \
13202*f5c631daSSadaf Ebrahimi     "C++11 should be sufficient to provide support for simulated runtime calls."
13203*f5c631daSSadaf Ebrahimi #endif  // #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && ...
13204*f5c631daSSadaf Ebrahimi 
13205*f5c631daSSadaf Ebrahimi #if (__cplusplus >= 201103L) && \
13206*f5c631daSSadaf Ebrahimi     !defined(VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT)
13207*f5c631daSSadaf Ebrahimi #error \
13208*f5c631daSSadaf Ebrahimi     "C++11 should be sufficient to provide support for `MacroAssembler::CallRuntime()`."
13209*f5c631daSSadaf Ebrahimi #endif  // #if (__cplusplus >= 201103L) && ...
13210*f5c631daSSadaf Ebrahimi 
13211*f5c631daSSadaf Ebrahimi #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
runtime_call_add_one(int32_t a)13212*f5c631daSSadaf Ebrahimi int32_t runtime_call_add_one(int32_t a) { return a + 1; }
13213*f5c631daSSadaf Ebrahimi 
runtime_call_add_doubles(double a,double b,double c)13214*f5c631daSSadaf Ebrahimi double runtime_call_add_doubles(double a, double b, double c) {
13215*f5c631daSSadaf Ebrahimi   return a + b + c;
13216*f5c631daSSadaf Ebrahimi }
13217*f5c631daSSadaf Ebrahimi 
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)13218*f5c631daSSadaf Ebrahimi int64_t runtime_call_one_argument_on_stack(int64_t arg1 __attribute__((unused)),
13219*f5c631daSSadaf Ebrahimi                                            int64_t arg2 __attribute__((unused)),
13220*f5c631daSSadaf Ebrahimi                                            int64_t arg3 __attribute__((unused)),
13221*f5c631daSSadaf Ebrahimi                                            int64_t arg4 __attribute__((unused)),
13222*f5c631daSSadaf Ebrahimi                                            int64_t arg5 __attribute__((unused)),
13223*f5c631daSSadaf Ebrahimi                                            int64_t arg6 __attribute__((unused)),
13224*f5c631daSSadaf Ebrahimi                                            int64_t arg7 __attribute__((unused)),
13225*f5c631daSSadaf Ebrahimi                                            int64_t arg8 __attribute__((unused)),
13226*f5c631daSSadaf Ebrahimi                                            int64_t arg9) {
13227*f5c631daSSadaf Ebrahimi   return arg9;
13228*f5c631daSSadaf Ebrahimi }
13229*f5c631daSSadaf Ebrahimi 
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)13230*f5c631daSSadaf Ebrahimi double runtime_call_two_arguments_on_stack(int64_t arg1 __attribute__((unused)),
13231*f5c631daSSadaf Ebrahimi                                            int64_t arg2 __attribute__((unused)),
13232*f5c631daSSadaf Ebrahimi                                            int64_t arg3 __attribute__((unused)),
13233*f5c631daSSadaf Ebrahimi                                            int64_t arg4 __attribute__((unused)),
13234*f5c631daSSadaf Ebrahimi                                            int64_t arg5 __attribute__((unused)),
13235*f5c631daSSadaf Ebrahimi                                            int64_t arg6 __attribute__((unused)),
13236*f5c631daSSadaf Ebrahimi                                            int64_t arg7 __attribute__((unused)),
13237*f5c631daSSadaf Ebrahimi                                            int64_t arg8 __attribute__((unused)),
13238*f5c631daSSadaf Ebrahimi                                            double arg9,
13239*f5c631daSSadaf Ebrahimi                                            double arg10) {
13240*f5c631daSSadaf Ebrahimi   return arg9 - arg10;
13241*f5c631daSSadaf Ebrahimi }
13242*f5c631daSSadaf Ebrahimi 
runtime_call_store_at_address(int64_t * address)13243*f5c631daSSadaf Ebrahimi void runtime_call_store_at_address(int64_t* address) { *address = 0xf00d; }
13244*f5c631daSSadaf Ebrahimi 
13245*f5c631daSSadaf Ebrahimi enum RuntimeCallTestEnum { Enum0 };
13246*f5c631daSSadaf Ebrahimi 
runtime_call_enum(RuntimeCallTestEnum e)13247*f5c631daSSadaf Ebrahimi RuntimeCallTestEnum runtime_call_enum(RuntimeCallTestEnum e) { return e; }
13248*f5c631daSSadaf Ebrahimi 
13249*f5c631daSSadaf Ebrahimi enum class RuntimeCallTestEnumClass { Enum0 };
13250*f5c631daSSadaf Ebrahimi 
runtime_call_enum_class(RuntimeCallTestEnumClass e)13251*f5c631daSSadaf Ebrahimi RuntimeCallTestEnumClass runtime_call_enum_class(RuntimeCallTestEnumClass e) {
13252*f5c631daSSadaf Ebrahimi   return e;
13253*f5c631daSSadaf Ebrahimi }
13254*f5c631daSSadaf Ebrahimi 
test_int8_t(int8_t x)13255*f5c631daSSadaf Ebrahimi int8_t test_int8_t(int8_t x) { return x; }
test_uint8_t(uint8_t x)13256*f5c631daSSadaf Ebrahimi uint8_t test_uint8_t(uint8_t x) { return x; }
test_int16_t(int16_t x)13257*f5c631daSSadaf Ebrahimi int16_t test_int16_t(int16_t x) { return x; }
test_uint16_t(uint16_t x)13258*f5c631daSSadaf Ebrahimi uint16_t test_uint16_t(uint16_t x) { return x; }
13259*f5c631daSSadaf Ebrahimi 
TEST(runtime_calls)13260*f5c631daSSadaf Ebrahimi TEST(runtime_calls) {
13261*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(CPUFeatures::kFP);
13262*f5c631daSSadaf Ebrahimi 
13263*f5c631daSSadaf Ebrahimi #ifndef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
13264*f5c631daSSadaf Ebrahimi   if (masm.GenerateSimulatorCode()) {
13265*f5c631daSSadaf Ebrahimi     // This configuration is unsupported and a `VIXL_UNREACHABLE()` would fire
13266*f5c631daSSadaf Ebrahimi     // while trying to generate `CallRuntime`. This configuration should only be
13267*f5c631daSSadaf Ebrahimi     // reachable with C++11 and a (buggy) version of GCC pre-4.9.1.
13268*f5c631daSSadaf Ebrahimi     return;
13269*f5c631daSSadaf Ebrahimi   }
13270*f5c631daSSadaf Ebrahimi #endif
13271*f5c631daSSadaf Ebrahimi 
13272*f5c631daSSadaf Ebrahimi   START();
13273*f5c631daSSadaf Ebrahimi 
13274*f5c631daSSadaf Ebrahimi   // Test `CallRuntime`.
13275*f5c631daSSadaf Ebrahimi 
13276*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
13277*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_add_one);
13278*f5c631daSSadaf Ebrahimi   __ Mov(w20, w0);
13279*f5c631daSSadaf Ebrahimi 
13280*f5c631daSSadaf Ebrahimi   __ Fmov(d0, 0.0);
13281*f5c631daSSadaf Ebrahimi   __ Fmov(d1, 1.5);
13282*f5c631daSSadaf Ebrahimi   __ Fmov(d2, 2.5);
13283*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_add_doubles);
13284*f5c631daSSadaf Ebrahimi   __ Fmov(d20, d0);
13285*f5c631daSSadaf Ebrahimi 
13286*f5c631daSSadaf Ebrahimi   __ Mov(x0, 0x123);
13287*f5c631daSSadaf Ebrahimi   __ Push(x0, x0);
13288*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_one_argument_on_stack);
13289*f5c631daSSadaf Ebrahimi   __ Mov(x21, x0);
13290*f5c631daSSadaf Ebrahimi   __ Pop(x0, x1);
13291*f5c631daSSadaf Ebrahimi 
13292*f5c631daSSadaf Ebrahimi   __ Fmov(d0, 314.0);
13293*f5c631daSSadaf Ebrahimi   __ Fmov(d1, 4.0);
13294*f5c631daSSadaf Ebrahimi   __ Push(d1, d0);
13295*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_two_arguments_on_stack);
13296*f5c631daSSadaf Ebrahimi   __ Fmov(d21, d0);
13297*f5c631daSSadaf Ebrahimi   __ Pop(d1, d0);
13298*f5c631daSSadaf Ebrahimi 
13299*f5c631daSSadaf Ebrahimi   // Test that the template mechanisms don't break with enums.
13300*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
13301*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_enum);
13302*f5c631daSSadaf Ebrahimi   __ Mov(w0, 0);
13303*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_enum_class);
13304*f5c631daSSadaf Ebrahimi 
13305*f5c631daSSadaf Ebrahimi   // Test `TailCallRuntime`.
13306*f5c631daSSadaf Ebrahimi 
13307*f5c631daSSadaf Ebrahimi   Label function, after_function;
13308*f5c631daSSadaf Ebrahimi   __ B(&after_function);
13309*f5c631daSSadaf Ebrahimi   __ Bind(&function);
13310*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0);
13311*f5c631daSSadaf Ebrahimi   __ Mov(w0, 123);
13312*f5c631daSSadaf Ebrahimi   __ TailCallRuntime(runtime_call_add_one);
13313*f5c631daSSadaf Ebrahimi   // Control should not fall through.
13314*f5c631daSSadaf Ebrahimi   __ Mov(x22, 0xbad);
13315*f5c631daSSadaf Ebrahimi   __ Ret();
13316*f5c631daSSadaf Ebrahimi   __ Bind(&after_function);
13317*f5c631daSSadaf Ebrahimi 
13318*f5c631daSSadaf Ebrahimi   // Call our placeholder function, taking care to preserve the link register.
13319*f5c631daSSadaf Ebrahimi   __ Push(ip0, lr);
13320*f5c631daSSadaf Ebrahimi   __ Bl(&function);
13321*f5c631daSSadaf Ebrahimi   __ Pop(lr, ip0);
13322*f5c631daSSadaf Ebrahimi   // Save the result.
13323*f5c631daSSadaf Ebrahimi   __ Mov(w23, w0);
13324*f5c631daSSadaf Ebrahimi 
13325*f5c631daSSadaf Ebrahimi   __ Mov(x24, 0);
13326*f5c631daSSadaf Ebrahimi   int test_values[] = {static_cast<int8_t>(-1),
13327*f5c631daSSadaf Ebrahimi                        static_cast<uint8_t>(-1),
13328*f5c631daSSadaf Ebrahimi                        static_cast<int16_t>(-1),
13329*f5c631daSSadaf Ebrahimi                        static_cast<uint16_t>(-1),
13330*f5c631daSSadaf Ebrahimi                        -256,
13331*f5c631daSSadaf Ebrahimi                        -1,
13332*f5c631daSSadaf Ebrahimi                        0,
13333*f5c631daSSadaf Ebrahimi                        1,
13334*f5c631daSSadaf Ebrahimi                        256};
13335*f5c631daSSadaf Ebrahimi   for (size_t i = 0; i < sizeof(test_values) / sizeof(test_values[0]); ++i) {
13336*f5c631daSSadaf Ebrahimi     Label pass_int8, pass_uint8, pass_int16, pass_uint16;
13337*f5c631daSSadaf Ebrahimi     int x = test_values[i];
13338*f5c631daSSadaf Ebrahimi     __ Mov(w0, x);
13339*f5c631daSSadaf Ebrahimi     __ CallRuntime(test_int8_t);
13340*f5c631daSSadaf Ebrahimi     __ Sxtb(w0, w0);
13341*f5c631daSSadaf Ebrahimi     __ Cmp(w0, ExtractSignedBitfield32(7, 0, x));
13342*f5c631daSSadaf Ebrahimi     __ Cinc(x24, x24, ne);
13343*f5c631daSSadaf Ebrahimi     __ Mov(w0, x);
13344*f5c631daSSadaf Ebrahimi     __ CallRuntime(test_uint8_t);
13345*f5c631daSSadaf Ebrahimi     __ Uxtb(w0, w0);
13346*f5c631daSSadaf Ebrahimi     __ Cmp(w0, ExtractUnsignedBitfield32(7, 0, x));
13347*f5c631daSSadaf Ebrahimi     __ Cinc(x24, x24, ne);
13348*f5c631daSSadaf Ebrahimi     __ Mov(w0, x);
13349*f5c631daSSadaf Ebrahimi     __ CallRuntime(test_int16_t);
13350*f5c631daSSadaf Ebrahimi     __ Sxth(w0, w0);
13351*f5c631daSSadaf Ebrahimi     __ Cmp(w0, ExtractSignedBitfield32(15, 0, x));
13352*f5c631daSSadaf Ebrahimi     __ Cinc(x24, x24, ne);
13353*f5c631daSSadaf Ebrahimi     __ Mov(w0, x);
13354*f5c631daSSadaf Ebrahimi     __ CallRuntime(test_uint16_t);
13355*f5c631daSSadaf Ebrahimi     __ Uxth(w0, w0);
13356*f5c631daSSadaf Ebrahimi     __ Cmp(w0, ExtractUnsignedBitfield32(15, 0, x));
13357*f5c631daSSadaf Ebrahimi     __ Cinc(x24, x24, ne);
13358*f5c631daSSadaf Ebrahimi   }
13359*f5c631daSSadaf Ebrahimi 
13360*f5c631daSSadaf Ebrahimi 
13361*f5c631daSSadaf Ebrahimi   int64_t value = 0xbadbeef;
13362*f5c631daSSadaf Ebrahimi   __ Mov(x0, reinterpret_cast<uint64_t>(&value));
13363*f5c631daSSadaf Ebrahimi   __ CallRuntime(runtime_call_store_at_address);
13364*f5c631daSSadaf Ebrahimi 
13365*f5c631daSSadaf Ebrahimi   END();
13366*f5c631daSSadaf Ebrahimi 
13367*f5c631daSSadaf Ebrahimi #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || \
13368*f5c631daSSadaf Ebrahimi     !defined(VIXL_INCLUDE_SIMULATOR_AARCH64)
13369*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13370*f5c631daSSadaf Ebrahimi     RUN();
13371*f5c631daSSadaf Ebrahimi 
13372*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(1, w20);
13373*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(4.0, d20);
13374*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0x123, x21);
13375*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_FP64(310.0, d21);
13376*f5c631daSSadaf Ebrahimi     VIXL_CHECK(value == 0xf00d);
13377*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x22);
13378*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_32(124, w23);
13379*f5c631daSSadaf Ebrahimi     ASSERT_EQUAL_64(0, x24);
13380*f5c631daSSadaf Ebrahimi   }
13381*f5c631daSSadaf Ebrahimi #endif  // #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || ...
13382*f5c631daSSadaf Ebrahimi }
13383*f5c631daSSadaf Ebrahimi #endif  // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
13384*f5c631daSSadaf Ebrahimi 
13385*f5c631daSSadaf Ebrahimi 
TEST(optimised_mov_register)13386*f5c631daSSadaf Ebrahimi TEST(optimised_mov_register) {
13387*f5c631daSSadaf Ebrahimi   SETUP();
13388*f5c631daSSadaf Ebrahimi 
13389*f5c631daSSadaf Ebrahimi   START();
13390*f5c631daSSadaf Ebrahimi   Label start;
13391*f5c631daSSadaf Ebrahimi   __ Bind(&start);
13392*f5c631daSSadaf Ebrahimi   __ Mov(x0, x0);
13393*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0);
13394*f5c631daSSadaf Ebrahimi   __ Mov(w0, w0, kDiscardForSameWReg);
13395*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0);
13396*f5c631daSSadaf Ebrahimi   __ Mov(w0, w0);
13397*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == kInstructionSize);
13398*f5c631daSSadaf Ebrahimi 
13399*f5c631daSSadaf Ebrahimi   END();
13400*f5c631daSSadaf Ebrahimi 
13401*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13402*f5c631daSSadaf Ebrahimi     RUN();
13403*f5c631daSSadaf Ebrahimi   }
13404*f5c631daSSadaf Ebrahimi }
13405*f5c631daSSadaf Ebrahimi 
13406*f5c631daSSadaf Ebrahimi 
TEST(nop)13407*f5c631daSSadaf Ebrahimi TEST(nop) {
13408*f5c631daSSadaf Ebrahimi   MacroAssembler masm;
13409*f5c631daSSadaf Ebrahimi 
13410*f5c631daSSadaf Ebrahimi   Label start;
13411*f5c631daSSadaf Ebrahimi   __ Bind(&start);
13412*f5c631daSSadaf Ebrahimi   __ Nop();
13413*f5c631daSSadaf Ebrahimi   // `MacroAssembler::Nop` must generate at least one nop.
13414*f5c631daSSadaf Ebrahimi   VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= kInstructionSize);
13415*f5c631daSSadaf Ebrahimi 
13416*f5c631daSSadaf Ebrahimi   masm.FinalizeCode();
13417*f5c631daSSadaf Ebrahimi }
13418*f5c631daSSadaf Ebrahimi 
13419*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
13420*f5c631daSSadaf Ebrahimi // Test the pseudo-instructions that control CPUFeatures dynamically in the
13421*f5c631daSSadaf Ebrahimi // Simulator. These are used by the test infrastructure itself, but in a fairly
13422*f5c631daSSadaf Ebrahimi // limited way.
13423*f5c631daSSadaf Ebrahimi 
RunHelperWithFeatureCombinations(void (* helper)(const CPUFeatures & base,const CPUFeatures & f))13424*f5c631daSSadaf Ebrahimi static void RunHelperWithFeatureCombinations(
13425*f5c631daSSadaf Ebrahimi     void (*helper)(const CPUFeatures& base, const CPUFeatures& f)) {
13426*f5c631daSSadaf Ebrahimi   // Iterate, testing the first n features in this list.
13427*f5c631daSSadaf Ebrahimi   CPUFeatures::Feature features[] = {
13428*f5c631daSSadaf Ebrahimi       // Put kNone first, so that the first iteration uses an empty feature set.
13429*f5c631daSSadaf Ebrahimi       CPUFeatures::kNone,
13430*f5c631daSSadaf Ebrahimi       // The remaining features used are arbitrary.
13431*f5c631daSSadaf Ebrahimi       CPUFeatures::kIDRegisterEmulation,
13432*f5c631daSSadaf Ebrahimi       CPUFeatures::kDCPoP,
13433*f5c631daSSadaf Ebrahimi       CPUFeatures::kPAuth,
13434*f5c631daSSadaf Ebrahimi       CPUFeatures::kFcma,
13435*f5c631daSSadaf Ebrahimi       CPUFeatures::kAES,
13436*f5c631daSSadaf Ebrahimi       CPUFeatures::kNEON,
13437*f5c631daSSadaf Ebrahimi       CPUFeatures::kCRC32,
13438*f5c631daSSadaf Ebrahimi       CPUFeatures::kFP,
13439*f5c631daSSadaf Ebrahimi       CPUFeatures::kPmull1Q,
13440*f5c631daSSadaf Ebrahimi       CPUFeatures::kSM4,
13441*f5c631daSSadaf Ebrahimi       CPUFeatures::kSM3,
13442*f5c631daSSadaf Ebrahimi       CPUFeatures::kDotProduct,
13443*f5c631daSSadaf Ebrahimi   };
13444*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(CPUFeatures(CPUFeatures::kNone) == CPUFeatures::None());
13445*f5c631daSSadaf Ebrahimi   // The features are not necessarily encoded in kInstructionSize-sized slots,
13446*f5c631daSSadaf Ebrahimi   // so the MacroAssembler must pad the list to align the following instruction.
13447*f5c631daSSadaf Ebrahimi   // Ensure that we have enough features in the list to cover all interesting
13448*f5c631daSSadaf Ebrahimi   // alignment cases, even if the highest common factor of kInstructionSize and
13449*f5c631daSSadaf Ebrahimi   // an encoded feature is one.
13450*f5c631daSSadaf Ebrahimi   VIXL_STATIC_ASSERT(ARRAY_SIZE(features) > kInstructionSize);
13451*f5c631daSSadaf Ebrahimi 
13452*f5c631daSSadaf Ebrahimi   CPUFeatures base = CPUFeatures::None();
13453*f5c631daSSadaf Ebrahimi   for (size_t i = 0; i < ARRAY_SIZE(features); i++) {
13454*f5c631daSSadaf Ebrahimi     base.Combine(features[i]);
13455*f5c631daSSadaf Ebrahimi     CPUFeatures f = CPUFeatures::None();
13456*f5c631daSSadaf Ebrahimi     for (size_t j = 0; j < ARRAY_SIZE(features); j++) {
13457*f5c631daSSadaf Ebrahimi       f.Combine(features[j]);
13458*f5c631daSSadaf Ebrahimi       helper(base, f);
13459*f5c631daSSadaf Ebrahimi     }
13460*f5c631daSSadaf Ebrahimi   }
13461*f5c631daSSadaf Ebrahimi }
13462*f5c631daSSadaf Ebrahimi 
SetSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)13463*f5c631daSSadaf Ebrahimi static void SetSimulatorCPUFeaturesHelper(const CPUFeatures& base,
13464*f5c631daSSadaf Ebrahimi                                           const CPUFeatures& f) {
13465*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(base);
13466*f5c631daSSadaf Ebrahimi   START();
13467*f5c631daSSadaf Ebrahimi 
13468*f5c631daSSadaf Ebrahimi   __ SetSimulatorCPUFeatures(f);
13469*f5c631daSSadaf Ebrahimi 
13470*f5c631daSSadaf Ebrahimi   END();
13471*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13472*f5c631daSSadaf Ebrahimi     RUN_WITHOUT_SEEN_FEATURE_CHECK();
13473*f5c631daSSadaf Ebrahimi     VIXL_CHECK(*(simulator.GetCPUFeatures()) == f);
13474*f5c631daSSadaf Ebrahimi   }
13475*f5c631daSSadaf Ebrahimi }
13476*f5c631daSSadaf Ebrahimi 
TEST(configure_cpu_features_set)13477*f5c631daSSadaf Ebrahimi TEST(configure_cpu_features_set) {
13478*f5c631daSSadaf Ebrahimi   RunHelperWithFeatureCombinations(SetSimulatorCPUFeaturesHelper);
13479*f5c631daSSadaf Ebrahimi }
13480*f5c631daSSadaf Ebrahimi 
EnableSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)13481*f5c631daSSadaf Ebrahimi static void EnableSimulatorCPUFeaturesHelper(const CPUFeatures& base,
13482*f5c631daSSadaf Ebrahimi                                              const CPUFeatures& f) {
13483*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(base);
13484*f5c631daSSadaf Ebrahimi   START();
13485*f5c631daSSadaf Ebrahimi 
13486*f5c631daSSadaf Ebrahimi   __ EnableSimulatorCPUFeatures(f);
13487*f5c631daSSadaf Ebrahimi 
13488*f5c631daSSadaf Ebrahimi   END();
13489*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13490*f5c631daSSadaf Ebrahimi     RUN_WITHOUT_SEEN_FEATURE_CHECK();
13491*f5c631daSSadaf Ebrahimi     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.With(f));
13492*f5c631daSSadaf Ebrahimi   }
13493*f5c631daSSadaf Ebrahimi }
13494*f5c631daSSadaf Ebrahimi 
TEST(configure_cpu_features_enable)13495*f5c631daSSadaf Ebrahimi TEST(configure_cpu_features_enable) {
13496*f5c631daSSadaf Ebrahimi   RunHelperWithFeatureCombinations(EnableSimulatorCPUFeaturesHelper);
13497*f5c631daSSadaf Ebrahimi }
13498*f5c631daSSadaf Ebrahimi 
DisableSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)13499*f5c631daSSadaf Ebrahimi static void DisableSimulatorCPUFeaturesHelper(const CPUFeatures& base,
13500*f5c631daSSadaf Ebrahimi                                               const CPUFeatures& f) {
13501*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(base);
13502*f5c631daSSadaf Ebrahimi   START();
13503*f5c631daSSadaf Ebrahimi 
13504*f5c631daSSadaf Ebrahimi   __ DisableSimulatorCPUFeatures(f);
13505*f5c631daSSadaf Ebrahimi 
13506*f5c631daSSadaf Ebrahimi   END();
13507*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13508*f5c631daSSadaf Ebrahimi     RUN_WITHOUT_SEEN_FEATURE_CHECK();
13509*f5c631daSSadaf Ebrahimi     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.Without(f));
13510*f5c631daSSadaf Ebrahimi   }
13511*f5c631daSSadaf Ebrahimi }
13512*f5c631daSSadaf Ebrahimi 
TEST(configure_cpu_features_disable)13513*f5c631daSSadaf Ebrahimi TEST(configure_cpu_features_disable) {
13514*f5c631daSSadaf Ebrahimi   RunHelperWithFeatureCombinations(DisableSimulatorCPUFeaturesHelper);
13515*f5c631daSSadaf Ebrahimi }
13516*f5c631daSSadaf Ebrahimi 
SaveRestoreSimulatorCPUFeaturesHelper(const CPUFeatures & base,const CPUFeatures & f)13517*f5c631daSSadaf Ebrahimi static void SaveRestoreSimulatorCPUFeaturesHelper(const CPUFeatures& base,
13518*f5c631daSSadaf Ebrahimi                                                   const CPUFeatures& f) {
13519*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(base);
13520*f5c631daSSadaf Ebrahimi   START();
13521*f5c631daSSadaf Ebrahimi 
13522*f5c631daSSadaf Ebrahimi   {
13523*f5c631daSSadaf Ebrahimi     __ SaveSimulatorCPUFeatures();
13524*f5c631daSSadaf Ebrahimi     __ SetSimulatorCPUFeatures(f);
13525*f5c631daSSadaf Ebrahimi     {
13526*f5c631daSSadaf Ebrahimi       __ SaveSimulatorCPUFeatures();
13527*f5c631daSSadaf Ebrahimi       __ SetSimulatorCPUFeatures(CPUFeatures::All());
13528*f5c631daSSadaf Ebrahimi       __ RestoreSimulatorCPUFeatures();
13529*f5c631daSSadaf Ebrahimi     }
13530*f5c631daSSadaf Ebrahimi     __ RestoreSimulatorCPUFeatures();
13531*f5c631daSSadaf Ebrahimi   }
13532*f5c631daSSadaf Ebrahimi 
13533*f5c631daSSadaf Ebrahimi   END();
13534*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13535*f5c631daSSadaf Ebrahimi     RUN_WITHOUT_SEEN_FEATURE_CHECK();
13536*f5c631daSSadaf Ebrahimi     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base);
13537*f5c631daSSadaf Ebrahimi   }
13538*f5c631daSSadaf Ebrahimi }
13539*f5c631daSSadaf Ebrahimi 
TEST(configure_cpu_features_save_restore)13540*f5c631daSSadaf Ebrahimi TEST(configure_cpu_features_save_restore) {
13541*f5c631daSSadaf Ebrahimi   RunHelperWithFeatureCombinations(SaveRestoreSimulatorCPUFeaturesHelper);
13542*f5c631daSSadaf Ebrahimi }
13543*f5c631daSSadaf Ebrahimi 
SimulationCPUFeaturesScopeHelper(const CPUFeatures & base,const CPUFeatures & f)13544*f5c631daSSadaf Ebrahimi static void SimulationCPUFeaturesScopeHelper(const CPUFeatures& base,
13545*f5c631daSSadaf Ebrahimi                                              const CPUFeatures& f) {
13546*f5c631daSSadaf Ebrahimi   SETUP_WITH_FEATURES(base);
13547*f5c631daSSadaf Ebrahimi   START();
13548*f5c631daSSadaf Ebrahimi 
13549*f5c631daSSadaf Ebrahimi   {
13550*f5c631daSSadaf Ebrahimi     SimulationCPUFeaturesScope scope_a(&masm, f);
13551*f5c631daSSadaf Ebrahimi     {
13552*f5c631daSSadaf Ebrahimi       SimulationCPUFeaturesScope scope_b(&masm, CPUFeatures::All());
13553*f5c631daSSadaf Ebrahimi       {
13554*f5c631daSSadaf Ebrahimi         SimulationCPUFeaturesScope scope_c(&masm, CPUFeatures::None());
13555*f5c631daSSadaf Ebrahimi         // The scope arguments should combine with 'Enable', so we should be
13556*f5c631daSSadaf Ebrahimi         // able to use any CPUFeatures here.
13557*f5c631daSSadaf Ebrahimi         __ Fadd(v0.V4S(), v1.V4S(), v2.V4S());  // Requires {FP, NEON}.
13558*f5c631daSSadaf Ebrahimi       }
13559*f5c631daSSadaf Ebrahimi     }
13560*f5c631daSSadaf Ebrahimi   }
13561*f5c631daSSadaf Ebrahimi 
13562*f5c631daSSadaf Ebrahimi   END();
13563*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13564*f5c631daSSadaf Ebrahimi     RUN_WITHOUT_SEEN_FEATURE_CHECK();
13565*f5c631daSSadaf Ebrahimi     VIXL_CHECK(*(simulator.GetCPUFeatures()) == base);
13566*f5c631daSSadaf Ebrahimi   }
13567*f5c631daSSadaf Ebrahimi }
13568*f5c631daSSadaf Ebrahimi 
TEST(configure_cpu_features_scope)13569*f5c631daSSadaf Ebrahimi TEST(configure_cpu_features_scope) {
13570*f5c631daSSadaf Ebrahimi   RunHelperWithFeatureCombinations(SimulationCPUFeaturesScopeHelper);
13571*f5c631daSSadaf Ebrahimi }
13572*f5c631daSSadaf Ebrahimi #endif
13573*f5c631daSSadaf Ebrahimi 
13574*f5c631daSSadaf Ebrahimi 
13575*f5c631daSSadaf Ebrahimi #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
TEST(large_sim_stack)13576*f5c631daSSadaf Ebrahimi TEST(large_sim_stack) {
13577*f5c631daSSadaf Ebrahimi   SimStack builder;
13578*f5c631daSSadaf Ebrahimi   builder.SetUsableSize(16 * 1024);  // The default is 8kB.
13579*f5c631daSSadaf Ebrahimi   SimStack::Allocated stack = builder.Allocate();
13580*f5c631daSSadaf Ebrahimi   uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
13581*f5c631daSSadaf Ebrahimi   uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
13582*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM_SIM(std::move(stack));
13583*f5c631daSSadaf Ebrahimi   START();
13584*f5c631daSSadaf Ebrahimi 
13585*f5c631daSSadaf Ebrahimi   // Check that we can access the extremes of the stack.
13586*f5c631daSSadaf Ebrahimi   __ Mov(x0, base);
13587*f5c631daSSadaf Ebrahimi   __ Mov(x1, limit);
13588*f5c631daSSadaf Ebrahimi   __ Mov(x2, sp);
13589*f5c631daSSadaf Ebrahimi   __ Add(sp, x1, 1);  // Avoid accessing memory below `sp`.
13590*f5c631daSSadaf Ebrahimi 
13591*f5c631daSSadaf Ebrahimi   __ Mov(x10, 42);
13592*f5c631daSSadaf Ebrahimi   __ Poke(x10, 0);
13593*f5c631daSSadaf Ebrahimi   __ Peek(x10, base - limit - kXRegSizeInBytes - 1);
13594*f5c631daSSadaf Ebrahimi 
13595*f5c631daSSadaf Ebrahimi   __ Mov(sp, x2);
13596*f5c631daSSadaf Ebrahimi 
13597*f5c631daSSadaf Ebrahimi   END();
13598*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13599*f5c631daSSadaf Ebrahimi     RUN();
13600*f5c631daSSadaf Ebrahimi   }
13601*f5c631daSSadaf Ebrahimi }
13602*f5c631daSSadaf Ebrahimi 
13603*f5c631daSSadaf Ebrahimi #ifdef VIXL_NEGATIVE_TESTING
TEST(sim_stack_limit_guard_read)13604*f5c631daSSadaf Ebrahimi TEST(sim_stack_limit_guard_read) {
13605*f5c631daSSadaf Ebrahimi   SimStack builder;
13606*f5c631daSSadaf Ebrahimi   SimStack::Allocated stack = builder.Allocate();
13607*f5c631daSSadaf Ebrahimi   uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
13608*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM_SIM(std::move(stack));
13609*f5c631daSSadaf Ebrahimi   START();
13610*f5c631daSSadaf Ebrahimi 
13611*f5c631daSSadaf Ebrahimi   __ Mov(x1, limit);
13612*f5c631daSSadaf Ebrahimi   __ Mov(x2, sp);
13613*f5c631daSSadaf Ebrahimi   __ Add(sp, x1, 1);  // Avoid accessing memory below `sp`.
13614*f5c631daSSadaf Ebrahimi 
13615*f5c631daSSadaf Ebrahimi   // `sp` points to the lowest usable byte of the stack.
13616*f5c631daSSadaf Ebrahimi   __ Mov(w10, 42);
13617*f5c631daSSadaf Ebrahimi   __ Ldrb(w10, MemOperand(sp, -1));
13618*f5c631daSSadaf Ebrahimi 
13619*f5c631daSSadaf Ebrahimi   __ Mov(sp, x2);
13620*f5c631daSSadaf Ebrahimi 
13621*f5c631daSSadaf Ebrahimi   END();
13622*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13623*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
13624*f5c631daSSadaf Ebrahimi   }
13625*f5c631daSSadaf Ebrahimi }
13626*f5c631daSSadaf Ebrahimi 
TEST(sim_stack_limit_guard_write)13627*f5c631daSSadaf Ebrahimi TEST(sim_stack_limit_guard_write) {
13628*f5c631daSSadaf Ebrahimi   SimStack builder;
13629*f5c631daSSadaf Ebrahimi   SimStack::Allocated stack = builder.Allocate();
13630*f5c631daSSadaf Ebrahimi   uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
13631*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM_SIM(std::move(stack));
13632*f5c631daSSadaf Ebrahimi   START();
13633*f5c631daSSadaf Ebrahimi 
13634*f5c631daSSadaf Ebrahimi   __ Mov(x1, limit);
13635*f5c631daSSadaf Ebrahimi   __ Mov(x2, sp);
13636*f5c631daSSadaf Ebrahimi   __ Add(sp, x1, 1);  // Avoid accessing memory below `sp`.
13637*f5c631daSSadaf Ebrahimi 
13638*f5c631daSSadaf Ebrahimi   // `sp` points to the lowest usable byte of the stack.
13639*f5c631daSSadaf Ebrahimi   __ Mov(w10, 42);
13640*f5c631daSSadaf Ebrahimi   __ Strb(w10, MemOperand(sp, -1));
13641*f5c631daSSadaf Ebrahimi 
13642*f5c631daSSadaf Ebrahimi   __ Mov(sp, x2);
13643*f5c631daSSadaf Ebrahimi 
13644*f5c631daSSadaf Ebrahimi   END();
13645*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13646*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
13647*f5c631daSSadaf Ebrahimi   }
13648*f5c631daSSadaf Ebrahimi }
13649*f5c631daSSadaf Ebrahimi 
TEST(sim_stack_base_guard_read)13650*f5c631daSSadaf Ebrahimi TEST(sim_stack_base_guard_read) {
13651*f5c631daSSadaf Ebrahimi   SimStack builder;
13652*f5c631daSSadaf Ebrahimi   SimStack::Allocated stack = builder.Allocate();
13653*f5c631daSSadaf Ebrahimi   uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
13654*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM_SIM(std::move(stack));
13655*f5c631daSSadaf Ebrahimi   START();
13656*f5c631daSSadaf Ebrahimi 
13657*f5c631daSSadaf Ebrahimi   __ Mov(x0, base);
13658*f5c631daSSadaf Ebrahimi   // `base` (x0) is the byte after the highest usable byte of the stack.
13659*f5c631daSSadaf Ebrahimi   // The last byte of this access will hit the guard region.
13660*f5c631daSSadaf Ebrahimi   __ Mov(x10, 42);
13661*f5c631daSSadaf Ebrahimi   __ Ldr(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
13662*f5c631daSSadaf Ebrahimi 
13663*f5c631daSSadaf Ebrahimi   END();
13664*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13665*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
13666*f5c631daSSadaf Ebrahimi   }
13667*f5c631daSSadaf Ebrahimi }
13668*f5c631daSSadaf Ebrahimi 
TEST(sim_stack_base_guard_write)13669*f5c631daSSadaf Ebrahimi TEST(sim_stack_base_guard_write) {
13670*f5c631daSSadaf Ebrahimi   SimStack builder;
13671*f5c631daSSadaf Ebrahimi   SimStack::Allocated stack = builder.Allocate();
13672*f5c631daSSadaf Ebrahimi   uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
13673*f5c631daSSadaf Ebrahimi   SETUP_CUSTOM_SIM(std::move(stack));
13674*f5c631daSSadaf Ebrahimi   START();
13675*f5c631daSSadaf Ebrahimi 
13676*f5c631daSSadaf Ebrahimi   __ Mov(x0, base);
13677*f5c631daSSadaf Ebrahimi   // `base` (x0) is the byte after the highest usable byte of the stack.
13678*f5c631daSSadaf Ebrahimi   // The last byte of this access will hit the guard region.
13679*f5c631daSSadaf Ebrahimi   __ Mov(x10, 42);
13680*f5c631daSSadaf Ebrahimi   __ Str(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
13681*f5c631daSSadaf Ebrahimi 
13682*f5c631daSSadaf Ebrahimi   END();
13683*f5c631daSSadaf Ebrahimi   if (CAN_RUN()) {
13684*f5c631daSSadaf Ebrahimi     MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
13685*f5c631daSSadaf Ebrahimi   }
13686*f5c631daSSadaf Ebrahimi }
13687*f5c631daSSadaf Ebrahimi #endif
13688*f5c631daSSadaf Ebrahimi #endif
13689*f5c631daSSadaf Ebrahimi 
13690*f5c631daSSadaf Ebrahimi }  // namespace aarch64
13691*f5c631daSSadaf Ebrahimi }  // namespace vixl
13692