1 // Copyright 2017, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include <cstdio>
28 #include <cstring>
29 #include <string>
30
31 #include "test-runner.h"
32 #include "test-utils.h"
33 #include "aarch64/test-utils-aarch64.h"
34
35 #include "aarch64/macro-assembler-aarch64.h"
36 #include "aarch64/registers-aarch64.h"
37 #include "aarch64/simulator-aarch64.h"
38
39 #define __ masm.
40 #define TEST(name) TEST_(AARCH64_API_##name)
41
42
43 namespace vixl {
44 namespace aarch64 {
45
46 // Check compiler intrinsics helpers.
47
TEST(count_leading_sign_bits)48 TEST(count_leading_sign_bits) {
49 class Helper {
50 public:
51 static void Check(int64_t value, int non_sign_bits) {
52 VIXL_ASSERT((0 <= non_sign_bits) && (non_sign_bits < 64));
53
54 for (int width = 1; width <= 64; width *= 2) {
55 // Note that leading_sign_bits does not include the topmost bit.
56 int leading_sign_bits = width - non_sign_bits - 1;
57 if (leading_sign_bits < 0) continue;
58
59 int64_t result = CountLeadingSignBits(value, width);
60 int64_t fallback_result = CountLeadingSignBitsFallBack(value, width);
61 VIXL_CHECK(result == leading_sign_bits);
62 VIXL_CHECK(fallback_result == leading_sign_bits);
63 }
64 }
65 };
66
67 // Basic positive (and zero) cases. Sign bits are all zeroes.
68 Helper::Check(0, 0); // 0b++++
69 Helper::Check(1, 1); // 0b+++1
70 Helper::Check(2, 2); // 0b++10
71 Helper::Check(3, 2); // 0b++11
72 Helper::Check(4, 3); // 0b+100
73
74 // Basic negative cases. Sign bits are all ones.
75 Helper::Check(-1, 0); // 0b----
76 Helper::Check(-2, 1); // 0b---0
77 Helper::Check(-3, 2); // 0b--01
78 Helper::Check(-4, 2); // 0b--00
79 Helper::Check(-5, 3); // 0b-011
80
81 // Boundary conditions.
82 Helper::Check(INT8_MAX, 7);
83 Helper::Check(INT8_MIN, 7);
84 Helper::Check(static_cast<int64_t>(INT8_MAX) + 1, 8);
85 Helper::Check(static_cast<int64_t>(INT8_MIN) - 1, 8);
86
87 Helper::Check(INT16_MAX, 15);
88 Helper::Check(INT16_MIN, 15);
89 Helper::Check(static_cast<int64_t>(INT16_MAX) + 1, 16);
90 Helper::Check(static_cast<int64_t>(INT16_MIN) - 1, 16);
91
92 Helper::Check(INT32_MAX, 31);
93 Helper::Check(INT32_MIN, 31);
94 Helper::Check(static_cast<int64_t>(INT32_MAX) + 1, 32);
95 Helper::Check(static_cast<int64_t>(INT32_MIN) - 1, 32);
96
97 Helper::Check(INT64_MAX, 63);
98 Helper::Check(INT64_MIN, 63);
99
100 // Check automatic width detection.
101 VIXL_CHECK(CountLeadingSignBits(static_cast<int8_t>(42)) == 1); // 0b00101010
102 VIXL_CHECK(CountLeadingSignBits(static_cast<int16_t>(42)) == 9);
103 VIXL_CHECK(CountLeadingSignBits(static_cast<int32_t>(42)) == 25);
104 VIXL_CHECK(CountLeadingSignBits(static_cast<int64_t>(42)) == 57);
105 }
106
107 // Check SimFloat16 class mechanics.
TEST(float16_operators)108 TEST(float16_operators) {
109 ::vixl::internal::SimFloat16 f1 = kFP16DefaultNaN;
110 ::vixl::internal::SimFloat16 f2 = kFP16DefaultNaN;
111 ::vixl::internal::SimFloat16 f3 = kFP16PositiveInfinity;
112 ::vixl::internal::SimFloat16 f4 = kFP16NegativeInfinity;
113 VIXL_CHECK(!(f1 == f2));
114 VIXL_CHECK(f1 != f2);
115 VIXL_CHECK(!(f3 == f4));
116 VIXL_CHECK(f3 != f4);
117 VIXL_CHECK(::vixl::internal::SimFloat16(kFP16PositiveZero) ==
118 ::vixl::internal::SimFloat16(kFP16NegativeZero));
119 VIXL_CHECK(!(::vixl::internal::SimFloat16(kFP16PositiveZero) !=
120 ::vixl::internal::SimFloat16(kFP16NegativeZero)));
121 }
122
TEST(rawbits_conversions)123 TEST(rawbits_conversions) {
124 VIXL_CHECK(RawbitsToInt64(0x0) == 0x0);
125 VIXL_CHECK(RawbitsToInt64(0x123) == 0x123);
126 VIXL_CHECK(RawbitsToInt64(INT64_MAX) == INT64_MAX);
127 VIXL_CHECK(RawbitsToInt64(UINT64_C(0xffffffffffffffff)) == -1);
128 VIXL_CHECK(RawbitsToInt64(UINT64_C(0x8000000000000000)) == INT64_MIN);
129 VIXL_CHECK(RawbitsToInt64(UINT64_C(0x8000000000000001)) == -INT64_MAX);
130
131 VIXL_CHECK(RawbitsToInt32(0x0) == 0x0);
132 VIXL_CHECK(RawbitsToInt32(0x123) == 0x123);
133 VIXL_CHECK(RawbitsToInt32(INT32_MAX) == INT32_MAX);
134 VIXL_CHECK(RawbitsToInt32(UINT32_C(0xffffffff)) == -1);
135 VIXL_CHECK(RawbitsToInt32(UINT32_C(0x80000000)) == INT32_MIN);
136 VIXL_CHECK(RawbitsToInt32(UINT32_C(0x80000001)) == -INT32_MAX);
137 }
138
139 // Check moved FP constants are still accessible via the AArch64 namespace.
TEST(float_constants_scope)140 TEST(float_constants_scope) {
141 VIXL_CHECK(vixl::aarch64::kFP64PositiveInfinity ==
142 vixl::kFP64PositiveInfinity);
143 VIXL_CHECK(vixl::aarch64::kFP64NegativeInfinity ==
144 vixl::kFP64NegativeInfinity);
145 VIXL_CHECK(vixl::aarch64::kFP32PositiveInfinity ==
146 vixl::kFP32PositiveInfinity);
147 VIXL_CHECK(vixl::aarch64::kFP32NegativeInfinity ==
148 vixl::kFP32NegativeInfinity);
149 VIXL_CHECK(Float16ToRawbits(vixl::aarch64::kFP16PositiveInfinity) ==
150 Float16ToRawbits(vixl::aarch64::kFP16PositiveInfinity));
151 VIXL_CHECK(Float16ToRawbits(vixl::aarch64::kFP16NegativeInfinity) ==
152 Float16ToRawbits(vixl::aarch64::kFP16NegativeInfinity));
153 VIXL_CHECK(DoubleToRawbits(vixl::aarch64::kFP64DefaultNaN) ==
154 DoubleToRawbits(vixl::kFP64DefaultNaN));
155 VIXL_CHECK(FloatToRawbits(vixl::aarch64::kFP32DefaultNaN) ==
156 FloatToRawbits(vixl::kFP32DefaultNaN));
157 VIXL_CHECK(IsNaN(vixl::aarch64::kFP16DefaultNaN) ==
158 IsNaN(vixl::kFP16DefaultNaN));
159 VIXL_CHECK(vixl::aarch64::kDoubleExponentBits == vixl::kDoubleExponentBits);
160 VIXL_CHECK(vixl::aarch64::kDoubleMantissaBits == vixl::kDoubleMantissaBits);
161 VIXL_CHECK(vixl::aarch64::kFloatExponentBits == vixl::kFloatExponentBits);
162 VIXL_CHECK(vixl::aarch64::kFloatMantissaBits == vixl::kFloatMantissaBits);
163 VIXL_CHECK(vixl::aarch64::kFloat16ExponentBits == vixl::kFloat16ExponentBits);
164 VIXL_CHECK(vixl::aarch64::kFloat16MantissaBits == vixl::kFloat16MantissaBits);
165 }
166
167
TEST(register_bit)168 TEST(register_bit) {
169 VIXL_CHECK(x0.GetBit() == (UINT64_C(1) << 0));
170 VIXL_CHECK(x1.GetBit() == (UINT64_C(1) << 1));
171 VIXL_CHECK(x10.GetBit() == (UINT64_C(1) << 10));
172
173 // AAPCS64 definitions.
174 VIXL_CHECK(lr.GetBit() == (UINT64_C(1) << kLinkRegCode));
175
176 // Fixed (hardware) definitions.
177 VIXL_CHECK(xzr.GetBit() == (UINT64_C(1) << kZeroRegCode));
178
179 // Internal ABI definitions.
180 VIXL_CHECK(sp.GetBit() == (UINT64_C(1) << kSPRegInternalCode));
181 VIXL_CHECK(sp.GetBit() != xzr.GetBit());
182
183 // xn.GetBit() == wn.GetBit() at all times, for the same n.
184 VIXL_CHECK(x0.GetBit() == w0.GetBit());
185 VIXL_CHECK(x1.GetBit() == w1.GetBit());
186 VIXL_CHECK(x10.GetBit() == w10.GetBit());
187 VIXL_CHECK(xzr.GetBit() == wzr.GetBit());
188 VIXL_CHECK(sp.GetBit() == wsp.GetBit());
189 }
190
191
TEST(noreg)192 TEST(noreg) {
193 VIXL_CHECK(NoReg.Is(NoVReg));
194 VIXL_CHECK(NoVReg.Is(NoReg));
195
196 VIXL_CHECK(NoVReg.Is(NoReg));
197 VIXL_CHECK(NoReg.Is(NoVReg));
198
199 VIXL_CHECK(NoReg.Is(NoCPUReg));
200 VIXL_CHECK(NoCPUReg.Is(NoReg));
201
202 VIXL_CHECK(NoVReg.Is(NoCPUReg));
203 VIXL_CHECK(NoCPUReg.Is(NoVReg));
204
205 VIXL_CHECK(NoVReg.Is(NoCPUReg));
206 VIXL_CHECK(NoCPUReg.Is(NoVReg));
207
208 VIXL_CHECK(NoReg.IsNone());
209 VIXL_CHECK(NoVReg.IsNone());
210 VIXL_CHECK(NoCPUReg.IsNone());
211 }
212
213
TEST(constructors)214 TEST(constructors) {
215 // *Register(code)
216 VIXL_CHECK(WRegister(0).Is(w0));
217 VIXL_CHECK(XRegister(1).Is(x1));
218
219 VIXL_CHECK(BRegister(2).Is(b2));
220 VIXL_CHECK(HRegister(3).Is(h3));
221 VIXL_CHECK(SRegister(4).Is(s4));
222 VIXL_CHECK(DRegister(5).Is(d5));
223 VIXL_CHECK(QRegister(6).Is(q6));
224
225 VIXL_CHECK(ZRegister(7).Is(z7));
226 VIXL_CHECK(PRegister(8).Is(p8));
227 }
228
229
TEST(constructors_r)230 TEST(constructors_r) {
231 // Register(code, size_in_bits)
232 VIXL_CHECK(Register(0, kWRegSize).Is(w0));
233 VIXL_CHECK(Register(1, kXRegSize).Is(x1));
234 }
235
236
TEST(constructors_v)237 TEST(constructors_v) {
238 // VRegister(code)
239 VIXL_CHECK(VRegister(0).Is(v0));
240 VIXL_CHECK(VRegister(1).Is(v1));
241 VIXL_CHECK(VRegister(2).Is(v2));
242 VIXL_CHECK(VRegister(3).Is(v3));
243 VIXL_CHECK(VRegister(4).Is(v4));
244
245 // VRegister(code, size_in_bits)
246 VIXL_CHECK(VRegister(0, kBRegSize).Is(b0));
247 VIXL_CHECK(VRegister(1, kHRegSize).Is(h1));
248 VIXL_CHECK(VRegister(2, kSRegSize).Is(s2));
249 VIXL_CHECK(VRegister(3, kDRegSize).Is(d3));
250 VIXL_CHECK(VRegister(4, kQRegSize).Is(q4));
251
252 // VRegister(code, size_in_bits, lanes)
253 VIXL_CHECK(VRegister(0, kBRegSize, 1).Is(b0));
254 VIXL_CHECK(VRegister(1, kHRegSize, 1).Is(h1));
255 VIXL_CHECK(VRegister(2, kSRegSize, 1).Is(s2));
256 VIXL_CHECK(VRegister(3, kDRegSize, 1).Is(d3));
257 VIXL_CHECK(VRegister(4, kQRegSize, 1).Is(q4));
258
259 VIXL_CHECK(VRegister(0, kSRegSize, 2).Is(v0.V2H()));
260
261 VIXL_CHECK(VRegister(1, kDRegSize, 1).Is(v1.V1D()));
262 VIXL_CHECK(VRegister(2, kDRegSize, 2).Is(v2.V2S()));
263 VIXL_CHECK(VRegister(3, kDRegSize, 4).Is(v3.V4H()));
264 VIXL_CHECK(VRegister(4, kDRegSize, 8).Is(v4.V8B()));
265
266 VIXL_CHECK(VRegister(5, kQRegSize, 2).Is(v5.V2D()));
267 VIXL_CHECK(VRegister(6, kQRegSize, 4).Is(v6.V4S()));
268 VIXL_CHECK(VRegister(7, kQRegSize, 8).Is(v7.V8H()));
269 VIXL_CHECK(VRegister(8, kQRegSize, 16).Is(v8.V16B()));
270
271 // VRegister(code, format)
272 VIXL_CHECK(VRegister(0, kFormatB).Is(b0));
273 VIXL_CHECK(VRegister(1, kFormatH).Is(h1));
274 VIXL_CHECK(VRegister(2, kFormatS).Is(s2));
275 VIXL_CHECK(VRegister(3, kFormatD).Is(d3));
276 VIXL_CHECK(VRegister(4, kFormat8B).Is(v4.V8B()));
277 VIXL_CHECK(VRegister(5, kFormat16B).Is(v5.V16B()));
278 VIXL_CHECK(VRegister(6, kFormat2H).Is(v6.V2H()));
279 VIXL_CHECK(VRegister(7, kFormat4H).Is(v7.V4H()));
280 VIXL_CHECK(VRegister(8, kFormat8H).Is(v8.V8H()));
281 VIXL_CHECK(VRegister(9, kFormat2S).Is(v9.V2S()));
282 VIXL_CHECK(VRegister(10, kFormat4S).Is(v10.V4S()));
283 VIXL_CHECK(VRegister(11, kFormat1D).Is(v11.V1D()));
284 VIXL_CHECK(VRegister(12, kFormat2D).Is(v12.V2D()));
285 }
286
287
TEST(constructors_z)288 TEST(constructors_z) {
289 // ZRegister(code, lane_size_in_bits)
290 VIXL_CHECK(ZRegister(0, kBRegSize).Is(z0.VnB()));
291 VIXL_CHECK(ZRegister(1, kHRegSize).Is(z1.VnH()));
292 VIXL_CHECK(ZRegister(2, kSRegSize).Is(z2.VnS()));
293 VIXL_CHECK(ZRegister(3, kDRegSize).Is(z3.VnD()));
294
295 // ZRegister(code, format)
296 VIXL_CHECK(ZRegister(0, kFormatVnB).Is(z0.VnB()));
297 VIXL_CHECK(ZRegister(1, kFormatVnH).Is(z1.VnH()));
298 VIXL_CHECK(ZRegister(2, kFormatVnS).Is(z2.VnS()));
299 VIXL_CHECK(ZRegister(3, kFormatVnD).Is(z3.VnD()));
300 }
301
302
TEST(constructors_p)303 TEST(constructors_p) {
304 // ZRegister(code, lane_size_in_bits)
305 VIXL_CHECK(PRegisterWithLaneSize(0, kBRegSize).Is(p0.VnB()));
306 VIXL_CHECK(PRegisterWithLaneSize(1, kHRegSize).Is(p1.VnH()));
307 VIXL_CHECK(PRegisterWithLaneSize(2, kSRegSize).Is(p2.VnS()));
308 VIXL_CHECK(PRegisterWithLaneSize(3, kDRegSize).Is(p3.VnD()));
309
310 // ZRegister(code, format)
311 VIXL_CHECK(PRegisterWithLaneSize(0, kFormatVnB).Is(p0.VnB()));
312 VIXL_CHECK(PRegisterWithLaneSize(1, kFormatVnH).Is(p1.VnH()));
313 VIXL_CHECK(PRegisterWithLaneSize(2, kFormatVnS).Is(p2.VnS()));
314 VIXL_CHECK(PRegisterWithLaneSize(3, kFormatVnD).Is(p3.VnD()));
315
316 VIXL_CHECK(PRegisterZ(0).Is(p0.Zeroing()));
317 VIXL_CHECK(PRegisterM(1).Is(p1.Merging()));
318 }
319
320
TEST(constructors_cpu)321 TEST(constructors_cpu) {
322 // ZRegister(code, size_in_bits, type)
323 VIXL_CHECK(CPURegister(0, kWRegSize, CPURegister::kRegister).Is(w0));
324 VIXL_CHECK(CPURegister(1, kXRegSize, CPURegister::kRegister).Is(x1));
325
326 VIXL_CHECK(CPURegister(2, kBRegSize, CPURegister::kVRegister).Is(b2));
327 VIXL_CHECK(CPURegister(3, kHRegSize, CPURegister::kVRegister).Is(h3));
328 VIXL_CHECK(CPURegister(4, kSRegSize, CPURegister::kVRegister).Is(s4));
329 VIXL_CHECK(CPURegister(5, kDRegSize, CPURegister::kVRegister).Is(d5));
330 VIXL_CHECK(CPURegister(6, kQRegSize, CPURegister::kVRegister).Is(q6));
331 VIXL_CHECK(CPURegister(7, kQRegSize, CPURegister::kVRegister).Is(v7));
332
333 VIXL_CHECK(CPURegister(0, CPURegister::kUnknownSize, CPURegister::kVRegister)
334 .Is(z0));
335 VIXL_CHECK(CPURegister(1, CPURegister::kUnknownSize, CPURegister::kPRegister)
336 .Is(p1));
337 }
338
339
340 #ifdef __aarch64__
CPURegisterByValueHelper(CPURegister reg)341 static void CPURegisterByValueHelper(CPURegister reg) {
342 // Test that `reg` can be passed in one register. We'd like to use
343 // __attribute__((naked)) for this, but it isn't supported for AArch64, so
344 // generate a function using VIXL instead.
345
346 MacroAssembler masm;
347 // CPURegister fn(int placeholder, CPURegister reg);
348 // Move `reg` to its result register.
349 __ Mov(x0, x1);
350 // Clobber all other result registers.
351 __ Mov(x1, 0xfffffffffffffff1);
352 __ Mov(x2, 0xfffffffffffffff2);
353 __ Mov(x3, 0xfffffffffffffff3);
354 __ Mov(x4, 0xfffffffffffffff4);
355 __ Mov(x5, 0xfffffffffffffff5);
356 __ Mov(x6, 0xfffffffffffffff6);
357 __ Mov(x7, 0xfffffffffffffff7);
358 __ Ret();
359 masm.FinalizeCode();
360
361 CodeBuffer* buffer = masm.GetBuffer();
362 auto fn = buffer->GetStartAddress<CPURegister (*)(int, CPURegister)>();
363 buffer->SetExecutable();
364 CPURegister out = fn(42, reg);
365
366 VIXL_CHECK(out.Is(reg));
367 }
368
369
TEST(cpureg_by_value)370 TEST(cpureg_by_value) {
371 VIXL_STATIC_ASSERT(sizeof(CPURegister) <= sizeof(void*));
372 // Check some arbitrary registers to try to exercise each encoding field.
373 CPURegisterByValueHelper(x0);
374 CPURegisterByValueHelper(v31.V8H());
375 CPURegisterByValueHelper(z16.VnD());
376 CPURegisterByValueHelper(p15.Merging());
377 }
378 #endif // __aarch64__
379
380
TEST(isvalid)381 TEST(isvalid) {
382 VIXL_CHECK(!NoReg.IsValid());
383 VIXL_CHECK(!NoVReg.IsValid());
384 VIXL_CHECK(!NoCPUReg.IsValid());
385
386 VIXL_CHECK(x0.IsValid());
387 VIXL_CHECK(w0.IsValid());
388 VIXL_CHECK(x30.IsValid());
389 VIXL_CHECK(w30.IsValid());
390 VIXL_CHECK(xzr.IsValid());
391 VIXL_CHECK(wzr.IsValid());
392
393 VIXL_CHECK(sp.IsValid());
394 VIXL_CHECK(wsp.IsValid());
395
396 VIXL_CHECK(d0.IsValid());
397 VIXL_CHECK(s0.IsValid());
398 VIXL_CHECK(d31.IsValid());
399 VIXL_CHECK(s31.IsValid());
400
401 VIXL_CHECK(x0.IsValidRegister());
402 VIXL_CHECK(w0.IsValidRegister());
403 VIXL_CHECK(xzr.IsValidRegister());
404 VIXL_CHECK(wzr.IsValidRegister());
405 VIXL_CHECK(sp.IsValidRegister());
406 VIXL_CHECK(wsp.IsValidRegister());
407 VIXL_CHECK(!x0.IsValidVRegister());
408 VIXL_CHECK(!w0.IsValidVRegister());
409 VIXL_CHECK(!xzr.IsValidVRegister());
410 VIXL_CHECK(!wzr.IsValidVRegister());
411 VIXL_CHECK(!sp.IsValidVRegister());
412 VIXL_CHECK(!wsp.IsValidVRegister());
413 VIXL_CHECK(!x0.IsValidFPRegister());
414 VIXL_CHECK(!w0.IsValidFPRegister());
415 VIXL_CHECK(!xzr.IsValidFPRegister());
416 VIXL_CHECK(!wzr.IsValidFPRegister());
417 VIXL_CHECK(!sp.IsValidFPRegister());
418 VIXL_CHECK(!wsp.IsValidFPRegister());
419
420 VIXL_CHECK(q0.IsValidVRegister());
421 VIXL_CHECK(!q0.IsValidFPRegister());
422 VIXL_CHECK(!q0.IsValidRegister());
423
424 VIXL_CHECK(d0.IsValidVRegister());
425 VIXL_CHECK(d0.IsValidFPRegister());
426 VIXL_CHECK(!d0.IsValidRegister());
427
428 VIXL_CHECK(s0.IsValidVRegister());
429 VIXL_CHECK(s0.IsValidFPRegister());
430 VIXL_CHECK(!s0.IsValidRegister());
431
432 VIXL_CHECK(h0.IsValidVRegister());
433 VIXL_CHECK(h0.IsValidFPRegister());
434 VIXL_CHECK(!h0.IsValidRegister());
435
436 VIXL_CHECK(b0.IsValidVRegister());
437 VIXL_CHECK(!b0.IsValidFPRegister());
438 VIXL_CHECK(!b0.IsValidRegister());
439
440 // IsValidFPRegister() is only true for scalar types.
441 VIXL_CHECK(q0.V2D().IsValidVRegister());
442 VIXL_CHECK(!q0.V2D().IsValidFPRegister());
443 VIXL_CHECK(d0.V2S().IsValidVRegister());
444 VIXL_CHECK(!d0.V2S().IsValidFPRegister());
445 VIXL_CHECK(s0.V2H().IsValidVRegister());
446 VIXL_CHECK(!s0.V2H().IsValidFPRegister());
447 }
448
449
TEST(isvalid_cpu)450 TEST(isvalid_cpu) {
451 // As 'isvalid', but using CPURegister types where possible. This shouldn't
452 // make any difference.
453 VIXL_CHECK(!static_cast<CPURegister>(NoReg).IsValid());
454 VIXL_CHECK(!static_cast<CPURegister>(NoVReg).IsValid());
455 VIXL_CHECK(!static_cast<CPURegister>(NoCPUReg).IsValid());
456
457 VIXL_CHECK(static_cast<CPURegister>(x0).IsValid());
458 VIXL_CHECK(static_cast<CPURegister>(w0).IsValid());
459 VIXL_CHECK(static_cast<CPURegister>(x30).IsValid());
460 VIXL_CHECK(static_cast<CPURegister>(w30).IsValid());
461 VIXL_CHECK(static_cast<CPURegister>(xzr).IsValid());
462 VIXL_CHECK(static_cast<CPURegister>(wzr).IsValid());
463
464 VIXL_CHECK(static_cast<CPURegister>(sp).IsValid());
465 VIXL_CHECK(static_cast<CPURegister>(wsp).IsValid());
466
467 VIXL_CHECK(static_cast<CPURegister>(d0).IsValid());
468 VIXL_CHECK(static_cast<CPURegister>(s0).IsValid());
469 VIXL_CHECK(static_cast<CPURegister>(d31).IsValid());
470 VIXL_CHECK(static_cast<CPURegister>(s31).IsValid());
471
472 VIXL_CHECK(static_cast<CPURegister>(x0).IsValidRegister());
473 VIXL_CHECK(static_cast<CPURegister>(w0).IsValidRegister());
474 VIXL_CHECK(static_cast<CPURegister>(xzr).IsValidRegister());
475 VIXL_CHECK(static_cast<CPURegister>(wzr).IsValidRegister());
476 VIXL_CHECK(static_cast<CPURegister>(sp).IsValidRegister());
477 VIXL_CHECK(static_cast<CPURegister>(wsp).IsValidRegister());
478 VIXL_CHECK(!static_cast<CPURegister>(x0).IsValidVRegister());
479 VIXL_CHECK(!static_cast<CPURegister>(w0).IsValidVRegister());
480 VIXL_CHECK(!static_cast<CPURegister>(xzr).IsValidVRegister());
481 VIXL_CHECK(!static_cast<CPURegister>(wzr).IsValidVRegister());
482 VIXL_CHECK(!static_cast<CPURegister>(sp).IsValidVRegister());
483 VIXL_CHECK(!static_cast<CPURegister>(wsp).IsValidVRegister());
484 VIXL_CHECK(!static_cast<CPURegister>(x0).IsValidFPRegister());
485 VIXL_CHECK(!static_cast<CPURegister>(w0).IsValidFPRegister());
486 VIXL_CHECK(!static_cast<CPURegister>(xzr).IsValidFPRegister());
487 VIXL_CHECK(!static_cast<CPURegister>(wzr).IsValidFPRegister());
488 VIXL_CHECK(!static_cast<CPURegister>(sp).IsValidFPRegister());
489 VIXL_CHECK(!static_cast<CPURegister>(wsp).IsValidFPRegister());
490
491 VIXL_CHECK(static_cast<CPURegister>(q0).IsValidVRegister());
492 VIXL_CHECK(!static_cast<CPURegister>(q0).IsValidFPRegister());
493 VIXL_CHECK(!static_cast<CPURegister>(q0).IsValidRegister());
494
495 VIXL_CHECK(static_cast<CPURegister>(d0).IsValidVRegister());
496 VIXL_CHECK(static_cast<CPURegister>(d0).IsValidFPRegister());
497 VIXL_CHECK(!static_cast<CPURegister>(d0).IsValidRegister());
498
499 VIXL_CHECK(static_cast<CPURegister>(s0).IsValidVRegister());
500 VIXL_CHECK(static_cast<CPURegister>(s0).IsValidFPRegister());
501 VIXL_CHECK(!static_cast<CPURegister>(s0).IsValidRegister());
502
503 VIXL_CHECK(static_cast<CPURegister>(h0).IsValidVRegister());
504 VIXL_CHECK(static_cast<CPURegister>(h0).IsValidFPRegister());
505 VIXL_CHECK(!static_cast<CPURegister>(h0).IsValidRegister());
506
507 VIXL_CHECK(static_cast<CPURegister>(b0).IsValidVRegister());
508 VIXL_CHECK(!static_cast<CPURegister>(b0).IsValidFPRegister());
509 VIXL_CHECK(!static_cast<CPURegister>(b0).IsValidRegister());
510 }
511
512
TEST(areconsecutive)513 TEST(areconsecutive) {
514 VIXL_CHECK(AreConsecutive(b0, NoVReg));
515 VIXL_CHECK(AreConsecutive(b1, b2));
516 VIXL_CHECK(AreConsecutive(b3, b4, b5));
517 VIXL_CHECK(AreConsecutive(b6, b7, b8, b9));
518 VIXL_CHECK(AreConsecutive(h10, NoVReg));
519 VIXL_CHECK(AreConsecutive(h11, h12));
520 VIXL_CHECK(AreConsecutive(h13, h14, h15));
521 VIXL_CHECK(AreConsecutive(h16, h17, h18, h19));
522 VIXL_CHECK(AreConsecutive(s20, NoVReg));
523 VIXL_CHECK(AreConsecutive(s21, s22));
524 VIXL_CHECK(AreConsecutive(s23, s24, s25));
525 VIXL_CHECK(AreConsecutive(s26, s27, s28, s29));
526 VIXL_CHECK(AreConsecutive(d30, NoVReg));
527 VIXL_CHECK(AreConsecutive(d31, d0));
528 VIXL_CHECK(AreConsecutive(d1, d2, d3));
529 VIXL_CHECK(AreConsecutive(d4, d5, d6, d7));
530 VIXL_CHECK(AreConsecutive(q8, NoVReg));
531 VIXL_CHECK(AreConsecutive(q9, q10));
532 VIXL_CHECK(AreConsecutive(q11, q12, q13));
533 VIXL_CHECK(AreConsecutive(q14, q15, q16, q17));
534 VIXL_CHECK(AreConsecutive(v18, NoVReg));
535 VIXL_CHECK(AreConsecutive(v19, v20));
536 VIXL_CHECK(AreConsecutive(v21, v22, v23));
537 VIXL_CHECK(AreConsecutive(v24, v25, v26, v27));
538 VIXL_CHECK(AreConsecutive(b29, h30));
539 VIXL_CHECK(AreConsecutive(s31, d0, q1));
540 VIXL_CHECK(AreConsecutive(v2, b3, h4, s5));
541
542 VIXL_CHECK(!AreConsecutive(b0, b2));
543 VIXL_CHECK(!AreConsecutive(h1, h0));
544 VIXL_CHECK(!AreConsecutive(s31, s1));
545 VIXL_CHECK(!AreConsecutive(d12, d12));
546 VIXL_CHECK(!AreConsecutive(q31, q1));
547
548 VIXL_CHECK(!AreConsecutive(b0, b1, b3));
549 VIXL_CHECK(!AreConsecutive(h4, h5, h6, h6));
550 VIXL_CHECK(!AreConsecutive(d11, d13, NoVReg, d14));
551 VIXL_CHECK(!AreConsecutive(d15, d16, d18, NoVReg));
552 VIXL_CHECK(!AreConsecutive(b26, b28, NoVReg, b29));
553 VIXL_CHECK(!AreConsecutive(s28, s30, NoVReg, NoVReg));
554
555 VIXL_CHECK(AreConsecutive(q19, NoVReg, NoVReg, q22));
556 VIXL_CHECK(AreConsecutive(v23, NoVReg, v25, NoVReg));
557 VIXL_CHECK(AreConsecutive(b26, b27, NoVReg, NoVReg));
558 VIXL_CHECK(AreConsecutive(h28, NoVReg, NoVReg, NoVReg));
559 VIXL_CHECK(AreConsecutive(s30, s31, NoVReg, s2));
560 VIXL_CHECK(AreConsecutive(d3, NoVReg, d6, d7));
561 }
562
563
TEST(sve_p_registers)564 TEST(sve_p_registers) {
565 enum Qualification { kNone, kZeroing, kMerging, kWithLaneSize };
566 class Helper {
567 public:
568 static Qualification GetQualification(PRegister) { return kNone; }
569 static Qualification GetQualification(PRegisterZ) { return kZeroing; }
570 static Qualification GetQualification(PRegisterM) { return kMerging; }
571 static Qualification GetQualification(PRegisterWithLaneSize) {
572 return kWithLaneSize;
573 }
574 };
575
576 VIXL_CHECK(kNumberOfPRegisters == 16);
577 VIXL_CHECK(p0.GetCode() == 0);
578 VIXL_CHECK(p15.GetCode() == 15);
579 VIXL_CHECK(p14.VnB().GetLaneSizeInBits() == kBRegSize);
580 VIXL_CHECK(p14.VnH().GetLaneSizeInBits() == kHRegSize);
581 VIXL_CHECK(p14.VnS().GetLaneSizeInBits() == kSRegSize);
582 VIXL_CHECK(p14.VnD().GetLaneSizeInBits() == kDRegSize);
583 VIXL_CHECK(p14.VnB().GetLaneSizeInBytes() == kBRegSizeInBytes);
584 VIXL_CHECK(p14.VnH().GetLaneSizeInBytes() == kHRegSizeInBytes);
585 VIXL_CHECK(p14.VnS().GetLaneSizeInBytes() == kSRegSizeInBytes);
586 VIXL_CHECK(p14.VnD().GetLaneSizeInBytes() == kDRegSizeInBytes);
587 VIXL_CHECK(Helper::GetQualification(p1) == kNone);
588 VIXL_CHECK(Helper::GetQualification(p2.Zeroing()) == kZeroing);
589 VIXL_CHECK(Helper::GetQualification(p3.Merging()) == kMerging);
590 VIXL_CHECK(Helper::GetQualification(p4.VnB()) == kWithLaneSize);
591 VIXL_CHECK(Helper::GetQualification(p5.VnH()) == kWithLaneSize);
592 VIXL_CHECK(Helper::GetQualification(p6.VnS()) == kWithLaneSize);
593 VIXL_CHECK(Helper::GetQualification(p7.VnD()) == kWithLaneSize);
594 }
595
596
TEST(sve_z_registers)597 TEST(sve_z_registers) {
598 VIXL_CHECK(z0.GetCode() == 0);
599 VIXL_CHECK(z31.GetCode() == 31);
600
601 VIXL_CHECK(z0.Is(z0));
602 VIXL_CHECK(!z0.Is(z1));
603 VIXL_CHECK(!z0.Is(v0));
604 VIXL_CHECK(!z0.Is(b0));
605 VIXL_CHECK(!z0.Is(q0));
606
607 VIXL_CHECK(AreAliased(z5, z5));
608 VIXL_CHECK(AreAliased(z5, b5));
609 VIXL_CHECK(AreAliased(b5, z5));
610 VIXL_CHECK(AreAliased(z5, z5.B()));
611 VIXL_CHECK(AreAliased(z5, z5.VnB()));
612
613 VIXL_CHECK(!AreAliased(z6, z7));
614 VIXL_CHECK(!AreAliased(b6, z7));
615 VIXL_CHECK(!AreAliased(x7, z7));
616 }
617
618
TEST(sve_z_registers_vs_neon)619 TEST(sve_z_registers_vs_neon) {
620 // There are three related register variants to consider in VIXL's API:
621 //
622 // "b0": NEON: The least-significant byte of v0.
623 // "v0.B": NEON: v0, with an unspecified number of byte-sized lanes.
624 // "z0.B": SVE: z0, with an unspecified number of byte-sized lanes.
625 //
626 // The first two cases are indistinguishable in VIXL; both are obtained using
627 // something like `v0.B()`. This is fine for NEON because there is no
628 // ambiguity in practice; the "v0.B" form is always used with an index that
629 // makes the meaning clear.
630
631 VIXL_ASSERT(v6.B().Is(b6));
632 VIXL_ASSERT(v7.H().Is(h7));
633 VIXL_ASSERT(v8.S().Is(s8));
634 VIXL_ASSERT(v9.D().Is(d9));
635
636 VIXL_ASSERT(z6.B().Is(b6));
637 VIXL_ASSERT(z7.H().Is(h7));
638 VIXL_ASSERT(z8.S().Is(s8));
639 VIXL_ASSERT(z9.D().Is(d9));
640
641 // We cannot use the same approach for SVE's "z0.B" because, for example,
642 // `Add(VRegister, ...)` and `Add(ZRegister, ...)` generate different
643 // instructions.
644
645 // Test that the variants can be distinguished with `Is`.
646 VIXL_CHECK(!z6.VnB().Is(b6));
647 VIXL_CHECK(!z7.VnH().Is(h7));
648 VIXL_CHECK(!z8.VnS().Is(s8));
649 VIXL_CHECK(!z9.VnD().Is(d9));
650
651 VIXL_CHECK(!z6.VnB().Is(v6.B()));
652 VIXL_CHECK(!z7.VnH().Is(v7.H()));
653 VIXL_CHECK(!z8.VnS().Is(v8.S()));
654 VIXL_CHECK(!z9.VnD().Is(v9.D()));
655
656 VIXL_CHECK(!z6.VnB().Is(z6.B()));
657 VIXL_CHECK(!z7.VnH().Is(z7.H()));
658 VIXL_CHECK(!z8.VnS().Is(z8.S()));
659 VIXL_CHECK(!z9.VnD().Is(z9.D()));
660
661 // Test that the variants can be distinguished at compile-time using
662 // overloading. VIXL's API relies on this.
663 enum Variant { kNEON, kSVE, kUnknown };
664 class Helper {
665 public:
666 static Variant GetVariant(ZRegister) { return kSVE; }
667 static Variant GetVariant(VRegister) { return kNEON; }
668 static Variant GetVariant(CPURegister) { return kUnknown; }
669 };
670 VIXL_CHECK(Helper::GetVariant(z10.VnB()) == kSVE);
671 VIXL_CHECK(Helper::GetVariant(z11.VnH()) == kSVE);
672 VIXL_CHECK(Helper::GetVariant(z12.VnS()) == kSVE);
673 VIXL_CHECK(Helper::GetVariant(z13.VnD()) == kSVE);
674
675 VIXL_CHECK(Helper::GetVariant(v10.B()) == kNEON);
676 VIXL_CHECK(Helper::GetVariant(v11.H()) == kNEON);
677 VIXL_CHECK(Helper::GetVariant(v12.S()) == kNEON);
678 VIXL_CHECK(Helper::GetVariant(v13.D()) == kNEON);
679
680 VIXL_CHECK(Helper::GetVariant(v10.V16B()) == kNEON);
681 VIXL_CHECK(Helper::GetVariant(v11.V8H()) == kNEON);
682 VIXL_CHECK(Helper::GetVariant(v12.V4S()) == kNEON);
683 VIXL_CHECK(Helper::GetVariant(v13.V2D()) == kNEON);
684
685 VIXL_CHECK(Helper::GetVariant(b10) == kNEON);
686 VIXL_CHECK(Helper::GetVariant(h11) == kNEON);
687 VIXL_CHECK(Helper::GetVariant(s12) == kNEON);
688 VIXL_CHECK(Helper::GetVariant(d13) == kNEON);
689 }
690
691
TEST(move_immediate_helpers)692 TEST(move_immediate_helpers) {
693 // Using these helpers to query information (without generating code) should
694 // not crash.
695 MacroAssembler::MoveImmediateHelper(NULL, x0, 0x12345678);
696 MacroAssembler::OneInstrMoveImmediateHelper(NULL, x1, 0xabcdef);
697 }
698
699
TEST(generic_operand_helpers)700 TEST(generic_operand_helpers) {
701 GenericOperand invalid_1;
702 GenericOperand invalid_2;
703 GenericOperand reg(x3);
704 GenericOperand mem(MemOperand(sp, 8), kXRegSizeInBytes);
705
706 VIXL_CHECK(!invalid_1.IsValid());
707 VIXL_CHECK(!invalid_2.IsValid());
708
709 VIXL_CHECK(invalid_1.Equals(invalid_1));
710 VIXL_CHECK(invalid_2.Equals(invalid_2));
711 VIXL_CHECK(reg.Equals(reg));
712 VIXL_CHECK(mem.Equals(mem));
713
714 VIXL_CHECK(invalid_1.Equals(invalid_2));
715 VIXL_CHECK(invalid_2.Equals(invalid_1));
716
717 VIXL_CHECK(!invalid_1.Equals(reg));
718 VIXL_CHECK(!invalid_1.Equals(mem));
719 VIXL_CHECK(!reg.Equals(invalid_1));
720 VIXL_CHECK(!reg.Equals(invalid_2));
721 VIXL_CHECK(!reg.Equals(mem));
722 VIXL_CHECK(!mem.Equals(invalid_1));
723 VIXL_CHECK(!mem.Equals(reg));
724 }
725
726
TEST(integer_operand_is)727 TEST(integer_operand_is) {
728 VIXL_CHECK(IntegerOperand(0).IsZero());
729 VIXL_CHECK(!IntegerOperand(1).IsZero());
730 VIXL_CHECK(!IntegerOperand(-1).IsZero());
731
732 VIXL_CHECK(!IntegerOperand(-0x81).IsIntN(8));
733 VIXL_CHECK(IntegerOperand(-0x80).IsIntN(8));
734 VIXL_CHECK(IntegerOperand(-1).IsIntN(8));
735 VIXL_CHECK(IntegerOperand(0).IsIntN(8));
736 VIXL_CHECK(IntegerOperand(1).IsIntN(8));
737 VIXL_CHECK(IntegerOperand(0x7f).IsIntN(8));
738 VIXL_CHECK(!IntegerOperand(0x80).IsIntN(8));
739
740 VIXL_CHECK(!IntegerOperand(-1).IsUintN(8));
741 VIXL_CHECK(IntegerOperand(0).IsUintN(8));
742 VIXL_CHECK(IntegerOperand(1).IsUintN(8));
743 VIXL_CHECK(IntegerOperand(0xff).IsUintN(8));
744 VIXL_CHECK(!IntegerOperand(0x100).IsUintN(8));
745
746 VIXL_CHECK(IntegerOperand(INT64_MIN).IsIntN(64));
747 VIXL_CHECK(IntegerOperand(0).IsIntN(64));
748 VIXL_CHECK(IntegerOperand(INT64_MAX).IsIntN(64));
749 VIXL_CHECK(!IntegerOperand(0x8000000000000000).IsIntN(64));
750
751 VIXL_CHECK(!IntegerOperand(-1).IsUintN(64));
752 VIXL_CHECK(IntegerOperand(0).IsUintN(64));
753 VIXL_CHECK(IntegerOperand(UINT64_MAX).IsUintN(64));
754
755 VIXL_CHECK(!IntegerOperand(-0x801).FitsInBits(12));
756 VIXL_CHECK(IntegerOperand(-0x800).FitsInBits(12));
757 VIXL_CHECK(IntegerOperand(0).FitsInBits(12));
758 VIXL_CHECK(IntegerOperand(0x7ff).FitsInBits(12));
759 VIXL_CHECK(IntegerOperand(0x800).FitsInBits(12));
760 VIXL_CHECK(IntegerOperand(0xfff).FitsInBits(12));
761 VIXL_CHECK(!IntegerOperand(0x1000).FitsInBits(12));
762
763 VIXL_CHECK(!IntegerOperand(-0x8001).FitsInLane(z0.VnH()));
764 VIXL_CHECK(IntegerOperand(-0x8000).FitsInLane(z0.VnH()));
765 VIXL_CHECK(IntegerOperand(0).FitsInLane(z0.VnH()));
766 VIXL_CHECK(IntegerOperand(0x7fff).FitsInLane(z0.VnH()));
767 VIXL_CHECK(IntegerOperand(0x8000).FitsInLane(z0.VnH()));
768 VIXL_CHECK(IntegerOperand(0xffff).FitsInLane(z0.VnH()));
769 VIXL_CHECK(!IntegerOperand(0x10000).FitsInLane(z0.VnH()));
770 }
771
TEST(integer_operand_as_uint)772 TEST(integer_operand_as_uint) {
773 // Simple cases.
774 VIXL_CHECK(IntegerOperand(1).AsUintN(8) == 1);
775 VIXL_CHECK(IntegerOperand(1).AsUintN(16) == 1);
776 VIXL_CHECK(IntegerOperand(1).AsUintN(32) == 1);
777 VIXL_CHECK(IntegerOperand(1).AsUintN(64) == 1);
778 VIXL_CHECK(IntegerOperand(-1).AsUintN(8) == 0xff);
779 VIXL_CHECK(IntegerOperand(-1).AsUintN(16) == 0xffff);
780 VIXL_CHECK(IntegerOperand(-1).AsUintN(32) == 0xffffffff);
781 VIXL_CHECK(IntegerOperand(-1).AsUintN(64) == 0xffffffffffffffff);
782 VIXL_CHECK(IntegerOperand(0xf0).AsUintN(8) == 0xf0);
783 VIXL_CHECK(IntegerOperand(0xf420).AsUintN(16) == 0xf420);
784 VIXL_CHECK(IntegerOperand(0xf4242420).AsUintN(32) == 0xf4242420);
785 VIXL_CHECK(IntegerOperand(0xf424242424242420).AsUintN(64) ==
786 0xf424242424242420);
787
788 // Boundary conditions for known-size types.
789 VIXL_CHECK(IntegerOperand(INT8_MIN).AsUintN(8) == 0x80);
790 VIXL_CHECK(IntegerOperand(INT8_MAX).AsUintN(8) == 0x7f);
791 VIXL_CHECK(IntegerOperand(UINT8_MAX).AsUintN(8) == 0xff);
792
793 VIXL_CHECK(IntegerOperand(INT16_MIN).AsUintN(16) == 0x8000);
794 VIXL_CHECK(IntegerOperand(INT16_MAX).AsUintN(16) == 0x7fff);
795 VIXL_CHECK(IntegerOperand(UINT16_MAX).AsUintN(16) == 0xffff);
796
797 VIXL_CHECK(IntegerOperand(INT32_MIN).AsUintN(32) == 0x80000000);
798 VIXL_CHECK(IntegerOperand(INT32_MAX).AsUintN(32) == 0x7fffffff);
799 VIXL_CHECK(IntegerOperand(UINT32_MAX).AsUintN(32) == 0xffffffff);
800
801 VIXL_CHECK(IntegerOperand(INT64_MIN).AsUintN(64) == 0x8000000000000000);
802 VIXL_CHECK(IntegerOperand(INT64_MAX).AsUintN(64) == 0x7fffffffffffffff);
803 VIXL_CHECK(IntegerOperand(UINT64_MAX).AsUintN(64) == 0xffffffffffffffff);
804 }
805
TEST(integer_operand_as_int)806 TEST(integer_operand_as_int) {
807 // Simple cases.
808 VIXL_CHECK(IntegerOperand(1).AsIntN(8) == 1);
809 VIXL_CHECK(IntegerOperand(1).AsIntN(16) == 1);
810 VIXL_CHECK(IntegerOperand(1).AsIntN(32) == 1);
811 VIXL_CHECK(IntegerOperand(1).AsIntN(64) == 1);
812 VIXL_CHECK(IntegerOperand(-1).AsIntN(8) == -1);
813 VIXL_CHECK(IntegerOperand(-1).AsIntN(16) == -1);
814 VIXL_CHECK(IntegerOperand(-1).AsIntN(32) == -1);
815 VIXL_CHECK(IntegerOperand(-1).AsIntN(64) == -1);
816 VIXL_CHECK(IntegerOperand(0x70).AsIntN(8) == 0x70);
817 VIXL_CHECK(IntegerOperand(0x7420).AsIntN(16) == 0x7420);
818 VIXL_CHECK(IntegerOperand(0x74242420).AsIntN(32) == 0x74242420);
819 VIXL_CHECK(IntegerOperand(0x7424242424242420).AsIntN(64) ==
820 0x7424242424242420);
821
822 // Boundary conditions for known-size types.
823 VIXL_CHECK(IntegerOperand(UINT8_MAX).AsIntN(8) == -1);
824 VIXL_CHECK(IntegerOperand(UINT16_MAX).AsIntN(16) == -1);
825 VIXL_CHECK(IntegerOperand(UINT32_MAX).AsIntN(32) == -1);
826 VIXL_CHECK(IntegerOperand(UINT64_MAX).AsIntN(64) == -1);
827
828 VIXL_CHECK(IntegerOperand(INT8_MAX).AsIntN(8) == INT8_MAX);
829 VIXL_CHECK(IntegerOperand(INT16_MAX).AsIntN(16) == INT16_MAX);
830 VIXL_CHECK(IntegerOperand(INT32_MAX).AsIntN(32) == INT32_MAX);
831 VIXL_CHECK(IntegerOperand(INT64_MAX).AsIntN(64) == INT64_MAX);
832
833 VIXL_CHECK(IntegerOperand(0x80).AsIntN(8) == INT8_MIN);
834 VIXL_CHECK(IntegerOperand(0x8000).AsIntN(16) == INT16_MIN);
835 VIXL_CHECK(IntegerOperand(0x80000000).AsIntN(32) == INT32_MIN);
836 VIXL_CHECK(IntegerOperand(0x8000000000000000).AsIntN(64) == INT64_MIN);
837 }
838
839 template <unsigned N>
840 class IntegerOperandTryEncodeShiftedIntHelper {
841 public:
IntegerOperandTryEncodeShiftedIntHelper()842 IntegerOperandTryEncodeShiftedIntHelper() {}
843
844 template <unsigned kShift, typename T>
TestEncodable(T value,const ZRegister & zd,int64_t expected_imm)845 void TestEncodable(T value, const ZRegister& zd, int64_t expected_imm) {
846 VIXL_CHECK(TestImpl<kShift>(value, zd, expected_imm));
847 }
848
849 template <unsigned kShift, typename T>
TestUnencodable(T value,const ZRegister & zd)850 void TestUnencodable(T value, const ZRegister& zd) {
851 // The `expected_imm` value is ignored, so its value is arbitrary.
852 VIXL_CHECK(!TestImpl<kShift>(value, zd, 0));
853 }
854
855 private:
856 template <unsigned kShift, typename T>
TestImpl(T value,const ZRegister & zd,int64_t expected_imm)857 bool TestImpl(T value, const ZRegister& zd, int64_t expected_imm) {
858 IntegerOperand operand(value);
859 int64_t imm = 0xdeadbeef42;
860 unsigned shift = 0xbeef43;
861 bool success =
862 operand.TryEncodeAsShiftedIntNForLane<N, kShift>(zd, &imm, &shift);
863 if (success) {
864 VIXL_CHECK(imm == expected_imm);
865 VIXL_CHECK(shift == kShift);
866 } else {
867 // Check that the outputs were unmodified.
868 VIXL_CHECK(imm == 0xdeadbeef42);
869 VIXL_CHECK(shift == 0xbeef43);
870 }
871
872 // If kShift is 0, also check TryEncodeAsIntNForLane.
873 if (kShift == 0) {
874 int64_t unshifted_imm = 0xdeadbeef99;
875 bool unshifted_success =
876 operand.TryEncodeAsIntNForLane<N>(zd, &unshifted_imm);
877
878 VIXL_CHECK(unshifted_success == success);
879 if (unshifted_success) {
880 VIXL_CHECK(unshifted_imm == expected_imm);
881 } else {
882 VIXL_CHECK(unshifted_imm == 0xdeadbeef99);
883 }
884 }
885
886 return success;
887 }
888 };
889
TEST(integer_operand_encode_as_intn)890 TEST(integer_operand_encode_as_intn) {
891 IntegerOperandTryEncodeShiftedIntHelper<4> int4_helper;
892 IntegerOperandTryEncodeShiftedIntHelper<8> int8_helper;
893 IntegerOperandTryEncodeShiftedIntHelper<12> int12_helper;
894
895 // Simple cases, where the value is directly encodable.
896 int4_helper.TestEncodable<0>(-8, z0.VnH(), -8);
897 int4_helper.TestEncodable<0>(-7, z0.VnH(), -7);
898 int4_helper.TestEncodable<0>(-1, z0.VnS(), -1);
899 int4_helper.TestEncodable<0>(0, z0.VnD(), 0);
900 int4_helper.TestEncodable<0>(1, z0.VnB(), 1);
901 int4_helper.TestEncodable<0>(7, z0.VnH(), 7);
902
903 int8_helper.TestEncodable<0>(0x7f, z0.VnB(), 0x7f);
904 int8_helper.TestEncodable<0>(0x7f, z0.VnH(), 0x7f);
905 int12_helper.TestEncodable<0>(0x7ff, z0.VnH(), 0x7ff);
906
907 int8_helper.TestEncodable<0>(-0x80, z0.VnB(), -0x80);
908 int8_helper.TestEncodable<0>(-0x80, z0.VnH(), -0x80);
909 int12_helper.TestEncodable<0>(-0x800, z0.VnH(), -0x800);
910
911 // Cases that are directly encodable with a shift.
912 int8_helper.TestEncodable<4>(-0x800, z0.VnH(), -0x80);
913 int8_helper.TestEncodable<4>(-0x7f0, z0.VnH(), -0x7f);
914 int8_helper.TestEncodable<4>(-0x010, z0.VnH(), -1);
915 int8_helper.TestEncodable<4>(0x000, z0.VnH(), 0);
916 int8_helper.TestEncodable<4>(0x010, z0.VnH(), 1);
917 int8_helper.TestEncodable<4>(0x7f0, z0.VnH(), 0x7f);
918
919 // Ensure that (positive) bit representations of negative values are treated
920 // as negative values, even though their arithmetic values are unencodable.
921 int12_helper.TestEncodable<0>(0xffd6, z0.VnH(), -42);
922 int12_helper.TestEncodable<0>(0xffffffd6, z0.VnS(), -42);
923 int12_helper.TestEncodable<4>(0xfd60, z0.VnH(), -42);
924 int12_helper.TestEncodable<8>(0xffffd600, z0.VnS(), -42);
925
926 int8_helper.TestEncodable<0>(UINT8_MAX, z0.VnB(), -1);
927 int8_helper.TestEncodable<0>(UINT16_MAX, z0.VnH(), -1);
928 int8_helper.TestEncodable<0>(UINT32_MAX, z0.VnS(), -1);
929 int8_helper.TestEncodable<0>(UINT64_MAX, z0.VnD(), -1);
930
931 int4_helper.TestEncodable<1>(UINT8_MAX ^ 0x1, z0.VnB(), -1);
932 int4_helper.TestEncodable<2>(UINT16_MAX ^ 0x3, z0.VnH(), -1);
933 int4_helper.TestEncodable<3>(UINT32_MAX ^ 0x7, z0.VnS(), -1);
934 int4_helper.TestEncodable<4>(UINT64_MAX ^ 0xf, z0.VnD(), -1);
935
936 // Unencodable cases.
937 int8_helper.TestUnencodable<0>(INT16_MAX, z0.VnH());
938 int8_helper.TestUnencodable<0>(INT32_MAX, z0.VnS());
939 int8_helper.TestUnencodable<0>(INT64_MAX, z0.VnD());
940
941 int4_helper.TestUnencodable<0>(0x10, z0.VnB());
942 int4_helper.TestUnencodable<1>(0x20, z0.VnB());
943
944 int12_helper.TestUnencodable<1>(1, z0.VnD());
945 int12_helper.TestUnencodable<12>(1, z0.VnD());
946 int12_helper.TestUnencodable<12>(0x800, z0.VnD());
947 }
948
TEST(static_register_types)949 TEST(static_register_types) {
950 // [WX]Register implicitly casts to Register.
951 XRegister x_x0(0);
952 WRegister w_w0(0);
953 Register r_x0 = x_x0;
954 Register r_w0 = w_w0;
955 VIXL_CHECK(r_x0.Is(x_x0));
956 VIXL_CHECK(x_x0.Is(r_x0));
957 VIXL_CHECK(r_w0.Is(w_w0));
958 VIXL_CHECK(w_w0.Is(r_w0));
959
960 // Register explicitly casts to [WX]Register.
961 Register r_x1(1, kXRegSize);
962 Register r_w1(1, kWRegSize);
963 XRegister x_x1(r_x1);
964 WRegister w_w1(r_w1);
965 VIXL_CHECK(r_x1.Is(x_x1));
966 VIXL_CHECK(x_x1.Is(r_x1));
967 VIXL_CHECK(r_w1.Is(w_w1));
968 VIXL_CHECK(w_w1.Is(r_w1));
969
970 // [WX]Register implicitly casts to CPURegister.
971 XRegister x_x2(2);
972 WRegister w_w2(2);
973 CPURegister cpu_x2 = x_x2;
974 CPURegister cpu_w2 = w_w2;
975 VIXL_CHECK(cpu_x2.Is(x_x2));
976 VIXL_CHECK(x_x2.Is(cpu_x2));
977 VIXL_CHECK(cpu_w2.Is(w_w2));
978 VIXL_CHECK(w_w2.Is(cpu_w2));
979 }
980
981
TEST(operand_is_plain_register)982 TEST(operand_is_plain_register) {
983 VIXL_CHECK(Operand(x0).IsPlainRegister());
984 VIXL_CHECK(Operand(x1, LSL, 0).IsPlainRegister());
985 VIXL_CHECK(Operand(x2, LSR, 0).IsPlainRegister());
986 VIXL_CHECK(Operand(x3, ASR, 0).IsPlainRegister());
987 VIXL_CHECK(Operand(x4, ROR, 0).IsPlainRegister());
988 VIXL_CHECK(Operand(x5, UXTX).IsPlainRegister());
989 VIXL_CHECK(Operand(x6, SXTX).IsPlainRegister());
990 VIXL_CHECK(Operand(w7).IsPlainRegister());
991 VIXL_CHECK(Operand(w8, LSL, 0).IsPlainRegister());
992 VIXL_CHECK(Operand(w9, LSR, 0).IsPlainRegister());
993 VIXL_CHECK(Operand(w10, ASR, 0).IsPlainRegister());
994 VIXL_CHECK(Operand(w11, ROR, 0).IsPlainRegister());
995
996 VIXL_CHECK(!Operand(x0, LSL, 1).IsPlainRegister());
997 VIXL_CHECK(!Operand(x1, LSR, 2).IsPlainRegister());
998 VIXL_CHECK(!Operand(x2, ASR, 3).IsPlainRegister());
999 VIXL_CHECK(!Operand(x3, ROR, 4).IsPlainRegister());
1000 VIXL_CHECK(!Operand(x5, UXTX, 1).IsPlainRegister());
1001 VIXL_CHECK(!Operand(x6, SXTX, 2).IsPlainRegister());
1002 VIXL_CHECK(!Operand(w7, LSL, 1).IsPlainRegister());
1003 VIXL_CHECK(!Operand(w8, LSR, 2).IsPlainRegister());
1004 VIXL_CHECK(!Operand(w9, ASR, 3).IsPlainRegister());
1005 VIXL_CHECK(!Operand(w10, ROR, 4).IsPlainRegister());
1006 VIXL_CHECK(!Operand(w11, UXTB).IsPlainRegister());
1007 VIXL_CHECK(!Operand(w12, SXTB).IsPlainRegister());
1008 VIXL_CHECK(!Operand(w13, UXTH).IsPlainRegister());
1009 VIXL_CHECK(!Operand(w14, SXTH).IsPlainRegister());
1010 // UXTW and SXTW could be treated as plain registers in 32-bit contexts, but
1011 // the Operand class doesn't know the context so it has to return false.
1012 VIXL_CHECK(!Operand(w15, UXTW).IsPlainRegister());
1013 VIXL_CHECK(!Operand(w16, SXTW).IsPlainRegister());
1014 }
1015
1016
TEST(memoperand_is_plain_register)1017 TEST(memoperand_is_plain_register) {
1018 VIXL_CHECK(MemOperand(x0).IsPlainRegister());
1019 VIXL_CHECK(MemOperand(sp).IsPlainRegister());
1020 VIXL_CHECK(MemOperand(x1, 0).IsPlainRegister());
1021
1022 VIXL_CHECK(!MemOperand(x2, xzr).IsPlainRegister());
1023 VIXL_CHECK(!MemOperand(x3, xzr, SXTX).IsPlainRegister());
1024 VIXL_CHECK(!MemOperand(x4, xzr, SXTX, 2).IsPlainRegister());
1025 VIXL_CHECK(!MemOperand(x5, wzr, UXTW).IsPlainRegister());
1026 VIXL_CHECK(!MemOperand(x6, wzr, UXTW, 3).IsPlainRegister());
1027
1028 VIXL_CHECK(!MemOperand(x7, 0, PostIndex).IsPlainRegister());
1029 VIXL_CHECK(!MemOperand(x8, 0, PreIndex).IsPlainRegister());
1030 VIXL_CHECK(!MemOperand(x9, xzr, PostIndex).IsPlainRegister());
1031
1032 VIXL_CHECK(!MemOperand(x20, 1).IsPlainRegister());
1033 VIXL_CHECK(!MemOperand(x21, x30).IsPlainRegister());
1034 }
1035
TEST(memoperand_is_plain_register_or_equivalent)1036 TEST(memoperand_is_plain_register_or_equivalent) {
1037 VIXL_CHECK(MemOperand(x0).IsEquivalentToPlainRegister());
1038 VIXL_CHECK(MemOperand(sp).IsEquivalentToPlainRegister());
1039 VIXL_CHECK(MemOperand(x1, 0).IsEquivalentToPlainRegister());
1040
1041 VIXL_CHECK(MemOperand(x2, xzr).IsEquivalentToPlainRegister());
1042 VIXL_CHECK(MemOperand(x3, xzr, SXTX).IsEquivalentToPlainRegister());
1043 VIXL_CHECK(MemOperand(x4, xzr, SXTX, 2).IsEquivalentToPlainRegister());
1044 VIXL_CHECK(MemOperand(x5, wzr, UXTW).IsEquivalentToPlainRegister());
1045 VIXL_CHECK(MemOperand(x6, wzr, UXTW, 3).IsEquivalentToPlainRegister());
1046
1047 VIXL_CHECK(MemOperand(x7, 0, PostIndex).IsEquivalentToPlainRegister());
1048 VIXL_CHECK(MemOperand(x8, 0, PreIndex).IsEquivalentToPlainRegister());
1049 VIXL_CHECK(MemOperand(x9, xzr, PostIndex).IsEquivalentToPlainRegister());
1050
1051 VIXL_CHECK(!MemOperand(x20, 1).IsEquivalentToPlainRegister());
1052 VIXL_CHECK(!MemOperand(x21, x30).IsEquivalentToPlainRegister());
1053 }
1054
TEST(sve_memoperand_is_plain_scalar)1055 TEST(sve_memoperand_is_plain_scalar) {
1056 VIXL_CHECK(SVEMemOperand(x0).IsPlainScalar());
1057 VIXL_CHECK(SVEMemOperand(sp).IsPlainScalar());
1058 VIXL_CHECK(SVEMemOperand(x1, 0).IsPlainScalar());
1059
1060 VIXL_CHECK(!SVEMemOperand(x2, xzr).IsPlainScalar());
1061 VIXL_CHECK(!SVEMemOperand(x4, xzr, LSL, 2).IsPlainScalar());
1062
1063 VIXL_CHECK(!SVEMemOperand(x20, 1).IsPlainScalar());
1064 VIXL_CHECK(!SVEMemOperand(x21, x30).IsPlainScalar());
1065
1066 VIXL_CHECK(!SVEMemOperand(x0, z1.VnD()).IsPlainScalar());
1067 VIXL_CHECK(!SVEMemOperand(x2, z3.VnS(), UXTW).IsPlainScalar());
1068 VIXL_CHECK(!SVEMemOperand(z4.VnD(), 0).IsPlainScalar());
1069 }
1070
TEST(sve_memoperand_is_scalar_or_equivalent)1071 TEST(sve_memoperand_is_scalar_or_equivalent) {
1072 VIXL_CHECK(SVEMemOperand(x0).IsEquivalentToScalar());
1073 VIXL_CHECK(SVEMemOperand(sp).IsEquivalentToScalar());
1074 VIXL_CHECK(SVEMemOperand(x1, 0).IsEquivalentToScalar());
1075
1076 VIXL_CHECK(SVEMemOperand(x2, xzr).IsEquivalentToScalar());
1077 VIXL_CHECK(SVEMemOperand(x4, xzr, LSL, 2).IsEquivalentToScalar());
1078
1079 VIXL_CHECK(!SVEMemOperand(x20, 1).IsEquivalentToScalar());
1080 VIXL_CHECK(!SVEMemOperand(x21, x30).IsEquivalentToScalar());
1081
1082 VIXL_CHECK(!SVEMemOperand(x0, z1.VnD()).IsEquivalentToScalar());
1083 VIXL_CHECK(!SVEMemOperand(x2, z3.VnD(), SXTW).IsEquivalentToScalar());
1084 VIXL_CHECK(!SVEMemOperand(z4.VnD(), 0).IsEquivalentToScalar());
1085 }
1086
TEST(sve_memoperand_types)1087 TEST(sve_memoperand_types) {
1088 VIXL_CHECK(SVEMemOperand(x0, 42).IsScalarPlusImmediate());
1089 VIXL_CHECK(SVEMemOperand(x1, 42, SVE_MUL_VL).IsScalarPlusImmediate());
1090 VIXL_CHECK(SVEMemOperand(x2, -42, SVE_MUL_VL).IsScalarPlusImmediate());
1091
1092 VIXL_CHECK(SVEMemOperand(sp, x3).IsScalarPlusScalar());
1093 VIXL_CHECK(SVEMemOperand(x4, xzr).IsScalarPlusScalar());
1094 VIXL_CHECK(SVEMemOperand(x5, x6, LSL, 1).IsScalarPlusScalar());
1095
1096 VIXL_CHECK(SVEMemOperand(x7, z0.VnD()).IsScalarPlusVector());
1097 VIXL_CHECK(SVEMemOperand(x8, z1.VnS(), SXTW).IsScalarPlusVector());
1098 VIXL_CHECK(SVEMemOperand(x9, z2.VnD(), UXTW).IsScalarPlusVector());
1099 VIXL_CHECK(SVEMemOperand(x10, z3.VnD(), LSL, 2).IsScalarPlusVector());
1100
1101 VIXL_CHECK(SVEMemOperand(z4.VnD(), 42).IsVectorPlusImmediate());
1102 VIXL_CHECK(SVEMemOperand(z5.VnS(), -42).IsVectorPlusImmediate());
1103 }
1104
TEST(sve_memoperand_scatter_gather)1105 TEST(sve_memoperand_scatter_gather) {
1106 // Single-address accesses.
1107 VIXL_CHECK(!SVEMemOperand(x0, 42).IsScatterGather());
1108 VIXL_CHECK(!SVEMemOperand(x1, 42, SVE_MUL_VL).IsScatterGather());
1109 VIXL_CHECK(!SVEMemOperand(x2, -42, SVE_MUL_VL).IsScatterGather());
1110
1111 VIXL_CHECK(!SVEMemOperand(sp, x3).IsScatterGather());
1112 VIXL_CHECK(!SVEMemOperand(x4, xzr).IsScatterGather());
1113 VIXL_CHECK(!SVEMemOperand(x5, x6, LSL, 1).IsScatterGather());
1114
1115 // Scatter-gather accesses.
1116 VIXL_CHECK(SVEMemOperand(x7, z0.VnD()).IsScatterGather());
1117 VIXL_CHECK(SVEMemOperand(x8, z1.VnS(), SXTW).IsScatterGather());
1118 VIXL_CHECK(SVEMemOperand(x9, z2.VnD(), UXTW).IsScatterGather());
1119 VIXL_CHECK(SVEMemOperand(x10, z3.VnD(), LSL, 2).IsScatterGather());
1120
1121 VIXL_CHECK(SVEMemOperand(z4.VnD(), 42).IsScatterGather());
1122 VIXL_CHECK(SVEMemOperand(z5.VnS(), -42).IsScatterGather());
1123 }
1124
TEST(scratch_scope_basic)1125 TEST(scratch_scope_basic) {
1126 MacroAssembler masm;
1127 // x16 and x17 are available as scratch registers by default.
1128 {
1129 UseScratchRegisterScope temps(&masm);
1130 Register temp1 = temps.AcquireW();
1131 Register temp2 = temps.AcquireX();
1132 VIXL_CHECK(temp1.Is(w16));
1133 VIXL_CHECK(temp2.Is(x17));
1134 }
1135 {
1136 UseScratchRegisterScope temps(&masm);
1137 Register temp1 = temps.AcquireRegisterOfSize(kXRegSize);
1138 Register temp2 = temps.AcquireRegisterOfSize(kWRegSize);
1139 VIXL_CHECK(temp1.Is(x16));
1140 VIXL_CHECK(temp2.Is(w17));
1141 }
1142 }
1143
TEST(scratch_scope_basic_v)1144 TEST(scratch_scope_basic_v) {
1145 MacroAssembler masm;
1146 // v31 is the only V scratch register available by default.
1147 {
1148 UseScratchRegisterScope temps(&masm);
1149 VRegister temp = temps.AcquireH();
1150 VIXL_CHECK(temp.Is(h31));
1151 }
1152 {
1153 UseScratchRegisterScope temps(&masm);
1154 VRegister temp = temps.AcquireS();
1155 VIXL_CHECK(temp.Is(s31));
1156 }
1157 {
1158 UseScratchRegisterScope temps(&masm);
1159 VRegister temp = temps.AcquireD();
1160 VIXL_CHECK(temp.Is(d31));
1161 }
1162 {
1163 UseScratchRegisterScope temps(&masm);
1164 VRegister temp = temps.AcquireVRegisterOfSize(kQRegSize);
1165 VIXL_CHECK(temp.Is(q31));
1166 }
1167 {
1168 UseScratchRegisterScope temps(&masm);
1169 VRegister temp = temps.AcquireVRegisterOfSize(kDRegSize);
1170 VIXL_CHECK(temp.Is(d31));
1171 }
1172 {
1173 UseScratchRegisterScope temps(&masm);
1174 VRegister temp = temps.AcquireVRegisterOfSize(kSRegSize);
1175 VIXL_CHECK(temp.Is(s31));
1176 }
1177 }
1178
TEST(scratch_scope_basic_z)1179 TEST(scratch_scope_basic_z) {
1180 MacroAssembler masm;
1181 // z31 is the only Z scratch register available by default.
1182 {
1183 UseScratchRegisterScope temps(&masm);
1184 VIXL_CHECK(temps.IsAvailable(v31));
1185 VIXL_CHECK(temps.IsAvailable(z31));
1186 ZRegister temp = temps.AcquireZ();
1187 VIXL_CHECK(temp.Is(z31));
1188 // Check that allocating a Z register properly reserves the corresponding V
1189 // register.
1190 VIXL_CHECK(!temps.IsAvailable(v31));
1191 VIXL_CHECK(!temps.IsAvailable(z31));
1192 }
1193 // Check that the destructor restored the acquired register.
1194 UseScratchRegisterScope temps(&masm);
1195 VIXL_CHECK(temps.IsAvailable(v31));
1196 VIXL_CHECK(temps.IsAvailable(z31));
1197 }
1198
TEST(scratch_scope_basic_p)1199 TEST(scratch_scope_basic_p) {
1200 MacroAssembler masm;
1201 {
1202 UseScratchRegisterScope temps(&masm);
1203 // There are no P scratch registers available by default.
1204 VIXL_CHECK(masm.GetScratchPRegisterList()->IsEmpty());
1205 temps.Include(p0, p1);
1206 VIXL_CHECK(temps.IsAvailable(p0));
1207 VIXL_CHECK(temps.IsAvailable(p1));
1208 temps.Include(p7, p8, p15);
1209 VIXL_CHECK(temps.IsAvailable(p7));
1210 VIXL_CHECK(temps.IsAvailable(p8));
1211 VIXL_CHECK(temps.IsAvailable(p15));
1212
1213 // AcquireGoverningP() can only return p0-p7.
1214 VIXL_CHECK(temps.AcquireGoverningP().GetCode() <
1215 kNumberOfGoverningPRegisters);
1216 VIXL_CHECK(temps.AcquireGoverningP().GetCode() <
1217 kNumberOfGoverningPRegisters);
1218 VIXL_CHECK(temps.IsAvailable(p8));
1219 VIXL_CHECK(temps.IsAvailable(p15));
1220
1221 // AcquireP() prefers p8-p15, ...
1222 VIXL_CHECK(temps.AcquireP().GetCode() >= kNumberOfGoverningPRegisters);
1223 VIXL_CHECK(temps.AcquireP().GetCode() >= kNumberOfGoverningPRegisters);
1224 // ... but will return p0-p7 if none of p8-p15 are available.
1225 VIXL_CHECK(temps.AcquireP().GetCode() < kNumberOfGoverningPRegisters);
1226
1227 VIXL_CHECK(masm.GetScratchPRegisterList()->IsEmpty());
1228
1229 // Leave some registers available so we can test the destructor.
1230 temps.Include(p3, p6, p9, p12);
1231 VIXL_CHECK(!masm.GetScratchPRegisterList()->IsEmpty());
1232 }
1233 // Check that the destructor correctly cleared the list.
1234 VIXL_CHECK(masm.GetScratchPRegisterList()->IsEmpty());
1235 }
1236
TEST(scratch_scope_include_ignored)1237 TEST(scratch_scope_include_ignored) {
1238 MacroAssembler masm;
1239 {
1240 UseScratchRegisterScope temps(&masm);
1241 // Start with an empty set of scratch registers.
1242 temps.ExcludeAll();
1243
1244 // Including NoReg has no effect.
1245 temps.Include(NoReg);
1246 temps.Include(NoCPUReg);
1247 temps.Include(CPURegList(CPURegister::kNoRegister, 0, 0));
1248
1249 // Including sp or zr has no effect, since they are never appropriate
1250 // scratch registers.
1251 temps.Include(sp);
1252 temps.Include(xzr, wsp);
1253 temps.Include(wzr);
1254 temps.Include(CPURegList(xzr, sp));
1255
1256 VIXL_CHECK(masm.GetScratchRegisterList()->IsEmpty());
1257 VIXL_CHECK(masm.GetScratchVRegisterList()->IsEmpty());
1258 }
1259 }
1260
1261 class ScratchScopeHelper {
1262 public:
1263 enum Action { kRelease, kInclude, kExclude };
1264
ScratchScopeHelper(MacroAssembler * masm,Action action,CPURegister::RegisterType type)1265 ScratchScopeHelper(MacroAssembler* masm,
1266 Action action,
1267 CPURegister::RegisterType type)
1268 : masm_(masm),
1269 action_(action),
1270 type_(type),
1271 expected_(GetGuardListFor(CPURegister::kRegister)),
1272 expected_v_(GetGuardListFor(CPURegister::kVRegister)),
1273 expected_p_(GetGuardListFor(CPURegister::kPRegister)) {
1274 *GetExpectedFor(type) = GetInitialList();
1275 masm->GetScratchRegisterList()->SetList(expected_);
1276 masm->GetScratchVRegisterList()->SetList(expected_v_);
1277 masm->GetScratchPRegisterList()->SetList(expected_p_);
1278 }
1279
1280 // Notify the helper that the registers in `update` have been passed into
1281 // DoAction(), and assert that the MacroAssembler's scratch lists are as
1282 // expected.
RecordActionsAndCheck(RegList update)1283 void RecordActionsAndCheck(RegList update) {
1284 RegList* expected = GetExpectedFor(type_);
1285 switch (action_) {
1286 case kRelease:
1287 // It isn't valid to release a register that is already available.
1288 VIXL_CHECK((*expected & update) == 0);
1289 VIXL_FALLTHROUGH();
1290 case kInclude:
1291 *expected |= update;
1292 break;
1293 case kExclude:
1294 *expected &= ~update;
1295 break;
1296 }
1297 VIXL_CHECK(masm_->GetScratchRegisterList()->GetList() == expected_);
1298 VIXL_CHECK(masm_->GetScratchVRegisterList()->GetList() == expected_v_);
1299 VIXL_CHECK(masm_->GetScratchPRegisterList()->GetList() == expected_p_);
1300 }
1301
1302 private:
GetInitialList()1303 RegList GetInitialList() {
1304 switch (action_) {
1305 case kRelease:
1306 case kInclude:
1307 return 0;
1308 case kExclude:
1309 return GetPotentialListFor(type_);
1310 }
1311 VIXL_UNREACHABLE();
1312 return 0;
1313 }
1314
1315 // Return some valid, non-zero RegList suitable for use as a guard value.
GetGuardListFor(CPURegister::RegisterType type)1316 static RegList GetGuardListFor(CPURegister::RegisterType type) {
1317 return (0x1111111111111111 * (type + 1)) & GetPotentialListFor(type);
1318 }
1319
GetPotentialListFor(CPURegister::RegisterType type)1320 static RegList GetPotentialListFor(CPURegister::RegisterType type) {
1321 RegList list = CPURegList::All(type).GetList();
1322 // The zr and sp registers cannot be scratch registers.
1323 if (type == CPURegister::kRegister) list &= ~(xzr.GetBit() | sp.GetBit());
1324 return list;
1325 }
1326
GetExpectedFor(CPURegister::RegisterType type)1327 RegList* GetExpectedFor(CPURegister::RegisterType type) {
1328 switch (type) {
1329 case CPURegister::kNoRegister:
1330 VIXL_UNREACHABLE();
1331 return NULL;
1332 case CPURegister::kRegister:
1333 return &expected_;
1334 case CPURegister::kVRegister:
1335 case CPURegister::kZRegister:
1336 return &expected_v_;
1337 case CPURegister::kPRegister:
1338 return &expected_p_;
1339 }
1340 VIXL_UNREACHABLE();
1341 return NULL;
1342 }
1343
1344 MacroAssembler* masm_;
1345 Action action_;
1346 CPURegister::RegisterType type_;
1347
1348 RegList expected_;
1349 RegList expected_v_;
1350 RegList expected_p_;
1351 };
1352
TEST(scratch_scope_include)1353 TEST(scratch_scope_include) {
1354 MacroAssembler masm;
1355 {
1356 UseScratchRegisterScope temps(&masm);
1357 ScratchScopeHelper helper(&masm,
1358 ScratchScopeHelper::kInclude,
1359 CPURegister::kRegister);
1360
1361 // Any suitable register type deriving from CPURegister can be included.
1362 temps.Include(w0);
1363 temps.Include(x1);
1364 temps.Include(WRegister(2));
1365 temps.Include(XRegister(3));
1366 temps.Include(Register(w4));
1367 temps.Include(Register(x5));
1368 temps.Include(CPURegister(w6));
1369 temps.Include(CPURegister(x7));
1370 helper.RecordActionsAndCheck(0xff);
1371 // Multiple registers can be included at once.
1372 temps.Include(x8, w9, x10);
1373 temps.Include(Register(w12), Register(x13), Register(w14));
1374 temps.Include(XRegister(16), XRegister(17), XRegister(18));
1375 temps.Include(WRegister(20), WRegister(21), WRegister(22));
1376 temps.Include(CPURegList(w24, w25, w26));
1377 helper.RecordActionsAndCheck(0x7777700);
1378 // Including a register again has no effect.
1379 temps.Include(Register(w26));
1380 temps.Include(Register(x25));
1381 temps.Include(CPURegister(x24));
1382 temps.Include(CPURegister(x22));
1383 temps.Include(x21, x20, w18, x17);
1384 temps.Include(CPURegList(x16, x14, x13, x12));
1385 helper.RecordActionsAndCheck(0x7777700);
1386 }
1387 }
1388
TEST(scratch_scope_exclude)1389 TEST(scratch_scope_exclude) {
1390 MacroAssembler masm;
1391 {
1392 UseScratchRegisterScope temps(&masm);
1393 ScratchScopeHelper helper(&masm,
1394 ScratchScopeHelper::kExclude,
1395 CPURegister::kRegister);
1396
1397 // Any suitable register type deriving from CPURegister can be excluded.
1398 temps.Exclude(w0);
1399 temps.Exclude(x1);
1400 temps.Exclude(WRegister(2));
1401 temps.Exclude(XRegister(3));
1402 temps.Exclude(Register(w4));
1403 temps.Exclude(Register(x5));
1404 temps.Exclude(CPURegister(w6));
1405 temps.Exclude(CPURegister(x7));
1406 helper.RecordActionsAndCheck(0xff);
1407 // Multiple registers can be excluded at once.
1408 temps.Exclude(x8, w9, x10);
1409 temps.Exclude(Register(w12), Register(x13), Register(w14));
1410 temps.Exclude(XRegister(16), XRegister(17), XRegister(18));
1411 temps.Exclude(WRegister(20), WRegister(21), WRegister(22));
1412 temps.Exclude(CPURegList(w24, w25, w26));
1413 helper.RecordActionsAndCheck(0x7777700);
1414 // Excluding a register again has no effect.
1415 temps.Exclude(Register(w26));
1416 temps.Exclude(Register(x25));
1417 temps.Exclude(CPURegister(x24));
1418 temps.Exclude(CPURegister(x22));
1419 temps.Exclude(x21, x20, w18, x17);
1420 temps.Exclude(CPURegList(x16, x14, x13, x12));
1421 helper.RecordActionsAndCheck(0x7777700);
1422 }
1423 }
1424
TEST(scratch_scope_release)1425 TEST(scratch_scope_release) {
1426 MacroAssembler masm;
1427 {
1428 UseScratchRegisterScope temps(&masm);
1429 ScratchScopeHelper helper(&masm,
1430 ScratchScopeHelper::kRelease,
1431 CPURegister::kRegister);
1432
1433 // Any suitable register type deriving from CPURegister can be released.
1434 temps.Release(w0);
1435 temps.Release(x1);
1436 temps.Release(WRegister(2));
1437 temps.Release(XRegister(3));
1438 temps.Release(Register(w4));
1439 temps.Release(Register(x5));
1440 temps.Release(CPURegister(w6));
1441 temps.Release(CPURegister(x7));
1442 helper.RecordActionsAndCheck(0xff);
1443 // It is not possible to release more than one register at a time, and it is
1444 // invalid to release a register that is already available.
1445 }
1446 }
1447
TEST(scratch_scope_include_v)1448 TEST(scratch_scope_include_v) {
1449 MacroAssembler masm;
1450 {
1451 UseScratchRegisterScope temps(&masm);
1452 ScratchScopeHelper helper(&masm,
1453 ScratchScopeHelper::kInclude,
1454 CPURegister::kVRegister);
1455
1456 // Any suitable register type deriving from CPURegister can be included.
1457 temps.Include(b0);
1458 temps.Include(h1);
1459 temps.Include(SRegister(2));
1460 temps.Include(DRegister(3));
1461 temps.Include(VRegister(q4));
1462 temps.Include(VRegister(v5.V8B()));
1463 temps.Include(CPURegister(d6));
1464 temps.Include(CPURegister(v7.S4B()));
1465 helper.RecordActionsAndCheck(0xff);
1466 // Multiple registers can be included at once.
1467 temps.Include(b8, h9, s10);
1468 temps.Include(VRegister(d12), VRegister(d13), VRegister(d14));
1469 temps.Include(QRegister(16), QRegister(17), QRegister(18));
1470 temps.Include(BRegister(20), BRegister(21), BRegister(22));
1471 temps.Include(CPURegList(s24, s25, s26));
1472 helper.RecordActionsAndCheck(0x7777700);
1473 // Including a register again has no effect.
1474 temps.Include(VRegister(b26));
1475 temps.Include(VRegister(h25));
1476 temps.Include(CPURegister(s24));
1477 temps.Include(CPURegister(v22.V4H()));
1478 temps.Include(q21, d20, s18, h17);
1479 temps.Include(CPURegList(h16, h14, h13, h12));
1480 helper.RecordActionsAndCheck(0x7777700);
1481 }
1482 }
1483
TEST(scratch_scope_exclude_v)1484 TEST(scratch_scope_exclude_v) {
1485 MacroAssembler masm;
1486 {
1487 UseScratchRegisterScope temps(&masm);
1488 ScratchScopeHelper helper(&masm,
1489 ScratchScopeHelper::kExclude,
1490 CPURegister::kVRegister);
1491
1492 // Any suitable register type deriving from CPURegister can be excluded.
1493 temps.Exclude(b0);
1494 temps.Exclude(h1);
1495 temps.Exclude(SRegister(2));
1496 temps.Exclude(DRegister(3));
1497 temps.Exclude(VRegister(q4));
1498 temps.Exclude(VRegister(v5.V8B()));
1499 temps.Exclude(CPURegister(d6));
1500 temps.Exclude(CPURegister(v7.S4B()));
1501 helper.RecordActionsAndCheck(0xff);
1502 // Multiple registers can be excluded at once.
1503 temps.Exclude(b8, h9, s10);
1504 temps.Exclude(VRegister(d12), VRegister(d13), VRegister(d14));
1505 temps.Exclude(QRegister(16), QRegister(17), QRegister(18));
1506 temps.Exclude(BRegister(20), BRegister(21), BRegister(22));
1507 temps.Exclude(CPURegList(s24, s25, s26));
1508 helper.RecordActionsAndCheck(0x7777700);
1509 // Excluding a register again has no effect.
1510 temps.Exclude(VRegister(b26));
1511 temps.Exclude(VRegister(h25));
1512 temps.Exclude(CPURegister(s24));
1513 temps.Exclude(CPURegister(v22.V4H()));
1514 temps.Exclude(q21, d20, s18, h17);
1515 temps.Exclude(CPURegList(h16, h14, h13, h12));
1516 helper.RecordActionsAndCheck(0x7777700);
1517 }
1518 }
1519
TEST(scratch_scope_release_v)1520 TEST(scratch_scope_release_v) {
1521 MacroAssembler masm;
1522 {
1523 UseScratchRegisterScope temps(&masm);
1524 ScratchScopeHelper helper(&masm,
1525 ScratchScopeHelper::kRelease,
1526 CPURegister::kVRegister);
1527
1528 // Any suitable register type deriving from CPURegister can be released.
1529 temps.Release(b0);
1530 temps.Release(h1);
1531 temps.Release(SRegister(2));
1532 temps.Release(DRegister(3));
1533 temps.Release(VRegister(q4));
1534 temps.Release(VRegister(v5.V8B()));
1535 temps.Release(CPURegister(d6));
1536 temps.Release(CPURegister(v7.S4B()));
1537 helper.RecordActionsAndCheck(0xff);
1538 // It is not possible to release more than one register at a time, and it is
1539 // invalid to release a register that is already available.
1540 }
1541 }
1542
TEST(scratch_scope_include_z)1543 TEST(scratch_scope_include_z) {
1544 MacroAssembler masm;
1545 {
1546 UseScratchRegisterScope temps(&masm);
1547 ScratchScopeHelper helper(&masm,
1548 ScratchScopeHelper::kInclude,
1549 CPURegister::kZRegister);
1550
1551 // Any suitable register type deriving from CPURegister can be included.
1552 temps.Include(z0);
1553 temps.Include(z1.VnB());
1554 temps.Include(ZRegister(2));
1555 temps.Include(ZRegister(3, kFormatVnD));
1556 temps.Include(CPURegister(z4));
1557 temps.Include(CPURegister(z5.VnH()));
1558 helper.RecordActionsAndCheck(0x3f);
1559 // Multiple registers can be included at once.
1560 temps.Include(z8, z9, z10.VnS());
1561 temps.Include(ZRegister(12), ZRegister(13, kHRegSize), z14);
1562 temps.Include(CPURegList(z16, z17, z18));
1563 helper.RecordActionsAndCheck(0x77700);
1564 // Including a register again has no effect.
1565 temps.Include(ZRegister(18));
1566 temps.Include(ZRegister(17, kFormatVnB));
1567 temps.Include(CPURegister(z16));
1568 temps.Include(CPURegister(z13.VnD()));
1569 temps.Include(z12, z10, z9.VnB(), z8);
1570 temps.Include(CPURegList(z5, z4, z3, z2));
1571 helper.RecordActionsAndCheck(0x77700);
1572 }
1573 }
1574
TEST(scratch_scope_exclude_z)1575 TEST(scratch_scope_exclude_z) {
1576 MacroAssembler masm;
1577 {
1578 UseScratchRegisterScope temps(&masm);
1579 ScratchScopeHelper helper(&masm,
1580 ScratchScopeHelper::kExclude,
1581 CPURegister::kZRegister);
1582
1583 // Any suitable register type deriving from CPURegister can be excluded.
1584 temps.Exclude(z0);
1585 temps.Exclude(z1.VnB());
1586 temps.Exclude(ZRegister(2));
1587 temps.Exclude(ZRegister(3, kFormatVnD));
1588 temps.Exclude(CPURegister(z4));
1589 temps.Exclude(CPURegister(z5.VnH()));
1590 helper.RecordActionsAndCheck(0x3f);
1591 // Multiple registers can be excluded at once.
1592 temps.Exclude(z8, z9, z10.VnS());
1593 temps.Exclude(ZRegister(12), ZRegister(13, kHRegSize), z14);
1594 temps.Exclude(CPURegList(z16, z17, z18));
1595 helper.RecordActionsAndCheck(0x77700);
1596 // Exluding a register again has no effect.
1597 temps.Exclude(ZRegister(18));
1598 temps.Exclude(ZRegister(17, kFormatVnB));
1599 temps.Exclude(CPURegister(z16));
1600 temps.Exclude(CPURegister(z13.VnD()));
1601 temps.Exclude(z12, z10, z9.VnB(), z8);
1602 temps.Exclude(CPURegList(z5, z4, z3, z2));
1603 helper.RecordActionsAndCheck(0x77700);
1604 }
1605 }
1606
TEST(scratch_scope_release_z)1607 TEST(scratch_scope_release_z) {
1608 MacroAssembler masm;
1609 {
1610 UseScratchRegisterScope temps(&masm);
1611 ScratchScopeHelper helper(&masm,
1612 ScratchScopeHelper::kRelease,
1613 CPURegister::kZRegister);
1614
1615 // Any suitable register type deriving from CPURegister can be released.
1616 temps.Release(z0);
1617 temps.Release(z1.VnB());
1618 temps.Release(ZRegister(2));
1619 temps.Release(ZRegister(3, kFormatVnD));
1620 temps.Release(CPURegister(z4));
1621 temps.Release(CPURegister(z5.VnH()));
1622 helper.RecordActionsAndCheck(0x3f);
1623 // It is not possible to release more than one register at a time, and it is
1624 // invalid to release a register that is already available.
1625 }
1626 }
1627
TEST(scratch_scope_include_p)1628 TEST(scratch_scope_include_p) {
1629 MacroAssembler masm;
1630 {
1631 UseScratchRegisterScope temps(&masm);
1632 ScratchScopeHelper helper(&masm,
1633 ScratchScopeHelper::kInclude,
1634 CPURegister::kPRegister);
1635
1636 // Any suitable register type deriving from CPURegister can be included.
1637 temps.Include(p0);
1638 temps.Include(PRegister(1));
1639 temps.Include(PRegisterWithLaneSize(2, kFormatVnD));
1640 temps.Include(PRegisterM(3));
1641 temps.Include(CPURegister(PRegister(4)));
1642 temps.Include(CPURegister(PRegisterZ(5)));
1643 helper.RecordActionsAndCheck(0x3f);
1644 // Multiple registers can be included at once.
1645 temps.Include(p7, p8.Merging(), p9.VnS());
1646 temps.Include(PRegister(11), PRegisterWithLaneSize(12, kHRegSize));
1647 temps.Include(CPURegList(p15));
1648 helper.RecordActionsAndCheck(0x9b80);
1649 // Including a register again has no effect.
1650 temps.Include(PRegister(15));
1651 temps.Include(PRegisterWithLaneSize(12, kFormatVnB));
1652 temps.Include(CPURegister(p11));
1653 temps.Include(CPURegister(p9.VnD()));
1654 temps.Include(p8.Merging(), p7.Zeroing(), p5.VnB(), p4);
1655 temps.Include(CPURegList(p3, p2, p1, p0));
1656 helper.RecordActionsAndCheck(0x9b80);
1657 }
1658 }
1659
TEST(scratch_scope_exclude_p)1660 TEST(scratch_scope_exclude_p) {
1661 MacroAssembler masm;
1662 {
1663 UseScratchRegisterScope temps(&masm);
1664 ScratchScopeHelper helper(&masm,
1665 ScratchScopeHelper::kExclude,
1666 CPURegister::kPRegister);
1667
1668 // Any suitable register type deriving from CPURegister can be excluded.
1669 temps.Exclude(p0);
1670 temps.Exclude(PRegister(1));
1671 temps.Exclude(PRegisterWithLaneSize(2, kFormatVnD));
1672 temps.Exclude(PRegisterM(3));
1673 temps.Exclude(CPURegister(PRegister(4)));
1674 temps.Exclude(CPURegister(PRegisterZ(5)));
1675 helper.RecordActionsAndCheck(0x3f);
1676 // Multiple registers can be excluded at once.
1677 temps.Exclude(p7, p8.Merging(), p9.VnS());
1678 temps.Exclude(PRegister(11), PRegisterWithLaneSize(12, kHRegSize));
1679 temps.Exclude(CPURegList(p15));
1680 helper.RecordActionsAndCheck(0x9b80);
1681 // Excluding a register again has no effect.
1682 temps.Exclude(PRegister(15));
1683 temps.Exclude(PRegisterWithLaneSize(12, kFormatVnB));
1684 temps.Exclude(CPURegister(p11));
1685 temps.Exclude(CPURegister(p9.VnD()));
1686 temps.Exclude(p8.Merging(), p7.Zeroing(), p5.VnB(), p4);
1687 temps.Exclude(CPURegList(p3, p2, p1, p0));
1688 helper.RecordActionsAndCheck(0x9b80);
1689 }
1690 }
1691
TEST(scratch_scope_release_p)1692 TEST(scratch_scope_release_p) {
1693 MacroAssembler masm;
1694 {
1695 UseScratchRegisterScope temps(&masm);
1696 ScratchScopeHelper helper(&masm,
1697 ScratchScopeHelper::kRelease,
1698 CPURegister::kPRegister);
1699
1700 // Any suitable register type deriving from CPURegister can be excluded.
1701 temps.Release(p0);
1702 temps.Release(PRegister(1));
1703 temps.Release(PRegisterWithLaneSize(2, kFormatVnD));
1704 temps.Release(PRegisterM(3));
1705 temps.Release(CPURegister(PRegister(4)));
1706 temps.Release(CPURegister(PRegisterZ(5)));
1707 helper.RecordActionsAndCheck(0x3f);
1708 // It is not possible to release more than one register at a time, and it is
1709 // invalid to release a register that is already available.
1710 }
1711 }
1712
1713 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
TEST(sim_stack_default)1714 TEST(sim_stack_default) {
1715 SimStack::Allocated s = SimStack().Allocate();
1716
1717 // The default stack is at least 16-byte aligned.
1718 VIXL_CHECK(IsAligned<16>(s.GetBase()));
1719 VIXL_CHECK(IsAligned<16>(s.GetLimit() + 1));
1720
1721 VIXL_CHECK(s.GetBase() > s.GetLimit());
1722
1723 // The default guard regions are sufficient to detect at least off-by-one
1724 // errors.
1725 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetBase(), 1));
1726 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetBase() - 1, 1));
1727 // The limit is one below the lowest address on the stack.
1728 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit(), 1));
1729 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 1));
1730
1731 // We need to be able to access 16-byte granules at both extremes.
1732 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetBase() - 16, 16));
1733 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 16));
1734 }
1735
TEST(sim_stack)1736 TEST(sim_stack) {
1737 SimStack builder;
1738 builder.AlignToBytesLog2(WhichPowerOf2(1024));
1739 builder.SetBaseGuardSize(42);
1740 builder.SetLimitGuardSize(2049);
1741 builder.SetUsableSize(2048);
1742 SimStack::Allocated s = builder.Allocate();
1743
1744 VIXL_CHECK(IsAligned<1024>(s.GetBase()));
1745 VIXL_CHECK(IsAligned<1024>(s.GetLimit() + 1));
1746
1747 // The stack is accessible for (limit, base), both exclusive.
1748 // This is checked precisely, using the base and limit modified to respect
1749 // alignment, so we can test the exact boundary condition.
1750 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetBase(), 1));
1751 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetBase() - 1, 1));
1752 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit(), 1));
1753 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 1));
1754 VIXL_CHECK((s.GetBase() - s.GetLimit() - 1) == 2048);
1755
1756 // We can access the whole range (limit, base), both exclusive.
1757 VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 2048));
1758 // Off-by-one.
1759 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit(), 2048));
1760 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit() + 1, 2049));
1761 // Accesses spanning whole guard regions.
1762 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetBase() - 42, 4096));
1763 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit() - 1280, 2048));
1764 VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit() - 1280, 10000));
1765 }
1766 #endif
1767
1768 } // namespace aarch64
1769 } // namespace vixl
1770