1// Copyright 2015, VIXL authors 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are met: 6// 7// * Redistributions of source code must retain the above copyright notice, 8// this list of conditions and the following disclaimer. 9// * Redistributions in binary form must reproduce the above copyright notice, 10// this list of conditions and the following disclaimer in the documentation 11// and/or other materials provided with the distribution. 12// * Neither the name of ARM Limited nor the names of its contributors may be 13// used to endorse or promote products derived from this software without 14// specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27#include "test-assembler-aarch64.h" 28 29#include <cfloat> 30#include <cmath> 31#include <cstdio> 32#include <cstdlib> 33#include <cstring> 34#include <sys/mman.h> 35 36#include "test-runner.h" 37#include "test-utils.h" 38 39#include "aarch64/cpu-aarch64.h" 40#include "aarch64/disasm-aarch64.h" 41#include "aarch64/macro-assembler-aarch64.h" 42#include "aarch64/simulator-aarch64.h" 43#include "aarch64/test-utils-aarch64.h" 44 45namespace vixl { 46namespace aarch64 { 47 48TEST(preshift_immediates) { 49 SETUP(); 50 51 START(); 52 // Test operations involving immediates that could be generated using a 53 // pre-shifted encodable immediate followed by a post-shift applied to 54 // the arithmetic or logical operation. 55 56 // Save sp. 57 __ Mov(x29, sp); 58 59 // Set the registers to known values. 60 __ Mov(x0, 0x1000); 61 __ Mov(sp, 0x1004); 62 63 // Arithmetic ops. 64 __ Add(x1, x0, 0x1f7de); 65 __ Add(w2, w0, 0xffffff1); 66 __ Adds(x3, x0, 0x18001); 67 __ Adds(w4, w0, 0xffffff1); 68 __ Sub(x5, x0, 0x1f7de); 69 __ Sub(w6, w0, 0xffffff1); 70 __ Subs(x7, x0, 0x18001); 71 __ Subs(w8, w0, 0xffffff1); 72 73 // Logical ops. 74 __ And(x9, x0, 0x1f7de); 75 __ Orr(w10, w0, 0xffffff1); 76 __ Eor(x11, x0, 0x18001); 77 78 // Ops using the stack pointer. 79 __ Add(sp, sp, 0x18001); 80 __ Mov(x12, sp); 81 __ Mov(sp, 0x1004); 82 83 __ Add(sp, sp, 0x1f7de); 84 __ Mov(x13, sp); 85 __ Mov(sp, 0x1004); 86 87 __ Adds(x14, sp, 0x1f7de); 88 89 __ Orr(sp, x0, 0x1f7de); 90 __ Mov(x15, sp); 91 92 // Restore sp. 93 __ Mov(sp, x29); 94 END(); 95 96 if (CAN_RUN()) { 97 RUN(); 98 99 ASSERT_EQUAL_64(0x1000, x0); 100 ASSERT_EQUAL_64(0x207de, x1); 101 ASSERT_EQUAL_64(0x10000ff1, x2); 102 ASSERT_EQUAL_64(0x19001, x3); 103 ASSERT_EQUAL_64(0x10000ff1, x4); 104 ASSERT_EQUAL_64(0xfffffffffffe1822, x5); 105 ASSERT_EQUAL_64(0xf000100f, x6); 106 ASSERT_EQUAL_64(0xfffffffffffe8fff, x7); 107 ASSERT_EQUAL_64(0xf000100f, x8); 108 ASSERT_EQUAL_64(0x1000, x9); 109 ASSERT_EQUAL_64(0xffffff1, x10); 110 ASSERT_EQUAL_64(0x19001, x11); 111 ASSERT_EQUAL_64(0x19005, x12); 112 ASSERT_EQUAL_64(0x207e2, x13); 113 ASSERT_EQUAL_64(0x207e2, x14); 114 ASSERT_EQUAL_64(0x1f7de, x15); 115 } 116} 117 118 119TEST(stack_ops) { 120 SETUP(); 121 122 START(); 123 // save sp. 124 __ Mov(x29, sp); 125 126 // Set the sp to a known value. 127 __ Mov(sp, 0x1004); 128 __ Mov(x0, sp); 129 130 // Add immediate to the sp, and move the result to a normal register. 131 __ Add(sp, sp, 0x50); 132 __ Mov(x1, sp); 133 134 // Add extended to the sp, and move the result to a normal register. 135 __ Mov(x17, 0xfff); 136 __ Add(sp, sp, Operand(x17, SXTB)); 137 __ Mov(x2, sp); 138 139 // Create an sp using a logical instruction, and move to normal register. 140 __ Orr(sp, xzr, 0x1fff); 141 __ Mov(x3, sp); 142 143 // Write wsp using a logical instruction. 144 __ Orr(wsp, wzr, 0xfffffff8); 145 __ Mov(x4, sp); 146 147 // Write sp, and read back wsp. 148 __ Orr(sp, xzr, 0xfffffff8); 149 __ Mov(w5, wsp); 150 151 // Test writing into wsp in cases where the immediate isn't encodable. 152 VIXL_ASSERT(!Assembler::IsImmLogical(0x1234, kWRegSize)); 153 __ Orr(wsp, w5, 0x1234); 154 __ Mov(w6, wsp); 155 156 // restore sp. 157 __ Mov(sp, x29); 158 END(); 159 160 if (CAN_RUN()) { 161 RUN(); 162 163 ASSERT_EQUAL_64(0x1004, x0); 164 ASSERT_EQUAL_64(0x1054, x1); 165 ASSERT_EQUAL_64(0x1053, x2); 166 ASSERT_EQUAL_64(0x1fff, x3); 167 ASSERT_EQUAL_64(0xfffffff8, x4); 168 ASSERT_EQUAL_64(0xfffffff8, x5); 169 ASSERT_EQUAL_64(0xfffffffc, x6); 170 } 171} 172 173 174TEST(mvn) { 175 SETUP(); 176 177 START(); 178 __ Mvn(w0, 0xfff); 179 __ Mvn(x1, 0xfff); 180 __ Mvn(w2, Operand(w0, LSL, 1)); 181 __ Mvn(x3, Operand(x1, LSL, 2)); 182 __ Mvn(w4, Operand(w0, LSR, 3)); 183 __ Mvn(x5, Operand(x1, LSR, 4)); 184 __ Mvn(w6, Operand(w0, ASR, 11)); 185 __ Mvn(x7, Operand(x1, ASR, 12)); 186 __ Mvn(w8, Operand(w0, ROR, 13)); 187 __ Mvn(x9, Operand(x1, ROR, 14)); 188 __ Mvn(w10, Operand(w2, UXTB)); 189 __ Mvn(x11, Operand(x2, SXTB, 1)); 190 __ Mvn(w12, Operand(w2, UXTH, 2)); 191 __ Mvn(x13, Operand(x2, SXTH, 3)); 192 __ Mvn(x14, Operand(w2, UXTW, 4)); 193 __ Mvn(x15, Operand(w2, SXTW, 4)); 194 END(); 195 196 if (CAN_RUN()) { 197 RUN(); 198 199 ASSERT_EQUAL_64(0xfffff000, x0); 200 ASSERT_EQUAL_64(0xfffffffffffff000, x1); 201 ASSERT_EQUAL_64(0x00001fff, x2); 202 ASSERT_EQUAL_64(0x0000000000003fff, x3); 203 ASSERT_EQUAL_64(0xe00001ff, x4); 204 ASSERT_EQUAL_64(0xf0000000000000ff, x5); 205 ASSERT_EQUAL_64(0x00000001, x6); 206 ASSERT_EQUAL_64(0x0000000000000000, x7); 207 ASSERT_EQUAL_64(0x7ff80000, x8); 208 ASSERT_EQUAL_64(0x3ffc000000000000, x9); 209 ASSERT_EQUAL_64(0xffffff00, x10); 210 ASSERT_EQUAL_64(0x0000000000000001, x11); 211 ASSERT_EQUAL_64(0xffff8003, x12); 212 ASSERT_EQUAL_64(0xffffffffffff0007, x13); 213 ASSERT_EQUAL_64(0xfffffffffffe000f, x14); 214 ASSERT_EQUAL_64(0xfffffffffffe000f, x15); 215 } 216} 217 218 219TEST(mov_imm_w) { 220 SETUP(); 221 222 START(); 223 __ Mov(w0, 0xffffffff); 224 __ Mov(w1, 0xffff1234); 225 __ Mov(w2, 0x1234ffff); 226 __ Mov(w3, 0x00000000); 227 __ Mov(w4, 0x00001234); 228 __ Mov(w5, 0x12340000); 229 __ Mov(w6, 0x12345678); 230 __ Mov(w7, (int32_t)0x80000000); 231 __ Mov(w8, (int32_t)0xffff0000); 232 __ Mov(w9, kWMinInt); 233 END(); 234 235 if (CAN_RUN()) { 236 RUN(); 237 238 ASSERT_EQUAL_64(0xffffffff, x0); 239 ASSERT_EQUAL_64(0xffff1234, x1); 240 ASSERT_EQUAL_64(0x1234ffff, x2); 241 ASSERT_EQUAL_64(0x00000000, x3); 242 ASSERT_EQUAL_64(0x00001234, x4); 243 ASSERT_EQUAL_64(0x12340000, x5); 244 ASSERT_EQUAL_64(0x12345678, x6); 245 ASSERT_EQUAL_64(0x80000000, x7); 246 ASSERT_EQUAL_64(0xffff0000, x8); 247 ASSERT_EQUAL_32(kWMinInt, w9); 248 } 249} 250 251 252TEST(mov_imm_x) { 253 SETUP(); 254 255 START(); 256 __ Mov(x0, 0xffffffffffffffff); 257 __ Mov(x1, 0xffffffffffff1234); 258 __ Mov(x2, 0xffffffff12345678); 259 __ Mov(x3, 0xffff1234ffff5678); 260 __ Mov(x4, 0x1234ffffffff5678); 261 __ Mov(x5, 0x1234ffff5678ffff); 262 __ Mov(x6, 0x12345678ffffffff); 263 __ Mov(x7, 0x1234ffffffffffff); 264 __ Mov(x8, 0x123456789abcffff); 265 __ Mov(x9, 0x12345678ffff9abc); 266 __ Mov(x10, 0x1234ffff56789abc); 267 __ Mov(x11, 0xffff123456789abc); 268 __ Mov(x12, 0x0000000000000000); 269 __ Mov(x13, 0x0000000000001234); 270 __ Mov(x14, 0x0000000012345678); 271 __ Mov(x15, 0x0000123400005678); 272 __ Mov(x18, 0x1234000000005678); 273 __ Mov(x19, 0x1234000056780000); 274 __ Mov(x20, 0x1234567800000000); 275 __ Mov(x21, 0x1234000000000000); 276 __ Mov(x22, 0x123456789abc0000); 277 __ Mov(x23, 0x1234567800009abc); 278 __ Mov(x24, 0x1234000056789abc); 279 __ Mov(x25, 0x0000123456789abc); 280 __ Mov(x26, 0x123456789abcdef0); 281 __ Mov(x27, 0xffff000000000001); 282 __ Mov(x28, 0x8000ffff00000000); 283 END(); 284 285 if (CAN_RUN()) { 286 RUN(); 287 288 ASSERT_EQUAL_64(0xffffffffffff1234, x1); 289 ASSERT_EQUAL_64(0xffffffff12345678, x2); 290 ASSERT_EQUAL_64(0xffff1234ffff5678, x3); 291 ASSERT_EQUAL_64(0x1234ffffffff5678, x4); 292 ASSERT_EQUAL_64(0x1234ffff5678ffff, x5); 293 ASSERT_EQUAL_64(0x12345678ffffffff, x6); 294 ASSERT_EQUAL_64(0x1234ffffffffffff, x7); 295 ASSERT_EQUAL_64(0x123456789abcffff, x8); 296 ASSERT_EQUAL_64(0x12345678ffff9abc, x9); 297 ASSERT_EQUAL_64(0x1234ffff56789abc, x10); 298 ASSERT_EQUAL_64(0xffff123456789abc, x11); 299 ASSERT_EQUAL_64(0x0000000000000000, x12); 300 ASSERT_EQUAL_64(0x0000000000001234, x13); 301 ASSERT_EQUAL_64(0x0000000012345678, x14); 302 ASSERT_EQUAL_64(0x0000123400005678, x15); 303 ASSERT_EQUAL_64(0x1234000000005678, x18); 304 ASSERT_EQUAL_64(0x1234000056780000, x19); 305 ASSERT_EQUAL_64(0x1234567800000000, x20); 306 ASSERT_EQUAL_64(0x1234000000000000, x21); 307 ASSERT_EQUAL_64(0x123456789abc0000, x22); 308 ASSERT_EQUAL_64(0x1234567800009abc, x23); 309 ASSERT_EQUAL_64(0x1234000056789abc, x24); 310 ASSERT_EQUAL_64(0x0000123456789abc, x25); 311 ASSERT_EQUAL_64(0x123456789abcdef0, x26); 312 ASSERT_EQUAL_64(0xffff000000000001, x27); 313 ASSERT_EQUAL_64(0x8000ffff00000000, x28); 314 } 315} 316 317 318TEST(mov) { 319 SETUP(); 320 321 START(); 322 __ Mov(x0, 0xffffffffffffffff); 323 __ Mov(x1, 0xffffffffffffffff); 324 __ Mov(x2, 0xffffffffffffffff); 325 __ Mov(x3, 0xffffffffffffffff); 326 327 __ Mov(x0, 0x0123456789abcdef); 328 329 { 330 ExactAssemblyScope scope(&masm, 3 * kInstructionSize); 331 __ movz(x1, UINT64_C(0xabcd) << 16); 332 __ movk(x2, UINT64_C(0xabcd) << 32); 333 __ movn(x3, UINT64_C(0xabcd) << 48); 334 } 335 336 __ Mov(x4, 0x0123456789abcdef); 337 __ Mov(x5, x4); 338 339 __ Mov(w6, -1); 340 341 // Test that moves back to the same register have the desired effect. This 342 // is a no-op for X registers, and a truncation for W registers. 343 __ Mov(x7, 0x0123456789abcdef); 344 __ Mov(x7, x7); 345 __ Mov(x8, 0x0123456789abcdef); 346 __ Mov(w8, w8); 347 __ Mov(x9, 0x0123456789abcdef); 348 __ Mov(x9, Operand(x9)); 349 __ Mov(x10, 0x0123456789abcdef); 350 __ Mov(w10, Operand(w10)); 351 352 __ Mov(w11, 0xfff); 353 __ Mov(x12, 0xfff); 354 __ Mov(w13, Operand(w11, LSL, 1)); 355 __ Mov(x14, Operand(x12, LSL, 2)); 356 __ Mov(w15, Operand(w11, LSR, 3)); 357 __ Mov(x18, Operand(x12, LSR, 4)); 358 __ Mov(w19, Operand(w11, ASR, 11)); 359 __ Mov(x20, Operand(x12, ASR, 12)); 360 __ Mov(w21, Operand(w11, ROR, 13)); 361 __ Mov(x22, Operand(x12, ROR, 14)); 362 __ Mov(w23, Operand(w13, UXTB)); 363 __ Mov(x24, Operand(x13, SXTB, 1)); 364 __ Mov(w25, Operand(w13, UXTH, 2)); 365 __ Mov(x26, Operand(x13, SXTH, 3)); 366 __ Mov(x27, Operand(w13, UXTW, 4)); 367 368 __ Mov(x28, 0x0123456789abcdef); 369 __ Mov(w28, w28, kDiscardForSameWReg); 370 END(); 371 372 if (CAN_RUN()) { 373 RUN(); 374 375 ASSERT_EQUAL_64(0x0123456789abcdef, x0); 376 ASSERT_EQUAL_64(0x00000000abcd0000, x1); 377 ASSERT_EQUAL_64(0xffffabcdffffffff, x2); 378 ASSERT_EQUAL_64(0x5432ffffffffffff, x3); 379 ASSERT_EQUAL_64(x4, x5); 380 ASSERT_EQUAL_32(-1, w6); 381 ASSERT_EQUAL_64(0x0123456789abcdef, x7); 382 ASSERT_EQUAL_32(0x89abcdef, w8); 383 ASSERT_EQUAL_64(0x0123456789abcdef, x9); 384 ASSERT_EQUAL_32(0x89abcdef, w10); 385 ASSERT_EQUAL_64(0x00000fff, x11); 386 ASSERT_EQUAL_64(0x0000000000000fff, x12); 387 ASSERT_EQUAL_64(0x00001ffe, x13); 388 ASSERT_EQUAL_64(0x0000000000003ffc, x14); 389 ASSERT_EQUAL_64(0x000001ff, x15); 390 ASSERT_EQUAL_64(0x00000000000000ff, x18); 391 ASSERT_EQUAL_64(0x00000001, x19); 392 ASSERT_EQUAL_64(0x0000000000000000, x20); 393 ASSERT_EQUAL_64(0x7ff80000, x21); 394 ASSERT_EQUAL_64(0x3ffc000000000000, x22); 395 ASSERT_EQUAL_64(0x000000fe, x23); 396 ASSERT_EQUAL_64(0xfffffffffffffffc, x24); 397 ASSERT_EQUAL_64(0x00007ff8, x25); 398 ASSERT_EQUAL_64(0x000000000000fff0, x26); 399 ASSERT_EQUAL_64(0x000000000001ffe0, x27); 400 ASSERT_EQUAL_64(0x0123456789abcdef, x28); 401 } 402} 403 404 405TEST(mov_negative) { 406 SETUP(); 407 408 START(); 409 __ Mov(w11, 0xffffffff); 410 __ Mov(x12, 0xffffffffffffffff); 411 412 __ Mov(w13, Operand(w11, LSL, 1)); 413 __ Mov(w14, Operand(w11, LSR, 1)); 414 __ Mov(w15, Operand(w11, ASR, 1)); 415 __ Mov(w18, Operand(w11, ROR, 1)); 416 __ Mov(w19, Operand(w11, UXTB, 1)); 417 __ Mov(w20, Operand(w11, SXTB, 1)); 418 __ Mov(w21, Operand(w11, UXTH, 1)); 419 __ Mov(w22, Operand(w11, SXTH, 1)); 420 421 __ Mov(x23, Operand(x12, LSL, 1)); 422 __ Mov(x24, Operand(x12, LSR, 1)); 423 __ Mov(x25, Operand(x12, ASR, 1)); 424 __ Mov(x26, Operand(x12, ROR, 1)); 425 __ Mov(x27, Operand(x12, UXTH, 1)); 426 __ Mov(x28, Operand(x12, SXTH, 1)); 427 __ Mov(x29, Operand(x12, UXTW, 1)); 428 __ Mov(x30, Operand(x12, SXTW, 1)); 429 END(); 430 431 if (CAN_RUN()) { 432 RUN(); 433 434 ASSERT_EQUAL_64(0xfffffffe, x13); 435 ASSERT_EQUAL_64(0x7fffffff, x14); 436 ASSERT_EQUAL_64(0xffffffff, x15); 437 ASSERT_EQUAL_64(0xffffffff, x18); 438 ASSERT_EQUAL_64(0x000001fe, x19); 439 ASSERT_EQUAL_64(0xfffffffe, x20); 440 ASSERT_EQUAL_64(0x0001fffe, x21); 441 ASSERT_EQUAL_64(0xfffffffe, x22); 442 443 ASSERT_EQUAL_64(0xfffffffffffffffe, x23); 444 ASSERT_EQUAL_64(0x7fffffffffffffff, x24); 445 ASSERT_EQUAL_64(0xffffffffffffffff, x25); 446 ASSERT_EQUAL_64(0xffffffffffffffff, x26); 447 ASSERT_EQUAL_64(0x000000000001fffe, x27); 448 ASSERT_EQUAL_64(0xfffffffffffffffe, x28); 449 ASSERT_EQUAL_64(0x00000001fffffffe, x29); 450 ASSERT_EQUAL_64(0xfffffffffffffffe, x30); 451 } 452} 453 454 455TEST(orr) { 456 SETUP(); 457 458 START(); 459 __ Mov(x0, 0xf0f0); 460 __ Mov(x1, 0xf00000ff); 461 462 __ Orr(x2, x0, Operand(x1)); 463 __ Orr(w3, w0, Operand(w1, LSL, 28)); 464 __ Orr(x4, x0, Operand(x1, LSL, 32)); 465 __ Orr(x5, x0, Operand(x1, LSR, 4)); 466 __ Orr(w6, w0, Operand(w1, ASR, 4)); 467 __ Orr(x7, x0, Operand(x1, ASR, 4)); 468 __ Orr(w8, w0, Operand(w1, ROR, 12)); 469 __ Orr(x9, x0, Operand(x1, ROR, 12)); 470 __ Orr(w10, w0, 0xf); 471 __ Orr(x11, x0, 0xf0000000f0000000); 472 END(); 473 474 if (CAN_RUN()) { 475 RUN(); 476 477 ASSERT_EQUAL_64(0x00000000f000f0ff, x2); 478 ASSERT_EQUAL_64(0xf000f0f0, x3); 479 ASSERT_EQUAL_64(0xf00000ff0000f0f0, x4); 480 ASSERT_EQUAL_64(0x000000000f00f0ff, x5); 481 ASSERT_EQUAL_64(0xff00f0ff, x6); 482 ASSERT_EQUAL_64(0x000000000f00f0ff, x7); 483 ASSERT_EQUAL_64(0x0ffff0f0, x8); 484 ASSERT_EQUAL_64(0x0ff00000000ff0f0, x9); 485 ASSERT_EQUAL_64(0x0000f0ff, x10); 486 ASSERT_EQUAL_64(0xf0000000f000f0f0, x11); 487 } 488} 489 490 491TEST(orr_extend) { 492 SETUP(); 493 494 START(); 495 __ Mov(x0, 1); 496 __ Mov(x1, 0x8000000080008080); 497 __ Orr(w6, w0, Operand(w1, UXTB)); 498 __ Orr(x7, x0, Operand(x1, UXTH, 1)); 499 __ Orr(w8, w0, Operand(w1, UXTW, 2)); 500 __ Orr(x9, x0, Operand(x1, UXTX, 3)); 501 __ Orr(w10, w0, Operand(w1, SXTB)); 502 __ Orr(x11, x0, Operand(x1, SXTH, 1)); 503 __ Orr(x12, x0, Operand(x1, SXTW, 2)); 504 __ Orr(x13, x0, Operand(x1, SXTX, 3)); 505 END(); 506 507 if (CAN_RUN()) { 508 RUN(); 509 510 ASSERT_EQUAL_64(0x00000081, x6); 511 ASSERT_EQUAL_64(0x0000000000010101, x7); 512 ASSERT_EQUAL_64(0x00020201, x8); 513 ASSERT_EQUAL_64(0x0000000400040401, x9); 514 ASSERT_EQUAL_64(0xffffff81, x10); 515 ASSERT_EQUAL_64(0xffffffffffff0101, x11); 516 ASSERT_EQUAL_64(0xfffffffe00020201, x12); 517 ASSERT_EQUAL_64(0x0000000400040401, x13); 518 } 519} 520 521 522TEST(bitwise_wide_imm) { 523 SETUP(); 524 525 START(); 526 __ Mov(x0, 0); 527 __ Mov(x1, 0xf0f0f0f0f0f0f0f0); 528 529 __ Orr(x10, x0, 0x1234567890abcdef); 530 __ Orr(w11, w1, 0x90abcdef); 531 532 __ Orr(w12, w0, kWMinInt); 533 __ Eor(w13, w0, kWMinInt); 534 END(); 535 536 if (CAN_RUN()) { 537 RUN(); 538 539 ASSERT_EQUAL_64(0, x0); 540 ASSERT_EQUAL_64(0xf0f0f0f0f0f0f0f0, x1); 541 ASSERT_EQUAL_64(0x1234567890abcdef, x10); 542 ASSERT_EQUAL_64(0x00000000f0fbfdff, x11); 543 ASSERT_EQUAL_32(kWMinInt, w12); 544 ASSERT_EQUAL_32(kWMinInt, w13); 545 } 546} 547 548 549TEST(orn) { 550 SETUP(); 551 552 START(); 553 __ Mov(x0, 0xf0f0); 554 __ Mov(x1, 0xf00000ff); 555 556 __ Orn(x2, x0, Operand(x1)); 557 __ Orn(w3, w0, Operand(w1, LSL, 4)); 558 __ Orn(x4, x0, Operand(x1, LSL, 4)); 559 __ Orn(x5, x0, Operand(x1, LSR, 1)); 560 __ Orn(w6, w0, Operand(w1, ASR, 1)); 561 __ Orn(x7, x0, Operand(x1, ASR, 1)); 562 __ Orn(w8, w0, Operand(w1, ROR, 16)); 563 __ Orn(x9, x0, Operand(x1, ROR, 16)); 564 __ Orn(w10, w0, 0x0000ffff); 565 __ Orn(x11, x0, 0x0000ffff0000ffff); 566 END(); 567 568 if (CAN_RUN()) { 569 RUN(); 570 571 ASSERT_EQUAL_64(0xffffffff0ffffff0, x2); 572 ASSERT_EQUAL_64(0xfffff0ff, x3); 573 ASSERT_EQUAL_64(0xfffffff0fffff0ff, x4); 574 ASSERT_EQUAL_64(0xffffffff87fffff0, x5); 575 ASSERT_EQUAL_64(0x07fffff0, x6); 576 ASSERT_EQUAL_64(0xffffffff87fffff0, x7); 577 ASSERT_EQUAL_64(0xff00ffff, x8); 578 ASSERT_EQUAL_64(0xff00ffffffffffff, x9); 579 ASSERT_EQUAL_64(0xfffff0f0, x10); 580 ASSERT_EQUAL_64(0xffff0000fffff0f0, x11); 581 } 582} 583 584 585TEST(orn_extend) { 586 SETUP(); 587 588 START(); 589 __ Mov(x0, 1); 590 __ Mov(x1, 0x8000000080008081); 591 __ Orn(w6, w0, Operand(w1, UXTB)); 592 __ Orn(x7, x0, Operand(x1, UXTH, 1)); 593 __ Orn(w8, w0, Operand(w1, UXTW, 2)); 594 __ Orn(x9, x0, Operand(x1, UXTX, 3)); 595 __ Orn(w10, w0, Operand(w1, SXTB)); 596 __ Orn(x11, x0, Operand(x1, SXTH, 1)); 597 __ Orn(x12, x0, Operand(x1, SXTW, 2)); 598 __ Orn(x13, x0, Operand(x1, SXTX, 3)); 599 END(); 600 601 if (CAN_RUN()) { 602 RUN(); 603 604 ASSERT_EQUAL_64(0xffffff7f, x6); 605 ASSERT_EQUAL_64(0xfffffffffffefefd, x7); 606 ASSERT_EQUAL_64(0xfffdfdfb, x8); 607 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9); 608 ASSERT_EQUAL_64(0x0000007f, x10); 609 ASSERT_EQUAL_64(0x000000000000fefd, x11); 610 ASSERT_EQUAL_64(0x00000001fffdfdfb, x12); 611 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13); 612 } 613} 614 615 616TEST(and_) { 617 SETUP(); 618 619 START(); 620 __ Mov(x0, 0xfff0); 621 __ Mov(x1, 0xf00000ff); 622 623 __ And(x2, x0, Operand(x1)); 624 __ And(w3, w0, Operand(w1, LSL, 4)); 625 __ And(x4, x0, Operand(x1, LSL, 4)); 626 __ And(x5, x0, Operand(x1, LSR, 1)); 627 __ And(w6, w0, Operand(w1, ASR, 20)); 628 __ And(x7, x0, Operand(x1, ASR, 20)); 629 __ And(w8, w0, Operand(w1, ROR, 28)); 630 __ And(x9, x0, Operand(x1, ROR, 28)); 631 __ And(w10, w0, Operand(0xff00)); 632 __ And(x11, x0, Operand(0xff)); 633 END(); 634 635 if (CAN_RUN()) { 636 RUN(); 637 638 ASSERT_EQUAL_64(0x000000f0, x2); 639 ASSERT_EQUAL_64(0x00000ff0, x3); 640 ASSERT_EQUAL_64(0x00000ff0, x4); 641 ASSERT_EQUAL_64(0x00000070, x5); 642 ASSERT_EQUAL_64(0x0000ff00, x6); 643 ASSERT_EQUAL_64(0x00000f00, x7); 644 ASSERT_EQUAL_64(0x00000ff0, x8); 645 ASSERT_EQUAL_64(0x00000000, x9); 646 ASSERT_EQUAL_64(0x0000ff00, x10); 647 ASSERT_EQUAL_64(0x000000f0, x11); 648 } 649} 650 651 652TEST(and_extend) { 653 SETUP(); 654 655 START(); 656 __ Mov(x0, 0xffffffffffffffff); 657 __ Mov(x1, 0x8000000080008081); 658 __ And(w6, w0, Operand(w1, UXTB)); 659 __ And(x7, x0, Operand(x1, UXTH, 1)); 660 __ And(w8, w0, Operand(w1, UXTW, 2)); 661 __ And(x9, x0, Operand(x1, UXTX, 3)); 662 __ And(w10, w0, Operand(w1, SXTB)); 663 __ And(x11, x0, Operand(x1, SXTH, 1)); 664 __ And(x12, x0, Operand(x1, SXTW, 2)); 665 __ And(x13, x0, Operand(x1, SXTX, 3)); 666 END(); 667 668 if (CAN_RUN()) { 669 RUN(); 670 671 ASSERT_EQUAL_64(0x00000081, x6); 672 ASSERT_EQUAL_64(0x0000000000010102, x7); 673 ASSERT_EQUAL_64(0x00020204, x8); 674 ASSERT_EQUAL_64(0x0000000400040408, x9); 675 ASSERT_EQUAL_64(0xffffff81, x10); 676 ASSERT_EQUAL_64(0xffffffffffff0102, x11); 677 ASSERT_EQUAL_64(0xfffffffe00020204, x12); 678 ASSERT_EQUAL_64(0x0000000400040408, x13); 679 } 680} 681 682 683TEST(ands) { 684 SETUP(); 685 686 START(); 687 __ Mov(x1, 0xf00000ff); 688 __ Ands(w0, w1, Operand(w1)); 689 END(); 690 691 if (CAN_RUN()) { 692 RUN(); 693 694 ASSERT_EQUAL_NZCV(NFlag); 695 ASSERT_EQUAL_64(0xf00000ff, x0); 696 } 697 698 START(); 699 __ Mov(x0, 0xfff0); 700 __ Mov(x1, 0xf00000ff); 701 __ Ands(w0, w0, Operand(w1, LSR, 4)); 702 END(); 703 704 if (CAN_RUN()) { 705 RUN(); 706 707 ASSERT_EQUAL_NZCV(ZFlag); 708 ASSERT_EQUAL_64(0x00000000, x0); 709 } 710 711 START(); 712 __ Mov(x0, 0x8000000000000000); 713 __ Mov(x1, 0x00000001); 714 __ Ands(x0, x0, Operand(x1, ROR, 1)); 715 END(); 716 717 if (CAN_RUN()) { 718 RUN(); 719 720 ASSERT_EQUAL_NZCV(NFlag); 721 ASSERT_EQUAL_64(0x8000000000000000, x0); 722 } 723 724 START(); 725 __ Mov(x0, 0xfff0); 726 __ Ands(w0, w0, Operand(0xf)); 727 END(); 728 729 if (CAN_RUN()) { 730 RUN(); 731 732 ASSERT_EQUAL_NZCV(ZFlag); 733 ASSERT_EQUAL_64(0x00000000, x0); 734 } 735 736 START(); 737 __ Mov(x0, 0xff000000); 738 __ Ands(w0, w0, Operand(0x80000000)); 739 END(); 740 741 if (CAN_RUN()) { 742 RUN(); 743 744 ASSERT_EQUAL_NZCV(NFlag); 745 ASSERT_EQUAL_64(0x80000000, x0); 746 } 747} 748 749 750TEST(bic) { 751 SETUP(); 752 753 START(); 754 __ Mov(x0, 0xfff0); 755 __ Mov(x1, 0xf00000ff); 756 757 __ Bic(x2, x0, Operand(x1)); 758 __ Bic(w3, w0, Operand(w1, LSL, 4)); 759 __ Bic(x4, x0, Operand(x1, LSL, 4)); 760 __ Bic(x5, x0, Operand(x1, LSR, 1)); 761 __ Bic(w6, w0, Operand(w1, ASR, 20)); 762 __ Bic(x7, x0, Operand(x1, ASR, 20)); 763 __ Bic(w8, w0, Operand(w1, ROR, 28)); 764 __ Bic(x9, x0, Operand(x1, ROR, 24)); 765 __ Bic(x10, x0, Operand(0x1f)); 766 __ Bic(x11, x0, Operand(0x100)); 767 768 // Test bic into sp when the constant cannot be encoded in the immediate 769 // field. 770 // Use x20 to preserve sp. We check for the result via x21 because the 771 // test infrastructure requires that sp be restored to its original value. 772 __ Mov(x20, sp); 773 __ Mov(x0, 0xffffff); 774 __ Bic(sp, x0, Operand(0xabcdef)); 775 __ Mov(x21, sp); 776 __ Mov(sp, x20); 777 END(); 778 779 if (CAN_RUN()) { 780 RUN(); 781 782 ASSERT_EQUAL_64(0x0000ff00, x2); 783 ASSERT_EQUAL_64(0x0000f000, x3); 784 ASSERT_EQUAL_64(0x0000f000, x4); 785 ASSERT_EQUAL_64(0x0000ff80, x5); 786 ASSERT_EQUAL_64(0x000000f0, x6); 787 ASSERT_EQUAL_64(0x0000f0f0, x7); 788 ASSERT_EQUAL_64(0x0000f000, x8); 789 ASSERT_EQUAL_64(0x0000ff00, x9); 790 ASSERT_EQUAL_64(0x0000ffe0, x10); 791 ASSERT_EQUAL_64(0x0000fef0, x11); 792 793 ASSERT_EQUAL_64(0x543210, x21); 794 } 795} 796 797 798TEST(bic_extend) { 799 SETUP(); 800 801 START(); 802 __ Mov(x0, 0xffffffffffffffff); 803 __ Mov(x1, 0x8000000080008081); 804 __ Bic(w6, w0, Operand(w1, UXTB)); 805 __ Bic(x7, x0, Operand(x1, UXTH, 1)); 806 __ Bic(w8, w0, Operand(w1, UXTW, 2)); 807 __ Bic(x9, x0, Operand(x1, UXTX, 3)); 808 __ Bic(w10, w0, Operand(w1, SXTB)); 809 __ Bic(x11, x0, Operand(x1, SXTH, 1)); 810 __ Bic(x12, x0, Operand(x1, SXTW, 2)); 811 __ Bic(x13, x0, Operand(x1, SXTX, 3)); 812 END(); 813 814 if (CAN_RUN()) { 815 RUN(); 816 817 ASSERT_EQUAL_64(0xffffff7e, x6); 818 ASSERT_EQUAL_64(0xfffffffffffefefd, x7); 819 ASSERT_EQUAL_64(0xfffdfdfb, x8); 820 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9); 821 ASSERT_EQUAL_64(0x0000007e, x10); 822 ASSERT_EQUAL_64(0x000000000000fefd, x11); 823 ASSERT_EQUAL_64(0x00000001fffdfdfb, x12); 824 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13); 825 } 826} 827 828 829TEST(bics) { 830 SETUP(); 831 832 START(); 833 __ Mov(x1, 0xffff); 834 __ Bics(w0, w1, Operand(w1)); 835 END(); 836 837 if (CAN_RUN()) { 838 RUN(); 839 840 ASSERT_EQUAL_NZCV(ZFlag); 841 ASSERT_EQUAL_64(0x00000000, x0); 842 } 843 844 START(); 845 __ Mov(x0, 0xffffffff); 846 __ Bics(w0, w0, Operand(w0, LSR, 1)); 847 END(); 848 849 if (CAN_RUN()) { 850 RUN(); 851 852 ASSERT_EQUAL_NZCV(NFlag); 853 ASSERT_EQUAL_64(0x80000000, x0); 854 } 855 856 START(); 857 __ Mov(x0, 0x8000000000000000); 858 __ Mov(x1, 0x00000001); 859 __ Bics(x0, x0, Operand(x1, ROR, 1)); 860 END(); 861 862 if (CAN_RUN()) { 863 RUN(); 864 865 ASSERT_EQUAL_NZCV(ZFlag); 866 ASSERT_EQUAL_64(0x00000000, x0); 867 } 868 869 START(); 870 __ Mov(x0, 0xffffffffffffffff); 871 __ Bics(x0, x0, 0x7fffffffffffffff); 872 END(); 873 874 if (CAN_RUN()) { 875 RUN(); 876 877 ASSERT_EQUAL_NZCV(NFlag); 878 ASSERT_EQUAL_64(0x8000000000000000, x0); 879 } 880 881 START(); 882 __ Mov(w0, 0xffff0000); 883 __ Bics(w0, w0, 0xfffffff0); 884 END(); 885 886 if (CAN_RUN()) { 887 RUN(); 888 889 ASSERT_EQUAL_NZCV(ZFlag); 890 ASSERT_EQUAL_64(0x00000000, x0); 891 } 892} 893 894 895TEST(eor) { 896 SETUP(); 897 898 START(); 899 __ Mov(x0, 0xfff0); 900 __ Mov(x1, 0xf00000ff); 901 902 __ Eor(x2, x0, Operand(x1)); 903 __ Eor(w3, w0, Operand(w1, LSL, 4)); 904 __ Eor(x4, x0, Operand(x1, LSL, 4)); 905 __ Eor(x5, x0, Operand(x1, LSR, 1)); 906 __ Eor(w6, w0, Operand(w1, ASR, 20)); 907 __ Eor(x7, x0, Operand(x1, ASR, 20)); 908 __ Eor(w8, w0, Operand(w1, ROR, 28)); 909 __ Eor(x9, x0, Operand(x1, ROR, 28)); 910 __ Eor(w10, w0, 0xff00ff00); 911 __ Eor(x11, x0, 0xff00ff00ff00ff00); 912 END(); 913 914 if (CAN_RUN()) { 915 RUN(); 916 917 ASSERT_EQUAL_64(0x00000000f000ff0f, x2); 918 ASSERT_EQUAL_64(0x0000f000, x3); 919 ASSERT_EQUAL_64(0x0000000f0000f000, x4); 920 ASSERT_EQUAL_64(0x000000007800ff8f, x5); 921 ASSERT_EQUAL_64(0xffff00f0, x6); 922 ASSERT_EQUAL_64(0x000000000000f0f0, x7); 923 ASSERT_EQUAL_64(0x0000f00f, x8); 924 ASSERT_EQUAL_64(0x00000ff00000ffff, x9); 925 ASSERT_EQUAL_64(0xff0000f0, x10); 926 ASSERT_EQUAL_64(0xff00ff00ff0000f0, x11); 927 } 928} 929 930TEST(eor_extend) { 931 SETUP(); 932 933 START(); 934 __ Mov(x0, 0x1111111111111111); 935 __ Mov(x1, 0x8000000080008081); 936 __ Eor(w6, w0, Operand(w1, UXTB)); 937 __ Eor(x7, x0, Operand(x1, UXTH, 1)); 938 __ Eor(w8, w0, Operand(w1, UXTW, 2)); 939 __ Eor(x9, x0, Operand(x1, UXTX, 3)); 940 __ Eor(w10, w0, Operand(w1, SXTB)); 941 __ Eor(x11, x0, Operand(x1, SXTH, 1)); 942 __ Eor(x12, x0, Operand(x1, SXTW, 2)); 943 __ Eor(x13, x0, Operand(x1, SXTX, 3)); 944 END(); 945 946 if (CAN_RUN()) { 947 RUN(); 948 949 ASSERT_EQUAL_64(0x11111190, x6); 950 ASSERT_EQUAL_64(0x1111111111101013, x7); 951 ASSERT_EQUAL_64(0x11131315, x8); 952 ASSERT_EQUAL_64(0x1111111511151519, x9); 953 ASSERT_EQUAL_64(0xeeeeee90, x10); 954 ASSERT_EQUAL_64(0xeeeeeeeeeeee1013, x11); 955 ASSERT_EQUAL_64(0xeeeeeeef11131315, x12); 956 ASSERT_EQUAL_64(0x1111111511151519, x13); 957 } 958} 959 960 961TEST(eon) { 962 SETUP(); 963 964 START(); 965 __ Mov(x0, 0xfff0); 966 __ Mov(x1, 0xf00000ff); 967 968 __ Eon(x2, x0, Operand(x1)); 969 __ Eon(w3, w0, Operand(w1, LSL, 4)); 970 __ Eon(x4, x0, Operand(x1, LSL, 4)); 971 __ Eon(x5, x0, Operand(x1, LSR, 1)); 972 __ Eon(w6, w0, Operand(w1, ASR, 20)); 973 __ Eon(x7, x0, Operand(x1, ASR, 20)); 974 __ Eon(w8, w0, Operand(w1, ROR, 28)); 975 __ Eon(x9, x0, Operand(x1, ROR, 28)); 976 __ Eon(w10, w0, 0x03c003c0); 977 __ Eon(x11, x0, 0x0000100000001000); 978 END(); 979 980 if (CAN_RUN()) { 981 RUN(); 982 983 ASSERT_EQUAL_64(0xffffffff0fff00f0, x2); 984 ASSERT_EQUAL_64(0xffff0fff, x3); 985 ASSERT_EQUAL_64(0xfffffff0ffff0fff, x4); 986 ASSERT_EQUAL_64(0xffffffff87ff0070, x5); 987 ASSERT_EQUAL_64(0x0000ff0f, x6); 988 ASSERT_EQUAL_64(0xffffffffffff0f0f, x7); 989 ASSERT_EQUAL_64(0xffff0ff0, x8); 990 ASSERT_EQUAL_64(0xfffff00fffff0000, x9); 991 ASSERT_EQUAL_64(0xfc3f03cf, x10); 992 ASSERT_EQUAL_64(0xffffefffffff100f, x11); 993 } 994} 995 996 997TEST(eon_extend) { 998 SETUP(); 999 1000 START(); 1001 __ Mov(x0, 0x1111111111111111); 1002 __ Mov(x1, 0x8000000080008081); 1003 __ Eon(w6, w0, Operand(w1, UXTB)); 1004 __ Eon(x7, x0, Operand(x1, UXTH, 1)); 1005 __ Eon(w8, w0, Operand(w1, UXTW, 2)); 1006 __ Eon(x9, x0, Operand(x1, UXTX, 3)); 1007 __ Eon(w10, w0, Operand(w1, SXTB)); 1008 __ Eon(x11, x0, Operand(x1, SXTH, 1)); 1009 __ Eon(x12, x0, Operand(x1, SXTW, 2)); 1010 __ Eon(x13, x0, Operand(x1, SXTX, 3)); 1011 END(); 1012 1013 if (CAN_RUN()) { 1014 RUN(); 1015 1016 ASSERT_EQUAL_64(0xeeeeee6f, x6); 1017 ASSERT_EQUAL_64(0xeeeeeeeeeeefefec, x7); 1018 ASSERT_EQUAL_64(0xeeececea, x8); 1019 ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x9); 1020 ASSERT_EQUAL_64(0x1111116f, x10); 1021 ASSERT_EQUAL_64(0x111111111111efec, x11); 1022 ASSERT_EQUAL_64(0x11111110eeececea, x12); 1023 ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x13); 1024 } 1025} 1026 1027 1028TEST(mul) { 1029 SETUP(); 1030 1031 START(); 1032 __ Mov(x25, 0); 1033 __ Mov(x26, 1); 1034 __ Mov(x18, 0xffffffff); 1035 __ Mov(x19, 0xffffffffffffffff); 1036 1037 __ Mul(w0, w25, w25); 1038 __ Mul(w1, w25, w26); 1039 __ Mul(w2, w26, w18); 1040 __ Mul(w3, w18, w19); 1041 __ Mul(x4, x25, x25); 1042 __ Mul(x5, x26, x18); 1043 __ Mul(x6, x18, x19); 1044 __ Mul(x7, x19, x19); 1045 __ Smull(x8, w26, w18); 1046 __ Smull(x9, w18, w18); 1047 __ Smull(x10, w19, w19); 1048 __ Mneg(w11, w25, w25); 1049 __ Mneg(w12, w25, w26); 1050 __ Mneg(w13, w26, w18); 1051 __ Mneg(w14, w18, w19); 1052 __ Mneg(x20, x25, x25); 1053 __ Mneg(x21, x26, x18); 1054 __ Mneg(x22, x18, x19); 1055 __ Mneg(x23, x19, x19); 1056 END(); 1057 1058 if (CAN_RUN()) { 1059 RUN(); 1060 1061 ASSERT_EQUAL_64(0, x0); 1062 ASSERT_EQUAL_64(0, x1); 1063 ASSERT_EQUAL_64(0xffffffff, x2); 1064 ASSERT_EQUAL_64(1, x3); 1065 ASSERT_EQUAL_64(0, x4); 1066 ASSERT_EQUAL_64(0xffffffff, x5); 1067 ASSERT_EQUAL_64(0xffffffff00000001, x6); 1068 ASSERT_EQUAL_64(1, x7); 1069 ASSERT_EQUAL_64(0xffffffffffffffff, x8); 1070 ASSERT_EQUAL_64(1, x9); 1071 ASSERT_EQUAL_64(1, x10); 1072 ASSERT_EQUAL_64(0, x11); 1073 ASSERT_EQUAL_64(0, x12); 1074 ASSERT_EQUAL_64(1, x13); 1075 ASSERT_EQUAL_64(0xffffffff, x14); 1076 ASSERT_EQUAL_64(0, x20); 1077 ASSERT_EQUAL_64(0xffffffff00000001, x21); 1078 ASSERT_EQUAL_64(0xffffffff, x22); 1079 ASSERT_EQUAL_64(0xffffffffffffffff, x23); 1080 } 1081} 1082 1083 1084static void SmullHelper(int64_t expected, int64_t a, int64_t b) { 1085 SETUP(); 1086 START(); 1087 __ Mov(w0, a); 1088 __ Mov(w1, b); 1089 __ Smull(x2, w0, w1); 1090 END(); 1091 if (CAN_RUN()) { 1092 RUN(); 1093 ASSERT_EQUAL_64(expected, x2); 1094 } 1095} 1096 1097 1098TEST(smull) { 1099 SmullHelper(0, 0, 0); 1100 SmullHelper(1, 1, 1); 1101 SmullHelper(-1, -1, 1); 1102 SmullHelper(1, -1, -1); 1103 SmullHelper(0xffffffff80000000, 0x80000000, 1); 1104 SmullHelper(0x0000000080000000, 0x00010000, 0x00008000); 1105} 1106 1107 1108TEST(madd) { 1109 SETUP(); 1110 1111 START(); 1112 __ Mov(x16, 0); 1113 __ Mov(x17, 1); 1114 __ Mov(x18, 0xffffffff); 1115 __ Mov(x19, 0xffffffffffffffff); 1116 1117 __ Madd(w0, w16, w16, w16); 1118 __ Madd(w1, w16, w16, w17); 1119 __ Madd(w2, w16, w16, w18); 1120 __ Madd(w3, w16, w16, w19); 1121 __ Madd(w4, w16, w17, w17); 1122 __ Madd(w5, w17, w17, w18); 1123 __ Madd(w6, w17, w17, w19); 1124 __ Madd(w7, w17, w18, w16); 1125 __ Madd(w8, w17, w18, w18); 1126 __ Madd(w9, w18, w18, w17); 1127 __ Madd(w10, w18, w19, w18); 1128 __ Madd(w11, w19, w19, w19); 1129 1130 __ Madd(x12, x16, x16, x16); 1131 __ Madd(x13, x16, x16, x17); 1132 __ Madd(x14, x16, x16, x18); 1133 __ Madd(x15, x16, x16, x19); 1134 __ Madd(x20, x16, x17, x17); 1135 __ Madd(x21, x17, x17, x18); 1136 __ Madd(x22, x17, x17, x19); 1137 __ Madd(x23, x17, x18, x16); 1138 __ Madd(x24, x17, x18, x18); 1139 __ Madd(x25, x18, x18, x17); 1140 __ Madd(x26, x18, x19, x18); 1141 __ Madd(x27, x19, x19, x19); 1142 1143 END(); 1144 1145 if (CAN_RUN()) { 1146 RUN(); 1147 1148 ASSERT_EQUAL_64(0, x0); 1149 ASSERT_EQUAL_64(1, x1); 1150 ASSERT_EQUAL_64(0xffffffff, x2); 1151 ASSERT_EQUAL_64(0xffffffff, x3); 1152 ASSERT_EQUAL_64(1, x4); 1153 ASSERT_EQUAL_64(0, x5); 1154 ASSERT_EQUAL_64(0, x6); 1155 ASSERT_EQUAL_64(0xffffffff, x7); 1156 ASSERT_EQUAL_64(0xfffffffe, x8); 1157 ASSERT_EQUAL_64(2, x9); 1158 ASSERT_EQUAL_64(0, x10); 1159 ASSERT_EQUAL_64(0, x11); 1160 1161 ASSERT_EQUAL_64(0, x12); 1162 ASSERT_EQUAL_64(1, x13); 1163 ASSERT_EQUAL_64(0x00000000ffffffff, x14); 1164 ASSERT_EQUAL_64(0xffffffffffffffff, x15); 1165 ASSERT_EQUAL_64(1, x20); 1166 ASSERT_EQUAL_64(0x0000000100000000, x21); 1167 ASSERT_EQUAL_64(0, x22); 1168 ASSERT_EQUAL_64(0x00000000ffffffff, x23); 1169 ASSERT_EQUAL_64(0x00000001fffffffe, x24); 1170 ASSERT_EQUAL_64(0xfffffffe00000002, x25); 1171 ASSERT_EQUAL_64(0, x26); 1172 ASSERT_EQUAL_64(0, x27); 1173 } 1174} 1175 1176 1177TEST(msub) { 1178 SETUP(); 1179 1180 START(); 1181 __ Mov(x16, 0); 1182 __ Mov(x17, 1); 1183 __ Mov(x18, 0xffffffff); 1184 __ Mov(x19, 0xffffffffffffffff); 1185 1186 __ Msub(w0, w16, w16, w16); 1187 __ Msub(w1, w16, w16, w17); 1188 __ Msub(w2, w16, w16, w18); 1189 __ Msub(w3, w16, w16, w19); 1190 __ Msub(w4, w16, w17, w17); 1191 __ Msub(w5, w17, w17, w18); 1192 __ Msub(w6, w17, w17, w19); 1193 __ Msub(w7, w17, w18, w16); 1194 __ Msub(w8, w17, w18, w18); 1195 __ Msub(w9, w18, w18, w17); 1196 __ Msub(w10, w18, w19, w18); 1197 __ Msub(w11, w19, w19, w19); 1198 1199 __ Msub(x12, x16, x16, x16); 1200 __ Msub(x13, x16, x16, x17); 1201 __ Msub(x14, x16, x16, x18); 1202 __ Msub(x15, x16, x16, x19); 1203 __ Msub(x20, x16, x17, x17); 1204 __ Msub(x21, x17, x17, x18); 1205 __ Msub(x22, x17, x17, x19); 1206 __ Msub(x23, x17, x18, x16); 1207 __ Msub(x24, x17, x18, x18); 1208 __ Msub(x25, x18, x18, x17); 1209 __ Msub(x26, x18, x19, x18); 1210 __ Msub(x27, x19, x19, x19); 1211 1212 END(); 1213 1214 if (CAN_RUN()) { 1215 RUN(); 1216 1217 ASSERT_EQUAL_64(0, x0); 1218 ASSERT_EQUAL_64(1, x1); 1219 ASSERT_EQUAL_64(0xffffffff, x2); 1220 ASSERT_EQUAL_64(0xffffffff, x3); 1221 ASSERT_EQUAL_64(1, x4); 1222 ASSERT_EQUAL_64(0xfffffffe, x5); 1223 ASSERT_EQUAL_64(0xfffffffe, x6); 1224 ASSERT_EQUAL_64(1, x7); 1225 ASSERT_EQUAL_64(0, x8); 1226 ASSERT_EQUAL_64(0, x9); 1227 ASSERT_EQUAL_64(0xfffffffe, x10); 1228 ASSERT_EQUAL_64(0xfffffffe, x11); 1229 1230 ASSERT_EQUAL_64(0, x12); 1231 ASSERT_EQUAL_64(1, x13); 1232 ASSERT_EQUAL_64(0x00000000ffffffff, x14); 1233 ASSERT_EQUAL_64(0xffffffffffffffff, x15); 1234 ASSERT_EQUAL_64(1, x20); 1235 ASSERT_EQUAL_64(0x00000000fffffffe, x21); 1236 ASSERT_EQUAL_64(0xfffffffffffffffe, x22); 1237 ASSERT_EQUAL_64(0xffffffff00000001, x23); 1238 ASSERT_EQUAL_64(0, x24); 1239 ASSERT_EQUAL_64(0x0000000200000000, x25); 1240 ASSERT_EQUAL_64(0x00000001fffffffe, x26); 1241 ASSERT_EQUAL_64(0xfffffffffffffffe, x27); 1242 } 1243} 1244 1245 1246TEST(smulh) { 1247 SETUP(); 1248 1249 START(); 1250 __ Mov(x20, 0); 1251 __ Mov(x21, 1); 1252 __ Mov(x22, 0x0000000100000000); 1253 __ Mov(x23, 0x0000000012345678); 1254 __ Mov(x24, 0x0123456789abcdef); 1255 __ Mov(x25, 0x0000000200000000); 1256 __ Mov(x26, 0x8000000000000000); 1257 __ Mov(x27, 0xffffffffffffffff); 1258 __ Mov(x28, 0x5555555555555555); 1259 __ Mov(x29, 0xaaaaaaaaaaaaaaaa); 1260 1261 __ Smulh(x0, x20, x24); 1262 __ Smulh(x1, x21, x24); 1263 __ Smulh(x2, x22, x23); 1264 __ Smulh(x3, x22, x24); 1265 __ Smulh(x4, x24, x25); 1266 __ Smulh(x5, x23, x27); 1267 __ Smulh(x6, x26, x26); 1268 __ Smulh(x7, x26, x27); 1269 __ Smulh(x8, x27, x27); 1270 __ Smulh(x9, x28, x28); 1271 __ Smulh(x10, x28, x29); 1272 __ Smulh(x11, x29, x29); 1273 END(); 1274 1275 if (CAN_RUN()) { 1276 RUN(); 1277 1278 ASSERT_EQUAL_64(0, x0); 1279 ASSERT_EQUAL_64(0, x1); 1280 ASSERT_EQUAL_64(0, x2); 1281 ASSERT_EQUAL_64(0x0000000001234567, x3); 1282 ASSERT_EQUAL_64(0x0000000002468acf, x4); 1283 ASSERT_EQUAL_64(0xffffffffffffffff, x5); 1284 ASSERT_EQUAL_64(0x4000000000000000, x6); 1285 ASSERT_EQUAL_64(0, x7); 1286 ASSERT_EQUAL_64(0, x8); 1287 ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9); 1288 ASSERT_EQUAL_64(0xe38e38e38e38e38e, x10); 1289 ASSERT_EQUAL_64(0x1c71c71c71c71c72, x11); 1290 } 1291} 1292 1293 1294TEST(umulh) { 1295 SETUP(); 1296 1297 START(); 1298 __ Mov(x20, 0); 1299 __ Mov(x21, 1); 1300 __ Mov(x22, 0x0000000100000000); 1301 __ Mov(x23, 0x0000000012345678); 1302 __ Mov(x24, 0x0123456789abcdef); 1303 __ Mov(x25, 0x0000000200000000); 1304 __ Mov(x26, 0x8000000000000000); 1305 __ Mov(x27, 0xffffffffffffffff); 1306 __ Mov(x28, 0x5555555555555555); 1307 __ Mov(x29, 0xaaaaaaaaaaaaaaaa); 1308 1309 __ Umulh(x0, x20, x24); 1310 __ Umulh(x1, x21, x24); 1311 __ Umulh(x2, x22, x23); 1312 __ Umulh(x3, x22, x24); 1313 __ Umulh(x4, x24, x25); 1314 __ Umulh(x5, x23, x27); 1315 __ Umulh(x6, x26, x26); 1316 __ Umulh(x7, x26, x27); 1317 __ Umulh(x8, x27, x27); 1318 __ Umulh(x9, x28, x28); 1319 __ Umulh(x10, x28, x29); 1320 __ Umulh(x11, x29, x29); 1321 END(); 1322 1323 if (CAN_RUN()) { 1324 RUN(); 1325 1326 ASSERT_EQUAL_64(0, x0); 1327 ASSERT_EQUAL_64(0, x1); 1328 ASSERT_EQUAL_64(0, x2); 1329 ASSERT_EQUAL_64(0x0000000001234567, x3); 1330 ASSERT_EQUAL_64(0x0000000002468acf, x4); 1331 ASSERT_EQUAL_64(0x0000000012345677, x5); 1332 ASSERT_EQUAL_64(0x4000000000000000, x6); 1333 ASSERT_EQUAL_64(0x7fffffffffffffff, x7); 1334 ASSERT_EQUAL_64(0xfffffffffffffffe, x8); 1335 ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9); 1336 ASSERT_EQUAL_64(0x38e38e38e38e38e3, x10); 1337 ASSERT_EQUAL_64(0x71c71c71c71c71c6, x11); 1338 } 1339} 1340 1341 1342TEST(smaddl_umaddl_umull) { 1343 SETUP(); 1344 1345 START(); 1346 __ Mov(x17, 1); 1347 __ Mov(x18, 0x00000000ffffffff); 1348 __ Mov(x19, 0xffffffffffffffff); 1349 __ Mov(x20, 4); 1350 __ Mov(x21, 0x0000000200000000); 1351 1352 __ Smaddl(x9, w17, w18, x20); 1353 __ Smaddl(x10, w18, w18, x20); 1354 __ Smaddl(x11, w19, w19, x20); 1355 __ Smaddl(x12, w19, w19, x21); 1356 __ Umaddl(x13, w17, w18, x20); 1357 __ Umaddl(x14, w18, w18, x20); 1358 __ Umaddl(x15, w19, w19, x20); 1359 __ Umaddl(x22, w19, w19, x21); 1360 __ Umull(x24, w19, w19); 1361 __ Umull(x25, w17, w18); 1362 END(); 1363 1364 if (CAN_RUN()) { 1365 RUN(); 1366 1367 ASSERT_EQUAL_64(3, x9); 1368 ASSERT_EQUAL_64(5, x10); 1369 ASSERT_EQUAL_64(5, x11); 1370 ASSERT_EQUAL_64(0x0000000200000001, x12); 1371 ASSERT_EQUAL_64(0x0000000100000003, x13); 1372 ASSERT_EQUAL_64(0xfffffffe00000005, x14); 1373 ASSERT_EQUAL_64(0xfffffffe00000005, x15); 1374 ASSERT_EQUAL_64(1, x22); 1375 ASSERT_EQUAL_64(0xfffffffe00000001, x24); 1376 ASSERT_EQUAL_64(0x00000000ffffffff, x25); 1377 } 1378} 1379 1380 1381TEST(smsubl_umsubl) { 1382 SETUP(); 1383 1384 START(); 1385 __ Mov(x17, 1); 1386 __ Mov(x18, 0x00000000ffffffff); 1387 __ Mov(x19, 0xffffffffffffffff); 1388 __ Mov(x20, 4); 1389 __ Mov(x21, 0x0000000200000000); 1390 1391 __ Smsubl(x9, w17, w18, x20); 1392 __ Smsubl(x10, w18, w18, x20); 1393 __ Smsubl(x11, w19, w19, x20); 1394 __ Smsubl(x12, w19, w19, x21); 1395 __ Umsubl(x13, w17, w18, x20); 1396 __ Umsubl(x14, w18, w18, x20); 1397 __ Umsubl(x15, w19, w19, x20); 1398 __ Umsubl(x22, w19, w19, x21); 1399 END(); 1400 1401 if (CAN_RUN()) { 1402 RUN(); 1403 1404 ASSERT_EQUAL_64(5, x9); 1405 ASSERT_EQUAL_64(3, x10); 1406 ASSERT_EQUAL_64(3, x11); 1407 ASSERT_EQUAL_64(0x00000001ffffffff, x12); 1408 ASSERT_EQUAL_64(0xffffffff00000005, x13); 1409 ASSERT_EQUAL_64(0x0000000200000003, x14); 1410 ASSERT_EQUAL_64(0x0000000200000003, x15); 1411 ASSERT_EQUAL_64(0x00000003ffffffff, x22); 1412 } 1413} 1414 1415 1416TEST(div) { 1417 SETUP(); 1418 1419 START(); 1420 __ Mov(x16, 1); 1421 __ Mov(x17, 0xffffffff); 1422 __ Mov(x18, 0xffffffffffffffff); 1423 __ Mov(x19, 0x80000000); 1424 __ Mov(x20, 0x8000000000000000); 1425 __ Mov(x21, 2); 1426 1427 __ Udiv(w0, w16, w16); 1428 __ Udiv(w1, w17, w16); 1429 __ Sdiv(w2, w16, w16); 1430 __ Sdiv(w3, w16, w17); 1431 __ Sdiv(w4, w17, w18); 1432 1433 __ Udiv(x5, x16, x16); 1434 __ Udiv(x6, x17, x18); 1435 __ Sdiv(x7, x16, x16); 1436 __ Sdiv(x8, x16, x17); 1437 __ Sdiv(x9, x17, x18); 1438 1439 __ Udiv(w10, w19, w21); 1440 __ Sdiv(w11, w19, w21); 1441 __ Udiv(x12, x19, x21); 1442 __ Sdiv(x13, x19, x21); 1443 __ Udiv(x14, x20, x21); 1444 __ Sdiv(x15, x20, x21); 1445 1446 __ Udiv(w22, w19, w17); 1447 __ Sdiv(w23, w19, w17); 1448 __ Udiv(x24, x20, x18); 1449 __ Sdiv(x25, x20, x18); 1450 1451 __ Udiv(x26, x16, x21); 1452 __ Sdiv(x27, x16, x21); 1453 __ Udiv(x28, x18, x21); 1454 __ Sdiv(x29, x18, x21); 1455 1456 __ Mov(x17, 0); 1457 __ Udiv(w18, w16, w17); 1458 __ Sdiv(w19, w16, w17); 1459 __ Udiv(x20, x16, x17); 1460 __ Sdiv(x21, x16, x17); 1461 END(); 1462 1463 if (CAN_RUN()) { 1464 RUN(); 1465 1466 ASSERT_EQUAL_64(1, x0); 1467 ASSERT_EQUAL_64(0xffffffff, x1); 1468 ASSERT_EQUAL_64(1, x2); 1469 ASSERT_EQUAL_64(0xffffffff, x3); 1470 ASSERT_EQUAL_64(1, x4); 1471 ASSERT_EQUAL_64(1, x5); 1472 ASSERT_EQUAL_64(0, x6); 1473 ASSERT_EQUAL_64(1, x7); 1474 ASSERT_EQUAL_64(0, x8); 1475 ASSERT_EQUAL_64(0xffffffff00000001, x9); 1476 ASSERT_EQUAL_64(0x40000000, x10); 1477 ASSERT_EQUAL_64(0xc0000000, x11); 1478 ASSERT_EQUAL_64(0x0000000040000000, x12); 1479 ASSERT_EQUAL_64(0x0000000040000000, x13); 1480 ASSERT_EQUAL_64(0x4000000000000000, x14); 1481 ASSERT_EQUAL_64(0xc000000000000000, x15); 1482 ASSERT_EQUAL_64(0, x22); 1483 ASSERT_EQUAL_64(0x80000000, x23); 1484 ASSERT_EQUAL_64(0, x24); 1485 ASSERT_EQUAL_64(0x8000000000000000, x25); 1486 ASSERT_EQUAL_64(0, x26); 1487 ASSERT_EQUAL_64(0, x27); 1488 ASSERT_EQUAL_64(0x7fffffffffffffff, x28); 1489 ASSERT_EQUAL_64(0, x29); 1490 ASSERT_EQUAL_64(0, x18); 1491 ASSERT_EQUAL_64(0, x19); 1492 ASSERT_EQUAL_64(0, x20); 1493 ASSERT_EQUAL_64(0, x21); 1494 } 1495} 1496 1497 1498TEST(rbit_rev) { 1499 SETUP(); 1500 1501 START(); 1502 __ Mov(x24, 0xfedcba9876543210); 1503 __ Rbit(w0, w24); 1504 __ Rbit(x1, x24); 1505 __ Rev16(w2, w24); 1506 __ Rev16(x3, x24); 1507 __ Rev(w4, w24); 1508 __ Rev32(x5, x24); 1509 __ Rev64(x6, x24); 1510 __ Rev(x7, x24); 1511 END(); 1512 1513 if (CAN_RUN()) { 1514 RUN(); 1515 1516 ASSERT_EQUAL_64(0x084c2a6e, x0); 1517 ASSERT_EQUAL_64(0x084c2a6e195d3b7f, x1); 1518 ASSERT_EQUAL_64(0x54761032, x2); 1519 ASSERT_EQUAL_64(0xdcfe98ba54761032, x3); 1520 ASSERT_EQUAL_64(0x10325476, x4); 1521 ASSERT_EQUAL_64(0x98badcfe10325476, x5); 1522 ASSERT_EQUAL_64(0x1032547698badcfe, x6); 1523 ASSERT_EQUAL_64(0x1032547698badcfe, x7); 1524 } 1525} 1526 1527typedef void (MacroAssembler::*TestBranchSignature)(const Register& rt, 1528 unsigned bit_pos, 1529 Label* label); 1530 1531static void TbzRangePoolLimitHelper(TestBranchSignature test_branch) { 1532 const int kTbzRange = 32768; 1533 const int kNumLdrLiteral = kTbzRange / 4; 1534 const int fuzz_range = 2; 1535 for (int n = kNumLdrLiteral - fuzz_range; n <= kNumLdrLiteral + fuzz_range; 1536 ++n) { 1537 for (int margin = -32; margin < 32; margin += 4) { 1538 SETUP(); 1539 1540 START(); 1541 1542 // Emit 32KB of literals (equal to the range of TBZ). 1543 for (int i = 0; i < n; ++i) { 1544 __ Ldr(w0, 0x12345678); 1545 } 1546 1547 const int kLiteralMargin = 128 * KBytes; 1548 1549 // Emit enough NOPs to be just about to emit the literal pool. 1550 ptrdiff_t end = 1551 masm.GetCursorOffset() + (kLiteralMargin - n * 4 + margin); 1552 while (masm.GetCursorOffset() < end) { 1553 __ Nop(); 1554 } 1555 1556 // Add a TBZ instruction. 1557 Label label; 1558 1559 (masm.*test_branch)(x0, 2, &label); 1560 1561 // Add enough NOPs to surpass its range, to make sure we can encode the 1562 // veneer. 1563 end = masm.GetCursorOffset() + (kTbzRange - 4); 1564 { 1565 ExactAssemblyScope scope(&masm, 1566 kTbzRange, 1567 ExactAssemblyScope::kMaximumSize); 1568 while (masm.GetCursorOffset() < end) __ nop(); 1569 } 1570 1571 // Finally, bind the label. 1572 __ Bind(&label); 1573 1574 END(); 1575 1576 if (CAN_RUN()) { 1577 RUN(); 1578 } 1579 } 1580 } 1581} 1582 1583TEST(test_branch_limits_literal_pool_size_tbz) { 1584 TbzRangePoolLimitHelper(&MacroAssembler::Tbz); 1585} 1586 1587TEST(test_branch_limits_literal_pool_size_tbnz) { 1588 TbzRangePoolLimitHelper(&MacroAssembler::Tbnz); 1589} 1590 1591TEST(clz_cls) { 1592 SETUP(); 1593 1594 START(); 1595 __ Mov(x24, 0x0008000000800000); 1596 __ Mov(x25, 0xff800000fff80000); 1597 __ Mov(x26, 0); 1598 __ Clz(w0, w24); 1599 __ Clz(x1, x24); 1600 __ Clz(w2, w25); 1601 __ Clz(x3, x25); 1602 __ Clz(w4, w26); 1603 __ Clz(x5, x26); 1604 __ Cls(w6, w24); 1605 __ Cls(x7, x24); 1606 __ Cls(w8, w25); 1607 __ Cls(x9, x25); 1608 __ Cls(w10, w26); 1609 __ Cls(x11, x26); 1610 END(); 1611 1612 if (CAN_RUN()) { 1613 RUN(); 1614 1615 ASSERT_EQUAL_64(8, x0); 1616 ASSERT_EQUAL_64(12, x1); 1617 ASSERT_EQUAL_64(0, x2); 1618 ASSERT_EQUAL_64(0, x3); 1619 ASSERT_EQUAL_64(32, x4); 1620 ASSERT_EQUAL_64(64, x5); 1621 ASSERT_EQUAL_64(7, x6); 1622 ASSERT_EQUAL_64(11, x7); 1623 ASSERT_EQUAL_64(12, x8); 1624 ASSERT_EQUAL_64(8, x9); 1625 ASSERT_EQUAL_64(31, x10); 1626 ASSERT_EQUAL_64(63, x11); 1627 } 1628} 1629 1630 1631TEST(pacia_pacib_autia_autib) { 1632 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 1633 1634 START(); 1635 1636 Register pointer = x24; 1637 Register modifier = x25; 1638 1639 __ Mov(pointer, 0x0000000012345678); 1640 __ Mov(modifier, 0x477d469dec0b8760); 1641 1642 // Generate PACs using keys A and B. 1643 __ Mov(x0, pointer); 1644 __ Pacia(x0, modifier); 1645 1646 __ Mov(x1, pointer); 1647 __ Pacib(x1, modifier); 1648 1649 // Authenticate the pointers above. 1650 __ Mov(x2, x0); 1651 __ Autia(x2, modifier); 1652 1653 __ Mov(x3, x1); 1654 __ Autib(x3, modifier); 1655 1656 // Attempt to authenticate incorrect pointers. 1657 __ Mov(x4, x1); 1658 __ Autia(x4, modifier); 1659 1660 __ Mov(x5, x0); 1661 __ Autib(x5, modifier); 1662 1663 // Mask out just the PAC code bits. 1664 // TODO: use Simulator::CalculatePACMask in a nice way. 1665 __ And(x0, x0, 0x007f000000000000); 1666 __ And(x1, x1, 0x007f000000000000); 1667 1668 END(); 1669 1670 if (CAN_RUN()) { 1671 RUN(); 1672 1673 // Check PAC codes have been generated and aren't equal. 1674 // NOTE: with a different ComputePAC implementation, there may be a 1675 // collision. 1676 ASSERT_NOT_EQUAL_64(0, x0); 1677 ASSERT_NOT_EQUAL_64(0, x1); 1678 ASSERT_NOT_EQUAL_64(x0, x1); 1679 1680 // Pointers correctly authenticated. 1681 ASSERT_EQUAL_64(pointer, x2); 1682 ASSERT_EQUAL_64(pointer, x3); 1683 1684 // Pointers corrupted after failing to authenticate. 1685 ASSERT_EQUAL_64(0x0020000012345678, x4); 1686 ASSERT_EQUAL_64(0x0040000012345678, x5); 1687 } 1688} 1689 1690 1691TEST(paciza_pacizb_autiza_autizb) { 1692 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 1693 1694 START(); 1695 1696 Register pointer = x24; 1697 1698 __ Mov(pointer, 0x0000000012345678); 1699 1700 // Generate PACs using keys A and B. 1701 __ Mov(x0, pointer); 1702 __ Paciza(x0); 1703 1704 __ Mov(x1, pointer); 1705 __ Pacizb(x1); 1706 1707 // Authenticate the pointers above. 1708 __ Mov(x2, x0); 1709 __ Autiza(x2); 1710 1711 __ Mov(x3, x1); 1712 __ Autizb(x3); 1713 1714 // Attempt to authenticate incorrect pointers. 1715 __ Mov(x4, x1); 1716 __ Autiza(x4); 1717 1718 __ Mov(x5, x0); 1719 __ Autizb(x5); 1720 1721 // Mask out just the PAC code bits. 1722 // TODO: use Simulator::CalculatePACMask in a nice way. 1723 __ And(x0, x0, 0x007f000000000000); 1724 __ And(x1, x1, 0x007f000000000000); 1725 1726 END(); 1727 1728 if (CAN_RUN()) { 1729 RUN(); 1730 1731 // Check PAC codes have been generated and aren't equal. 1732 // NOTE: with a different ComputePAC implementation, there may be a 1733 // collision. 1734 ASSERT_NOT_EQUAL_64(0, x0); 1735 ASSERT_NOT_EQUAL_64(0, x1); 1736 ASSERT_NOT_EQUAL_64(x0, x1); 1737 1738 // Pointers correctly authenticated. 1739 ASSERT_EQUAL_64(pointer, x2); 1740 ASSERT_EQUAL_64(pointer, x3); 1741 1742 // Pointers corrupted after failing to authenticate. 1743 ASSERT_EQUAL_64(0x0020000012345678, x4); 1744 ASSERT_EQUAL_64(0x0040000012345678, x5); 1745 } 1746} 1747 1748 1749TEST(pacda_pacdb_autda_autdb) { 1750 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 1751 1752 START(); 1753 1754 Register pointer = x24; 1755 Register modifier = x25; 1756 1757 __ Mov(pointer, 0x0000000012345678); 1758 __ Mov(modifier, 0x477d469dec0b8760); 1759 1760 // Generate PACs using keys A and B. 1761 __ Mov(x0, pointer); 1762 __ Pacda(x0, modifier); 1763 1764 __ Mov(x1, pointer); 1765 __ Pacdb(x1, modifier); 1766 1767 // Authenticate the pointers above. 1768 __ Mov(x2, x0); 1769 __ Autda(x2, modifier); 1770 1771 __ Mov(x3, x1); 1772 __ Autdb(x3, modifier); 1773 1774 // Attempt to authenticate incorrect pointers. 1775 __ Mov(x4, x1); 1776 __ Autda(x4, modifier); 1777 1778 __ Mov(x5, x0); 1779 __ Autdb(x5, modifier); 1780 1781 // Mask out just the PAC code bits. 1782 // TODO: use Simulator::CalculatePACMask in a nice way. 1783 __ And(x0, x0, 0x007f000000000000); 1784 __ And(x1, x1, 0x007f000000000000); 1785 1786 END(); 1787 1788 if (CAN_RUN()) { 1789 RUN(); 1790 1791 // Check PAC codes have been generated and aren't equal. 1792 // NOTE: with a different ComputePAC implementation, there may be a 1793 // collision. 1794 ASSERT_NOT_EQUAL_64(0, x0); 1795 ASSERT_NOT_EQUAL_64(0, x1); 1796 ASSERT_NOT_EQUAL_64(x0, x1); 1797 1798 // Pointers correctly authenticated. 1799 ASSERT_EQUAL_64(pointer, x2); 1800 ASSERT_EQUAL_64(pointer, x3); 1801 1802 // Pointers corrupted after failing to authenticate. 1803 ASSERT_EQUAL_64(0x0020000012345678, x4); 1804 ASSERT_EQUAL_64(0x0040000012345678, x5); 1805 } 1806} 1807 1808 1809TEST(pacdza_pacdzb_autdza_autdzb) { 1810 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 1811 1812 START(); 1813 1814 Register pointer = x24; 1815 1816 __ Mov(pointer, 0x0000000012345678); 1817 1818 // Generate PACs using keys A and B. 1819 __ Mov(x0, pointer); 1820 __ Pacdza(x0); 1821 1822 __ Mov(x1, pointer); 1823 __ Pacdzb(x1); 1824 1825 // Authenticate the pointers above. 1826 __ Mov(x2, x0); 1827 __ Autdza(x2); 1828 1829 __ Mov(x3, x1); 1830 __ Autdzb(x3); 1831 1832 // Attempt to authenticate incorrect pointers. 1833 __ Mov(x4, x1); 1834 __ Autdza(x4); 1835 1836 __ Mov(x5, x0); 1837 __ Autdzb(x5); 1838 1839 // Mask out just the PAC code bits. 1840 // TODO: use Simulator::CalculatePACMask in a nice way. 1841 __ And(x0, x0, 0x007f000000000000); 1842 __ And(x1, x1, 0x007f000000000000); 1843 1844 END(); 1845 1846 if (CAN_RUN()) { 1847 RUN(); 1848 1849 // Check PAC codes have been generated and aren't equal. 1850 // NOTE: with a different ComputePAC implementation, there may be a 1851 // collision. 1852 ASSERT_NOT_EQUAL_64(0, x0); 1853 ASSERT_NOT_EQUAL_64(0, x1); 1854 ASSERT_NOT_EQUAL_64(x0, x1); 1855 1856 // Pointers correctly authenticated. 1857 ASSERT_EQUAL_64(pointer, x2); 1858 ASSERT_EQUAL_64(pointer, x3); 1859 1860 // Pointers corrupted after failing to authenticate. 1861 ASSERT_EQUAL_64(0x0020000012345678, x4); 1862 ASSERT_EQUAL_64(0x0040000012345678, x5); 1863 } 1864} 1865 1866 1867TEST(pacga_xpaci_xpacd) { 1868 SETUP_WITH_FEATURES(CPUFeatures::kPAuth, CPUFeatures::kPAuthGeneric); 1869 1870 START(); 1871 1872 Register pointer = x24; 1873 Register modifier = x25; 1874 1875 __ Mov(pointer, 0x0000000012345678); 1876 __ Mov(modifier, 0x477d469dec0b8760); 1877 1878 // Generate generic PAC. 1879 __ Pacga(x0, pointer, modifier); 1880 1881 // Generate PACs using key A. 1882 __ Mov(x1, pointer); 1883 __ Mov(x2, pointer); 1884 __ Pacia(x1, modifier); 1885 __ Pacda(x2, modifier); 1886 1887 // Strip PACs. 1888 __ Mov(x3, x1); 1889 __ Mov(x4, x2); 1890 __ Xpaci(x3); 1891 __ Xpacd(x4); 1892 1893 // Mask out just the PAC code bits. 1894 // TODO: use Simulator::CalculatePACMask in a nice way. 1895 __ And(x0, x0, 0xffffffff00000000); 1896 __ And(x1, x1, 0x007f000000000000); 1897 __ And(x2, x2, 0x007f000000000000); 1898 1899 END(); 1900 1901 if (CAN_RUN()) { 1902 RUN(); 1903 1904 1905 // Check PAC codes have been generated and aren't equal. 1906 // NOTE: with a different ComputePAC implementation, there may be a 1907 // collision. 1908 ASSERT_NOT_EQUAL_64(0, x0); 1909 1910 ASSERT_NOT_EQUAL_64(0, x1); 1911 ASSERT_NOT_EQUAL_64(0, x2); 1912 ASSERT_NOT_EQUAL_64(x1, x2); 1913 1914 ASSERT_EQUAL_64(pointer, x3); 1915 ASSERT_EQUAL_64(pointer, x4); 1916 } 1917} 1918 1919TEST(pac_sp_modifier) { 1920 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 1921 1922 START(); 1923 1924 __ Mov(x0, 0x0000000012345678); 1925 __ Mov(x1, x0); 1926 __ Mov(x10, sp); 1927 1928 // Generate PACs using sp and register containing a copy of sp. 1929 __ Pacia(x0, x10); 1930 __ Pacia(x1, sp); 1931 1932 // Authenticate the pointers, exchanging (equal) modifiers. 1933 __ Mov(x2, x0); 1934 __ Mov(x3, x1); 1935 __ Autia(x2, sp); 1936 __ Autia(x3, x10); 1937 1938 END(); 1939 1940 if (CAN_RUN()) { 1941 RUN(); 1942 1943 ASSERT_EQUAL_64(x0, x1); 1944 ASSERT_EQUAL_64(x2, x3); 1945 } 1946} 1947 1948TEST(label) { 1949 SETUP(); 1950 1951 Label label_1, label_2, label_3, label_4; 1952 1953 START(); 1954 __ Mov(x0, 0x1); 1955 __ Mov(x1, 0x0); 1956 __ Mov(x22, lr); // Save lr. 1957 1958 __ B(&label_1); 1959 __ B(&label_1); 1960 __ B(&label_1); // Multiple branches to the same label. 1961 __ Mov(x0, 0x0); 1962 __ Bind(&label_2); 1963 __ B(&label_3); // Forward branch. 1964 __ Mov(x0, 0x0); 1965 __ Bind(&label_1); 1966 __ B(&label_2); // Backward branch. 1967 __ Mov(x0, 0x0); 1968 __ Bind(&label_3); 1969 __ Bl(&label_4); 1970 END(); 1971 1972 __ Bind(&label_4); 1973 __ Mov(x1, 0x1); 1974 __ Mov(lr, x22); 1975 END(); 1976 1977 if (CAN_RUN()) { 1978 RUN(); 1979 1980 ASSERT_EQUAL_64(0x1, x0); 1981 ASSERT_EQUAL_64(0x1, x1); 1982 } 1983} 1984 1985 1986TEST(label_2) { 1987 SETUP(); 1988 1989 Label label_1, label_2, label_3; 1990 Label first_jump_to_3; 1991 1992 START(); 1993 __ Mov(x0, 0x0); 1994 1995 __ B(&label_1); 1996 ptrdiff_t offset_2 = masm.GetCursorOffset(); 1997 __ Orr(x0, x0, 1 << 1); 1998 __ B(&label_3); 1999 ptrdiff_t offset_1 = masm.GetCursorOffset(); 2000 __ Orr(x0, x0, 1 << 0); 2001 __ B(&label_2); 2002 ptrdiff_t offset_3 = masm.GetCursorOffset(); 2003 __ Tbz(x0, 2, &first_jump_to_3); 2004 __ Orr(x0, x0, 1 << 3); 2005 __ Bind(&first_jump_to_3); 2006 __ Orr(x0, x0, 1 << 2); 2007 __ Tbz(x0, 3, &label_3); 2008 2009 // Labels 1, 2, and 3 are bound before the current buffer offset. Branches to 2010 // label_1 and label_2 branch respectively forward and backward. Branches to 2011 // label 3 include both forward and backward branches. 2012 masm.BindToOffset(&label_1, offset_1); 2013 masm.BindToOffset(&label_2, offset_2); 2014 masm.BindToOffset(&label_3, offset_3); 2015 2016 END(); 2017 2018 if (CAN_RUN()) { 2019 RUN(); 2020 2021 ASSERT_EQUAL_64(0xf, x0); 2022 } 2023} 2024 2025 2026TEST(adr) { 2027 SETUP(); 2028 2029 Label label_1, label_2, label_3, label_4; 2030 2031 START(); 2032 __ Mov(x0, 0x0); // Set to non-zero to indicate failure. 2033 __ Adr(x1, &label_3); // Set to zero to indicate success. 2034 2035 __ Adr(x2, &label_1); // Multiple forward references to the same label. 2036 __ Adr(x3, &label_1); 2037 __ Adr(x4, &label_1); 2038 2039 __ Bind(&label_2); 2040 __ Eor(x5, x2, Operand(x3)); // Ensure that x2,x3 and x4 are identical. 2041 __ Eor(x6, x2, Operand(x4)); 2042 __ Orr(x0, x0, Operand(x5)); 2043 __ Orr(x0, x0, Operand(x6)); 2044 __ Br(x2); // label_1, label_3 2045 2046 __ Bind(&label_3); 2047 __ Adr(x2, &label_3); // Self-reference (offset 0). 2048 __ Eor(x1, x1, Operand(x2)); 2049 __ Adr(x2, &label_4); // Simple forward reference. 2050 __ Br(x2); // label_4 2051 2052 __ Bind(&label_1); 2053 __ Adr(x2, &label_3); // Multiple reverse references to the same label. 2054 __ Adr(x3, &label_3); 2055 __ Adr(x4, &label_3); 2056 __ Adr(x5, &label_2); // Simple reverse reference. 2057 __ Br(x5); // label_2 2058 2059 __ Bind(&label_4); 2060 END(); 2061 2062 if (CAN_RUN()) { 2063 RUN(); 2064 2065 ASSERT_EQUAL_64(0x0, x0); 2066 ASSERT_EQUAL_64(0x0, x1); 2067 } 2068} 2069 2070 2071// Simple adrp tests: check that labels are linked and handled properly. 2072// This is similar to the adr test, but all the adrp instructions are put on the 2073// same page so that they return the same value. 2074TEST(adrp) { 2075 Label start; 2076 Label label_1, label_2, label_3; 2077 2078 SETUP_CUSTOM(2 * kPageSize, PageOffsetDependentCode); 2079 START(); 2080 2081 // Waste space until the start of a page. 2082 { 2083 ExactAssemblyScope scope(&masm, 2084 kPageSize, 2085 ExactAssemblyScope::kMaximumSize); 2086 const uintptr_t kPageOffsetMask = kPageSize - 1; 2087 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) { 2088 __ b(&start); 2089 } 2090 __ bind(&start); 2091 } 2092 2093 // Simple forward reference. 2094 __ Adrp(x0, &label_2); 2095 2096 __ Bind(&label_1); 2097 2098 // Multiple forward references to the same label. 2099 __ Adrp(x1, &label_3); 2100 __ Adrp(x2, &label_3); 2101 __ Adrp(x3, &label_3); 2102 2103 __ Bind(&label_2); 2104 2105 // Self-reference (offset 0). 2106 __ Adrp(x4, &label_2); 2107 2108 __ Bind(&label_3); 2109 2110 // Simple reverse reference. 2111 __ Adrp(x5, &label_1); 2112 2113 // Multiple reverse references to the same label. 2114 __ Adrp(x6, &label_2); 2115 __ Adrp(x7, &label_2); 2116 __ Adrp(x8, &label_2); 2117 2118 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&start) < kPageSize); 2119 END(); 2120 if (CAN_RUN()) { 2121 RUN(); 2122 2123 uint64_t expected = reinterpret_cast<uint64_t>( 2124 AlignDown(masm.GetLabelAddress<uint64_t*>(&start), kPageSize)); 2125 ASSERT_EQUAL_64(expected, x0); 2126 ASSERT_EQUAL_64(expected, x1); 2127 ASSERT_EQUAL_64(expected, x2); 2128 ASSERT_EQUAL_64(expected, x3); 2129 ASSERT_EQUAL_64(expected, x4); 2130 ASSERT_EQUAL_64(expected, x5); 2131 ASSERT_EQUAL_64(expected, x6); 2132 ASSERT_EQUAL_64(expected, x7); 2133 ASSERT_EQUAL_64(expected, x8); 2134 } 2135} 2136 2137 2138static void AdrpPageBoundaryHelper(unsigned offset_into_page) { 2139 VIXL_ASSERT(offset_into_page < kPageSize); 2140 VIXL_ASSERT((offset_into_page % kInstructionSize) == 0); 2141 2142 const uintptr_t kPageOffsetMask = kPageSize - 1; 2143 2144 // The test label is always bound on page 0. Adrp instructions are generated 2145 // on pages from kStartPage to kEndPage (inclusive). 2146 const int kStartPage = -16; 2147 const int kEndPage = 16; 2148 const int kMaxCodeSize = (kEndPage - kStartPage + 2) * kPageSize; 2149 2150 SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode); 2151 START(); 2152 2153 Label test; 2154 Label start; 2155 2156 { 2157 ExactAssemblyScope scope(&masm, 2158 kMaxCodeSize, 2159 ExactAssemblyScope::kMaximumSize); 2160 // Initialize NZCV with `eq` flags. 2161 __ cmp(wzr, wzr); 2162 // Waste space until the start of a page. 2163 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) { 2164 __ b(&start); 2165 } 2166 2167 // The first page. 2168 VIXL_STATIC_ASSERT(kStartPage < 0); 2169 { 2170 ExactAssemblyScope scope_page(&masm, kPageSize); 2171 __ bind(&start); 2172 __ adrp(x0, &test); 2173 __ adrp(x1, &test); 2174 for (size_t i = 2; i < (kPageSize / kInstructionSize); i += 2) { 2175 __ ccmp(x0, x1, NoFlag, eq); 2176 __ adrp(x1, &test); 2177 } 2178 } 2179 2180 // Subsequent pages. 2181 VIXL_STATIC_ASSERT(kEndPage >= 0); 2182 for (int page = (kStartPage + 1); page <= kEndPage; page++) { 2183 ExactAssemblyScope scope_page(&masm, kPageSize); 2184 if (page == 0) { 2185 for (size_t i = 0; i < (kPageSize / kInstructionSize);) { 2186 if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test); 2187 __ ccmp(x0, x1, NoFlag, eq); 2188 if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test); 2189 __ adrp(x1, &test); 2190 } 2191 } else { 2192 for (size_t i = 0; i < (kPageSize / kInstructionSize); i += 2) { 2193 __ ccmp(x0, x1, NoFlag, eq); 2194 __ adrp(x1, &test); 2195 } 2196 } 2197 } 2198 } 2199 2200 // Every adrp instruction pointed to the same label (`test`), so they should 2201 // all have produced the same result. 2202 2203 END(); 2204 if (CAN_RUN()) { 2205 RUN(); 2206 2207 uintptr_t expected = 2208 AlignDown(masm.GetLabelAddress<uintptr_t>(&test), kPageSize); 2209 ASSERT_EQUAL_64(expected, x0); 2210 ASSERT_EQUAL_64(expected, x1); 2211 ASSERT_EQUAL_NZCV(ZCFlag); 2212 } 2213} 2214 2215 2216// Test that labels are correctly referenced by adrp across page boundaries. 2217TEST(adrp_page_boundaries) { 2218 VIXL_STATIC_ASSERT(kPageSize == 4096); 2219 AdrpPageBoundaryHelper(kInstructionSize * 0); 2220 AdrpPageBoundaryHelper(kInstructionSize * 1); 2221 AdrpPageBoundaryHelper(kInstructionSize * 512); 2222 AdrpPageBoundaryHelper(kInstructionSize * 1022); 2223 AdrpPageBoundaryHelper(kInstructionSize * 1023); 2224} 2225 2226 2227static void AdrpOffsetHelper(int64_t offset) { 2228 const size_t kPageOffsetMask = kPageSize - 1; 2229 const int kMaxCodeSize = 2 * kPageSize; 2230 2231 SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode); 2232 START(); 2233 2234 Label page; 2235 2236 { 2237 ExactAssemblyScope scope(&masm, 2238 kMaxCodeSize, 2239 ExactAssemblyScope::kMaximumSize); 2240 // Initialize NZCV with `eq` flags. 2241 __ cmp(wzr, wzr); 2242 // Waste space until the start of a page. 2243 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) { 2244 __ b(&page); 2245 } 2246 __ bind(&page); 2247 2248 { 2249 ExactAssemblyScope scope_page(&masm, kPageSize); 2250 // Every adrp instruction on this page should return the same value. 2251 __ adrp(x0, offset); 2252 __ adrp(x1, offset); 2253 for (size_t i = 2; i < kPageSize / kInstructionSize; i += 2) { 2254 __ ccmp(x0, x1, NoFlag, eq); 2255 __ adrp(x1, offset); 2256 } 2257 } 2258 } 2259 2260 END(); 2261 if (CAN_RUN()) { 2262 RUN(); 2263 2264 uintptr_t expected = 2265 masm.GetLabelAddress<uintptr_t>(&page) + (kPageSize * offset); 2266 ASSERT_EQUAL_64(expected, x0); 2267 ASSERT_EQUAL_64(expected, x1); 2268 ASSERT_EQUAL_NZCV(ZCFlag); 2269 } 2270} 2271 2272 2273// Check that adrp produces the correct result for a specific offset. 2274TEST(adrp_offset) { 2275 AdrpOffsetHelper(0); 2276 AdrpOffsetHelper(1); 2277 AdrpOffsetHelper(-1); 2278 AdrpOffsetHelper(4); 2279 AdrpOffsetHelper(-4); 2280 AdrpOffsetHelper(0x000fffff); 2281 AdrpOffsetHelper(-0x000fffff); 2282 AdrpOffsetHelper(-0x00100000); 2283} 2284 2285 2286TEST(branch_cond) { 2287 SETUP(); 2288 2289 Label done, wrong; 2290 2291 START(); 2292 __ Mov(x0, 0x1); 2293 __ Mov(x1, 0x1); 2294 __ Mov(x2, 0x8000000000000000); 2295 2296 // For each 'cmp' instruction below, condition codes other than the ones 2297 // following it would branch. 2298 2299 __ Cmp(x1, 0); 2300 __ B(&wrong, eq); 2301 __ B(&wrong, lo); 2302 __ B(&wrong, mi); 2303 __ B(&wrong, vs); 2304 __ B(&wrong, ls); 2305 __ B(&wrong, lt); 2306 __ B(&wrong, le); 2307 Label ok_1; 2308 __ B(&ok_1, ne); 2309 __ Mov(x0, 0x0); 2310 __ Bind(&ok_1); 2311 2312 __ Cmp(x1, 1); 2313 __ B(&wrong, ne); 2314 __ B(&wrong, lo); 2315 __ B(&wrong, mi); 2316 __ B(&wrong, vs); 2317 __ B(&wrong, hi); 2318 __ B(&wrong, lt); 2319 __ B(&wrong, gt); 2320 Label ok_2; 2321 __ B(&ok_2, pl); 2322 __ Mov(x0, 0x0); 2323 __ Bind(&ok_2); 2324 2325 __ Cmp(x1, 2); 2326 __ B(&wrong, eq); 2327 __ B(&wrong, hs); 2328 __ B(&wrong, pl); 2329 __ B(&wrong, vs); 2330 __ B(&wrong, hi); 2331 __ B(&wrong, ge); 2332 __ B(&wrong, gt); 2333 Label ok_3; 2334 __ B(&ok_3, vc); 2335 __ Mov(x0, 0x0); 2336 __ Bind(&ok_3); 2337 2338 __ Cmp(x2, 1); 2339 __ B(&wrong, eq); 2340 __ B(&wrong, lo); 2341 __ B(&wrong, mi); 2342 __ B(&wrong, vc); 2343 __ B(&wrong, ls); 2344 __ B(&wrong, ge); 2345 __ B(&wrong, gt); 2346 Label ok_4; 2347 __ B(&ok_4, le); 2348 __ Mov(x0, 0x0); 2349 __ Bind(&ok_4); 2350 2351 // The MacroAssembler does not allow al as a branch condition. 2352 Label ok_5; 2353 { 2354 ExactAssemblyScope scope(&masm, kInstructionSize); 2355 __ b(&ok_5, al); 2356 } 2357 __ Mov(x0, 0x0); 2358 __ Bind(&ok_5); 2359 2360 // The MacroAssembler does not allow nv as a branch condition. 2361 Label ok_6; 2362 { 2363 ExactAssemblyScope scope(&masm, kInstructionSize); 2364 __ b(&ok_6, nv); 2365 } 2366 __ Mov(x0, 0x0); 2367 __ Bind(&ok_6); 2368 2369 __ B(&done); 2370 2371 __ Bind(&wrong); 2372 __ Mov(x0, 0x0); 2373 2374 __ Bind(&done); 2375 END(); 2376 2377 if (CAN_RUN()) { 2378 RUN(); 2379 2380 ASSERT_EQUAL_64(0x1, x0); 2381 } 2382} 2383 2384 2385TEST(branch_to_reg) { 2386 SETUP(); 2387 2388 // Test br. 2389 Label fn1, after_fn1; 2390 2391 START(); 2392 __ Mov(x29, lr); 2393 2394 __ Mov(x1, 0); 2395 __ B(&after_fn1); 2396 2397 __ Bind(&fn1); 2398 __ Mov(x0, lr); 2399 __ Mov(x1, 42); 2400 __ Br(x0); 2401 2402 __ Bind(&after_fn1); 2403 __ Bl(&fn1); 2404 2405 // Test blr. 2406 Label fn2, after_fn2, after_bl2; 2407 2408 __ Mov(x2, 0); 2409 __ B(&after_fn2); 2410 2411 __ Bind(&fn2); 2412 __ Mov(x0, lr); 2413 __ Mov(x2, 84); 2414 __ Blr(x0); 2415 2416 __ Bind(&after_fn2); 2417 __ Bl(&fn2); 2418 __ Bind(&after_bl2); 2419 __ Mov(x3, lr); 2420 __ Adr(x4, &after_bl2); 2421 __ Adr(x5, &after_fn2); 2422 2423 __ Mov(lr, x29); 2424 END(); 2425 2426 if (CAN_RUN()) { 2427 RUN(); 2428 2429 ASSERT_EQUAL_64(x4, x0); 2430 ASSERT_EQUAL_64(x5, x3); 2431 ASSERT_EQUAL_64(42, x1); 2432 ASSERT_EQUAL_64(84, x2); 2433 } 2434} 2435 2436TEST(branch_to_reg_auth_a) { 2437 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 2438 2439 START(); 2440 2441 Label fn1, after_fn1; 2442 2443 __ Mov(x28, 0x477d469dec0b8760); 2444 __ Mov(x29, lr); 2445 2446 __ Mov(x1, 0); 2447 __ B(&after_fn1); 2448 2449 __ Bind(&fn1); 2450 __ Mov(x0, lr); 2451 __ Mov(x1, 42); 2452 __ Pacia(x0, x28); 2453 __ Braa(x0, x28); 2454 2455 __ Bind(&after_fn1); 2456 __ Bl(&fn1); 2457 2458 Label fn2, after_fn2, after_bl2; 2459 2460 __ Mov(x2, 0); 2461 __ B(&after_fn2); 2462 2463 __ Bind(&fn2); 2464 __ Mov(x0, lr); 2465 __ Mov(x2, 84); 2466 __ Pacia(x0, x28); 2467 __ Blraa(x0, x28); 2468 2469 __ Bind(&after_fn2); 2470 __ Bl(&fn2); 2471 __ Bind(&after_bl2); 2472 __ Mov(x3, lr); 2473 __ Adr(x4, &after_bl2); 2474 __ Adr(x5, &after_fn2); 2475 2476 __ Xpaci(x0); 2477 __ Mov(lr, x29); 2478 END(); 2479 2480 if (CAN_RUN()) { 2481 RUN(); 2482 2483 ASSERT_EQUAL_64(x4, x0); 2484 ASSERT_EQUAL_64(x5, x3); 2485 ASSERT_EQUAL_64(42, x1); 2486 ASSERT_EQUAL_64(84, x2); 2487 } 2488} 2489 2490TEST(return_to_reg_auth) { 2491 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 2492 2493 START(); 2494 2495 Label fn1, after_fn1; 2496 2497 __ Mov(x28, sp); 2498 __ Mov(x29, lr); 2499 __ Mov(sp, 0x477d469dec0b8760); 2500 2501 __ Mov(x0, 0); 2502 __ B(&after_fn1); 2503 2504 __ Bind(&fn1); 2505 __ Mov(x0, 42); 2506 __ Paciasp(); 2507 __ Retaa(); 2508 2509 __ Bind(&after_fn1); 2510 __ Bl(&fn1); 2511 2512 Label fn2, after_fn2; 2513 2514 __ Mov(x1, 0); 2515 __ B(&after_fn2); 2516 2517 __ Bind(&fn2); 2518 __ Mov(x1, 84); 2519 __ Pacibsp(); 2520 __ Retab(); 2521 2522 __ Bind(&after_fn2); 2523 __ Bl(&fn2); 2524 2525 __ Mov(sp, x28); 2526 __ Mov(lr, x29); 2527 END(); 2528 2529 if (CAN_RUN()) { 2530 RUN(); 2531 2532 ASSERT_EQUAL_64(42, x0); 2533 ASSERT_EQUAL_64(84, x1); 2534 } 2535} 2536 2537TEST(return_to_reg_auth_guarded) { 2538 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 2539 2540 START(); 2541 2542 Label fn1, after_fn1; 2543 2544 __ Mov(x28, sp); 2545 __ Mov(x29, lr); 2546 __ Mov(sp, 0x477d469dec0b8760); 2547 2548 __ Mov(x0, 0); 2549 __ B(&after_fn1); 2550 2551 __ Bind(&fn1, EmitPACIASP); 2552 __ Mov(x0, 42); 2553 __ Retaa(); 2554 2555 __ Bind(&after_fn1); 2556 __ Adr(x2, &fn1); 2557 __ Blr(x2); 2558 2559 Label fn2, after_fn2; 2560 2561 __ Mov(x1, 0); 2562 __ B(&after_fn2); 2563 2564 __ Bind(&fn2, EmitPACIBSP); 2565 __ Mov(x1, 84); 2566 __ Retab(); 2567 2568 __ Bind(&after_fn2); 2569 __ Adr(x2, &fn2); 2570 __ Blr(x2); 2571 2572 __ Mov(sp, x28); 2573 __ Mov(lr, x29); 2574 END(); 2575 2576 if (CAN_RUN()) { 2577#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 2578 simulator.SetGuardedPages(true); 2579#else 2580 VIXL_UNIMPLEMENTED(); 2581#endif 2582 RUN(); 2583 2584 ASSERT_EQUAL_64(42, x0); 2585 ASSERT_EQUAL_64(84, x1); 2586 } 2587} 2588 2589#ifdef VIXL_NEGATIVE_TESTING 2590TEST(branch_to_reg_auth_fail) { 2591 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 2592 2593 START(); 2594 2595 Label fn1, after_fn1; 2596 2597 __ Mov(x29, lr); 2598 2599 __ B(&after_fn1); 2600 2601 __ Bind(&fn1); 2602 __ Mov(x0, lr); 2603 __ Pacizb(x0); 2604 __ Blraaz(x0); 2605 2606 __ Bind(&after_fn1); 2607 // There is a small but not negligible chance (1 in 127 runs) that the PAC 2608 // codes for keys A and B will collide and BLRAAZ won't abort. To mitigate 2609 // this, we simply repeat the test a few more times. 2610 for (unsigned i = 0; i < 32; i++) { 2611 __ Bl(&fn1); 2612 } 2613 2614 __ Mov(lr, x29); 2615 END(); 2616 2617 if (CAN_RUN()) { 2618 MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer."); 2619 } 2620} 2621#endif // VIXL_NEGATIVE_TESTING 2622 2623#ifdef VIXL_NEGATIVE_TESTING 2624TEST(return_to_reg_auth_fail) { 2625 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 2626 2627 START(); 2628 2629 Label fn1, after_fn1; 2630 2631 __ Mov(x28, sp); 2632 __ Mov(x29, lr); 2633 __ Mov(sp, 0x477d469dec0b8760); 2634 2635 __ B(&after_fn1); 2636 2637 __ Bind(&fn1); 2638 __ Paciasp(); 2639 __ Retab(); 2640 2641 __ Bind(&after_fn1); 2642 // There is a small but not negligible chance (1 in 127 runs) that the PAC 2643 // codes for keys A and B will collide and RETAB won't abort. To mitigate 2644 // this, we simply repeat the test a few more times. 2645 for (unsigned i = 0; i < 32; i++) { 2646 __ Bl(&fn1); 2647 } 2648 2649 __ Mov(sp, x28); 2650 __ Mov(lr, x29); 2651 END(); 2652 2653 if (CAN_RUN()) { 2654 MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer."); 2655 } 2656} 2657#endif // VIXL_NEGATIVE_TESTING 2658 2659TEST(branch_to_reg_auth_a_zero) { 2660 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 2661 2662 START(); 2663 2664 Label fn1, after_fn1; 2665 2666 __ Mov(x29, lr); 2667 2668 __ Mov(x1, 0); 2669 __ B(&after_fn1); 2670 2671 __ Bind(&fn1); 2672 __ Mov(x0, lr); 2673 __ Mov(x1, 42); 2674 __ Paciza(x0); 2675 __ Braaz(x0); 2676 2677 __ Bind(&after_fn1); 2678 __ Bl(&fn1); 2679 2680 Label fn2, after_fn2, after_bl2; 2681 2682 __ Mov(x2, 0); 2683 __ B(&after_fn2); 2684 2685 __ Bind(&fn2); 2686 __ Mov(x0, lr); 2687 __ Mov(x2, 84); 2688 __ Paciza(x0); 2689 __ Blraaz(x0); 2690 2691 __ Bind(&after_fn2); 2692 __ Bl(&fn2); 2693 __ Bind(&after_bl2); 2694 __ Mov(x3, lr); 2695 __ Adr(x4, &after_bl2); 2696 __ Adr(x5, &after_fn2); 2697 2698 __ Xpaci(x0); 2699 __ Mov(lr, x29); 2700 END(); 2701 2702 if (CAN_RUN()) { 2703 RUN(); 2704 2705 ASSERT_EQUAL_64(x4, x0); 2706 ASSERT_EQUAL_64(x5, x3); 2707 ASSERT_EQUAL_64(42, x1); 2708 ASSERT_EQUAL_64(84, x2); 2709 } 2710} 2711 2712 2713TEST(compare_branch) { 2714 SETUP(); 2715 2716 START(); 2717 __ Mov(x0, 0); 2718 __ Mov(x1, 0); 2719 __ Mov(x2, 0); 2720 __ Mov(x3, 0); 2721 __ Mov(x4, 0); 2722 __ Mov(x5, 0); 2723 __ Mov(x16, 0); 2724 __ Mov(x17, 42); 2725 2726 Label zt, zt_end; 2727 __ Cbz(w16, &zt); 2728 __ B(&zt_end); 2729 __ Bind(&zt); 2730 __ Mov(x0, 1); 2731 __ Bind(&zt_end); 2732 2733 Label zf, zf_end; 2734 __ Cbz(x17, &zf); 2735 __ B(&zf_end); 2736 __ Bind(&zf); 2737 __ Mov(x1, 1); 2738 __ Bind(&zf_end); 2739 2740 Label nzt, nzt_end; 2741 __ Cbnz(w17, &nzt); 2742 __ B(&nzt_end); 2743 __ Bind(&nzt); 2744 __ Mov(x2, 1); 2745 __ Bind(&nzt_end); 2746 2747 Label nzf, nzf_end; 2748 __ Cbnz(x16, &nzf); 2749 __ B(&nzf_end); 2750 __ Bind(&nzf); 2751 __ Mov(x3, 1); 2752 __ Bind(&nzf_end); 2753 2754 __ Mov(x18, 0xffffffff00000000); 2755 2756 Label a, a_end; 2757 __ Cbz(w18, &a); 2758 __ B(&a_end); 2759 __ Bind(&a); 2760 __ Mov(x4, 1); 2761 __ Bind(&a_end); 2762 2763 Label b, b_end; 2764 __ Cbnz(w18, &b); 2765 __ B(&b_end); 2766 __ Bind(&b); 2767 __ Mov(x5, 1); 2768 __ Bind(&b_end); 2769 2770 END(); 2771 2772 if (CAN_RUN()) { 2773 RUN(); 2774 2775 ASSERT_EQUAL_64(1, x0); 2776 ASSERT_EQUAL_64(0, x1); 2777 ASSERT_EQUAL_64(1, x2); 2778 ASSERT_EQUAL_64(0, x3); 2779 ASSERT_EQUAL_64(1, x4); 2780 ASSERT_EQUAL_64(0, x5); 2781 } 2782} 2783 2784 2785TEST(test_branch) { 2786 SETUP(); 2787 2788 START(); 2789 __ Mov(x0, 0); 2790 __ Mov(x1, 0); 2791 __ Mov(x2, 0); 2792 __ Mov(x3, 0); 2793 __ Mov(x16, 0xaaaaaaaaaaaaaaaa); 2794 2795 Label bz, bz_end; 2796 __ Tbz(w16, 0, &bz); 2797 __ B(&bz_end); 2798 __ Bind(&bz); 2799 __ Mov(x0, 1); 2800 __ Bind(&bz_end); 2801 2802 Label bo, bo_end; 2803 __ Tbz(x16, 63, &bo); 2804 __ B(&bo_end); 2805 __ Bind(&bo); 2806 __ Mov(x1, 1); 2807 __ Bind(&bo_end); 2808 2809 Label nbz, nbz_end; 2810 __ Tbnz(x16, 61, &nbz); 2811 __ B(&nbz_end); 2812 __ Bind(&nbz); 2813 __ Mov(x2, 1); 2814 __ Bind(&nbz_end); 2815 2816 Label nbo, nbo_end; 2817 __ Tbnz(w16, 2, &nbo); 2818 __ B(&nbo_end); 2819 __ Bind(&nbo); 2820 __ Mov(x3, 1); 2821 __ Bind(&nbo_end); 2822 END(); 2823 2824 if (CAN_RUN()) { 2825 RUN(); 2826 2827 ASSERT_EQUAL_64(1, x0); 2828 ASSERT_EQUAL_64(0, x1); 2829 ASSERT_EQUAL_64(1, x2); 2830 ASSERT_EQUAL_64(0, x3); 2831 } 2832} 2833 2834 2835TEST(branch_type) { 2836 SETUP(); 2837 2838 Label fail, done; 2839 2840 START(); 2841 __ Mov(x0, 0x0); 2842 __ Mov(x10, 0x7); 2843 __ Mov(x11, 0x0); 2844 2845 // Test non taken branches. 2846 __ Cmp(x10, 0x7); 2847 __ B(&fail, ne); 2848 __ B(&fail, never); 2849 __ B(&fail, reg_zero, x10); 2850 __ B(&fail, reg_not_zero, x11); 2851 __ B(&fail, reg_bit_clear, x10, 0); 2852 __ B(&fail, reg_bit_set, x10, 3); 2853 2854 // Test taken branches. 2855 Label l1, l2, l3, l4, l5; 2856 __ Cmp(x10, 0x7); 2857 __ B(&l1, eq); 2858 __ B(&fail); 2859 __ Bind(&l1); 2860 __ B(&l2, always); 2861 __ B(&fail); 2862 __ Bind(&l2); 2863 __ B(&l3, reg_not_zero, x10); 2864 __ B(&fail); 2865 __ Bind(&l3); 2866 __ B(&l4, reg_bit_clear, x10, 15); 2867 __ B(&fail); 2868 __ Bind(&l4); 2869 __ B(&l5, reg_bit_set, x10, 1); 2870 __ B(&fail); 2871 __ Bind(&l5); 2872 2873 __ B(&done); 2874 2875 __ Bind(&fail); 2876 __ Mov(x0, 0x1); 2877 2878 __ Bind(&done); 2879 2880 END(); 2881 2882 if (CAN_RUN()) { 2883 RUN(); 2884 2885 ASSERT_EQUAL_64(0x0, x0); 2886 } 2887} 2888 2889enum MTEStgAttribute { 2890 StgNoSideEffect = 0, 2891 StgPairTag = 1, 2892 StgZeroing = 2, 2893 StgPairReg = 4 2894}; 2895 2896// Support st2g, stg, stz2g and stzg. 2897template <typename Op> 2898static void MTEStoreTagHelper(Op op, 2899 AddrMode addr_mode, 2900 int attr = StgNoSideEffect) { 2901 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 2902 START(); 2903 2904 // This method does nothing when the size is zero. i.e. stg and st2g. 2905 // Reserve x9 and x10. 2906 auto LoadDataAndSum = [&](Register reg, int off, unsigned size_in_bytes) { 2907 for (unsigned j = 0; j < size_in_bytes / kXRegSizeInBytes; j++) { 2908 __ Ldr(x9, MemOperand(reg, off)); 2909 __ Add(x10, x9, x10); 2910 off += kXRegSizeInBytes; 2911 } 2912 }; 2913 2914 // Initialize registers to zero. 2915 for (int i = 0; i < 29; i++) { 2916 __ Mov(XRegister(i), 0); 2917 } 2918 2919 Register base = x28; 2920 Register base_tag = x27; 2921 uint32_t* data_ptr = nullptr; 2922 const int data_size = 640; 2923#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 2924 data_ptr = reinterpret_cast<uint32_t*>( 2925 simulator.Mmap(NULL, 2926 data_size * sizeof(uint32_t), 2927 PROT_READ | PROT_WRITE | PROT_MTE, 2928 MAP_PRIVATE | MAP_ANONYMOUS, 2929 -1, 2930 0)); 2931 2932 VIXL_ASSERT(data_ptr != nullptr); 2933 uint32_t* untagged_ptr = AddressUntag(data_ptr); 2934 memset(untagged_ptr, 0xae, data_size * sizeof(uint32_t)); 2935#else 2936// TODO: Port the memory allocation to work on MTE supported platform natively. 2937// Note that `CAN_RUN` prevents running in MTE-unsupported environments. 2938#endif 2939 2940 __ Mov(base, reinterpret_cast<uint64_t>(&data_ptr[data_size / 2])); 2941 2942 VIXL_STATIC_ASSERT(kMTETagGranuleInBytes == 16); 2943 const int tag_granule = kMTETagGranuleInBytes; 2944 int size = ((attr & StgZeroing) != 0) ? tag_granule : 0; 2945 // lsb of MTE tag field. 2946 const int tag_lsb = 56; 2947 2948 for (int i = 1; i < 7; i++) { 2949 uint64_t tag = static_cast<uint64_t>(i) << tag_lsb; 2950 int offset = 2 * i * tag_granule; 2951 __ Mov(XRegister(i), tag); 2952 (masm.*op)(XRegister(i), MemOperand(base, offset, addr_mode)); 2953 2954 // The address tag has been changed after the execution of store tag 2955 // instructions, so update the pointer tag as well. 2956 __ Bic(base_tag, base, 0x0f00000000000000); 2957 __ Orr(base_tag, base_tag, XRegister(i)); 2958 2959 switch (addr_mode) { 2960 case Offset: 2961 __ Ldg(XRegister(i + 10), MemOperand(base_tag, offset)); 2962 LoadDataAndSum(base_tag, offset, size); 2963 if ((attr & StgPairTag) != 0) { 2964 __ Ldg(XRegister(i + 20), MemOperand(base_tag, offset + tag_granule)); 2965 LoadDataAndSum(base_tag, offset + tag_granule, size); 2966 } 2967 break; 2968 2969 case PreIndex: 2970 __ Ldg(XRegister(i + 10), MemOperand(base_tag)); 2971 LoadDataAndSum(base_tag, 0, size); 2972 if ((attr & StgPairTag) != 0) { 2973 __ Ldg(XRegister(i + 20), MemOperand(base_tag, tag_granule)); 2974 LoadDataAndSum(base_tag, tag_granule, size); 2975 } 2976 break; 2977 2978 case PostIndex: 2979 __ Ldg(XRegister(i + 10), MemOperand(base_tag, -offset)); 2980 LoadDataAndSum(base_tag, -offset, size); 2981 if ((attr & StgPairTag) != 0) { 2982 __ Ldg(XRegister(i + 20), 2983 MemOperand(base_tag, -offset + tag_granule)); 2984 LoadDataAndSum(base_tag, -offset + tag_granule, size); 2985 } 2986 break; 2987 2988 default: 2989 VIXL_UNIMPLEMENTED(); 2990 break; 2991 } 2992 2993 // Switch the sign to test both positive and negative offsets. 2994 offset = -offset; 2995 } 2996 2997 int pos_offset = 304; 2998 int neg_offset = -256; 2999 3000 // Backup stack pointer and others. 3001 __ Mov(x7, sp); 3002 __ Mov(base_tag, base); 3003 3004 // Test the cases where operand is the stack pointer. 3005 __ Mov(x8, 11UL << tag_lsb); 3006 __ Mov(sp, x8); 3007 (masm.*op)(sp, MemOperand(base, neg_offset, addr_mode)); 3008 3009 // Synthesise a new address with new tag and assign to the stack pointer. 3010 __ Add(sp, base_tag, 32); 3011 (masm.*op)(x8, MemOperand(sp, pos_offset, addr_mode)); 3012 3013 switch (addr_mode) { 3014 case Offset: 3015 __ Ldg(x17, MemOperand(base, neg_offset)); 3016 __ Ldg(x19, MemOperand(sp, pos_offset)); 3017 if ((attr & StgPairTag) != 0) { 3018 __ Ldg(x18, MemOperand(base, neg_offset + tag_granule)); 3019 __ Ldg(x20, MemOperand(sp, pos_offset + tag_granule)); 3020 } 3021 break; 3022 case PreIndex: 3023 __ Ldg(x17, MemOperand(base)); 3024 __ Ldg(x19, MemOperand(sp)); 3025 if ((attr & StgPairTag) != 0) { 3026 __ Ldg(x18, MemOperand(base, tag_granule)); 3027 __ Ldg(x20, MemOperand(sp, tag_granule)); 3028 } 3029 break; 3030 case PostIndex: 3031 __ Ldg(x17, MemOperand(base, -neg_offset)); 3032 __ Ldg(x19, MemOperand(sp, -pos_offset)); 3033 if ((attr & StgPairTag) != 0) { 3034 __ Ldg(x18, MemOperand(base, -neg_offset + tag_granule)); 3035 __ Ldg(x20, MemOperand(sp, -pos_offset + tag_granule)); 3036 } 3037 break; 3038 default: 3039 VIXL_UNIMPLEMENTED(); 3040 break; 3041 } 3042 3043 // Restore stack pointer. 3044 __ Mov(sp, x7); 3045 3046 END(); 3047 3048 if (CAN_RUN()) { 3049#ifndef VIXL_INCLUDE_SIMULATOR_AARCH64 3050 VIXL_UNIMPLEMENTED(); 3051#endif 3052 RUN(); 3053 3054 ASSERT_EQUAL_64(1UL << tag_lsb, x11); 3055 ASSERT_EQUAL_64(2UL << tag_lsb, x12); 3056 ASSERT_EQUAL_64(3UL << tag_lsb, x13); 3057 ASSERT_EQUAL_64(4UL << tag_lsb, x14); 3058 ASSERT_EQUAL_64(5UL << tag_lsb, x15); 3059 ASSERT_EQUAL_64(6UL << tag_lsb, x16); 3060 ASSERT_EQUAL_64(11UL << tag_lsb, x17); 3061 ASSERT_EQUAL_64(11UL << tag_lsb, x19); 3062 3063 if ((attr & StgPairTag) != 0) { 3064 ASSERT_EQUAL_64(1UL << tag_lsb, x21); 3065 ASSERT_EQUAL_64(2UL << tag_lsb, x22); 3066 ASSERT_EQUAL_64(3UL << tag_lsb, x23); 3067 ASSERT_EQUAL_64(4UL << tag_lsb, x24); 3068 ASSERT_EQUAL_64(5UL << tag_lsb, x25); 3069 ASSERT_EQUAL_64(6UL << tag_lsb, x26); 3070 ASSERT_EQUAL_64(11UL << tag_lsb, x18); 3071 ASSERT_EQUAL_64(11UL << tag_lsb, x20); 3072 } 3073 3074 if ((attr & StgZeroing) != 0) { 3075 ASSERT_EQUAL_64(0, x10); 3076 } 3077 } 3078 3079#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 3080 simulator.Munmap(data_ptr, data_size, PROT_MTE); 3081#endif 3082} 3083 3084TEST(st2g_ldg) { 3085 MTEStoreTagHelper(&MacroAssembler::St2g, Offset, StgPairTag); 3086 MTEStoreTagHelper(&MacroAssembler::St2g, PreIndex, StgPairTag); 3087 MTEStoreTagHelper(&MacroAssembler::St2g, PostIndex, StgPairTag); 3088} 3089 3090TEST(stg_ldg) { 3091 MTEStoreTagHelper(&MacroAssembler::Stg, Offset); 3092 MTEStoreTagHelper(&MacroAssembler::Stg, PreIndex); 3093 MTEStoreTagHelper(&MacroAssembler::Stg, PostIndex); 3094} 3095 3096TEST(stz2g_ldg) { 3097 MTEStoreTagHelper(&MacroAssembler::Stz2g, Offset, StgPairTag | StgZeroing); 3098 MTEStoreTagHelper(&MacroAssembler::Stz2g, PreIndex, StgPairTag | StgZeroing); 3099 MTEStoreTagHelper(&MacroAssembler::Stz2g, PostIndex, StgPairTag | StgZeroing); 3100} 3101 3102TEST(stzg_ldg) { 3103 MTEStoreTagHelper(&MacroAssembler::Stzg, Offset, StgZeroing); 3104 MTEStoreTagHelper(&MacroAssembler::Stzg, PreIndex, StgZeroing); 3105 MTEStoreTagHelper(&MacroAssembler::Stzg, PostIndex, StgZeroing); 3106} 3107 3108TEST(stgp_ldg) { 3109 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 3110 START(); 3111 3112 // Initialize registers to zero. 3113 for (int i = 0; i < 29; i++) { 3114 __ Mov(XRegister(i), 0); 3115 } 3116 3117 // Reserve x14 and x15. 3118 auto LoadDataAndSum = [&](Register reg, int off) { 3119 __ Ldr(x14, MemOperand(reg, off)); 3120 __ Add(x15, x14, x15); 3121 __ Ldr(x14, MemOperand(reg, off + static_cast<int>(kXRegSizeInBytes))); 3122 __ Add(x15, x14, x15); 3123 }; 3124 3125 Register base = x28; 3126 uint32_t* data_ptr = nullptr; 3127 const int data_size = 640; 3128 uint64_t init_tag = 17; 3129#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 3130 data_ptr = reinterpret_cast<uint32_t*>( 3131 simulator.Mmap(NULL, 3132 data_size * sizeof(uint32_t), 3133 PROT_READ | PROT_WRITE | PROT_MTE, 3134 MAP_PRIVATE | MAP_ANONYMOUS, 3135 -1, 3136 0)); 3137 3138 VIXL_ASSERT(data_ptr != nullptr); 3139 init_tag = CPU::GetPointerTag(data_ptr); 3140 uint32_t* untagged_ptr = AddressUntag(data_ptr); 3141 memset(untagged_ptr, 0xc9, data_size * sizeof(uint32_t)); 3142#else 3143// TODO: Port the memory allocation to work on MTE supported platform natively. 3144// Note that `CAN_RUN` prevents running in MTE-unsupported environments. 3145#endif 3146 3147 __ Mov(base, reinterpret_cast<uint64_t>(&data_ptr[data_size / 2])); 3148 3149 // lsb of MTE tag field. 3150 const int tag_lsb = 56; 3151 for (int i = 0; i < 11; i++) { 3152 // <63..60> <59..56> <55........5> <4..0> 3153 // 0 i 0 i 3154 __ Mov(XRegister(i), i | (static_cast<uint64_t>(i) << tag_lsb)); 3155 } 3156 3157 // Backup stack pointer. 3158 __ Mov(x0, sp); 3159 3160 int offset = -16; 3161 __ Addg(base, base, 0, 1); 3162 __ Stgp(x1, x2, MemOperand(base, offset, Offset)); 3163 // Make sure `ldg` works well with address that isn't tag-granule aligned. 3164 __ Add(x29, base, 8); 3165 __ Ldg(x18, MemOperand(x29, offset)); 3166 LoadDataAndSum(base, offset); 3167 3168 offset = -304; 3169 __ Addg(base, base, 0, 1); 3170 __ Stgp(x2, x3, MemOperand(base, offset, Offset)); 3171 __ Add(x29, base, 4); 3172 __ Ldg(x19, MemOperand(x29, offset)); 3173 LoadDataAndSum(base, offset); 3174 3175 offset = 128; 3176 __ Addg(base, base, 0, 1); 3177 __ Stgp(x3, x4, MemOperand(base, offset, Offset)); 3178 __ Mov(sp, base); 3179 __ Ldg(x20, MemOperand(sp, offset)); 3180 LoadDataAndSum(base, offset); 3181 3182 offset = -48; 3183 __ Addg(base, base, 0, 1); 3184 __ Stgp(x4, x5, MemOperand(base, offset, PreIndex)); 3185 __ Add(x29, base, 8); 3186 __ Ldg(x21, MemOperand(x29)); 3187 LoadDataAndSum(base, 0); 3188 3189 offset = 64; 3190 __ Addg(base, base, 0, 1); 3191 __ Stgp(x5, x6, MemOperand(base, offset, PreIndex)); 3192 __ Add(x29, base, 4); 3193 __ Ldg(x22, MemOperand(x29)); 3194 LoadDataAndSum(base, 0); 3195 3196 offset = -288; 3197 __ Addg(base, base, 0, 1); 3198 __ Stgp(x6, x7, MemOperand(base, offset, PreIndex)); 3199 __ Mov(sp, base); 3200 __ Ldg(x23, MemOperand(sp)); 3201 LoadDataAndSum(base, 0); 3202 3203 offset = -96; 3204 __ Addg(base, base, 0, 1); 3205 __ Stgp(x7, x8, MemOperand(base, offset, PostIndex)); 3206 __ Add(x29, base, 8); 3207 __ Ldg(x24, MemOperand(x29, -offset)); 3208 LoadDataAndSum(base, -offset); 3209 3210 offset = 80; 3211 __ Addg(base, base, 0, 1); 3212 __ Stgp(x8, x9, MemOperand(base, offset, PostIndex)); 3213 __ Add(x29, base, 4); 3214 __ Ldg(x25, MemOperand(x29, -offset)); 3215 LoadDataAndSum(base, -offset); 3216 3217 offset = -224; 3218 __ Addg(base, base, 0, 1); 3219 __ Stgp(x9, x10, MemOperand(base, offset, PostIndex)); 3220 __ Mov(sp, base); 3221 __ Ldg(x26, MemOperand(sp, -offset)); 3222 LoadDataAndSum(base, -offset); 3223 3224 __ Mov(sp, x0); 3225 3226 END(); 3227 3228 if (CAN_RUN()) { 3229#ifndef VIXL_INCLUDE_SIMULATOR_AARCH64 3230 VIXL_UNIMPLEMENTED(); 3231#endif 3232 RUN(); 3233 3234 const uint64_t k = kMTETagGranuleInBytes; 3235 USE(k); 3236 ASSERT_EQUAL_64(((init_tag + 1) % k) << tag_lsb, x18); 3237 ASSERT_EQUAL_64(((init_tag + 2) % k) << tag_lsb, x19); 3238 ASSERT_EQUAL_64(((init_tag + 3) % k) << tag_lsb, x20); 3239 ASSERT_EQUAL_64(((init_tag + 4) % k) << tag_lsb, x21); 3240 ASSERT_EQUAL_64(((init_tag + 5) % k) << tag_lsb, x22); 3241 ASSERT_EQUAL_64(((init_tag + 6) % k) << tag_lsb, x23); 3242 ASSERT_EQUAL_64(((init_tag + 7) % k) << tag_lsb, x24); 3243 ASSERT_EQUAL_64(((init_tag + 8) % k) << tag_lsb, x25); 3244 ASSERT_EQUAL_64(((init_tag + 9) % k) << tag_lsb, x26); 3245 3246 // We store 1, 2, 2, 3, 3, 4, ....9, 9, 10 to memory, so the total sum of 3247 // these values is 1 + (2 * (2 + 9) * 8 / 2) + 10 = 99. 3248 ASSERT_EQUAL_64((99UL << tag_lsb | 99UL), x15); 3249 } 3250 3251#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 3252 simulator.Munmap(data_ptr, data_size, PROT_MTE); 3253#endif 3254} 3255 3256TEST(ldr_str_offset) { 3257 SETUP(); 3258 3259 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef}; 3260 uint64_t dst[5] = {0, 0, 0, 0, 0}; 3261 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3262 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3263 3264 START(); 3265 __ Mov(x17, src_base); 3266 __ Mov(x18, dst_base); 3267 __ Ldr(w0, MemOperand(x17)); 3268 __ Str(w0, MemOperand(x18)); 3269 __ Ldr(w1, MemOperand(x17, 4)); 3270 __ Str(w1, MemOperand(x18, 12)); 3271 __ Ldr(x2, MemOperand(x17, 8)); 3272 __ Str(x2, MemOperand(x18, 16)); 3273 __ Ldrb(w3, MemOperand(x17, 1)); 3274 __ Strb(w3, MemOperand(x18, 25)); 3275 __ Ldrh(w4, MemOperand(x17, 2)); 3276 __ Strh(w4, MemOperand(x18, 33)); 3277 END(); 3278 3279 if (CAN_RUN()) { 3280 RUN(); 3281 3282 ASSERT_EQUAL_64(0x76543210, x0); 3283 ASSERT_EQUAL_64(0x76543210, dst[0]); 3284 ASSERT_EQUAL_64(0xfedcba98, x1); 3285 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]); 3286 ASSERT_EQUAL_64(0x0123456789abcdef, x2); 3287 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]); 3288 ASSERT_EQUAL_64(0x32, x3); 3289 ASSERT_EQUAL_64(0x3200, dst[3]); 3290 ASSERT_EQUAL_64(0x7654, x4); 3291 ASSERT_EQUAL_64(0x765400, dst[4]); 3292 ASSERT_EQUAL_64(src_base, x17); 3293 ASSERT_EQUAL_64(dst_base, x18); 3294 } 3295} 3296 3297 3298TEST(ldr_str_wide) { 3299 SETUP(); 3300 3301 uint32_t src[8192]; 3302 uint32_t dst[8192]; 3303 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3304 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3305 memset(src, 0xaa, 8192 * sizeof(src[0])); 3306 memset(dst, 0xaa, 8192 * sizeof(dst[0])); 3307 src[0] = 0; 3308 src[6144] = 6144; 3309 src[8191] = 8191; 3310 3311 START(); 3312 __ Mov(x22, src_base); 3313 __ Mov(x23, dst_base); 3314 __ Mov(x24, src_base); 3315 __ Mov(x25, dst_base); 3316 __ Mov(x26, src_base); 3317 __ Mov(x27, dst_base); 3318 3319 __ Ldr(w0, MemOperand(x22, 8191 * sizeof(src[0]))); 3320 __ Str(w0, MemOperand(x23, 8191 * sizeof(dst[0]))); 3321 __ Ldr(w1, MemOperand(x24, 4096 * sizeof(src[0]), PostIndex)); 3322 __ Str(w1, MemOperand(x25, 4096 * sizeof(dst[0]), PostIndex)); 3323 __ Ldr(w2, MemOperand(x26, 6144 * sizeof(src[0]), PreIndex)); 3324 __ Str(w2, MemOperand(x27, 6144 * sizeof(dst[0]), PreIndex)); 3325 END(); 3326 3327 if (CAN_RUN()) { 3328 RUN(); 3329 3330 ASSERT_EQUAL_32(8191, w0); 3331 ASSERT_EQUAL_32(8191, dst[8191]); 3332 ASSERT_EQUAL_64(src_base, x22); 3333 ASSERT_EQUAL_64(dst_base, x23); 3334 ASSERT_EQUAL_32(0, w1); 3335 ASSERT_EQUAL_32(0, dst[0]); 3336 ASSERT_EQUAL_64(src_base + 4096 * sizeof(src[0]), x24); 3337 ASSERT_EQUAL_64(dst_base + 4096 * sizeof(dst[0]), x25); 3338 ASSERT_EQUAL_32(6144, w2); 3339 ASSERT_EQUAL_32(6144, dst[6144]); 3340 ASSERT_EQUAL_64(src_base + 6144 * sizeof(src[0]), x26); 3341 ASSERT_EQUAL_64(dst_base + 6144 * sizeof(dst[0]), x27); 3342 } 3343} 3344 3345 3346TEST(ldr_str_preindex) { 3347 SETUP(); 3348 3349 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef}; 3350 uint64_t dst[6] = {0, 0, 0, 0, 0, 0}; 3351 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3352 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3353 3354 START(); 3355 __ Mov(x17, src_base); 3356 __ Mov(x18, dst_base); 3357 __ Mov(x19, src_base); 3358 __ Mov(x20, dst_base); 3359 __ Mov(x21, src_base + 16); 3360 __ Mov(x22, dst_base + 40); 3361 __ Mov(x23, src_base); 3362 __ Mov(x24, dst_base); 3363 __ Mov(x25, src_base); 3364 __ Mov(x26, dst_base); 3365 __ Ldr(w0, MemOperand(x17, 4, PreIndex)); 3366 __ Str(w0, MemOperand(x18, 12, PreIndex)); 3367 __ Ldr(x1, MemOperand(x19, 8, PreIndex)); 3368 __ Str(x1, MemOperand(x20, 16, PreIndex)); 3369 __ Ldr(w2, MemOperand(x21, -4, PreIndex)); 3370 __ Str(w2, MemOperand(x22, -4, PreIndex)); 3371 __ Ldrb(w3, MemOperand(x23, 1, PreIndex)); 3372 __ Strb(w3, MemOperand(x24, 25, PreIndex)); 3373 __ Ldrh(w4, MemOperand(x25, 3, PreIndex)); 3374 __ Strh(w4, MemOperand(x26, 41, PreIndex)); 3375 END(); 3376 3377 if (CAN_RUN()) { 3378 RUN(); 3379 3380 ASSERT_EQUAL_64(0xfedcba98, x0); 3381 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]); 3382 ASSERT_EQUAL_64(0x0123456789abcdef, x1); 3383 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]); 3384 ASSERT_EQUAL_64(0x01234567, x2); 3385 ASSERT_EQUAL_64(0x0123456700000000, dst[4]); 3386 ASSERT_EQUAL_64(0x32, x3); 3387 ASSERT_EQUAL_64(0x3200, dst[3]); 3388 ASSERT_EQUAL_64(0x9876, x4); 3389 ASSERT_EQUAL_64(0x987600, dst[5]); 3390 ASSERT_EQUAL_64(src_base + 4, x17); 3391 ASSERT_EQUAL_64(dst_base + 12, x18); 3392 ASSERT_EQUAL_64(src_base + 8, x19); 3393 ASSERT_EQUAL_64(dst_base + 16, x20); 3394 ASSERT_EQUAL_64(src_base + 12, x21); 3395 ASSERT_EQUAL_64(dst_base + 36, x22); 3396 ASSERT_EQUAL_64(src_base + 1, x23); 3397 ASSERT_EQUAL_64(dst_base + 25, x24); 3398 ASSERT_EQUAL_64(src_base + 3, x25); 3399 ASSERT_EQUAL_64(dst_base + 41, x26); 3400 } 3401} 3402 3403 3404TEST(ldr_str_postindex) { 3405 SETUP(); 3406 3407 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef}; 3408 uint64_t dst[6] = {0, 0, 0, 0, 0, 0}; 3409 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3410 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3411 3412 START(); 3413 __ Mov(x17, src_base + 4); 3414 __ Mov(x18, dst_base + 12); 3415 __ Mov(x19, src_base + 8); 3416 __ Mov(x20, dst_base + 16); 3417 __ Mov(x21, src_base + 8); 3418 __ Mov(x22, dst_base + 32); 3419 __ Mov(x23, src_base + 1); 3420 __ Mov(x24, dst_base + 25); 3421 __ Mov(x25, src_base + 3); 3422 __ Mov(x26, dst_base + 41); 3423 __ Ldr(w0, MemOperand(x17, 4, PostIndex)); 3424 __ Str(w0, MemOperand(x18, 12, PostIndex)); 3425 __ Ldr(x1, MemOperand(x19, 8, PostIndex)); 3426 __ Str(x1, MemOperand(x20, 16, PostIndex)); 3427 __ Ldr(x2, MemOperand(x21, -8, PostIndex)); 3428 __ Str(x2, MemOperand(x22, -32, PostIndex)); 3429 __ Ldrb(w3, MemOperand(x23, 1, PostIndex)); 3430 __ Strb(w3, MemOperand(x24, 5, PostIndex)); 3431 __ Ldrh(w4, MemOperand(x25, -3, PostIndex)); 3432 __ Strh(w4, MemOperand(x26, -41, PostIndex)); 3433 END(); 3434 3435 if (CAN_RUN()) { 3436 RUN(); 3437 3438 ASSERT_EQUAL_64(0xfedcba98, x0); 3439 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]); 3440 ASSERT_EQUAL_64(0x0123456789abcdef, x1); 3441 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]); 3442 ASSERT_EQUAL_64(0x0123456789abcdef, x2); 3443 ASSERT_EQUAL_64(0x0123456789abcdef, dst[4]); 3444 ASSERT_EQUAL_64(0x32, x3); 3445 ASSERT_EQUAL_64(0x3200, dst[3]); 3446 ASSERT_EQUAL_64(0x9876, x4); 3447 ASSERT_EQUAL_64(0x987600, dst[5]); 3448 ASSERT_EQUAL_64(src_base + 8, x17); 3449 ASSERT_EQUAL_64(dst_base + 24, x18); 3450 ASSERT_EQUAL_64(src_base + 16, x19); 3451 ASSERT_EQUAL_64(dst_base + 32, x20); 3452 ASSERT_EQUAL_64(src_base, x21); 3453 ASSERT_EQUAL_64(dst_base, x22); 3454 ASSERT_EQUAL_64(src_base + 2, x23); 3455 ASSERT_EQUAL_64(dst_base + 30, x24); 3456 ASSERT_EQUAL_64(src_base, x25); 3457 ASSERT_EQUAL_64(dst_base, x26); 3458 } 3459} 3460 3461 3462TEST(ldr_str_largeindex) { 3463 SETUP(); 3464 3465 // This value won't fit in the immediate offset field of ldr/str instructions. 3466 int largeoffset = 0xabcdef; 3467 3468 int64_t data[3] = {0x1122334455667788, 0, 0}; 3469 uint64_t base_addr = reinterpret_cast<uintptr_t>(data); 3470 uint64_t drifted_addr = base_addr - largeoffset; 3471 3472 // This test checks that we we can use large immediate offsets when 3473 // using PreIndex or PostIndex addressing mode of the MacroAssembler 3474 // Ldr/Str instructions. 3475 3476 START(); 3477 __ Mov(x19, drifted_addr); 3478 __ Ldr(x0, MemOperand(x19, largeoffset, PreIndex)); 3479 3480 __ Mov(x20, base_addr); 3481 __ Ldr(x1, MemOperand(x20, largeoffset, PostIndex)); 3482 3483 __ Mov(x21, drifted_addr); 3484 __ Str(x0, MemOperand(x21, largeoffset + 8, PreIndex)); 3485 3486 __ Mov(x22, base_addr + 16); 3487 __ Str(x0, MemOperand(x22, largeoffset, PostIndex)); 3488 END(); 3489 3490 if (CAN_RUN()) { 3491 RUN(); 3492 3493 ASSERT_EQUAL_64(0x1122334455667788, data[0]); 3494 ASSERT_EQUAL_64(0x1122334455667788, data[1]); 3495 ASSERT_EQUAL_64(0x1122334455667788, data[2]); 3496 ASSERT_EQUAL_64(0x1122334455667788, x0); 3497 ASSERT_EQUAL_64(0x1122334455667788, x1); 3498 3499 ASSERT_EQUAL_64(base_addr, x19); 3500 ASSERT_EQUAL_64(base_addr + largeoffset, x20); 3501 ASSERT_EQUAL_64(base_addr + 8, x21); 3502 ASSERT_EQUAL_64(base_addr + 16 + largeoffset, x22); 3503 } 3504} 3505 3506 3507TEST(load_signed) { 3508 SETUP(); 3509 3510 uint32_t src[2] = {0x80008080, 0x7fff7f7f}; 3511 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3512 3513 START(); 3514 __ Mov(x24, src_base); 3515 __ Ldrsb(w0, MemOperand(x24)); 3516 __ Ldrsb(w1, MemOperand(x24, 4)); 3517 __ Ldrsh(w2, MemOperand(x24)); 3518 __ Ldrsh(w3, MemOperand(x24, 4)); 3519 __ Ldrsb(x4, MemOperand(x24)); 3520 __ Ldrsb(x5, MemOperand(x24, 4)); 3521 __ Ldrsh(x6, MemOperand(x24)); 3522 __ Ldrsh(x7, MemOperand(x24, 4)); 3523 __ Ldrsw(x8, MemOperand(x24)); 3524 __ Ldrsw(x9, MemOperand(x24, 4)); 3525 END(); 3526 3527 if (CAN_RUN()) { 3528 RUN(); 3529 3530 ASSERT_EQUAL_64(0xffffff80, x0); 3531 ASSERT_EQUAL_64(0x0000007f, x1); 3532 ASSERT_EQUAL_64(0xffff8080, x2); 3533 ASSERT_EQUAL_64(0x00007f7f, x3); 3534 ASSERT_EQUAL_64(0xffffffffffffff80, x4); 3535 ASSERT_EQUAL_64(0x000000000000007f, x5); 3536 ASSERT_EQUAL_64(0xffffffffffff8080, x6); 3537 ASSERT_EQUAL_64(0x0000000000007f7f, x7); 3538 ASSERT_EQUAL_64(0xffffffff80008080, x8); 3539 ASSERT_EQUAL_64(0x000000007fff7f7f, x9); 3540 } 3541} 3542 3543 3544TEST(load_store_regoffset) { 3545 SETUP(); 3546 3547 uint32_t src[3] = {1, 2, 3}; 3548 uint32_t dst[4] = {0, 0, 0, 0}; 3549 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3550 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3551 3552 START(); 3553 __ Mov(x16, src_base); 3554 __ Mov(x17, dst_base); 3555 __ Mov(x18, src_base + 3 * sizeof(src[0])); 3556 __ Mov(x19, dst_base + 3 * sizeof(dst[0])); 3557 __ Mov(x20, dst_base + 4 * sizeof(dst[0])); 3558 __ Mov(x24, 0); 3559 __ Mov(x25, 4); 3560 __ Mov(x26, -4); 3561 __ Mov(x27, 0xfffffffc); // 32-bit -4. 3562 __ Mov(x28, 0xfffffffe); // 32-bit -2. 3563 __ Mov(x29, 0xffffffff); // 32-bit -1. 3564 3565 __ Ldr(w0, MemOperand(x16, x24)); 3566 __ Ldr(x1, MemOperand(x16, x25)); 3567 __ Ldr(w2, MemOperand(x18, x26)); 3568 __ Ldr(w3, MemOperand(x18, x27, SXTW)); 3569 __ Ldr(w4, MemOperand(x18, x28, SXTW, 2)); 3570 __ Str(w0, MemOperand(x17, x24)); 3571 __ Str(x1, MemOperand(x17, x25)); 3572 __ Str(w2, MemOperand(x20, x29, SXTW, 2)); 3573 END(); 3574 3575 if (CAN_RUN()) { 3576 RUN(); 3577 3578 ASSERT_EQUAL_64(1, x0); 3579 ASSERT_EQUAL_64(0x0000000300000002, x1); 3580 ASSERT_EQUAL_64(3, x2); 3581 ASSERT_EQUAL_64(3, x3); 3582 ASSERT_EQUAL_64(2, x4); 3583 ASSERT_EQUAL_32(1, dst[0]); 3584 ASSERT_EQUAL_32(2, dst[1]); 3585 ASSERT_EQUAL_32(3, dst[2]); 3586 ASSERT_EQUAL_32(3, dst[3]); 3587 } 3588} 3589 3590 3591TEST(load_pauth) { 3592 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 3593 3594 uint64_t src[4] = {1, 2, 3, 4}; 3595 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3596 3597 START(); 3598 __ Mov(x16, src_base); 3599 __ Mov(x17, src_base); 3600 __ Mov(x18, src_base + 4 * sizeof(src[0])); 3601 __ Mov(x19, src_base + 4 * sizeof(src[0])); 3602 3603 // Add PAC codes to addresses 3604 __ Pacdza(x16); 3605 __ Pacdzb(x17); 3606 __ Pacdza(x18); 3607 __ Pacdzb(x19); 3608 3609 __ Ldraa(x0, MemOperand(x16)); 3610 __ Ldraa(x1, MemOperand(x16, sizeof(src[0]))); 3611 __ Ldraa(x2, MemOperand(x16, 2 * sizeof(src[0]), PreIndex)); 3612 __ Ldraa(x3, MemOperand(x18, -sizeof(src[0]))); 3613 __ Ldrab(x4, MemOperand(x17)); 3614 __ Ldrab(x5, MemOperand(x17, sizeof(src[0]))); 3615 __ Ldrab(x6, MemOperand(x17, 2 * sizeof(src[0]), PreIndex)); 3616 __ Ldrab(x7, MemOperand(x19, -sizeof(src[0]))); 3617 END(); 3618 3619 if (CAN_RUN()) { 3620 RUN(); 3621 3622 ASSERT_EQUAL_64(1, x0); 3623 ASSERT_EQUAL_64(2, x1); 3624 ASSERT_EQUAL_64(3, x2); 3625 ASSERT_EQUAL_64(4, x3); 3626 ASSERT_EQUAL_64(1, x4); 3627 ASSERT_EQUAL_64(2, x5); 3628 ASSERT_EQUAL_64(3, x6); 3629 ASSERT_EQUAL_64(4, x7); 3630 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x16); 3631 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x17); 3632 } 3633} 3634 3635 3636#ifdef VIXL_NEGATIVE_TESTING 3637TEST(load_pauth_negative_test) { 3638 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 3639 3640 uint64_t src[4] = {1, 2, 3, 4}; 3641 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3642 3643 START(); 3644 __ Mov(x16, src_base); 3645 3646 // There is a small but not negligible chance (1 in 127 runs) that the PAC 3647 // codes for keys A and B will collide and LDRAB won't abort. To mitigate 3648 // this, we simply repeat the test a few more times. 3649 for (unsigned i = 0; i < 32; i++) { 3650 __ Add(x17, x16, i); 3651 __ Pacdza(x17); 3652 __ Ldrab(x0, MemOperand(x17)); 3653 } 3654 END(); 3655 3656 if (CAN_RUN()) { 3657 MUST_FAIL_WITH_MESSAGE(RUN(), "Failed to authenticate pointer."); 3658 } 3659} 3660#endif // VIXL_NEGATIVE_TESTING 3661 3662 3663TEST(ldp_stp_offset) { 3664 SETUP(); 3665 3666 uint64_t src[3] = {0x0011223344556677, 3667 0x8899aabbccddeeff, 3668 0xffeeddccbbaa9988}; 3669 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0}; 3670 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3671 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3672 3673 START(); 3674 __ Mov(x16, src_base); 3675 __ Mov(x17, dst_base); 3676 __ Mov(x18, src_base + 24); 3677 __ Mov(x19, dst_base + 56); 3678 __ Ldp(w0, w1, MemOperand(x16)); 3679 __ Ldp(w2, w3, MemOperand(x16, 4)); 3680 __ Ldp(x4, x5, MemOperand(x16, 8)); 3681 __ Ldp(w6, w7, MemOperand(x18, -12)); 3682 __ Ldp(x8, x9, MemOperand(x18, -16)); 3683 __ Stp(w0, w1, MemOperand(x17)); 3684 __ Stp(w2, w3, MemOperand(x17, 8)); 3685 __ Stp(x4, x5, MemOperand(x17, 16)); 3686 __ Stp(w6, w7, MemOperand(x19, -24)); 3687 __ Stp(x8, x9, MemOperand(x19, -16)); 3688 END(); 3689 3690 if (CAN_RUN()) { 3691 RUN(); 3692 3693 ASSERT_EQUAL_64(0x44556677, x0); 3694 ASSERT_EQUAL_64(0x00112233, x1); 3695 ASSERT_EQUAL_64(0x0011223344556677, dst[0]); 3696 ASSERT_EQUAL_64(0x00112233, x2); 3697 ASSERT_EQUAL_64(0xccddeeff, x3); 3698 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]); 3699 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4); 3700 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]); 3701 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5); 3702 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]); 3703 ASSERT_EQUAL_64(0x8899aabb, x6); 3704 ASSERT_EQUAL_64(0xbbaa9988, x7); 3705 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]); 3706 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8); 3707 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]); 3708 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9); 3709 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]); 3710 ASSERT_EQUAL_64(src_base, x16); 3711 ASSERT_EQUAL_64(dst_base, x17); 3712 ASSERT_EQUAL_64(src_base + 24, x18); 3713 ASSERT_EQUAL_64(dst_base + 56, x19); 3714 } 3715} 3716 3717 3718TEST(ldp_stp_offset_wide) { 3719 SETUP(); 3720 3721 uint64_t src[3] = {0x0011223344556677, 3722 0x8899aabbccddeeff, 3723 0xffeeddccbbaa9988}; 3724 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0}; 3725 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3726 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3727 // Move base too far from the array to force multiple instructions 3728 // to be emitted. 3729 const int64_t base_offset = 1024; 3730 3731 START(); 3732 __ Mov(x20, src_base - base_offset); 3733 __ Mov(x21, dst_base - base_offset); 3734 __ Mov(x18, src_base + base_offset + 24); 3735 __ Mov(x19, dst_base + base_offset + 56); 3736 __ Ldp(w0, w1, MemOperand(x20, base_offset)); 3737 __ Ldp(w2, w3, MemOperand(x20, base_offset + 4)); 3738 __ Ldp(x4, x5, MemOperand(x20, base_offset + 8)); 3739 __ Ldp(w6, w7, MemOperand(x18, -12 - base_offset)); 3740 __ Ldp(x8, x9, MemOperand(x18, -16 - base_offset)); 3741 __ Stp(w0, w1, MemOperand(x21, base_offset)); 3742 __ Stp(w2, w3, MemOperand(x21, base_offset + 8)); 3743 __ Stp(x4, x5, MemOperand(x21, base_offset + 16)); 3744 __ Stp(w6, w7, MemOperand(x19, -24 - base_offset)); 3745 __ Stp(x8, x9, MemOperand(x19, -16 - base_offset)); 3746 END(); 3747 3748 if (CAN_RUN()) { 3749 RUN(); 3750 3751 ASSERT_EQUAL_64(0x44556677, x0); 3752 ASSERT_EQUAL_64(0x00112233, x1); 3753 ASSERT_EQUAL_64(0x0011223344556677, dst[0]); 3754 ASSERT_EQUAL_64(0x00112233, x2); 3755 ASSERT_EQUAL_64(0xccddeeff, x3); 3756 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]); 3757 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4); 3758 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]); 3759 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5); 3760 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]); 3761 ASSERT_EQUAL_64(0x8899aabb, x6); 3762 ASSERT_EQUAL_64(0xbbaa9988, x7); 3763 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]); 3764 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8); 3765 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]); 3766 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9); 3767 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]); 3768 ASSERT_EQUAL_64(src_base - base_offset, x20); 3769 ASSERT_EQUAL_64(dst_base - base_offset, x21); 3770 ASSERT_EQUAL_64(src_base + base_offset + 24, x18); 3771 ASSERT_EQUAL_64(dst_base + base_offset + 56, x19); 3772 } 3773} 3774 3775 3776TEST(ldnp_stnp_offset) { 3777 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 3778 3779 uint64_t src[4] = {0x0011223344556677, 3780 0x8899aabbccddeeff, 3781 0xffeeddccbbaa9988, 3782 0x7766554433221100}; 3783 uint64_t dst[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 3784 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3785 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3786 3787 START(); 3788 __ Mov(x16, src_base); 3789 __ Mov(x17, dst_base); 3790 __ Mov(x18, src_base + 24); 3791 __ Mov(x19, dst_base + 64); 3792 __ Mov(x20, src_base + 32); 3793 3794 // Ensure address set up has happened before executing non-temporal ops. 3795 __ Dmb(InnerShareable, BarrierAll); 3796 3797 __ Ldnp(w0, w1, MemOperand(x16)); 3798 __ Ldnp(w2, w3, MemOperand(x16, 4)); 3799 __ Ldnp(x4, x5, MemOperand(x16, 8)); 3800 __ Ldnp(w6, w7, MemOperand(x18, -12)); 3801 __ Ldnp(x8, x9, MemOperand(x18, -16)); 3802 __ Ldnp(q16, q17, MemOperand(x16)); 3803 __ Ldnp(q19, q18, MemOperand(x20, -32)); 3804 __ Stnp(w0, w1, MemOperand(x17)); 3805 __ Stnp(w2, w3, MemOperand(x17, 8)); 3806 __ Stnp(x4, x5, MemOperand(x17, 16)); 3807 __ Stnp(w6, w7, MemOperand(x19, -32)); 3808 __ Stnp(x8, x9, MemOperand(x19, -24)); 3809 __ Stnp(q17, q16, MemOperand(x19)); 3810 __ Stnp(q18, q19, MemOperand(x19, 32)); 3811 END(); 3812 3813 if (CAN_RUN()) { 3814 RUN(); 3815 3816 ASSERT_EQUAL_64(0x44556677, x0); 3817 ASSERT_EQUAL_64(0x00112233, x1); 3818 ASSERT_EQUAL_64(0x0011223344556677, dst[0]); 3819 ASSERT_EQUAL_64(0x00112233, x2); 3820 ASSERT_EQUAL_64(0xccddeeff, x3); 3821 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]); 3822 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4); 3823 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]); 3824 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5); 3825 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]); 3826 ASSERT_EQUAL_64(0x8899aabb, x6); 3827 ASSERT_EQUAL_64(0xbbaa9988, x7); 3828 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]); 3829 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8); 3830 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]); 3831 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9); 3832 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]); 3833 ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q16); 3834 ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q17); 3835 ASSERT_EQUAL_128(0x7766554433221100, 0xffeeddccbbaa9988, q18); 3836 ASSERT_EQUAL_128(0x8899aabbccddeeff, 0x0011223344556677, q19); 3837 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[8]); 3838 ASSERT_EQUAL_64(0x7766554433221100, dst[9]); 3839 ASSERT_EQUAL_64(0x0011223344556677, dst[10]); 3840 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[11]); 3841 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[12]); 3842 ASSERT_EQUAL_64(0x7766554433221100, dst[13]); 3843 ASSERT_EQUAL_64(0x0011223344556677, dst[14]); 3844 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[15]); 3845 ASSERT_EQUAL_64(src_base, x16); 3846 ASSERT_EQUAL_64(dst_base, x17); 3847 ASSERT_EQUAL_64(src_base + 24, x18); 3848 ASSERT_EQUAL_64(dst_base + 64, x19); 3849 ASSERT_EQUAL_64(src_base + 32, x20); 3850 } 3851} 3852 3853TEST(ldp_stp_preindex) { 3854 SETUP(); 3855 3856 uint64_t src[3] = {0x0011223344556677, 3857 0x8899aabbccddeeff, 3858 0xffeeddccbbaa9988}; 3859 uint64_t dst[5] = {0, 0, 0, 0, 0}; 3860 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3861 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3862 3863 START(); 3864 __ Mov(x16, src_base); 3865 __ Mov(x17, dst_base); 3866 __ Mov(x18, dst_base + 16); 3867 __ Ldp(w0, w1, MemOperand(x16, 4, PreIndex)); 3868 __ Mov(x19, x16); 3869 __ Ldp(w2, w3, MemOperand(x16, -4, PreIndex)); 3870 __ Stp(w2, w3, MemOperand(x17, 4, PreIndex)); 3871 __ Mov(x20, x17); 3872 __ Stp(w0, w1, MemOperand(x17, -4, PreIndex)); 3873 __ Ldp(x4, x5, MemOperand(x16, 8, PreIndex)); 3874 __ Mov(x21, x16); 3875 __ Ldp(x6, x7, MemOperand(x16, -8, PreIndex)); 3876 __ Stp(x7, x6, MemOperand(x18, 8, PreIndex)); 3877 __ Mov(x22, x18); 3878 __ Stp(x5, x4, MemOperand(x18, -8, PreIndex)); 3879 END(); 3880 3881 if (CAN_RUN()) { 3882 RUN(); 3883 3884 ASSERT_EQUAL_64(0x00112233, x0); 3885 ASSERT_EQUAL_64(0xccddeeff, x1); 3886 ASSERT_EQUAL_64(0x44556677, x2); 3887 ASSERT_EQUAL_64(0x00112233, x3); 3888 ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]); 3889 ASSERT_EQUAL_64(0x0000000000112233, dst[1]); 3890 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4); 3891 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5); 3892 ASSERT_EQUAL_64(0x0011223344556677, x6); 3893 ASSERT_EQUAL_64(0x8899aabbccddeeff, x7); 3894 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]); 3895 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]); 3896 ASSERT_EQUAL_64(0x0011223344556677, dst[4]); 3897 ASSERT_EQUAL_64(src_base, x16); 3898 ASSERT_EQUAL_64(dst_base, x17); 3899 ASSERT_EQUAL_64(dst_base + 16, x18); 3900 ASSERT_EQUAL_64(src_base + 4, x19); 3901 ASSERT_EQUAL_64(dst_base + 4, x20); 3902 ASSERT_EQUAL_64(src_base + 8, x21); 3903 ASSERT_EQUAL_64(dst_base + 24, x22); 3904 } 3905} 3906 3907 3908TEST(ldp_stp_preindex_wide) { 3909 SETUP(); 3910 3911 uint64_t src[3] = {0x0011223344556677, 3912 0x8899aabbccddeeff, 3913 0xffeeddccbbaa9988}; 3914 uint64_t dst[5] = {0, 0, 0, 0, 0}; 3915 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3916 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3917 // Move base too far from the array to force multiple instructions 3918 // to be emitted. 3919 const int64_t base_offset = 1024; 3920 3921 START(); 3922 __ Mov(x24, src_base - base_offset); 3923 __ Mov(x25, dst_base + base_offset); 3924 __ Mov(x18, dst_base + base_offset + 16); 3925 __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PreIndex)); 3926 __ Mov(x19, x24); 3927 __ Mov(x24, src_base - base_offset + 4); 3928 __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PreIndex)); 3929 __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PreIndex)); 3930 __ Mov(x20, x25); 3931 __ Mov(x25, dst_base + base_offset + 4); 3932 __ Mov(x24, src_base - base_offset); 3933 __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PreIndex)); 3934 __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PreIndex)); 3935 __ Mov(x21, x24); 3936 __ Mov(x24, src_base - base_offset + 8); 3937 __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PreIndex)); 3938 __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PreIndex)); 3939 __ Mov(x22, x18); 3940 __ Mov(x18, dst_base + base_offset + 16 + 8); 3941 __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PreIndex)); 3942 END(); 3943 3944 if (CAN_RUN()) { 3945 RUN(); 3946 3947 ASSERT_EQUAL_64(0x00112233, x0); 3948 ASSERT_EQUAL_64(0xccddeeff, x1); 3949 ASSERT_EQUAL_64(0x44556677, x2); 3950 ASSERT_EQUAL_64(0x00112233, x3); 3951 ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]); 3952 ASSERT_EQUAL_64(0x0000000000112233, dst[1]); 3953 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4); 3954 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5); 3955 ASSERT_EQUAL_64(0x0011223344556677, x6); 3956 ASSERT_EQUAL_64(0x8899aabbccddeeff, x7); 3957 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]); 3958 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]); 3959 ASSERT_EQUAL_64(0x0011223344556677, dst[4]); 3960 ASSERT_EQUAL_64(src_base, x24); 3961 ASSERT_EQUAL_64(dst_base, x25); 3962 ASSERT_EQUAL_64(dst_base + 16, x18); 3963 ASSERT_EQUAL_64(src_base + 4, x19); 3964 ASSERT_EQUAL_64(dst_base + 4, x20); 3965 ASSERT_EQUAL_64(src_base + 8, x21); 3966 ASSERT_EQUAL_64(dst_base + 24, x22); 3967 } 3968} 3969 3970 3971TEST(ldp_stp_postindex) { 3972 SETUP(); 3973 3974 uint64_t src[4] = {0x0011223344556677, 3975 0x8899aabbccddeeff, 3976 0xffeeddccbbaa9988, 3977 0x7766554433221100}; 3978 uint64_t dst[5] = {0, 0, 0, 0, 0}; 3979 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 3980 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 3981 3982 START(); 3983 __ Mov(x16, src_base); 3984 __ Mov(x17, dst_base); 3985 __ Mov(x18, dst_base + 16); 3986 __ Ldp(w0, w1, MemOperand(x16, 4, PostIndex)); 3987 __ Mov(x19, x16); 3988 __ Ldp(w2, w3, MemOperand(x16, -4, PostIndex)); 3989 __ Stp(w2, w3, MemOperand(x17, 4, PostIndex)); 3990 __ Mov(x20, x17); 3991 __ Stp(w0, w1, MemOperand(x17, -4, PostIndex)); 3992 __ Ldp(x4, x5, MemOperand(x16, 8, PostIndex)); 3993 __ Mov(x21, x16); 3994 __ Ldp(x6, x7, MemOperand(x16, -8, PostIndex)); 3995 __ Stp(x7, x6, MemOperand(x18, 8, PostIndex)); 3996 __ Mov(x22, x18); 3997 __ Stp(x5, x4, MemOperand(x18, -8, PostIndex)); 3998 END(); 3999 4000 if (CAN_RUN()) { 4001 RUN(); 4002 4003 ASSERT_EQUAL_64(0x44556677, x0); 4004 ASSERT_EQUAL_64(0x00112233, x1); 4005 ASSERT_EQUAL_64(0x00112233, x2); 4006 ASSERT_EQUAL_64(0xccddeeff, x3); 4007 ASSERT_EQUAL_64(0x4455667700112233, dst[0]); 4008 ASSERT_EQUAL_64(0x0000000000112233, dst[1]); 4009 ASSERT_EQUAL_64(0x0011223344556677, x4); 4010 ASSERT_EQUAL_64(0x8899aabbccddeeff, x5); 4011 ASSERT_EQUAL_64(0x8899aabbccddeeff, x6); 4012 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7); 4013 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]); 4014 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]); 4015 ASSERT_EQUAL_64(0x0011223344556677, dst[4]); 4016 ASSERT_EQUAL_64(src_base, x16); 4017 ASSERT_EQUAL_64(dst_base, x17); 4018 ASSERT_EQUAL_64(dst_base + 16, x18); 4019 ASSERT_EQUAL_64(src_base + 4, x19); 4020 ASSERT_EQUAL_64(dst_base + 4, x20); 4021 ASSERT_EQUAL_64(src_base + 8, x21); 4022 ASSERT_EQUAL_64(dst_base + 24, x22); 4023 } 4024} 4025 4026 4027TEST(ldp_stp_postindex_wide) { 4028 SETUP(); 4029 4030 uint64_t src[4] = {0x0011223344556677, 4031 0x8899aabbccddeeff, 4032 0xffeeddccbbaa9988, 4033 0x7766554433221100}; 4034 uint64_t dst[5] = {0, 0, 0, 0, 0}; 4035 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 4036 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 4037 // Move base too far from the array to force multiple instructions 4038 // to be emitted. 4039 const int64_t base_offset = 1024; 4040 4041 START(); 4042 __ Mov(x24, src_base); 4043 __ Mov(x25, dst_base); 4044 __ Mov(x18, dst_base + 16); 4045 __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PostIndex)); 4046 __ Mov(x19, x24); 4047 __ Sub(x24, x24, base_offset); 4048 __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PostIndex)); 4049 __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PostIndex)); 4050 __ Mov(x20, x25); 4051 __ Sub(x24, x24, base_offset); 4052 __ Add(x25, x25, base_offset); 4053 __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PostIndex)); 4054 __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PostIndex)); 4055 __ Mov(x21, x24); 4056 __ Sub(x24, x24, base_offset); 4057 __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PostIndex)); 4058 __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PostIndex)); 4059 __ Mov(x22, x18); 4060 __ Add(x18, x18, base_offset); 4061 __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PostIndex)); 4062 END(); 4063 4064 if (CAN_RUN()) { 4065 RUN(); 4066 4067 ASSERT_EQUAL_64(0x44556677, x0); 4068 ASSERT_EQUAL_64(0x00112233, x1); 4069 ASSERT_EQUAL_64(0x00112233, x2); 4070 ASSERT_EQUAL_64(0xccddeeff, x3); 4071 ASSERT_EQUAL_64(0x4455667700112233, dst[0]); 4072 ASSERT_EQUAL_64(0x0000000000112233, dst[1]); 4073 ASSERT_EQUAL_64(0x0011223344556677, x4); 4074 ASSERT_EQUAL_64(0x8899aabbccddeeff, x5); 4075 ASSERT_EQUAL_64(0x8899aabbccddeeff, x6); 4076 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7); 4077 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]); 4078 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]); 4079 ASSERT_EQUAL_64(0x0011223344556677, dst[4]); 4080 ASSERT_EQUAL_64(src_base + base_offset, x24); 4081 ASSERT_EQUAL_64(dst_base - base_offset, x25); 4082 ASSERT_EQUAL_64(dst_base - base_offset + 16, x18); 4083 ASSERT_EQUAL_64(src_base + base_offset + 4, x19); 4084 ASSERT_EQUAL_64(dst_base - base_offset + 4, x20); 4085 ASSERT_EQUAL_64(src_base + base_offset + 8, x21); 4086 ASSERT_EQUAL_64(dst_base - base_offset + 24, x22); 4087 } 4088} 4089 4090 4091TEST(ldp_sign_extend) { 4092 SETUP(); 4093 4094 uint32_t src[2] = {0x80000000, 0x7fffffff}; 4095 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 4096 4097 START(); 4098 __ Mov(x24, src_base); 4099 __ Ldpsw(x0, x1, MemOperand(x24)); 4100 END(); 4101 4102 if (CAN_RUN()) { 4103 RUN(); 4104 4105 ASSERT_EQUAL_64(0xffffffff80000000, x0); 4106 ASSERT_EQUAL_64(0x000000007fffffff, x1); 4107 } 4108} 4109 4110 4111TEST(ldur_stur) { 4112 SETUP(); 4113 4114 int64_t src[2] = {0x0123456789abcdef, 0x0123456789abcdef}; 4115 int64_t dst[5] = {0, 0, 0, 0, 0}; 4116 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 4117 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 4118 4119 START(); 4120 __ Mov(x17, src_base); 4121 __ Mov(x18, dst_base); 4122 __ Mov(x19, src_base + 16); 4123 __ Mov(x20, dst_base + 32); 4124 __ Mov(x21, dst_base + 40); 4125 __ Ldr(w0, MemOperand(x17, 1)); 4126 __ Str(w0, MemOperand(x18, 2)); 4127 __ Ldr(x1, MemOperand(x17, 3)); 4128 __ Str(x1, MemOperand(x18, 9)); 4129 __ Ldr(w2, MemOperand(x19, -9)); 4130 __ Str(w2, MemOperand(x20, -5)); 4131 __ Ldrb(w3, MemOperand(x19, -1)); 4132 __ Strb(w3, MemOperand(x21, -1)); 4133 END(); 4134 4135 if (CAN_RUN()) { 4136 RUN(); 4137 4138 ASSERT_EQUAL_64(0x6789abcd, x0); 4139 ASSERT_EQUAL_64(0x00006789abcd0000, dst[0]); 4140 ASSERT_EQUAL_64(0xabcdef0123456789, x1); 4141 ASSERT_EQUAL_64(0xcdef012345678900, dst[1]); 4142 ASSERT_EQUAL_64(0x000000ab, dst[2]); 4143 ASSERT_EQUAL_64(0xabcdef01, x2); 4144 ASSERT_EQUAL_64(0x00abcdef01000000, dst[3]); 4145 ASSERT_EQUAL_64(0x00000001, x3); 4146 ASSERT_EQUAL_64(0x0100000000000000, dst[4]); 4147 ASSERT_EQUAL_64(src_base, x17); 4148 ASSERT_EQUAL_64(dst_base, x18); 4149 ASSERT_EQUAL_64(src_base + 16, x19); 4150 ASSERT_EQUAL_64(dst_base + 32, x20); 4151 } 4152} 4153 4154 4155TEST(ldur_stur_neon) { 4156 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 4157 4158 int64_t src[3] = {0x0123456789abcdef, 0x0123456789abcdef, 0x0123456789abcdef}; 4159 int64_t dst[5] = {0, 0, 0, 0, 0}; 4160 uintptr_t src_base = reinterpret_cast<uintptr_t>(src); 4161 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst); 4162 4163 START(); 4164 __ Mov(x17, src_base); 4165 __ Mov(x18, dst_base); 4166 __ Ldr(b0, MemOperand(x17)); 4167 __ Str(b0, MemOperand(x18)); 4168 __ Ldr(h1, MemOperand(x17, 1)); 4169 __ Str(h1, MemOperand(x18, 1)); 4170 __ Ldr(s2, MemOperand(x17, 2)); 4171 __ Str(s2, MemOperand(x18, 3)); 4172 __ Ldr(d3, MemOperand(x17, 3)); 4173 __ Str(d3, MemOperand(x18, 7)); 4174 __ Ldr(q4, MemOperand(x17, 4)); 4175 __ Str(q4, MemOperand(x18, 15)); 4176 END(); 4177 4178 if (CAN_RUN()) { 4179 RUN(); 4180 4181 ASSERT_EQUAL_128(0, 0xef, q0); 4182 ASSERT_EQUAL_128(0, 0xabcd, q1); 4183 ASSERT_EQUAL_128(0, 0x456789ab, q2); 4184 ASSERT_EQUAL_128(0, 0xabcdef0123456789, q3); 4185 ASSERT_EQUAL_128(0x89abcdef01234567, 0x89abcdef01234567, q4); 4186 ASSERT_EQUAL_64(0x89456789ababcdef, dst[0]); 4187 ASSERT_EQUAL_64(0x67abcdef01234567, dst[1]); 4188 ASSERT_EQUAL_64(0x6789abcdef012345, dst[2]); 4189 ASSERT_EQUAL_64(0x0089abcdef012345, dst[3]); 4190 } 4191} 4192 4193 4194TEST(ldr_literal) { 4195 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 4196 4197 START(); 4198 __ Ldr(x2, 0x1234567890abcdef); 4199 __ Ldr(w3, 0xfedcba09); 4200 __ Ldrsw(x4, 0x7fffffff); 4201 __ Ldrsw(x5, 0x80000000); 4202 __ Ldr(q11, 0x1234000056780000, 0xabcd0000ef000000); 4203 __ Ldr(d13, 1.234); 4204 __ Ldr(s25, 2.5); 4205 END(); 4206 4207 if (CAN_RUN()) { 4208 RUN(); 4209 4210 ASSERT_EQUAL_64(0x1234567890abcdef, x2); 4211 ASSERT_EQUAL_64(0xfedcba09, x3); 4212 ASSERT_EQUAL_64(0x7fffffff, x4); 4213 ASSERT_EQUAL_64(0xffffffff80000000, x5); 4214 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11); 4215 ASSERT_EQUAL_FP64(1.234, d13); 4216 ASSERT_EQUAL_FP32(2.5, s25); 4217 } 4218} 4219 4220 4221TEST(ldr_literal_range) { 4222 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 4223 4224 START(); 4225 // Make sure the pool is empty; 4226 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 4227 ASSERT_LITERAL_POOL_SIZE(0); 4228 4229 // Create some literal pool entries. 4230 __ Ldr(x0, 0x1234567890abcdef); 4231 __ Ldr(w1, 0xfedcba09); 4232 __ Ldrsw(x2, 0x7fffffff); 4233 __ Ldrsw(x3, 0x80000000); 4234 __ Ldr(q2, 0x1234000056780000, 0xabcd0000ef000000); 4235 __ Ldr(d0, 1.234); 4236 __ Ldr(s1, 2.5); 4237 ASSERT_LITERAL_POOL_SIZE(48); 4238 4239 // Emit more code than the maximum literal load range to ensure the pool 4240 // should be emitted. 4241 const ptrdiff_t end = masm.GetCursorOffset() + 2 * kMaxLoadLiteralRange; 4242 while (masm.GetCursorOffset() < end) { 4243 __ Nop(); 4244 } 4245 4246 // The pool should have been emitted. 4247 ASSERT_LITERAL_POOL_SIZE(0); 4248 4249 // These loads should be after the pool (and will require a new one). 4250 __ Ldr(x4, 0x34567890abcdef12); 4251 __ Ldr(w5, 0xdcba09fe); 4252 __ Ldrsw(x6, 0x7fffffff); 4253 __ Ldrsw(x7, 0x80000000); 4254 __ Ldr(q6, 0x1234000056780000, 0xabcd0000ef000000); 4255 __ Ldr(d4, 123.4); 4256 __ Ldr(s5, 250.0); 4257 ASSERT_LITERAL_POOL_SIZE(48); 4258 END(); 4259 4260 if (CAN_RUN()) { 4261 RUN(); 4262 4263 // Check that the literals loaded correctly. 4264 ASSERT_EQUAL_64(0x1234567890abcdef, x0); 4265 ASSERT_EQUAL_64(0xfedcba09, x1); 4266 ASSERT_EQUAL_64(0x7fffffff, x2); 4267 ASSERT_EQUAL_64(0xffffffff80000000, x3); 4268 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q2); 4269 ASSERT_EQUAL_FP64(1.234, d0); 4270 ASSERT_EQUAL_FP32(2.5, s1); 4271 ASSERT_EQUAL_64(0x34567890abcdef12, x4); 4272 ASSERT_EQUAL_64(0xdcba09fe, x5); 4273 ASSERT_EQUAL_64(0x7fffffff, x6); 4274 ASSERT_EQUAL_64(0xffffffff80000000, x7); 4275 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q6); 4276 ASSERT_EQUAL_FP64(123.4, d4); 4277 ASSERT_EQUAL_FP32(250.0, s5); 4278 } 4279} 4280 4281 4282template <typename T> 4283void LoadIntValueHelper(T values[], int card) { 4284 SETUP(); 4285 4286 const bool is_32bit = (sizeof(T) == 4); 4287 Register tgt1 = is_32bit ? Register(w1) : Register(x1); 4288 Register tgt2 = is_32bit ? Register(w2) : Register(x2); 4289 4290 START(); 4291 __ Mov(x0, 0); 4292 4293 // If one of the values differ then x0 will be one. 4294 for (int i = 0; i < card; ++i) { 4295 __ Mov(tgt1, values[i]); 4296 __ Ldr(tgt2, values[i]); 4297 __ Cmp(tgt1, tgt2); 4298 __ Cset(x0, ne); 4299 } 4300 END(); 4301 4302 if (CAN_RUN()) { 4303 RUN(); 4304 4305 // If one of the values differs, the trace can be used to identify which 4306 // one. 4307 ASSERT_EQUAL_64(0, x0); 4308 } 4309} 4310 4311 4312TEST(ldr_literal_values_x) { 4313 static const uint64_t kValues[] = {0x8000000000000000, 4314 0x7fffffffffffffff, 4315 0x0000000000000000, 4316 0xffffffffffffffff, 4317 0x00ff00ff00ff00ff, 4318 0x1234567890abcdef}; 4319 4320 LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0])); 4321} 4322 4323 4324TEST(ldr_literal_values_w) { 4325 static const uint32_t kValues[] = {0x80000000, 4326 0x7fffffff, 4327 0x00000000, 4328 0xffffffff, 4329 0x00ff00ff, 4330 0x12345678, 4331 0x90abcdef}; 4332 4333 LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0])); 4334} 4335 4336TEST(ldr_literal_custom) { 4337 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 4338 4339 Label end_of_pool_before; 4340 Label end_of_pool_after; 4341 4342 const size_t kSizeOfPoolInBytes = 44; 4343 4344 Literal<uint64_t> before_x(0x1234567890abcdef); 4345 Literal<uint32_t> before_w(0xfedcba09); 4346 Literal<uint32_t> before_sx(0x80000000); 4347 Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000); 4348 Literal<double> before_d(1.234); 4349 Literal<float> before_s(2.5); 4350 4351 Literal<uint64_t> after_x(0x1234567890abcdef); 4352 Literal<uint32_t> after_w(0xfedcba09); 4353 Literal<uint32_t> after_sx(0x80000000); 4354 Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000); 4355 Literal<double> after_d(1.234); 4356 Literal<float> after_s(2.5); 4357 4358 START(); 4359 4360 // Manually generate a pool. 4361 __ B(&end_of_pool_before); 4362 { 4363 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes); 4364 __ place(&before_x); 4365 __ place(&before_w); 4366 __ place(&before_sx); 4367 __ place(&before_q); 4368 __ place(&before_d); 4369 __ place(&before_s); 4370 } 4371 __ Bind(&end_of_pool_before); 4372 4373 { 4374 ExactAssemblyScope scope(&masm, 12 * kInstructionSize); 4375 __ ldr(x2, &before_x); 4376 __ ldr(w3, &before_w); 4377 __ ldrsw(x5, &before_sx); 4378 __ ldr(q11, &before_q); 4379 __ ldr(d13, &before_d); 4380 __ ldr(s25, &before_s); 4381 4382 __ ldr(x6, &after_x); 4383 __ ldr(w7, &after_w); 4384 __ ldrsw(x8, &after_sx); 4385 __ ldr(q18, &after_q); 4386 __ ldr(d14, &after_d); 4387 __ ldr(s26, &after_s); 4388 } 4389 4390 // Manually generate a pool. 4391 __ B(&end_of_pool_after); 4392 { 4393 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes); 4394 __ place(&after_x); 4395 __ place(&after_w); 4396 __ place(&after_sx); 4397 __ place(&after_q); 4398 __ place(&after_d); 4399 __ place(&after_s); 4400 } 4401 __ Bind(&end_of_pool_after); 4402 4403 END(); 4404 4405 if (CAN_RUN()) { 4406 RUN(); 4407 4408 ASSERT_EQUAL_64(0x1234567890abcdef, x2); 4409 ASSERT_EQUAL_64(0xfedcba09, x3); 4410 ASSERT_EQUAL_64(0xffffffff80000000, x5); 4411 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11); 4412 ASSERT_EQUAL_FP64(1.234, d13); 4413 ASSERT_EQUAL_FP32(2.5, s25); 4414 4415 ASSERT_EQUAL_64(0x1234567890abcdef, x6); 4416 ASSERT_EQUAL_64(0xfedcba09, x7); 4417 ASSERT_EQUAL_64(0xffffffff80000000, x8); 4418 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18); 4419 ASSERT_EQUAL_FP64(1.234, d14); 4420 ASSERT_EQUAL_FP32(2.5, s26); 4421 } 4422} 4423 4424 4425TEST(ldr_literal_custom_shared) { 4426 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 4427 4428 Label end_of_pool_before; 4429 Label end_of_pool_after; 4430 4431 const size_t kSizeOfPoolInBytes = 40; 4432 4433 Literal<uint64_t> before_x(0x1234567890abcdef); 4434 Literal<uint32_t> before_w(0xfedcba09); 4435 Literal<uint64_t> before_q(0x1234000056780000, 0xabcd0000ef000000); 4436 Literal<double> before_d(1.234); 4437 Literal<float> before_s(2.5); 4438 4439 Literal<uint64_t> after_x(0x1234567890abcdef); 4440 Literal<uint32_t> after_w(0xfedcba09); 4441 Literal<uint64_t> after_q(0x1234000056780000, 0xabcd0000ef000000); 4442 Literal<double> after_d(1.234); 4443 Literal<float> after_s(2.5); 4444 4445 START(); 4446 4447 // Manually generate a pool. 4448 __ B(&end_of_pool_before); 4449 { 4450 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes); 4451 __ place(&before_x); 4452 __ place(&before_w); 4453 __ place(&before_q); 4454 __ place(&before_d); 4455 __ place(&before_s); 4456 } 4457 __ Bind(&end_of_pool_before); 4458 4459 // Load the entries several times to test that literals can be shared. 4460 for (int i = 0; i < 50; i++) { 4461 ExactAssemblyScope scope(&masm, 12 * kInstructionSize); 4462 __ ldr(x2, &before_x); 4463 __ ldr(w3, &before_w); 4464 __ ldrsw(x5, &before_w); // Re-use before_w. 4465 __ ldr(q11, &before_q); 4466 __ ldr(d13, &before_d); 4467 __ ldr(s25, &before_s); 4468 4469 __ ldr(x6, &after_x); 4470 __ ldr(w7, &after_w); 4471 __ ldrsw(x8, &after_w); // Re-use after_w. 4472 __ ldr(q18, &after_q); 4473 __ ldr(d14, &after_d); 4474 __ ldr(s26, &after_s); 4475 } 4476 4477 // Manually generate a pool. 4478 __ B(&end_of_pool_after); 4479 { 4480 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes); 4481 __ place(&after_x); 4482 __ place(&after_w); 4483 __ place(&after_q); 4484 __ place(&after_d); 4485 __ place(&after_s); 4486 } 4487 __ Bind(&end_of_pool_after); 4488 4489 END(); 4490 4491 if (CAN_RUN()) { 4492 RUN(); 4493 4494 ASSERT_EQUAL_64(0x1234567890abcdef, x2); 4495 ASSERT_EQUAL_64(0xfedcba09, x3); 4496 ASSERT_EQUAL_64(0xfffffffffedcba09, x5); 4497 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q11); 4498 ASSERT_EQUAL_FP64(1.234, d13); 4499 ASSERT_EQUAL_FP32(2.5, s25); 4500 4501 ASSERT_EQUAL_64(0x1234567890abcdef, x6); 4502 ASSERT_EQUAL_64(0xfedcba09, x7); 4503 ASSERT_EQUAL_64(0xfffffffffedcba09, x8); 4504 ASSERT_EQUAL_128(0x1234000056780000, 0xabcd0000ef000000, q18); 4505 ASSERT_EQUAL_FP64(1.234, d14); 4506 ASSERT_EQUAL_FP32(2.5, s26); 4507 } 4508} 4509 4510static const PrefetchOperation kPrfmOperations[] = {PLDL1KEEP, 4511 PLDL1STRM, 4512 PLDL2KEEP, 4513 PLDL2STRM, 4514 PLDL3KEEP, 4515 PLDL3STRM, 4516 4517 PLIL1KEEP, 4518 PLIL1STRM, 4519 PLIL2KEEP, 4520 PLIL2STRM, 4521 PLIL3KEEP, 4522 PLIL3STRM, 4523 4524 PSTL1KEEP, 4525 PSTL1STRM, 4526 PSTL2KEEP, 4527 PSTL2STRM, 4528 PSTL3KEEP, 4529 PSTL3STRM}; 4530 4531TEST(prfm_offset) { 4532 SETUP(); 4533 4534 START(); 4535 // The address used in prfm doesn't have to be valid. 4536 __ Mov(x0, 0x0123456789abcdef); 4537 4538 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) { 4539 // Unallocated prefetch operations are ignored, so test all of them. 4540 // We have to use the Assembler directly for this. 4541 ExactAssemblyScope guard(&masm, 3 * kInstructionSize); 4542 __ prfm(op, MemOperand(x0)); 4543 __ prfm(op, MemOperand(x0, 8)); 4544 __ prfm(op, MemOperand(x0, 32760)); 4545 } 4546 4547 for (PrefetchOperation op : kPrfmOperations) { 4548 // Also test named operations. 4549 __ Prfm(op, MemOperand(x0, 32768)); 4550 __ Prfm(op, MemOperand(x0, 1)); 4551 __ Prfm(op, MemOperand(x0, 9)); 4552 __ Prfm(op, MemOperand(x0, 255)); 4553 __ Prfm(op, MemOperand(x0, 257)); 4554 __ Prfm(op, MemOperand(x0, -1)); 4555 __ Prfm(op, MemOperand(x0, -9)); 4556 __ Prfm(op, MemOperand(x0, -255)); 4557 __ Prfm(op, MemOperand(x0, -257)); 4558 4559 __ Prfm(op, MemOperand(x0, 0xfedcba9876543210)); 4560 } 4561 4562 END(); 4563 if (CAN_RUN()) { 4564 RUN(); 4565 } 4566} 4567 4568 4569TEST(prfm_regoffset) { 4570 SETUP(); 4571 4572 START(); 4573 // The address used in prfm doesn't have to be valid. 4574 __ Mov(x0, 0x0123456789abcdef); 4575 4576 CPURegList inputs(CPURegister::kRegister, kXRegSize, 10, 18); 4577 __ Mov(x10, 0); 4578 __ Mov(x11, 1); 4579 __ Mov(x12, 8); 4580 __ Mov(x13, 255); 4581 __ Mov(x14, -0); 4582 __ Mov(x15, -1); 4583 __ Mov(x16, -8); 4584 __ Mov(x17, -255); 4585 __ Mov(x18, 0xfedcba9876543210); 4586 4587 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) { 4588 // Unallocated prefetch operations are ignored, so test all of them. 4589 // We have to use the Assembler directly for this. 4590 4591 // Prefetch operations of the form 0b11xxx are allocated to another 4592 // instruction. 4593 if (op >= 0b11000) continue; 4594 4595 ExactAssemblyScope guard(&masm, inputs.GetCount() * kInstructionSize); 4596 CPURegList loop = inputs; 4597 while (!loop.IsEmpty()) { 4598 __ prfm(op, MemOperand(x0, Register(loop.PopLowestIndex()))); 4599 } 4600 } 4601 4602 for (PrefetchOperation op : kPrfmOperations) { 4603 // Also test named operations. 4604 CPURegList loop = inputs; 4605 while (!loop.IsEmpty()) { 4606 Register input(loop.PopLowestIndex()); 4607 __ Prfm(op, MemOperand(x0, input, UXTW)); 4608 __ Prfm(op, MemOperand(x0, input, UXTW, 3)); 4609 __ Prfm(op, MemOperand(x0, input, LSL)); 4610 __ Prfm(op, MemOperand(x0, input, LSL, 3)); 4611 __ Prfm(op, MemOperand(x0, input, SXTW)); 4612 __ Prfm(op, MemOperand(x0, input, SXTW, 3)); 4613 __ Prfm(op, MemOperand(x0, input, SXTX)); 4614 __ Prfm(op, MemOperand(x0, input, SXTX, 3)); 4615 } 4616 } 4617 4618 END(); 4619 if (CAN_RUN()) { 4620 RUN(); 4621 } 4622} 4623 4624 4625TEST(prfm_literal_imm19) { 4626 SETUP(); 4627 START(); 4628 4629 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) { 4630 // Unallocated prefetch operations are ignored, so test all of them. 4631 // We have to use the Assembler directly for this. 4632 ExactAssemblyScope guard(&masm, 3 * kInstructionSize); 4633 __ prfm(op, INT64_C(0)); 4634 __ prfm(op, 1); 4635 __ prfm(op, -1); 4636 } 4637 4638 for (PrefetchOperation op : kPrfmOperations) { 4639 // Also test named operations. 4640 ExactAssemblyScope guard(&masm, 4 * kInstructionSize); 4641 // The address used in prfm doesn't have to be valid. 4642 __ prfm(op, 1000); 4643 __ prfm(op, -1000); 4644 __ prfm(op, 0x3ffff); 4645 __ prfm(op, -0x40000); 4646 } 4647 4648 END(); 4649 if (CAN_RUN()) { 4650 RUN(); 4651 } 4652} 4653 4654 4655TEST(prfm_literal) { 4656 SETUP(); 4657 4658 Label end_of_pool_before; 4659 Label end_of_pool_after; 4660 Literal<uint64_t> before(0); 4661 Literal<uint64_t> after(0); 4662 4663 START(); 4664 4665 // Manually generate a pool. 4666 __ B(&end_of_pool_before); 4667 { 4668 ExactAssemblyScope scope(&masm, before.GetSize()); 4669 __ place(&before); 4670 } 4671 __ Bind(&end_of_pool_before); 4672 4673 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) { 4674 // Unallocated prefetch operations are ignored, so test all of them. 4675 // We have to use the Assembler directly for this. 4676 ExactAssemblyScope guard(&masm, 2 * kInstructionSize); 4677 __ prfm(op, &before); 4678 __ prfm(op, &after); 4679 } 4680 4681 for (PrefetchOperation op : kPrfmOperations) { 4682 // Also test named operations. 4683 ExactAssemblyScope guard(&masm, 2 * kInstructionSize); 4684 __ prfm(op, &before); 4685 __ prfm(op, &after); 4686 } 4687 4688 // Manually generate a pool. 4689 __ B(&end_of_pool_after); 4690 { 4691 ExactAssemblyScope scope(&masm, after.GetSize()); 4692 __ place(&after); 4693 } 4694 __ Bind(&end_of_pool_after); 4695 4696 END(); 4697 if (CAN_RUN()) { 4698 RUN(); 4699 } 4700} 4701 4702 4703TEST(prfm_wide) { 4704 SETUP(); 4705 4706 START(); 4707 // The address used in prfm doesn't have to be valid. 4708 __ Mov(x0, 0x0123456789abcdef); 4709 4710 for (PrefetchOperation op : kPrfmOperations) { 4711 __ Prfm(op, MemOperand(x0, 0x40000)); 4712 __ Prfm(op, MemOperand(x0, -0x40001)); 4713 __ Prfm(op, MemOperand(x0, UINT64_C(0x5555555555555555))); 4714 __ Prfm(op, MemOperand(x0, UINT64_C(0xfedcba9876543210))); 4715 } 4716 4717 END(); 4718 if (CAN_RUN()) { 4719 RUN(); 4720 } 4721} 4722 4723 4724TEST(load_prfm_literal) { 4725 // Test literals shared between both prfm and ldr. 4726 SETUP_WITH_FEATURES(CPUFeatures::kFP); 4727 4728 Label end_of_pool_before; 4729 Label end_of_pool_after; 4730 4731 const size_t kSizeOfPoolInBytes = 28; 4732 4733 Literal<uint64_t> before_x(0x1234567890abcdef); 4734 Literal<uint32_t> before_w(0xfedcba09); 4735 Literal<uint32_t> before_sx(0x80000000); 4736 Literal<double> before_d(1.234); 4737 Literal<float> before_s(2.5); 4738 Literal<uint64_t> after_x(0x1234567890abcdef); 4739 Literal<uint32_t> after_w(0xfedcba09); 4740 Literal<uint32_t> after_sx(0x80000000); 4741 Literal<double> after_d(1.234); 4742 Literal<float> after_s(2.5); 4743 4744 START(); 4745 4746 // Manually generate a pool. 4747 __ B(&end_of_pool_before); 4748 { 4749 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes); 4750 __ place(&before_x); 4751 __ place(&before_w); 4752 __ place(&before_sx); 4753 __ place(&before_d); 4754 __ place(&before_s); 4755 } 4756 __ Bind(&end_of_pool_before); 4757 4758 for (int op = 0; op < (1 << ImmPrefetchOperation_width); op++) { 4759 // Unallocated prefetch operations are ignored, so test all of them. 4760 ExactAssemblyScope scope(&masm, 10 * kInstructionSize); 4761 4762 __ prfm(op, &before_x); 4763 __ prfm(op, &before_w); 4764 __ prfm(op, &before_sx); 4765 __ prfm(op, &before_d); 4766 __ prfm(op, &before_s); 4767 4768 __ prfm(op, &after_x); 4769 __ prfm(op, &after_w); 4770 __ prfm(op, &after_sx); 4771 __ prfm(op, &after_d); 4772 __ prfm(op, &after_s); 4773 } 4774 4775 for (PrefetchOperation op : kPrfmOperations) { 4776 // Also test named operations. 4777 ExactAssemblyScope scope(&masm, 10 * kInstructionSize); 4778 4779 __ prfm(op, &before_x); 4780 __ prfm(op, &before_w); 4781 __ prfm(op, &before_sx); 4782 __ prfm(op, &before_d); 4783 __ prfm(op, &before_s); 4784 4785 __ prfm(op, &after_x); 4786 __ prfm(op, &after_w); 4787 __ prfm(op, &after_sx); 4788 __ prfm(op, &after_d); 4789 __ prfm(op, &after_s); 4790 } 4791 4792 { 4793 ExactAssemblyScope scope(&masm, 10 * kInstructionSize); 4794 __ ldr(x2, &before_x); 4795 __ ldr(w3, &before_w); 4796 __ ldrsw(x5, &before_sx); 4797 __ ldr(d13, &before_d); 4798 __ ldr(s25, &before_s); 4799 4800 __ ldr(x6, &after_x); 4801 __ ldr(w7, &after_w); 4802 __ ldrsw(x8, &after_sx); 4803 __ ldr(d14, &after_d); 4804 __ ldr(s26, &after_s); 4805 } 4806 4807 // Manually generate a pool. 4808 __ B(&end_of_pool_after); 4809 { 4810 ExactAssemblyScope scope(&masm, kSizeOfPoolInBytes); 4811 __ place(&after_x); 4812 __ place(&after_w); 4813 __ place(&after_sx); 4814 __ place(&after_d); 4815 __ place(&after_s); 4816 } 4817 __ Bind(&end_of_pool_after); 4818 4819 END(); 4820 4821 if (CAN_RUN()) { 4822 RUN(); 4823 4824 ASSERT_EQUAL_64(0x1234567890abcdef, x2); 4825 ASSERT_EQUAL_64(0xfedcba09, x3); 4826 ASSERT_EQUAL_64(0xffffffff80000000, x5); 4827 ASSERT_EQUAL_FP64(1.234, d13); 4828 ASSERT_EQUAL_FP32(2.5, s25); 4829 4830 ASSERT_EQUAL_64(0x1234567890abcdef, x6); 4831 ASSERT_EQUAL_64(0xfedcba09, x7); 4832 ASSERT_EQUAL_64(0xffffffff80000000, x8); 4833 ASSERT_EQUAL_FP64(1.234, d14); 4834 ASSERT_EQUAL_FP32(2.5, s26); 4835 } 4836} 4837 4838 4839TEST(add_sub_imm) { 4840 SETUP(); 4841 4842 START(); 4843 __ Mov(x0, 0x0); 4844 __ Mov(x1, 0x1111); 4845 __ Mov(x2, 0xffffffffffffffff); 4846 __ Mov(x3, 0x8000000000000000); 4847 4848 __ Add(x10, x0, Operand(0x123)); 4849 __ Add(x11, x1, Operand(0x122000)); 4850 __ Add(x12, x0, Operand(0xabc << 12)); 4851 __ Add(x13, x2, Operand(1)); 4852 4853 __ Add(w14, w0, Operand(0x123)); 4854 __ Add(w15, w1, Operand(0x122000)); 4855 __ Add(w16, w0, Operand(0xabc << 12)); 4856 __ Add(w17, w2, Operand(1)); 4857 4858 __ Sub(x20, x0, Operand(0x1)); 4859 __ Sub(x21, x1, Operand(0x111)); 4860 __ Sub(x22, x1, Operand(0x1 << 12)); 4861 __ Sub(x23, x3, Operand(1)); 4862 4863 __ Sub(w24, w0, Operand(0x1)); 4864 __ Sub(w25, w1, Operand(0x111)); 4865 __ Sub(w26, w1, Operand(0x1 << 12)); 4866 __ Sub(w27, w3, Operand(1)); 4867 END(); 4868 4869 if (CAN_RUN()) { 4870 RUN(); 4871 4872 ASSERT_EQUAL_64(0x123, x10); 4873 ASSERT_EQUAL_64(0x123111, x11); 4874 ASSERT_EQUAL_64(0xabc000, x12); 4875 ASSERT_EQUAL_64(0x0, x13); 4876 4877 ASSERT_EQUAL_32(0x123, w14); 4878 ASSERT_EQUAL_32(0x123111, w15); 4879 ASSERT_EQUAL_32(0xabc000, w16); 4880 ASSERT_EQUAL_32(0x0, w17); 4881 4882 ASSERT_EQUAL_64(0xffffffffffffffff, x20); 4883 ASSERT_EQUAL_64(0x1000, x21); 4884 ASSERT_EQUAL_64(0x111, x22); 4885 ASSERT_EQUAL_64(0x7fffffffffffffff, x23); 4886 4887 ASSERT_EQUAL_32(0xffffffff, w24); 4888 ASSERT_EQUAL_32(0x1000, w25); 4889 ASSERT_EQUAL_32(0x111, w26); 4890 ASSERT_EQUAL_32(0xffffffff, w27); 4891 } 4892} 4893 4894 4895TEST(add_sub_wide_imm) { 4896 SETUP(); 4897 4898 START(); 4899 __ Mov(x0, 0x0); 4900 __ Mov(x1, 0x1); 4901 4902 __ Add(x10, x0, Operand(0x1234567890abcdef)); 4903 __ Add(x11, x1, Operand(0xffffffff)); 4904 4905 __ Add(w12, w0, Operand(0x12345678)); 4906 __ Add(w13, w1, Operand(0xffffffff)); 4907 4908 __ Add(w18, w0, Operand(kWMinInt)); 4909 __ Sub(w19, w0, Operand(kWMinInt)); 4910 4911 __ Sub(x20, x0, Operand(0x1234567890abcdef)); 4912 __ Sub(w21, w0, Operand(0x12345678)); 4913 4914 END(); 4915 4916 if (CAN_RUN()) { 4917 RUN(); 4918 4919 ASSERT_EQUAL_64(0x1234567890abcdef, x10); 4920 ASSERT_EQUAL_64(0x100000000, x11); 4921 4922 ASSERT_EQUAL_32(0x12345678, w12); 4923 ASSERT_EQUAL_64(0x0, x13); 4924 4925 ASSERT_EQUAL_32(kWMinInt, w18); 4926 ASSERT_EQUAL_32(kWMinInt, w19); 4927 4928 ASSERT_EQUAL_64(-0x1234567890abcdef, x20); 4929 ASSERT_EQUAL_32(-0x12345678, w21); 4930 } 4931} 4932 4933 4934TEST(add_sub_shifted) { 4935 SETUP(); 4936 4937 START(); 4938 __ Mov(x0, 0); 4939 __ Mov(x1, 0x0123456789abcdef); 4940 __ Mov(x2, 0xfedcba9876543210); 4941 __ Mov(x3, 0xffffffffffffffff); 4942 4943 __ Add(x10, x1, Operand(x2)); 4944 __ Add(x11, x0, Operand(x1, LSL, 8)); 4945 __ Add(x12, x0, Operand(x1, LSR, 8)); 4946 __ Add(x13, x0, Operand(x1, ASR, 8)); 4947 __ Add(x14, x0, Operand(x2, ASR, 8)); 4948 __ Add(w15, w0, Operand(w1, ASR, 8)); 4949 __ Add(w18, w3, Operand(w1, ROR, 8)); 4950 __ Add(x19, x3, Operand(x1, ROR, 8)); 4951 4952 __ Sub(x20, x3, Operand(x2)); 4953 __ Sub(x21, x3, Operand(x1, LSL, 8)); 4954 __ Sub(x22, x3, Operand(x1, LSR, 8)); 4955 __ Sub(x23, x3, Operand(x1, ASR, 8)); 4956 __ Sub(x24, x3, Operand(x2, ASR, 8)); 4957 __ Sub(w25, w3, Operand(w1, ASR, 8)); 4958 __ Sub(w26, w3, Operand(w1, ROR, 8)); 4959 __ Sub(x27, x3, Operand(x1, ROR, 8)); 4960 END(); 4961 4962 if (CAN_RUN()) { 4963 RUN(); 4964 4965 ASSERT_EQUAL_64(0xffffffffffffffff, x10); 4966 ASSERT_EQUAL_64(0x23456789abcdef00, x11); 4967 ASSERT_EQUAL_64(0x000123456789abcd, x12); 4968 ASSERT_EQUAL_64(0x000123456789abcd, x13); 4969 ASSERT_EQUAL_64(0xfffedcba98765432, x14); 4970 ASSERT_EQUAL_64(0xff89abcd, x15); 4971 ASSERT_EQUAL_64(0xef89abcc, x18); 4972 ASSERT_EQUAL_64(0xef0123456789abcc, x19); 4973 4974 ASSERT_EQUAL_64(0x0123456789abcdef, x20); 4975 ASSERT_EQUAL_64(0xdcba9876543210ff, x21); 4976 ASSERT_EQUAL_64(0xfffedcba98765432, x22); 4977 ASSERT_EQUAL_64(0xfffedcba98765432, x23); 4978 ASSERT_EQUAL_64(0x000123456789abcd, x24); 4979 ASSERT_EQUAL_64(0x00765432, x25); 4980 ASSERT_EQUAL_64(0x10765432, x26); 4981 ASSERT_EQUAL_64(0x10fedcba98765432, x27); 4982 } 4983} 4984 4985 4986TEST(add_sub_extended) { 4987 SETUP(); 4988 4989 START(); 4990 __ Mov(x0, 0); 4991 __ Mov(x1, 0x0123456789abcdef); 4992 __ Mov(x2, 0xfedcba9876543210); 4993 __ Mov(w3, 0x80); 4994 4995 __ Add(x10, x0, Operand(x1, UXTB, 0)); 4996 __ Add(x11, x0, Operand(x1, UXTB, 1)); 4997 __ Add(x12, x0, Operand(x1, UXTH, 2)); 4998 __ Add(x13, x0, Operand(x1, UXTW, 4)); 4999 5000 __ Add(x14, x0, Operand(x1, SXTB, 0)); 5001 __ Add(x15, x0, Operand(x1, SXTB, 1)); 5002 __ Add(x16, x0, Operand(x1, SXTH, 2)); 5003 __ Add(x17, x0, Operand(x1, SXTW, 3)); 5004 __ Add(x18, x0, Operand(x2, SXTB, 0)); 5005 __ Add(x19, x0, Operand(x2, SXTB, 1)); 5006 __ Add(x20, x0, Operand(x2, SXTH, 2)); 5007 __ Add(x21, x0, Operand(x2, SXTW, 3)); 5008 5009 __ Add(x22, x1, Operand(x2, SXTB, 1)); 5010 __ Sub(x23, x1, Operand(x2, SXTB, 1)); 5011 5012 __ Add(w24, w1, Operand(w2, UXTB, 2)); 5013 __ Add(w25, w0, Operand(w1, SXTB, 0)); 5014 __ Add(w26, w0, Operand(w1, SXTB, 1)); 5015 __ Add(w27, w2, Operand(w1, SXTW, 3)); 5016 5017 __ Add(w28, w0, Operand(w1, SXTW, 3)); 5018 __ Add(x29, x0, Operand(w1, SXTW, 3)); 5019 5020 __ Sub(x30, x0, Operand(w3, SXTB, 1)); 5021 END(); 5022 5023 if (CAN_RUN()) { 5024 RUN(); 5025 5026 ASSERT_EQUAL_64(0xef, x10); 5027 ASSERT_EQUAL_64(0x1de, x11); 5028 ASSERT_EQUAL_64(0x337bc, x12); 5029 ASSERT_EQUAL_64(0x89abcdef0, x13); 5030 5031 ASSERT_EQUAL_64(0xffffffffffffffef, x14); 5032 ASSERT_EQUAL_64(0xffffffffffffffde, x15); 5033 ASSERT_EQUAL_64(0xffffffffffff37bc, x16); 5034 ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x17); 5035 ASSERT_EQUAL_64(0x10, x18); 5036 ASSERT_EQUAL_64(0x20, x19); 5037 ASSERT_EQUAL_64(0xc840, x20); 5038 ASSERT_EQUAL_64(0x3b2a19080, x21); 5039 5040 ASSERT_EQUAL_64(0x0123456789abce0f, x22); 5041 ASSERT_EQUAL_64(0x0123456789abcdcf, x23); 5042 5043 ASSERT_EQUAL_32(0x89abce2f, w24); 5044 ASSERT_EQUAL_32(0xffffffef, w25); 5045 ASSERT_EQUAL_32(0xffffffde, w26); 5046 ASSERT_EQUAL_32(0xc3b2a188, w27); 5047 5048 ASSERT_EQUAL_32(0x4d5e6f78, w28); 5049 ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x29); 5050 5051 ASSERT_EQUAL_64(256, x30); 5052 } 5053} 5054 5055 5056TEST(add_sub_negative) { 5057 SETUP(); 5058 5059 START(); 5060 __ Mov(x0, 0); 5061 __ Mov(x1, 4687); 5062 __ Mov(x2, 0x1122334455667788); 5063 __ Mov(w3, 0x11223344); 5064 __ Mov(w4, 400000); 5065 5066 __ Add(x10, x0, -42); 5067 __ Add(x11, x1, -687); 5068 __ Add(x12, x2, -0x88); 5069 5070 __ Sub(x13, x0, -600); 5071 __ Sub(x14, x1, -313); 5072 __ Sub(x15, x2, -0x555); 5073 5074 __ Add(w19, w3, -0x344); 5075 __ Add(w20, w4, -2000); 5076 5077 __ Sub(w21, w3, -0xbc); 5078 __ Sub(w22, w4, -2000); 5079 END(); 5080 5081 if (CAN_RUN()) { 5082 RUN(); 5083 5084 ASSERT_EQUAL_64(-42, x10); 5085 ASSERT_EQUAL_64(4000, x11); 5086 ASSERT_EQUAL_64(0x1122334455667700, x12); 5087 5088 ASSERT_EQUAL_64(600, x13); 5089 ASSERT_EQUAL_64(5000, x14); 5090 ASSERT_EQUAL_64(0x1122334455667cdd, x15); 5091 5092 ASSERT_EQUAL_32(0x11223000, w19); 5093 ASSERT_EQUAL_32(398000, w20); 5094 5095 ASSERT_EQUAL_32(0x11223400, w21); 5096 ASSERT_EQUAL_32(402000, w22); 5097 } 5098} 5099 5100 5101TEST(add_sub_zero) { 5102 SETUP(); 5103 5104 START(); 5105 __ Mov(x0, 0); 5106 __ Mov(x1, 0); 5107 __ Mov(x2, 0); 5108 5109 Label blob1; 5110 __ Bind(&blob1); 5111 __ Add(x0, x0, 0); 5112 __ Sub(x1, x1, 0); 5113 __ Sub(x2, x2, xzr); 5114 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob1) == 0); 5115 5116 Label blob2; 5117 __ Bind(&blob2); 5118 __ Add(w3, w3, 0); 5119 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob2) != 0); 5120 5121 Label blob3; 5122 __ Bind(&blob3); 5123 __ Sub(w3, w3, wzr); 5124 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&blob3) != 0); 5125 5126 END(); 5127 5128 if (CAN_RUN()) { 5129 RUN(); 5130 5131 ASSERT_EQUAL_64(0, x0); 5132 ASSERT_EQUAL_64(0, x1); 5133 ASSERT_EQUAL_64(0, x2); 5134 } 5135} 5136 5137 5138TEST(claim_drop_zero) { 5139 SETUP(); 5140 5141 START(); 5142 5143 Label start; 5144 __ Bind(&start); 5145 __ Claim(Operand(0)); 5146 __ Drop(Operand(0)); 5147 __ Claim(Operand(xzr)); 5148 __ Drop(Operand(xzr)); 5149 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0); 5150 5151 END(); 5152 5153 if (CAN_RUN()) { 5154 RUN(); 5155 } 5156} 5157 5158 5159TEST(neg) { 5160 SETUP(); 5161 5162 START(); 5163 __ Mov(x0, 0xf123456789abcdef); 5164 5165 // Immediate. 5166 __ Neg(x1, 0x123); 5167 __ Neg(w2, 0x123); 5168 5169 // Shifted. 5170 __ Neg(x3, Operand(x0, LSL, 1)); 5171 __ Neg(w4, Operand(w0, LSL, 2)); 5172 __ Neg(x5, Operand(x0, LSR, 3)); 5173 __ Neg(w6, Operand(w0, LSR, 4)); 5174 __ Neg(x7, Operand(x0, ASR, 5)); 5175 __ Neg(w8, Operand(w0, ASR, 6)); 5176 5177 // Extended. 5178 __ Neg(w9, Operand(w0, UXTB)); 5179 __ Neg(x10, Operand(x0, SXTB, 1)); 5180 __ Neg(w11, Operand(w0, UXTH, 2)); 5181 __ Neg(x12, Operand(x0, SXTH, 3)); 5182 __ Neg(w13, Operand(w0, UXTW, 4)); 5183 __ Neg(x14, Operand(x0, SXTW, 4)); 5184 END(); 5185 5186 if (CAN_RUN()) { 5187 RUN(); 5188 5189 ASSERT_EQUAL_64(0xfffffffffffffedd, x1); 5190 ASSERT_EQUAL_64(0xfffffedd, x2); 5191 ASSERT_EQUAL_64(0x1db97530eca86422, x3); 5192 ASSERT_EQUAL_64(0xd950c844, x4); 5193 ASSERT_EQUAL_64(0xe1db97530eca8643, x5); 5194 ASSERT_EQUAL_64(0xf7654322, x6); 5195 ASSERT_EQUAL_64(0x0076e5d4c3b2a191, x7); 5196 ASSERT_EQUAL_64(0x01d950c9, x8); 5197 ASSERT_EQUAL_64(0xffffff11, x9); 5198 ASSERT_EQUAL_64(0x0000000000000022, x10); 5199 ASSERT_EQUAL_64(0xfffcc844, x11); 5200 ASSERT_EQUAL_64(0x0000000000019088, x12); 5201 ASSERT_EQUAL_64(0x65432110, x13); 5202 ASSERT_EQUAL_64(0x0000000765432110, x14); 5203 } 5204} 5205 5206 5207template <typename T, typename Op> 5208static void AdcsSbcsHelper( 5209 Op op, T left, T right, int carry, T expected, StatusFlags expected_flags) { 5210 int reg_size = sizeof(T) * 8; 5211 Register left_reg(0, reg_size); 5212 Register right_reg(1, reg_size); 5213 Register result_reg(2, reg_size); 5214 5215 SETUP(); 5216 START(); 5217 5218 __ Mov(left_reg, left); 5219 __ Mov(right_reg, right); 5220 __ Mov(x10, (carry ? CFlag : NoFlag)); 5221 5222 __ Msr(NZCV, x10); 5223 (masm.*op)(result_reg, left_reg, right_reg); 5224 5225 END(); 5226 if (CAN_RUN()) { 5227 RUN(); 5228 5229 ASSERT_EQUAL_64(left, left_reg.X()); 5230 ASSERT_EQUAL_64(right, right_reg.X()); 5231 ASSERT_EQUAL_64(expected, result_reg.X()); 5232 ASSERT_EQUAL_NZCV(expected_flags); 5233 } 5234} 5235 5236 5237TEST(adcs_sbcs_x) { 5238 uint64_t inputs[] = { 5239 0x0000000000000000, 5240 0x0000000000000001, 5241 0x7ffffffffffffffe, 5242 0x7fffffffffffffff, 5243 0x8000000000000000, 5244 0x8000000000000001, 5245 0xfffffffffffffffe, 5246 0xffffffffffffffff, 5247 }; 5248 static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]); 5249 5250 struct Expected { 5251 uint64_t carry0_result; 5252 StatusFlags carry0_flags; 5253 uint64_t carry1_result; 5254 StatusFlags carry1_flags; 5255 }; 5256 5257 static const Expected expected_adcs_x[input_count][input_count] = 5258 {{{0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}, 5259 {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}, 5260 {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}, 5261 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5262 {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}, 5263 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5264 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5265 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}}, 5266 {{0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}, 5267 {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag}, 5268 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5269 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, 5270 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5271 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, 5272 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5273 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}}, 5274 {{0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}, 5275 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5276 {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag}, 5277 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, 5278 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5279 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5280 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, 5281 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}}, 5282 {{0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5283 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, 5284 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, 5285 {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag}, 5286 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5287 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5288 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5289 {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}}, 5290 {{0x8000000000000000, NFlag, 0x8000000000000001, NFlag}, 5291 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5292 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5293 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5294 {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag}, 5295 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, 5296 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, 5297 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}}, 5298 {{0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5299 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, 5300 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5301 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5302 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, 5303 {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag}, 5304 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5305 {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}}, 5306 {{0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5307 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5308 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, 5309 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5310 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, 5311 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5312 {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag}, 5313 {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}}, 5314 {{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5315 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5316 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5317 {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}, 5318 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5319 {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}, 5320 {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}, 5321 {0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}}}; 5322 5323 static const Expected expected_sbcs_x[input_count][input_count] = 5324 {{{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5325 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5326 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5327 {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}, 5328 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5329 {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}, 5330 {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}, 5331 {0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}}, 5332 {{0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5333 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5334 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, 5335 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5336 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, 5337 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5338 {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag}, 5339 {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}}, 5340 {{0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5341 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, 5342 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5343 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5344 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, 5345 {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag}, 5346 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, 5347 {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}}, 5348 {{0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}, 5349 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5350 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5351 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5352 {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag}, 5353 {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, 5354 {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, 5355 {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}}, 5356 {{0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5357 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, 5358 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, 5359 {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag}, 5360 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5361 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, 5362 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, 5363 {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}}, 5364 {{0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}, 5365 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5366 {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag}, 5367 {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, 5368 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5369 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5370 {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, 5371 {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}}, 5372 {{0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}, 5373 {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag}, 5374 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5375 {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, 5376 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5377 {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, 5378 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, 5379 {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}}, 5380 {{0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}, 5381 {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}, 5382 {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}, 5383 {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, 5384 {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}, 5385 {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, 5386 {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, 5387 {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}}}; 5388 5389 for (size_t left = 0; left < input_count; left++) { 5390 for (size_t right = 0; right < input_count; right++) { 5391 const Expected& expected = expected_adcs_x[left][right]; 5392 AdcsSbcsHelper(&MacroAssembler::Adcs, 5393 inputs[left], 5394 inputs[right], 5395 0, 5396 expected.carry0_result, 5397 expected.carry0_flags); 5398 AdcsSbcsHelper(&MacroAssembler::Adcs, 5399 inputs[left], 5400 inputs[right], 5401 1, 5402 expected.carry1_result, 5403 expected.carry1_flags); 5404 } 5405 } 5406 5407 for (size_t left = 0; left < input_count; left++) { 5408 for (size_t right = 0; right < input_count; right++) { 5409 const Expected& expected = expected_sbcs_x[left][right]; 5410 AdcsSbcsHelper(&MacroAssembler::Sbcs, 5411 inputs[left], 5412 inputs[right], 5413 0, 5414 expected.carry0_result, 5415 expected.carry0_flags); 5416 AdcsSbcsHelper(&MacroAssembler::Sbcs, 5417 inputs[left], 5418 inputs[right], 5419 1, 5420 expected.carry1_result, 5421 expected.carry1_flags); 5422 } 5423 } 5424} 5425 5426 5427TEST(adcs_sbcs_w) { 5428 uint32_t inputs[] = { 5429 0x00000000, 5430 0x00000001, 5431 0x7ffffffe, 5432 0x7fffffff, 5433 0x80000000, 5434 0x80000001, 5435 0xfffffffe, 5436 0xffffffff, 5437 }; 5438 static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]); 5439 5440 struct Expected { 5441 uint32_t carry0_result; 5442 StatusFlags carry0_flags; 5443 uint32_t carry1_result; 5444 StatusFlags carry1_flags; 5445 }; 5446 5447 static const Expected expected_adcs_w[input_count][input_count] = 5448 {{{0x00000000, ZFlag, 0x00000001, NoFlag}, 5449 {0x00000001, NoFlag, 0x00000002, NoFlag}, 5450 {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}, 5451 {0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5452 {0x80000000, NFlag, 0x80000001, NFlag}, 5453 {0x80000001, NFlag, 0x80000002, NFlag}, 5454 {0xfffffffe, NFlag, 0xffffffff, NFlag}, 5455 {0xffffffff, NFlag, 0x00000000, ZCFlag}}, 5456 {{0x00000001, NoFlag, 0x00000002, NoFlag}, 5457 {0x00000002, NoFlag, 0x00000003, NoFlag}, 5458 {0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5459 {0x80000000, NVFlag, 0x80000001, NVFlag}, 5460 {0x80000001, NFlag, 0x80000002, NFlag}, 5461 {0x80000002, NFlag, 0x80000003, NFlag}, 5462 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5463 {0x00000000, ZCFlag, 0x00000001, CFlag}}, 5464 {{0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}, 5465 {0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5466 {0xfffffffc, NVFlag, 0xfffffffd, NVFlag}, 5467 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, 5468 {0xfffffffe, NFlag, 0xffffffff, NFlag}, 5469 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5470 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, 5471 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}}, 5472 {{0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5473 {0x80000000, NVFlag, 0x80000001, NVFlag}, 5474 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, 5475 {0xfffffffe, NVFlag, 0xffffffff, NVFlag}, 5476 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5477 {0x00000000, ZCFlag, 0x00000001, CFlag}, 5478 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5479 {0x7ffffffe, CFlag, 0x7fffffff, CFlag}}, 5480 {{0x80000000, NFlag, 0x80000001, NFlag}, 5481 {0x80000001, NFlag, 0x80000002, NFlag}, 5482 {0xfffffffe, NFlag, 0xffffffff, NFlag}, 5483 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5484 {0x00000000, ZCVFlag, 0x00000001, CVFlag}, 5485 {0x00000001, CVFlag, 0x00000002, CVFlag}, 5486 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, 5487 {0x7fffffff, CVFlag, 0x80000000, NCFlag}}, 5488 {{0x80000001, NFlag, 0x80000002, NFlag}, 5489 {0x80000002, NFlag, 0x80000003, NFlag}, 5490 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5491 {0x00000000, ZCFlag, 0x00000001, CFlag}, 5492 {0x00000001, CVFlag, 0x00000002, CVFlag}, 5493 {0x00000002, CVFlag, 0x00000003, CVFlag}, 5494 {0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5495 {0x80000000, NCFlag, 0x80000001, NCFlag}}, 5496 {{0xfffffffe, NFlag, 0xffffffff, NFlag}, 5497 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5498 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, 5499 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5500 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, 5501 {0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5502 {0xfffffffc, NCFlag, 0xfffffffd, NCFlag}, 5503 {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}}, 5504 {{0xffffffff, NFlag, 0x00000000, ZCFlag}, 5505 {0x00000000, ZCFlag, 0x00000001, CFlag}, 5506 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5507 {0x7ffffffe, CFlag, 0x7fffffff, CFlag}, 5508 {0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5509 {0x80000000, NCFlag, 0x80000001, NCFlag}, 5510 {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}, 5511 {0xfffffffe, NCFlag, 0xffffffff, NCFlag}}}; 5512 5513 static const Expected expected_sbcs_w[input_count][input_count] = 5514 {{{0xffffffff, NFlag, 0x00000000, ZCFlag}, 5515 {0xfffffffe, NFlag, 0xffffffff, NFlag}, 5516 {0x80000001, NFlag, 0x80000002, NFlag}, 5517 {0x80000000, NFlag, 0x80000001, NFlag}, 5518 {0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5519 {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}, 5520 {0x00000001, NoFlag, 0x00000002, NoFlag}, 5521 {0x00000000, ZFlag, 0x00000001, NoFlag}}, 5522 {{0x00000000, ZCFlag, 0x00000001, CFlag}, 5523 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5524 {0x80000002, NFlag, 0x80000003, NFlag}, 5525 {0x80000001, NFlag, 0x80000002, NFlag}, 5526 {0x80000000, NVFlag, 0x80000001, NVFlag}, 5527 {0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5528 {0x00000002, NoFlag, 0x00000003, NoFlag}, 5529 {0x00000001, NoFlag, 0x00000002, NoFlag}}, 5530 {{0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5531 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, 5532 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5533 {0xfffffffe, NFlag, 0xffffffff, NFlag}, 5534 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, 5535 {0xfffffffc, NVFlag, 0xfffffffd, NVFlag}, 5536 {0x7fffffff, NoFlag, 0x80000000, NVFlag}, 5537 {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}}, 5538 {{0x7ffffffe, CFlag, 0x7fffffff, CFlag}, 5539 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5540 {0x00000000, ZCFlag, 0x00000001, CFlag}, 5541 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5542 {0xfffffffe, NVFlag, 0xffffffff, NVFlag}, 5543 {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, 5544 {0x80000000, NVFlag, 0x80000001, NVFlag}, 5545 {0x7fffffff, NoFlag, 0x80000000, NVFlag}}, 5546 {{0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5547 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, 5548 {0x00000001, CVFlag, 0x00000002, CVFlag}, 5549 {0x00000000, ZCVFlag, 0x00000001, CVFlag}, 5550 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5551 {0xfffffffe, NFlag, 0xffffffff, NFlag}, 5552 {0x80000001, NFlag, 0x80000002, NFlag}, 5553 {0x80000000, NFlag, 0x80000001, NFlag}}, 5554 {{0x80000000, NCFlag, 0x80000001, NCFlag}, 5555 {0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5556 {0x00000002, CVFlag, 0x00000003, CVFlag}, 5557 {0x00000001, CVFlag, 0x00000002, CVFlag}, 5558 {0x00000000, ZCFlag, 0x00000001, CFlag}, 5559 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5560 {0x80000002, NFlag, 0x80000003, NFlag}, 5561 {0x80000001, NFlag, 0x80000002, NFlag}}, 5562 {{0xfffffffd, NCFlag, 0xfffffffe, NCFlag}, 5563 {0xfffffffc, NCFlag, 0xfffffffd, NCFlag}, 5564 {0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5565 {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, 5566 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5567 {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, 5568 {0xffffffff, NFlag, 0x00000000, ZCFlag}, 5569 {0xfffffffe, NFlag, 0xffffffff, NFlag}}, 5570 {{0xfffffffe, NCFlag, 0xffffffff, NCFlag}, 5571 {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}, 5572 {0x80000000, NCFlag, 0x80000001, NCFlag}, 5573 {0x7fffffff, CVFlag, 0x80000000, NCFlag}, 5574 {0x7ffffffe, CFlag, 0x7fffffff, CFlag}, 5575 {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, 5576 {0x00000000, ZCFlag, 0x00000001, CFlag}, 5577 {0xffffffff, NFlag, 0x00000000, ZCFlag}}}; 5578 5579 for (size_t left = 0; left < input_count; left++) { 5580 for (size_t right = 0; right < input_count; right++) { 5581 const Expected& expected = expected_adcs_w[left][right]; 5582 AdcsSbcsHelper(&MacroAssembler::Adcs, 5583 inputs[left], 5584 inputs[right], 5585 0, 5586 expected.carry0_result, 5587 expected.carry0_flags); 5588 AdcsSbcsHelper(&MacroAssembler::Adcs, 5589 inputs[left], 5590 inputs[right], 5591 1, 5592 expected.carry1_result, 5593 expected.carry1_flags); 5594 } 5595 } 5596 5597 for (size_t left = 0; left < input_count; left++) { 5598 for (size_t right = 0; right < input_count; right++) { 5599 const Expected& expected = expected_sbcs_w[left][right]; 5600 AdcsSbcsHelper(&MacroAssembler::Sbcs, 5601 inputs[left], 5602 inputs[right], 5603 0, 5604 expected.carry0_result, 5605 expected.carry0_flags); 5606 AdcsSbcsHelper(&MacroAssembler::Sbcs, 5607 inputs[left], 5608 inputs[right], 5609 1, 5610 expected.carry1_result, 5611 expected.carry1_flags); 5612 } 5613 } 5614} 5615 5616 5617TEST(adc_sbc_shift) { 5618 SETUP(); 5619 5620 START(); 5621 __ Mov(x0, 0); 5622 __ Mov(x1, 1); 5623 __ Mov(x2, 0x0123456789abcdef); 5624 __ Mov(x3, 0xfedcba9876543210); 5625 __ Mov(x4, 0xffffffffffffffff); 5626 5627 // Clear the C flag. 5628 __ Adds(x0, x0, Operand(0)); 5629 5630 __ Adc(x5, x2, Operand(x3)); 5631 __ Adc(x6, x0, Operand(x1, LSL, 60)); 5632 __ Sbc(x7, x4, Operand(x3, LSR, 4)); 5633 __ Adc(x8, x2, Operand(x3, ASR, 4)); 5634 __ Adc(x9, x2, Operand(x3, ROR, 8)); 5635 5636 __ Adc(w10, w2, Operand(w3)); 5637 __ Adc(w11, w0, Operand(w1, LSL, 30)); 5638 __ Sbc(w12, w4, Operand(w3, LSR, 4)); 5639 __ Adc(w13, w2, Operand(w3, ASR, 4)); 5640 __ Adc(w14, w2, Operand(w3, ROR, 8)); 5641 5642 // Set the C flag. 5643 __ Cmp(w0, Operand(w0)); 5644 5645 __ Adc(x18, x2, Operand(x3)); 5646 __ Adc(x19, x0, Operand(x1, LSL, 60)); 5647 __ Sbc(x20, x4, Operand(x3, LSR, 4)); 5648 __ Adc(x21, x2, Operand(x3, ASR, 4)); 5649 __ Adc(x22, x2, Operand(x3, ROR, 8)); 5650 5651 __ Adc(w23, w2, Operand(w3)); 5652 __ Adc(w24, w0, Operand(w1, LSL, 30)); 5653 __ Sbc(w25, w4, Operand(w3, LSR, 4)); 5654 __ Adc(w26, w2, Operand(w3, ASR, 4)); 5655 __ Adc(w27, w2, Operand(w3, ROR, 8)); 5656 END(); 5657 5658 if (CAN_RUN()) { 5659 RUN(); 5660 5661 ASSERT_EQUAL_64(0xffffffffffffffff, x5); 5662 ASSERT_EQUAL_64(INT64_C(1) << 60, x6); 5663 ASSERT_EQUAL_64(0xf0123456789abcdd, x7); 5664 ASSERT_EQUAL_64(0x0111111111111110, x8); 5665 ASSERT_EQUAL_64(0x1222222222222221, x9); 5666 5667 ASSERT_EQUAL_32(0xffffffff, w10); 5668 ASSERT_EQUAL_32(INT32_C(1) << 30, w11); 5669 ASSERT_EQUAL_32(0xf89abcdd, w12); 5670 ASSERT_EQUAL_32(0x91111110, w13); 5671 ASSERT_EQUAL_32(0x9a222221, w14); 5672 5673 ASSERT_EQUAL_64(0xffffffffffffffff + 1, x18); 5674 ASSERT_EQUAL_64((INT64_C(1) << 60) + 1, x19); 5675 ASSERT_EQUAL_64(0xf0123456789abcdd + 1, x20); 5676 ASSERT_EQUAL_64(0x0111111111111110 + 1, x21); 5677 ASSERT_EQUAL_64(0x1222222222222221 + 1, x22); 5678 5679 ASSERT_EQUAL_32(0xffffffff + 1, w23); 5680 ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, w24); 5681 ASSERT_EQUAL_32(0xf89abcdd + 1, w25); 5682 ASSERT_EQUAL_32(0x91111110 + 1, w26); 5683 ASSERT_EQUAL_32(0x9a222221 + 1, w27); 5684 } 5685} 5686 5687 5688TEST(adc_sbc_extend) { 5689 SETUP(); 5690 5691 START(); 5692 // Clear the C flag. 5693 __ Adds(x0, x0, Operand(0)); 5694 5695 __ Mov(x0, 0); 5696 __ Mov(x1, 1); 5697 __ Mov(x2, 0x0123456789abcdef); 5698 5699 __ Adc(x10, x1, Operand(w2, UXTB, 1)); 5700 __ Adc(x11, x1, Operand(x2, SXTH, 2)); 5701 __ Sbc(x12, x1, Operand(w2, UXTW, 4)); 5702 __ Adc(x13, x1, Operand(x2, UXTX, 4)); 5703 5704 __ Adc(w14, w1, Operand(w2, UXTB, 1)); 5705 __ Adc(w15, w1, Operand(w2, SXTH, 2)); 5706 __ Adc(w9, w1, Operand(w2, UXTW, 4)); 5707 5708 // Set the C flag. 5709 __ Cmp(w0, Operand(w0)); 5710 5711 __ Adc(x20, x1, Operand(w2, UXTB, 1)); 5712 __ Adc(x21, x1, Operand(x2, SXTH, 2)); 5713 __ Sbc(x22, x1, Operand(w2, UXTW, 4)); 5714 __ Adc(x23, x1, Operand(x2, UXTX, 4)); 5715 5716 __ Adc(w24, w1, Operand(w2, UXTB, 1)); 5717 __ Adc(w25, w1, Operand(w2, SXTH, 2)); 5718 __ Adc(w26, w1, Operand(w2, UXTW, 4)); 5719 END(); 5720 5721 if (CAN_RUN()) { 5722 RUN(); 5723 5724 ASSERT_EQUAL_64(0x1df, x10); 5725 ASSERT_EQUAL_64(0xffffffffffff37bd, x11); 5726 ASSERT_EQUAL_64(0xfffffff765432110, x12); 5727 ASSERT_EQUAL_64(0x123456789abcdef1, x13); 5728 5729 ASSERT_EQUAL_32(0x1df, w14); 5730 ASSERT_EQUAL_32(0xffff37bd, w15); 5731 ASSERT_EQUAL_32(0x9abcdef1, w9); 5732 5733 ASSERT_EQUAL_64(0x1df + 1, x20); 5734 ASSERT_EQUAL_64(0xffffffffffff37bd + 1, x21); 5735 ASSERT_EQUAL_64(0xfffffff765432110 + 1, x22); 5736 ASSERT_EQUAL_64(0x123456789abcdef1 + 1, x23); 5737 5738 ASSERT_EQUAL_32(0x1df + 1, w24); 5739 ASSERT_EQUAL_32(0xffff37bd + 1, w25); 5740 ASSERT_EQUAL_32(0x9abcdef1 + 1, w26); 5741 } 5742 5743 // Check that adc correctly sets the condition flags. 5744 START(); 5745 __ Mov(x0, 0xff); 5746 __ Mov(x1, 0xffffffffffffffff); 5747 // Clear the C flag. 5748 __ Adds(x0, x0, Operand(0)); 5749 __ Adcs(x10, x0, Operand(x1, SXTX, 1)); 5750 END(); 5751 5752 if (CAN_RUN()) { 5753 RUN(); 5754 5755 ASSERT_EQUAL_NZCV(CFlag); 5756 } 5757 5758 START(); 5759 __ Mov(x0, 0x7fffffffffffffff); 5760 __ Mov(x1, 1); 5761 // Clear the C flag. 5762 __ Adds(x0, x0, Operand(0)); 5763 __ Adcs(x10, x0, Operand(x1, UXTB, 2)); 5764 END(); 5765 5766 if (CAN_RUN()) { 5767 RUN(); 5768 5769 ASSERT_EQUAL_NZCV(NVFlag); 5770 } 5771 5772 START(); 5773 __ Mov(x0, 0x7fffffffffffffff); 5774 // Clear the C flag. 5775 __ Adds(x0, x0, Operand(0)); 5776 __ Adcs(x10, x0, Operand(1)); 5777 END(); 5778 5779 if (CAN_RUN()) { 5780 RUN(); 5781 5782 ASSERT_EQUAL_NZCV(NVFlag); 5783 } 5784} 5785 5786 5787TEST(adc_sbc_wide_imm) { 5788 SETUP(); 5789 5790 START(); 5791 __ Mov(x0, 0); 5792 5793 // Clear the C flag. 5794 __ Adds(x0, x0, Operand(0)); 5795 5796 __ Adc(x7, x0, Operand(0x1234567890abcdef)); 5797 __ Adc(w8, w0, Operand(0xffffffff)); 5798 __ Sbc(x9, x0, Operand(0x1234567890abcdef)); 5799 __ Sbc(w10, w0, Operand(0xffffffff)); 5800 __ Ngc(x11, Operand(0xffffffff00000000)); 5801 __ Ngc(w12, Operand(0xffff0000)); 5802 5803 // Set the C flag. 5804 __ Cmp(w0, Operand(w0)); 5805 5806 __ Adc(x18, x0, Operand(0x1234567890abcdef)); 5807 __ Adc(w19, w0, Operand(0xffffffff)); 5808 __ Sbc(x20, x0, Operand(0x1234567890abcdef)); 5809 __ Sbc(w21, w0, Operand(0xffffffff)); 5810 __ Ngc(x22, Operand(0xffffffff00000000)); 5811 __ Ngc(w23, Operand(0xffff0000)); 5812 END(); 5813 5814 if (CAN_RUN()) { 5815 RUN(); 5816 5817 ASSERT_EQUAL_64(0x1234567890abcdef, x7); 5818 ASSERT_EQUAL_64(0xffffffff, x8); 5819 ASSERT_EQUAL_64(0xedcba9876f543210, x9); 5820 ASSERT_EQUAL_64(0, x10); 5821 ASSERT_EQUAL_64(0xffffffff, x11); 5822 ASSERT_EQUAL_64(0xffff, x12); 5823 5824 ASSERT_EQUAL_64(0x1234567890abcdef + 1, x18); 5825 ASSERT_EQUAL_64(0, x19); 5826 ASSERT_EQUAL_64(0xedcba9876f543211, x20); 5827 ASSERT_EQUAL_64(1, x21); 5828 ASSERT_EQUAL_64(0x0000000100000000, x22); 5829 ASSERT_EQUAL_64(0x0000000000010000, x23); 5830 } 5831} 5832 5833 5834TEST(rmif) { 5835 SETUP_WITH_FEATURES(CPUFeatures::kFlagM); 5836 5837 START(); 5838 __ Mov(x0, 0x0123456789abcdef); 5839 5840 // Set NZCV to 0b1011 (0xb) 5841 __ Rmif(x0, 0, NCVFlag); 5842 __ Mrs(x1, NZCV); 5843 5844 // Set NZCV to 0b0111 (0x7) 5845 __ Rmif(x0, 6, NZCVFlag); 5846 __ Mrs(x2, NZCV); 5847 5848 // Set Z to 0, NZCV = 0b0011 (0x3) 5849 __ Rmif(x0, 60, ZFlag); 5850 __ Mrs(x3, NZCV); 5851 5852 // Set N to 1 and C to 0, NZCV = 0b1001 (0x9) 5853 __ Rmif(x0, 62, NCFlag); 5854 __ Mrs(x4, NZCV); 5855 5856 // No change to NZCV 5857 __ Rmif(x0, 0, NoFlag); 5858 __ Mrs(x5, NZCV); 5859 END(); 5860 5861 if (CAN_RUN()) { 5862 RUN(); 5863 ASSERT_EQUAL_32(NCVFlag, w1); 5864 ASSERT_EQUAL_32(ZCVFlag, w2); 5865 ASSERT_EQUAL_32(CVFlag, w3); 5866 ASSERT_EQUAL_32(NVFlag, w4); 5867 ASSERT_EQUAL_32(NVFlag, w5); 5868 } 5869} 5870 5871 5872TEST(setf8_setf16) { 5873 SETUP_WITH_FEATURES(CPUFeatures::kFlagM); 5874 5875 START(); 5876 __ Mov(x0, 0x0); 5877 __ Mov(x1, 0x1); 5878 __ Mov(x2, 0xff); 5879 __ Mov(x3, 0x100); 5880 __ Mov(x4, 0x101); 5881 __ Mov(x5, 0xffff); 5882 __ Mov(x6, 0x10000); 5883 __ Mov(x7, 0x10001); 5884 __ Mov(x8, 0xfffffffff); 5885 5886 __ Setf8(w0); 5887 __ Mrs(x9, NZCV); 5888 __ Setf8(w1); 5889 __ Mrs(x10, NZCV); 5890 __ Setf8(w2); 5891 __ Mrs(x11, NZCV); 5892 __ Setf8(w3); 5893 __ Mrs(x12, NZCV); 5894 __ Setf8(w4); 5895 __ Mrs(x13, NZCV); 5896 __ Setf8(w8); 5897 __ Mrs(x14, NZCV); 5898 5899 __ Setf16(w0); 5900 __ Mrs(x15, NZCV); 5901 __ Setf16(w1); 5902 __ Mrs(x16, NZCV); 5903 __ Setf16(w5); 5904 __ Mrs(x17, NZCV); 5905 __ Setf16(w6); 5906 __ Mrs(x18, NZCV); 5907 __ Setf16(w7); 5908 __ Mrs(x19, NZCV); 5909 __ Setf16(w8); 5910 __ Mrs(x20, NZCV); 5911 END(); 5912 5913 if (CAN_RUN()) { 5914 RUN(); 5915 5916 ASSERT_EQUAL_32(ZFlag, w9); // Zero 5917 ASSERT_EQUAL_32(NoFlag, w10); // Regular int8 5918 ASSERT_EQUAL_32(NVFlag, w11); // Negative but not sign-extended (overflow) 5919 ASSERT_EQUAL_32(ZVFlag, w12); // Overflow with zero remainder 5920 ASSERT_EQUAL_32(VFlag, w13); // Overflow with non-zero remainder 5921 ASSERT_EQUAL_32(NFlag, w14); // Negative and sign-extended 5922 5923 ASSERT_EQUAL_32(ZFlag, w15); // Zero 5924 ASSERT_EQUAL_32(NoFlag, w16); // Regular int16 5925 ASSERT_EQUAL_32(NVFlag, w17); // Negative but not sign-extended (overflow) 5926 ASSERT_EQUAL_32(ZVFlag, w18); // Overflow with zero remainder 5927 ASSERT_EQUAL_32(VFlag, w19); // Overflow with non-zero remainder 5928 ASSERT_EQUAL_32(NFlag, w20); // Negative and sign-extended 5929 } 5930} 5931 5932 5933TEST(flags) { 5934 SETUP(); 5935 5936 START(); 5937 __ Mov(x0, 0); 5938 __ Mov(x1, 0x1111111111111111); 5939 __ Neg(x10, Operand(x0)); 5940 __ Neg(x11, Operand(x1)); 5941 __ Neg(w12, Operand(w1)); 5942 // Clear the C flag. 5943 __ Adds(x0, x0, Operand(0)); 5944 __ Ngc(x13, Operand(x0)); 5945 // Set the C flag. 5946 __ Cmp(x0, Operand(x0)); 5947 __ Ngc(w14, Operand(w0)); 5948 END(); 5949 5950 if (CAN_RUN()) { 5951 RUN(); 5952 5953 ASSERT_EQUAL_64(0, x10); 5954 ASSERT_EQUAL_64(-0x1111111111111111, x11); 5955 ASSERT_EQUAL_32(-0x11111111, w12); 5956 ASSERT_EQUAL_64(-1, x13); 5957 ASSERT_EQUAL_32(0, w14); 5958 } 5959 5960 START(); 5961 __ Mov(x0, 0); 5962 __ Cmp(x0, Operand(x0)); 5963 END(); 5964 5965 if (CAN_RUN()) { 5966 RUN(); 5967 5968 ASSERT_EQUAL_NZCV(ZCFlag); 5969 } 5970 5971 START(); 5972 __ Mov(w0, 0); 5973 __ Cmp(w0, Operand(w0)); 5974 END(); 5975 5976 if (CAN_RUN()) { 5977 RUN(); 5978 5979 ASSERT_EQUAL_NZCV(ZCFlag); 5980 } 5981 5982 START(); 5983 __ Mov(x0, 0); 5984 __ Mov(x1, 0x1111111111111111); 5985 __ Cmp(x0, Operand(x1)); 5986 END(); 5987 5988 if (CAN_RUN()) { 5989 RUN(); 5990 5991 ASSERT_EQUAL_NZCV(NFlag); 5992 } 5993 5994 START(); 5995 __ Mov(w0, 0); 5996 __ Mov(w1, 0x11111111); 5997 __ Cmp(w0, Operand(w1)); 5998 END(); 5999 6000 if (CAN_RUN()) { 6001 RUN(); 6002 6003 ASSERT_EQUAL_NZCV(NFlag); 6004 } 6005 6006 START(); 6007 __ Mov(x1, 0x1111111111111111); 6008 __ Cmp(x1, Operand(0)); 6009 END(); 6010 6011 if (CAN_RUN()) { 6012 RUN(); 6013 6014 ASSERT_EQUAL_NZCV(CFlag); 6015 } 6016 6017 START(); 6018 __ Mov(w1, 0x11111111); 6019 __ Cmp(w1, Operand(0)); 6020 END(); 6021 6022 if (CAN_RUN()) { 6023 RUN(); 6024 6025 ASSERT_EQUAL_NZCV(CFlag); 6026 } 6027 6028 START(); 6029 __ Mov(x0, 1); 6030 __ Mov(x1, 0x7fffffffffffffff); 6031 __ Cmn(x1, Operand(x0)); 6032 END(); 6033 6034 if (CAN_RUN()) { 6035 RUN(); 6036 6037 ASSERT_EQUAL_NZCV(NVFlag); 6038 } 6039 6040 START(); 6041 __ Mov(w0, 1); 6042 __ Mov(w1, 0x7fffffff); 6043 __ Cmn(w1, Operand(w0)); 6044 END(); 6045 6046 if (CAN_RUN()) { 6047 RUN(); 6048 6049 ASSERT_EQUAL_NZCV(NVFlag); 6050 } 6051 6052 START(); 6053 __ Mov(x0, 1); 6054 __ Mov(x1, 0xffffffffffffffff); 6055 __ Cmn(x1, Operand(x0)); 6056 END(); 6057 6058 if (CAN_RUN()) { 6059 RUN(); 6060 6061 ASSERT_EQUAL_NZCV(ZCFlag); 6062 } 6063 6064 START(); 6065 __ Mov(w0, 1); 6066 __ Mov(w1, 0xffffffff); 6067 __ Cmn(w1, Operand(w0)); 6068 END(); 6069 6070 if (CAN_RUN()) { 6071 RUN(); 6072 6073 ASSERT_EQUAL_NZCV(ZCFlag); 6074 } 6075 6076 START(); 6077 __ Mov(w0, 0); 6078 __ Mov(w1, 1); 6079 // Clear the C flag. 6080 __ Adds(w0, w0, Operand(0)); 6081 __ Ngcs(w0, Operand(w1)); 6082 END(); 6083 6084 if (CAN_RUN()) { 6085 RUN(); 6086 6087 ASSERT_EQUAL_NZCV(NFlag); 6088 } 6089 6090 START(); 6091 __ Mov(w0, 0); 6092 __ Mov(w1, 0); 6093 // Set the C flag. 6094 __ Cmp(w0, Operand(w0)); 6095 __ Ngcs(w0, Operand(w1)); 6096 END(); 6097 6098 if (CAN_RUN()) { 6099 RUN(); 6100 6101 ASSERT_EQUAL_NZCV(ZCFlag); 6102 } 6103} 6104 6105 6106TEST(cmp_shift) { 6107 SETUP(); 6108 6109 START(); 6110 __ Mov(x18, 0xf0000000); 6111 __ Mov(x19, 0xf000000010000000); 6112 __ Mov(x20, 0xf0000000f0000000); 6113 __ Mov(x21, 0x7800000078000000); 6114 __ Mov(x22, 0x3c0000003c000000); 6115 __ Mov(x23, 0x8000000780000000); 6116 __ Mov(x24, 0x0000000f00000000); 6117 __ Mov(x25, 0x00000003c0000000); 6118 __ Mov(x26, 0x8000000780000000); 6119 __ Mov(x27, 0xc0000003); 6120 6121 __ Cmp(w20, Operand(w21, LSL, 1)); 6122 __ Mrs(x0, NZCV); 6123 6124 __ Cmp(x20, Operand(x22, LSL, 2)); 6125 __ Mrs(x1, NZCV); 6126 6127 __ Cmp(w19, Operand(w23, LSR, 3)); 6128 __ Mrs(x2, NZCV); 6129 6130 __ Cmp(x18, Operand(x24, LSR, 4)); 6131 __ Mrs(x3, NZCV); 6132 6133 __ Cmp(w20, Operand(w25, ASR, 2)); 6134 __ Mrs(x4, NZCV); 6135 6136 __ Cmp(x20, Operand(x26, ASR, 3)); 6137 __ Mrs(x5, NZCV); 6138 6139 __ Cmp(w27, Operand(w22, ROR, 28)); 6140 __ Mrs(x6, NZCV); 6141 6142 __ Cmp(x20, Operand(x21, ROR, 31)); 6143 __ Mrs(x7, NZCV); 6144 END(); 6145 6146 if (CAN_RUN()) { 6147 RUN(); 6148 6149 ASSERT_EQUAL_32(ZCFlag, w0); 6150 ASSERT_EQUAL_32(ZCFlag, w1); 6151 ASSERT_EQUAL_32(ZCFlag, w2); 6152 ASSERT_EQUAL_32(ZCFlag, w3); 6153 ASSERT_EQUAL_32(ZCFlag, w4); 6154 ASSERT_EQUAL_32(ZCFlag, w5); 6155 ASSERT_EQUAL_32(ZCFlag, w6); 6156 ASSERT_EQUAL_32(ZCFlag, w7); 6157 } 6158} 6159 6160 6161TEST(cmp_extend) { 6162 SETUP(); 6163 6164 START(); 6165 __ Mov(w20, 0x2); 6166 __ Mov(w21, 0x1); 6167 __ Mov(x22, 0xffffffffffffffff); 6168 __ Mov(x23, 0xff); 6169 __ Mov(x24, 0xfffffffffffffffe); 6170 __ Mov(x25, 0xffff); 6171 __ Mov(x26, 0xffffffff); 6172 6173 __ Cmp(w20, Operand(w21, LSL, 1)); 6174 __ Mrs(x0, NZCV); 6175 6176 __ Cmp(x22, Operand(x23, SXTB, 0)); 6177 __ Mrs(x1, NZCV); 6178 6179 __ Cmp(x24, Operand(x23, SXTB, 1)); 6180 __ Mrs(x2, NZCV); 6181 6182 __ Cmp(x24, Operand(x23, UXTB, 1)); 6183 __ Mrs(x3, NZCV); 6184 6185 __ Cmp(w22, Operand(w25, UXTH)); 6186 __ Mrs(x4, NZCV); 6187 6188 __ Cmp(x22, Operand(x25, SXTH)); 6189 __ Mrs(x5, NZCV); 6190 6191 __ Cmp(x22, Operand(x26, UXTW)); 6192 __ Mrs(x6, NZCV); 6193 6194 __ Cmp(x24, Operand(x26, SXTW, 1)); 6195 __ Mrs(x7, NZCV); 6196 END(); 6197 6198 if (CAN_RUN()) { 6199 RUN(); 6200 6201 ASSERT_EQUAL_32(ZCFlag, w0); 6202 ASSERT_EQUAL_32(ZCFlag, w1); 6203 ASSERT_EQUAL_32(ZCFlag, w2); 6204 ASSERT_EQUAL_32(NCFlag, w3); 6205 ASSERT_EQUAL_32(NCFlag, w4); 6206 ASSERT_EQUAL_32(ZCFlag, w5); 6207 ASSERT_EQUAL_32(NCFlag, w6); 6208 ASSERT_EQUAL_32(ZCFlag, w7); 6209 } 6210} 6211 6212 6213TEST(ccmp) { 6214 SETUP(); 6215 6216 START(); 6217 __ Mov(w16, 0); 6218 __ Mov(w17, 1); 6219 __ Cmp(w16, w16); 6220 __ Ccmp(w16, w17, NCFlag, eq); 6221 __ Mrs(x0, NZCV); 6222 6223 __ Cmp(w16, w16); 6224 __ Ccmp(w16, w17, NCFlag, ne); 6225 __ Mrs(x1, NZCV); 6226 6227 __ Cmp(x16, x16); 6228 __ Ccmn(x16, 2, NZCVFlag, eq); 6229 __ Mrs(x2, NZCV); 6230 6231 __ Cmp(x16, x16); 6232 __ Ccmn(x16, 2, NZCVFlag, ne); 6233 __ Mrs(x3, NZCV); 6234 6235 // The MacroAssembler does not allow al as a condition. 6236 { 6237 ExactAssemblyScope scope(&masm, kInstructionSize); 6238 __ ccmp(x16, x16, NZCVFlag, al); 6239 } 6240 __ Mrs(x4, NZCV); 6241 6242 // The MacroAssembler does not allow nv as a condition. 6243 { 6244 ExactAssemblyScope scope(&masm, kInstructionSize); 6245 __ ccmp(x16, x16, NZCVFlag, nv); 6246 } 6247 __ Mrs(x5, NZCV); 6248 6249 END(); 6250 6251 if (CAN_RUN()) { 6252 RUN(); 6253 6254 ASSERT_EQUAL_32(NFlag, w0); 6255 ASSERT_EQUAL_32(NCFlag, w1); 6256 ASSERT_EQUAL_32(NoFlag, w2); 6257 ASSERT_EQUAL_32(NZCVFlag, w3); 6258 ASSERT_EQUAL_32(ZCFlag, w4); 6259 ASSERT_EQUAL_32(ZCFlag, w5); 6260 } 6261} 6262 6263 6264TEST(ccmp_wide_imm) { 6265 SETUP(); 6266 6267 START(); 6268 __ Mov(w20, 0); 6269 6270 __ Cmp(w20, Operand(w20)); 6271 __ Ccmp(w20, Operand(0x12345678), NZCVFlag, eq); 6272 __ Mrs(x0, NZCV); 6273 6274 __ Cmp(w20, Operand(w20)); 6275 __ Ccmp(x20, Operand(0xffffffffffffffff), NZCVFlag, eq); 6276 __ Mrs(x1, NZCV); 6277 END(); 6278 6279 if (CAN_RUN()) { 6280 RUN(); 6281 6282 ASSERT_EQUAL_32(NFlag, w0); 6283 ASSERT_EQUAL_32(NoFlag, w1); 6284 } 6285} 6286 6287 6288TEST(ccmp_shift_extend) { 6289 SETUP(); 6290 6291 START(); 6292 __ Mov(w20, 0x2); 6293 __ Mov(w21, 0x1); 6294 __ Mov(x22, 0xffffffffffffffff); 6295 __ Mov(x23, 0xff); 6296 __ Mov(x24, 0xfffffffffffffffe); 6297 6298 __ Cmp(w20, Operand(w20)); 6299 __ Ccmp(w20, Operand(w21, LSL, 1), NZCVFlag, eq); 6300 __ Mrs(x0, NZCV); 6301 6302 __ Cmp(w20, Operand(w20)); 6303 __ Ccmp(x22, Operand(x23, SXTB, 0), NZCVFlag, eq); 6304 __ Mrs(x1, NZCV); 6305 6306 __ Cmp(w20, Operand(w20)); 6307 __ Ccmp(x24, Operand(x23, SXTB, 1), NZCVFlag, eq); 6308 __ Mrs(x2, NZCV); 6309 6310 __ Cmp(w20, Operand(w20)); 6311 __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, eq); 6312 __ Mrs(x3, NZCV); 6313 6314 __ Cmp(w20, Operand(w20)); 6315 __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, ne); 6316 __ Mrs(x4, NZCV); 6317 END(); 6318 6319 if (CAN_RUN()) { 6320 RUN(); 6321 6322 ASSERT_EQUAL_32(ZCFlag, w0); 6323 ASSERT_EQUAL_32(ZCFlag, w1); 6324 ASSERT_EQUAL_32(ZCFlag, w2); 6325 ASSERT_EQUAL_32(NCFlag, w3); 6326 ASSERT_EQUAL_32(NZCVFlag, w4); 6327 } 6328} 6329 6330 6331TEST(csel_reg) { 6332 SETUP(); 6333 6334 START(); 6335 __ Mov(x16, 0); 6336 __ Mov(x24, 0x0000000f0000000f); 6337 __ Mov(x25, 0x0000001f0000001f); 6338 6339 __ Cmp(w16, Operand(0)); 6340 __ Csel(w0, w24, w25, eq); 6341 __ Csel(w1, w24, w25, ne); 6342 __ Csinc(w2, w24, w25, mi); 6343 __ Csinc(w3, w24, w25, pl); 6344 6345 // The MacroAssembler does not allow al or nv as a condition. 6346 { 6347 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 6348 __ csel(w13, w24, w25, al); 6349 __ csel(x14, x24, x25, nv); 6350 } 6351 6352 __ Cmp(x16, Operand(1)); 6353 __ Csinv(x4, x24, x25, gt); 6354 __ Csinv(x5, x24, x25, le); 6355 __ Csneg(x6, x24, x25, hs); 6356 __ Csneg(x7, x24, x25, lo); 6357 6358 __ Cset(w8, ne); 6359 __ Csetm(w9, ne); 6360 __ Cinc(x10, x25, ne); 6361 __ Cinv(x11, x24, ne); 6362 __ Cneg(x12, x24, ne); 6363 6364 // The MacroAssembler does not allow al or nv as a condition. 6365 { 6366 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 6367 __ csel(w15, w24, w25, al); 6368 __ csel(x17, x24, x25, nv); 6369 } 6370 6371 END(); 6372 6373 if (CAN_RUN()) { 6374 RUN(); 6375 6376 ASSERT_EQUAL_64(0x0000000f, x0); 6377 ASSERT_EQUAL_64(0x0000001f, x1); 6378 ASSERT_EQUAL_64(0x00000020, x2); 6379 ASSERT_EQUAL_64(0x0000000f, x3); 6380 ASSERT_EQUAL_64(0xffffffe0ffffffe0, x4); 6381 ASSERT_EQUAL_64(0x0000000f0000000f, x5); 6382 ASSERT_EQUAL_64(0xffffffe0ffffffe1, x6); 6383 ASSERT_EQUAL_64(0x0000000f0000000f, x7); 6384 ASSERT_EQUAL_64(0x00000001, x8); 6385 ASSERT_EQUAL_64(0xffffffff, x9); 6386 ASSERT_EQUAL_64(0x0000001f00000020, x10); 6387 ASSERT_EQUAL_64(0xfffffff0fffffff0, x11); 6388 ASSERT_EQUAL_64(0xfffffff0fffffff1, x12); 6389 ASSERT_EQUAL_64(0x0000000f, x13); 6390 ASSERT_EQUAL_64(0x0000000f0000000f, x14); 6391 ASSERT_EQUAL_64(0x0000000f, x15); 6392 ASSERT_EQUAL_64(0x0000000f0000000f, x17); 6393 } 6394} 6395 6396TEST(csel_zero) { 6397 SETUP(); 6398 6399 START(); 6400 6401 __ Mov(x15, 0x0); 6402 __ Mov(x16, 0x0000001f0000002f); 6403 6404 // Check results when zero registers are used as inputs 6405 // for Csinc, Csinv and Csneg for both true and false conditions. 6406 __ Cmp(x15, 0); 6407 __ Csinc(x0, x16, xzr, eq); 6408 __ Csinc(x1, xzr, x16, eq); 6409 __ Cmp(x15, 1); 6410 __ Csinc(w2, w16, wzr, eq); 6411 __ Csinc(w3, wzr, w16, eq); 6412 6413 __ Csinc(x4, xzr, xzr, eq); 6414 6415 __ Cmp(x15, 0); 6416 __ Csinv(x5, x16, xzr, eq); 6417 __ Csinv(x6, xzr, x16, eq); 6418 __ Cmp(x15, 1); 6419 __ Csinv(w7, w16, wzr, eq); 6420 __ Csinv(w8, wzr, w16, eq); 6421 6422 __ Csinv(x9, xzr, xzr, eq); 6423 6424 __ Cmp(x15, 0); 6425 __ Csneg(x10, x16, xzr, eq); 6426 __ Csneg(x11, xzr, x16, eq); 6427 __ Cmp(x15, 1); 6428 __ Csneg(w12, w16, wzr, eq); 6429 __ Csneg(w13, wzr, w16, eq); 6430 6431 __ Csneg(x14, xzr, xzr, eq); 6432 6433 END(); 6434 6435 if (CAN_RUN()) { 6436 RUN(); 6437 6438 ASSERT_EQUAL_64(0x0000001f0000002f, x0); 6439 ASSERT_EQUAL_64(0x0, x1); 6440 ASSERT_EQUAL_32(0x1, w2); 6441 ASSERT_EQUAL_32(0x30, w3); 6442 ASSERT_EQUAL_64(0x1, x4); 6443 ASSERT_EQUAL_64(0x0000001f0000002f, x5); 6444 ASSERT_EQUAL_64(0x0, x6); 6445 ASSERT_EQUAL_32(0xffffffff, w7); 6446 ASSERT_EQUAL_32(0xffffffd0, w8); 6447 ASSERT_EQUAL_64(0xffffffffffffffff, x9); 6448 ASSERT_EQUAL_64(0x0000001f0000002f, x10); 6449 ASSERT_EQUAL_64(0x0, x11); 6450 ASSERT_EQUAL_32(0x0, w12); 6451 ASSERT_EQUAL_32(0xffffffd1, w13); 6452 ASSERT_EQUAL_64(0x0, x14); 6453 } 6454} 6455 6456 6457TEST(csel_imm) { 6458 SETUP(); 6459 6460 int values[] = {-123, -2, -1, 0, 1, 2, 123}; 6461 int n_values = sizeof(values) / sizeof(values[0]); 6462 6463 for (int i = 0; i < n_values; i++) { 6464 for (int j = 0; j < n_values; j++) { 6465 int left = values[i]; 6466 int right = values[j]; 6467 6468 START(); 6469 __ Mov(x10, 0); 6470 __ Cmp(x10, 0); 6471 __ Csel(w0, left, right, eq); 6472 __ Csel(w1, left, right, ne); 6473 __ Csel(x2, left, right, eq); 6474 __ Csel(x3, left, right, ne); 6475 6476 END(); 6477 6478 if (CAN_RUN()) { 6479 RUN(); 6480 6481 ASSERT_EQUAL_32(left, w0); 6482 ASSERT_EQUAL_32(right, w1); 6483 ASSERT_EQUAL_64(left, x2); 6484 ASSERT_EQUAL_64(right, x3); 6485 } 6486 } 6487 } 6488} 6489 6490 6491TEST(csel_mixed) { 6492 SETUP(); 6493 6494 START(); 6495 __ Mov(x18, 0); 6496 __ Mov(x19, 0x80000000); 6497 __ Mov(x20, 0x8000000000000000); 6498 6499 __ Cmp(x18, Operand(0)); 6500 __ Csel(w0, w19, -2, ne); 6501 __ Csel(w1, w19, -1, ne); 6502 __ Csel(w2, w19, 0, ne); 6503 __ Csel(w3, w19, 1, ne); 6504 __ Csel(w4, w19, 2, ne); 6505 __ Csel(w5, w19, Operand(w19, ASR, 31), ne); 6506 __ Csel(w6, w19, Operand(w19, ROR, 1), ne); 6507 __ Csel(w7, w19, 3, eq); 6508 6509 __ Csel(x8, x20, -2, ne); 6510 __ Csel(x9, x20, -1, ne); 6511 __ Csel(x10, x20, 0, ne); 6512 __ Csel(x11, x20, 1, ne); 6513 __ Csel(x12, x20, 2, ne); 6514 __ Csel(x13, x20, Operand(x20, ASR, 63), ne); 6515 __ Csel(x14, x20, Operand(x20, ROR, 1), ne); 6516 __ Csel(x15, x20, 3, eq); 6517 6518 END(); 6519 6520 if (CAN_RUN()) { 6521 RUN(); 6522 6523 ASSERT_EQUAL_32(-2, w0); 6524 ASSERT_EQUAL_32(-1, w1); 6525 ASSERT_EQUAL_32(0, w2); 6526 ASSERT_EQUAL_32(1, w3); 6527 ASSERT_EQUAL_32(2, w4); 6528 ASSERT_EQUAL_32(-1, w5); 6529 ASSERT_EQUAL_32(0x40000000, w6); 6530 ASSERT_EQUAL_32(0x80000000, w7); 6531 6532 ASSERT_EQUAL_64(-2, x8); 6533 ASSERT_EQUAL_64(-1, x9); 6534 ASSERT_EQUAL_64(0, x10); 6535 ASSERT_EQUAL_64(1, x11); 6536 ASSERT_EQUAL_64(2, x12); 6537 ASSERT_EQUAL_64(-1, x13); 6538 ASSERT_EQUAL_64(0x4000000000000000, x14); 6539 ASSERT_EQUAL_64(0x8000000000000000, x15); 6540 } 6541} 6542 6543 6544TEST(lslv) { 6545 SETUP(); 6546 6547 uint64_t value = 0x0123456789abcdef; 6548 int shift[] = {1, 3, 5, 9, 17, 33}; 6549 6550 START(); 6551 __ Mov(x0, value); 6552 __ Mov(w1, shift[0]); 6553 __ Mov(w2, shift[1]); 6554 __ Mov(w3, shift[2]); 6555 __ Mov(w4, shift[3]); 6556 __ Mov(w5, shift[4]); 6557 __ Mov(w6, shift[5]); 6558 6559 // The MacroAssembler does not allow zr as an argument. 6560 { 6561 ExactAssemblyScope scope(&masm, kInstructionSize); 6562 __ lslv(x0, x0, xzr); 6563 } 6564 6565 __ Lsl(x16, x0, x1); 6566 __ Lsl(x17, x0, x2); 6567 __ Lsl(x18, x0, x3); 6568 __ Lsl(x19, x0, x4); 6569 __ Lsl(x20, x0, x5); 6570 __ Lsl(x21, x0, x6); 6571 6572 __ Lsl(w22, w0, w1); 6573 __ Lsl(w23, w0, w2); 6574 __ Lsl(w24, w0, w3); 6575 __ Lsl(w25, w0, w4); 6576 __ Lsl(w26, w0, w5); 6577 __ Lsl(w27, w0, w6); 6578 END(); 6579 6580 if (CAN_RUN()) { 6581 RUN(); 6582 6583 ASSERT_EQUAL_64(value, x0); 6584 ASSERT_EQUAL_64(value << (shift[0] & 63), x16); 6585 ASSERT_EQUAL_64(value << (shift[1] & 63), x17); 6586 ASSERT_EQUAL_64(value << (shift[2] & 63), x18); 6587 ASSERT_EQUAL_64(value << (shift[3] & 63), x19); 6588 ASSERT_EQUAL_64(value << (shift[4] & 63), x20); 6589 ASSERT_EQUAL_64(value << (shift[5] & 63), x21); 6590 ASSERT_EQUAL_32(value << (shift[0] & 31), w22); 6591 ASSERT_EQUAL_32(value << (shift[1] & 31), w23); 6592 ASSERT_EQUAL_32(value << (shift[2] & 31), w24); 6593 ASSERT_EQUAL_32(value << (shift[3] & 31), w25); 6594 ASSERT_EQUAL_32(value << (shift[4] & 31), w26); 6595 ASSERT_EQUAL_32(value << (shift[5] & 31), w27); 6596 } 6597} 6598 6599 6600TEST(lsrv) { 6601 SETUP(); 6602 6603 uint64_t value = 0x0123456789abcdef; 6604 int shift[] = {1, 3, 5, 9, 17, 33}; 6605 6606 START(); 6607 __ Mov(x0, value); 6608 __ Mov(w1, shift[0]); 6609 __ Mov(w2, shift[1]); 6610 __ Mov(w3, shift[2]); 6611 __ Mov(w4, shift[3]); 6612 __ Mov(w5, shift[4]); 6613 __ Mov(w6, shift[5]); 6614 6615 // The MacroAssembler does not allow zr as an argument. 6616 { 6617 ExactAssemblyScope scope(&masm, kInstructionSize); 6618 __ lsrv(x0, x0, xzr); 6619 } 6620 6621 __ Lsr(x16, x0, x1); 6622 __ Lsr(x17, x0, x2); 6623 __ Lsr(x18, x0, x3); 6624 __ Lsr(x19, x0, x4); 6625 __ Lsr(x20, x0, x5); 6626 __ Lsr(x21, x0, x6); 6627 6628 __ Lsr(w22, w0, w1); 6629 __ Lsr(w23, w0, w2); 6630 __ Lsr(w24, w0, w3); 6631 __ Lsr(w25, w0, w4); 6632 __ Lsr(w26, w0, w5); 6633 __ Lsr(w27, w0, w6); 6634 END(); 6635 6636 if (CAN_RUN()) { 6637 RUN(); 6638 6639 ASSERT_EQUAL_64(value, x0); 6640 ASSERT_EQUAL_64(value >> (shift[0] & 63), x16); 6641 ASSERT_EQUAL_64(value >> (shift[1] & 63), x17); 6642 ASSERT_EQUAL_64(value >> (shift[2] & 63), x18); 6643 ASSERT_EQUAL_64(value >> (shift[3] & 63), x19); 6644 ASSERT_EQUAL_64(value >> (shift[4] & 63), x20); 6645 ASSERT_EQUAL_64(value >> (shift[5] & 63), x21); 6646 6647 value &= 0xffffffff; 6648 ASSERT_EQUAL_32(value >> (shift[0] & 31), w22); 6649 ASSERT_EQUAL_32(value >> (shift[1] & 31), w23); 6650 ASSERT_EQUAL_32(value >> (shift[2] & 31), w24); 6651 ASSERT_EQUAL_32(value >> (shift[3] & 31), w25); 6652 ASSERT_EQUAL_32(value >> (shift[4] & 31), w26); 6653 ASSERT_EQUAL_32(value >> (shift[5] & 31), w27); 6654 } 6655} 6656 6657 6658TEST(asrv) { 6659 SETUP(); 6660 6661 int64_t value = 0xfedcba98fedcba98; 6662 int shift[] = {1, 3, 5, 9, 17, 33}; 6663 6664 START(); 6665 __ Mov(x0, value); 6666 __ Mov(w1, shift[0]); 6667 __ Mov(w2, shift[1]); 6668 __ Mov(w3, shift[2]); 6669 __ Mov(w4, shift[3]); 6670 __ Mov(w5, shift[4]); 6671 __ Mov(w6, shift[5]); 6672 6673 // The MacroAssembler does not allow zr as an argument. 6674 { 6675 ExactAssemblyScope scope(&masm, kInstructionSize); 6676 __ asrv(x0, x0, xzr); 6677 } 6678 6679 __ Asr(x16, x0, x1); 6680 __ Asr(x17, x0, x2); 6681 __ Asr(x18, x0, x3); 6682 __ Asr(x19, x0, x4); 6683 __ Asr(x20, x0, x5); 6684 __ Asr(x21, x0, x6); 6685 6686 __ Asr(w22, w0, w1); 6687 __ Asr(w23, w0, w2); 6688 __ Asr(w24, w0, w3); 6689 __ Asr(w25, w0, w4); 6690 __ Asr(w26, w0, w5); 6691 __ Asr(w27, w0, w6); 6692 END(); 6693 6694 if (CAN_RUN()) { 6695 RUN(); 6696 6697 ASSERT_EQUAL_64(value, x0); 6698 ASSERT_EQUAL_64(value >> (shift[0] & 63), x16); 6699 ASSERT_EQUAL_64(value >> (shift[1] & 63), x17); 6700 ASSERT_EQUAL_64(value >> (shift[2] & 63), x18); 6701 ASSERT_EQUAL_64(value >> (shift[3] & 63), x19); 6702 ASSERT_EQUAL_64(value >> (shift[4] & 63), x20); 6703 ASSERT_EQUAL_64(value >> (shift[5] & 63), x21); 6704 6705 int32_t value32 = static_cast<int32_t>(value & 0xffffffff); 6706 ASSERT_EQUAL_32(value32 >> (shift[0] & 31), w22); 6707 ASSERT_EQUAL_32(value32 >> (shift[1] & 31), w23); 6708 ASSERT_EQUAL_32(value32 >> (shift[2] & 31), w24); 6709 ASSERT_EQUAL_32(value32 >> (shift[3] & 31), w25); 6710 ASSERT_EQUAL_32(value32 >> (shift[4] & 31), w26); 6711 ASSERT_EQUAL_32(value32 >> (shift[5] & 31), w27); 6712 } 6713} 6714 6715 6716TEST(rorv) { 6717 SETUP(); 6718 6719 uint64_t value = 0x0123456789abcdef; 6720 int shift[] = {4, 8, 12, 16, 24, 36}; 6721 6722 START(); 6723 __ Mov(x0, value); 6724 __ Mov(w1, shift[0]); 6725 __ Mov(w2, shift[1]); 6726 __ Mov(w3, shift[2]); 6727 __ Mov(w4, shift[3]); 6728 __ Mov(w5, shift[4]); 6729 __ Mov(w6, shift[5]); 6730 6731 // The MacroAssembler does not allow zr as an argument. 6732 { 6733 ExactAssemblyScope scope(&masm, kInstructionSize); 6734 __ rorv(x0, x0, xzr); 6735 } 6736 6737 __ Ror(x16, x0, x1); 6738 __ Ror(x17, x0, x2); 6739 __ Ror(x18, x0, x3); 6740 __ Ror(x19, x0, x4); 6741 __ Ror(x20, x0, x5); 6742 __ Ror(x21, x0, x6); 6743 6744 __ Ror(w22, w0, w1); 6745 __ Ror(w23, w0, w2); 6746 __ Ror(w24, w0, w3); 6747 __ Ror(w25, w0, w4); 6748 __ Ror(w26, w0, w5); 6749 __ Ror(w27, w0, w6); 6750 END(); 6751 6752 if (CAN_RUN()) { 6753 RUN(); 6754 6755 ASSERT_EQUAL_64(value, x0); 6756 ASSERT_EQUAL_64(0xf0123456789abcde, x16); 6757 ASSERT_EQUAL_64(0xef0123456789abcd, x17); 6758 ASSERT_EQUAL_64(0xdef0123456789abc, x18); 6759 ASSERT_EQUAL_64(0xcdef0123456789ab, x19); 6760 ASSERT_EQUAL_64(0xabcdef0123456789, x20); 6761 ASSERT_EQUAL_64(0x789abcdef0123456, x21); 6762 ASSERT_EQUAL_32(0xf89abcde, w22); 6763 ASSERT_EQUAL_32(0xef89abcd, w23); 6764 ASSERT_EQUAL_32(0xdef89abc, w24); 6765 ASSERT_EQUAL_32(0xcdef89ab, w25); 6766 ASSERT_EQUAL_32(0xabcdef89, w26); 6767 ASSERT_EQUAL_32(0xf89abcde, w27); 6768 } 6769} 6770 6771 6772TEST(bfm) { 6773 SETUP(); 6774 6775 START(); 6776 __ Mov(x1, 0x0123456789abcdef); 6777 6778 __ Mov(x10, 0x8888888888888888); 6779 __ Mov(x11, 0x8888888888888888); 6780 __ Mov(x12, 0x8888888888888888); 6781 __ Mov(x13, 0x8888888888888888); 6782 __ Mov(x14, 0xffffffffffffffff); 6783 __ Mov(w20, 0x88888888); 6784 __ Mov(w21, 0x88888888); 6785 6786 __ Bfm(x10, x1, 16, 31); 6787 __ Bfm(x11, x1, 32, 15); 6788 6789 __ Bfm(w20, w1, 16, 23); 6790 __ Bfm(w21, w1, 24, 15); 6791 6792 // Aliases. 6793 __ Bfi(x12, x1, 16, 8); 6794 __ Bfxil(x13, x1, 16, 8); 6795 __ Bfc(x14, 16, 8); 6796 END(); 6797 6798 if (CAN_RUN()) { 6799 RUN(); 6800 6801 6802 ASSERT_EQUAL_64(0x88888888888889ab, x10); 6803 ASSERT_EQUAL_64(0x8888cdef88888888, x11); 6804 6805 ASSERT_EQUAL_32(0x888888ab, w20); 6806 ASSERT_EQUAL_32(0x88cdef88, w21); 6807 6808 ASSERT_EQUAL_64(0x8888888888ef8888, x12); 6809 ASSERT_EQUAL_64(0x88888888888888ab, x13); 6810 ASSERT_EQUAL_64(0xffffffffff00ffff, x14); 6811 } 6812} 6813 6814 6815TEST(sbfm) { 6816 SETUP(); 6817 6818 START(); 6819 __ Mov(x1, 0x0123456789abcdef); 6820 __ Mov(x2, 0xfedcba9876543210); 6821 6822 __ Sbfm(x10, x1, 16, 31); 6823 __ Sbfm(x11, x1, 32, 15); 6824 __ Sbfm(x12, x1, 32, 47); 6825 __ Sbfm(x13, x1, 48, 35); 6826 6827 __ Sbfm(w14, w1, 16, 23); 6828 __ Sbfm(w15, w1, 24, 15); 6829 __ Sbfm(w16, w2, 16, 23); 6830 __ Sbfm(w17, w2, 24, 15); 6831 6832 // Aliases. 6833 __ Asr(x18, x1, 32); 6834 __ Asr(x19, x2, 32); 6835 __ Sbfiz(x20, x1, 8, 16); 6836 __ Sbfiz(x21, x2, 8, 16); 6837 __ Sbfx(x22, x1, 8, 16); 6838 __ Sbfx(x23, x2, 8, 16); 6839 __ Sxtb(x24, w1); 6840 __ Sxtb(x25, x2); 6841 __ Sxth(x26, w1); 6842 __ Sxth(x27, x2); 6843 __ Sxtw(x28, w1); 6844 __ Sxtw(x29, x2); 6845 END(); 6846 6847 if (CAN_RUN()) { 6848 RUN(); 6849 6850 6851 ASSERT_EQUAL_64(0xffffffffffff89ab, x10); 6852 ASSERT_EQUAL_64(0xffffcdef00000000, x11); 6853 ASSERT_EQUAL_64(0x0000000000004567, x12); 6854 ASSERT_EQUAL_64(0x000789abcdef0000, x13); 6855 6856 ASSERT_EQUAL_32(0xffffffab, w14); 6857 ASSERT_EQUAL_32(0xffcdef00, w15); 6858 ASSERT_EQUAL_32(0x00000054, w16); 6859 ASSERT_EQUAL_32(0x00321000, w17); 6860 6861 ASSERT_EQUAL_64(0x0000000001234567, x18); 6862 ASSERT_EQUAL_64(0xfffffffffedcba98, x19); 6863 ASSERT_EQUAL_64(0xffffffffffcdef00, x20); 6864 ASSERT_EQUAL_64(0x0000000000321000, x21); 6865 ASSERT_EQUAL_64(0xffffffffffffabcd, x22); 6866 ASSERT_EQUAL_64(0x0000000000005432, x23); 6867 ASSERT_EQUAL_64(0xffffffffffffffef, x24); 6868 ASSERT_EQUAL_64(0x0000000000000010, x25); 6869 ASSERT_EQUAL_64(0xffffffffffffcdef, x26); 6870 ASSERT_EQUAL_64(0x0000000000003210, x27); 6871 ASSERT_EQUAL_64(0xffffffff89abcdef, x28); 6872 ASSERT_EQUAL_64(0x0000000076543210, x29); 6873 } 6874} 6875 6876 6877TEST(ubfm) { 6878 SETUP(); 6879 6880 START(); 6881 __ Mov(x1, 0x0123456789abcdef); 6882 __ Mov(x2, 0xfedcba9876543210); 6883 6884 __ Mov(x10, 0x8888888888888888); 6885 __ Mov(x11, 0x8888888888888888); 6886 6887 __ Ubfm(x10, x1, 16, 31); 6888 __ Ubfm(x11, x1, 32, 15); 6889 __ Ubfm(x12, x1, 32, 47); 6890 __ Ubfm(x13, x1, 48, 35); 6891 6892 __ Ubfm(w25, w1, 16, 23); 6893 __ Ubfm(w26, w1, 24, 15); 6894 __ Ubfm(w27, w2, 16, 23); 6895 __ Ubfm(w28, w2, 24, 15); 6896 6897 // Aliases 6898 __ Lsl(x15, x1, 63); 6899 __ Lsl(x16, x1, 0); 6900 __ Lsr(x17, x1, 32); 6901 __ Ubfiz(x18, x1, 8, 16); 6902 __ Ubfx(x19, x1, 8, 16); 6903 __ Uxtb(x20, x1); 6904 __ Uxth(x21, x1); 6905 __ Uxtw(x22, x1); 6906 END(); 6907 6908 if (CAN_RUN()) { 6909 RUN(); 6910 6911 ASSERT_EQUAL_64(0x00000000000089ab, x10); 6912 ASSERT_EQUAL_64(0x0000cdef00000000, x11); 6913 ASSERT_EQUAL_64(0x0000000000004567, x12); 6914 ASSERT_EQUAL_64(0x000789abcdef0000, x13); 6915 6916 ASSERT_EQUAL_32(0x000000ab, w25); 6917 ASSERT_EQUAL_32(0x00cdef00, w26); 6918 ASSERT_EQUAL_32(0x00000054, w27); 6919 ASSERT_EQUAL_32(0x00321000, w28); 6920 6921 ASSERT_EQUAL_64(0x8000000000000000, x15); 6922 ASSERT_EQUAL_64(0x0123456789abcdef, x16); 6923 ASSERT_EQUAL_64(0x0000000001234567, x17); 6924 ASSERT_EQUAL_64(0x0000000000cdef00, x18); 6925 ASSERT_EQUAL_64(0x000000000000abcd, x19); 6926 ASSERT_EQUAL_64(0x00000000000000ef, x20); 6927 ASSERT_EQUAL_64(0x000000000000cdef, x21); 6928 ASSERT_EQUAL_64(0x0000000089abcdef, x22); 6929 } 6930} 6931 6932 6933TEST(extr) { 6934 SETUP(); 6935 6936 START(); 6937 __ Mov(x1, 0x0123456789abcdef); 6938 __ Mov(x2, 0xfedcba9876543210); 6939 6940 __ Extr(w10, w1, w2, 0); 6941 __ Extr(w11, w1, w2, 1); 6942 __ Extr(x12, x2, x1, 2); 6943 6944 __ Ror(w13, w1, 0); 6945 __ Ror(w14, w2, 17); 6946 __ Ror(w15, w1, 31); 6947 __ Ror(x18, x2, 0); 6948 __ Ror(x19, x2, 1); 6949 __ Ror(x20, x1, 63); 6950 END(); 6951 6952 if (CAN_RUN()) { 6953 RUN(); 6954 6955 ASSERT_EQUAL_64(0x76543210, x10); 6956 ASSERT_EQUAL_64(0xbb2a1908, x11); 6957 ASSERT_EQUAL_64(0x0048d159e26af37b, x12); 6958 ASSERT_EQUAL_64(0x89abcdef, x13); 6959 ASSERT_EQUAL_64(0x19083b2a, x14); 6960 ASSERT_EQUAL_64(0x13579bdf, x15); 6961 ASSERT_EQUAL_64(0xfedcba9876543210, x18); 6962 ASSERT_EQUAL_64(0x7f6e5d4c3b2a1908, x19); 6963 ASSERT_EQUAL_64(0x02468acf13579bde, x20); 6964 } 6965} 6966 6967 6968TEST(system_mrs) { 6969 SETUP(); 6970 6971 START(); 6972 __ Mov(w0, 0); 6973 __ Mov(w1, 1); 6974 __ Mov(w2, 0x80000000); 6975 6976 // Set the Z and C flags. 6977 __ Cmp(w0, w0); 6978 __ Mrs(x3, NZCV); 6979 6980 // Set the N flag. 6981 __ Cmp(w0, w1); 6982 __ Mrs(x4, NZCV); 6983 6984 // Set the Z, C and V flags. 6985 __ Adds(w0, w2, w2); 6986 __ Mrs(x5, NZCV); 6987 6988 // Read the default FPCR. 6989 __ Mrs(x6, FPCR); 6990 END(); 6991 6992 if (CAN_RUN()) { 6993 RUN(); 6994 6995 // NZCV 6996 ASSERT_EQUAL_32(ZCFlag, w3); 6997 ASSERT_EQUAL_32(NFlag, w4); 6998 ASSERT_EQUAL_32(ZCVFlag, w5); 6999 7000 // FPCR 7001 // The default FPCR on Linux-based platforms is 0. 7002 ASSERT_EQUAL_32(0, w6); 7003 } 7004} 7005 7006TEST(system_rng) { 7007 SETUP_WITH_FEATURES(CPUFeatures::kRNG); 7008 7009 START(); 7010 // Random number. 7011 __ Mrs(x1, RNDR); 7012 // Assume that each generation is successful now. 7013 // TODO: Return failure occasionally. 7014 __ Mrs(x2, NZCV); 7015 __ Mrs(x3, RNDR); 7016 __ Mrs(x4, NZCV); 7017 7018 // Reseeded random number. 7019 __ Mrs(x5, RNDRRS); 7020 // Assume that each generation is successful now. 7021 // TODO: Return failure occasionally. 7022 __ Mrs(x6, NZCV); 7023 __ Mrs(x7, RNDRRS); 7024 __ Mrs(x8, NZCV); 7025 END(); 7026 7027 if (CAN_RUN()) { 7028 RUN(); 7029 // Random number generation series. 7030 // Check random numbers have been generated and aren't equal when reseed has 7031 // happened. 7032 // NOTE: With a different architectural implementation, there may be a 7033 // collison. 7034 // TODO: Return failure occasionally. Set ZFlag and return UNKNOWN value. 7035 ASSERT_NOT_EQUAL_64(x1, x3); 7036 ASSERT_EQUAL_64(NoFlag, x2); 7037 ASSERT_EQUAL_64(NoFlag, x4); 7038 ASSERT_NOT_EQUAL_64(x5, x7); 7039 ASSERT_EQUAL_64(NoFlag, x6); 7040 ASSERT_EQUAL_64(NoFlag, x8); 7041 } 7042} 7043 7044TEST(cfinv) { 7045 SETUP_WITH_FEATURES(CPUFeatures::kFlagM); 7046 7047 START(); 7048 __ Mov(w0, 1); 7049 7050 // Set the C flag. 7051 __ Cmp(w0, 0); 7052 __ Mrs(x1, NZCV); 7053 7054 // Invert the C flag. 7055 __ Cfinv(); 7056 __ Mrs(x2, NZCV); 7057 7058 // Invert the C flag again. 7059 __ Cfinv(); 7060 __ Mrs(x3, NZCV); 7061 END(); 7062 7063 if (CAN_RUN()) { 7064 RUN(); 7065 7066 ASSERT_EQUAL_32(CFlag, w1); 7067 ASSERT_EQUAL_32(NoFlag, w2); 7068 ASSERT_EQUAL_32(CFlag, w3); 7069 } 7070} 7071 7072 7073TEST(axflag_xaflag) { 7074 // The AXFLAG and XAFLAG instructions are designed for converting the FP 7075 // conditional flags from Arm format to an alternate format efficiently. 7076 // There are only 4 cases which are relevant for this conversion but we test 7077 // the behaviour for all 16 cases anyway. The 4 important cases are labelled 7078 // below. 7079 StatusFlags expected_x[16] = {NoFlag, 7080 ZFlag, 7081 CFlag, // Greater than 7082 ZFlag, // Unordered 7083 ZFlag, 7084 ZFlag, 7085 ZCFlag, // Equal to 7086 ZFlag, 7087 NoFlag, // Less than 7088 ZFlag, 7089 CFlag, 7090 ZFlag, 7091 ZFlag, 7092 ZFlag, 7093 ZCFlag, 7094 ZFlag}; 7095 StatusFlags expected_a[16] = {NFlag, // Less than 7096 NFlag, 7097 CFlag, // Greater than 7098 CFlag, 7099 CVFlag, // Unordered 7100 CVFlag, 7101 ZCFlag, // Equal to 7102 ZCFlag, 7103 NFlag, 7104 NFlag, 7105 CFlag, 7106 CFlag, 7107 CVFlag, 7108 CVFlag, 7109 ZCFlag, 7110 ZCFlag}; 7111 7112 for (unsigned i = 0; i < 16; i++) { 7113 SETUP_WITH_FEATURES(CPUFeatures::kAXFlag); 7114 7115 START(); 7116 __ Mov(x0, i << Flags_offset); 7117 __ Msr(NZCV, x0); 7118 __ Axflag(); 7119 __ Mrs(x1, NZCV); 7120 __ Msr(NZCV, x0); 7121 __ Xaflag(); 7122 __ Mrs(x2, NZCV); 7123 END(); 7124 7125 if (CAN_RUN()) { 7126 RUN(); 7127 ASSERT_EQUAL_32(expected_x[i], w1); 7128 ASSERT_EQUAL_32(expected_a[i], w2); 7129 } 7130 } 7131} 7132 7133 7134TEST(system_msr) { 7135 // All FPCR fields that must be implemented: AHP, DN, FZ, RMode 7136 const uint64_t fpcr_core = (0b1 << 26) | // AHP 7137 (0b1 << 25) | // DN 7138 (0b1 << 24) | // FZ 7139 (0b11 << 22); // RMode 7140 7141 SETUP(); 7142 7143 START(); 7144 __ Mov(w0, 0); 7145 __ Mov(w1, 0x7fffffff); 7146 7147 __ Mov(x7, 0); 7148 7149 __ Mov(x10, NVFlag); 7150 __ Cmp(w0, w0); // Set Z and C. 7151 __ Msr(NZCV, x10); // Set N and V. 7152 // The Msr should have overwritten every flag set by the Cmp. 7153 __ Cinc(x7, x7, mi); // N 7154 __ Cinc(x7, x7, ne); // !Z 7155 __ Cinc(x7, x7, lo); // !C 7156 __ Cinc(x7, x7, vs); // V 7157 7158 __ Mov(x10, ZCFlag); 7159 __ Cmn(w1, w1); // Set N and V. 7160 __ Msr(NZCV, x10); // Set Z and C. 7161 // The Msr should have overwritten every flag set by the Cmn. 7162 __ Cinc(x7, x7, pl); // !N 7163 __ Cinc(x7, x7, eq); // Z 7164 __ Cinc(x7, x7, hs); // C 7165 __ Cinc(x7, x7, vc); // !V 7166 7167 Register old_fpcr = x15; 7168 __ Mrs(old_fpcr, FPCR); 7169 7170 // All core FPCR fields must be writable. 7171 __ Mov(x8, fpcr_core); 7172 __ Msr(FPCR, x8); 7173 __ Mrs(x8, FPCR); 7174 7175#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7176 // All FPCR fields that aren't `RES0`: 7177 const uint64_t fpcr_all = fpcr_core | (0b11 << 20) | // Stride 7178 (0b1 << 19) | // FZ16 7179 (0b111 << 16) | // Len 7180 (0b1 << 15) | // IDE 7181 (0b1 << 12) | // IXE 7182 (0b1 << 11) | // UFE 7183 (0b1 << 10) | // OFE 7184 (0b1 << 9) | // DZE 7185 (0b1 << 8); // IOE 7186 7187 // All FPCR fields, including optional ones. This part of the test doesn't 7188 // achieve much other than ensuring that supported fields can be cleared by 7189 // the next test. 7190 __ Mov(x9, fpcr_all); 7191 __ Msr(FPCR, x9); 7192 __ Mrs(x9, FPCR); 7193 __ And(x9, x9, fpcr_core); 7194 7195 // The undefined bits must ignore writes. 7196 // It's conceivable that a future version of the architecture could use these 7197 // fields (making this test fail), but in the meantime this is a useful test 7198 // for the simulator. 7199 __ Mov(x10, ~fpcr_all); 7200 __ Msr(FPCR, x10); 7201 __ Mrs(x10, FPCR); 7202#endif 7203 7204 __ Msr(FPCR, old_fpcr); 7205 7206 END(); 7207 7208 if (CAN_RUN()) { 7209 RUN(); 7210 7211 // We should have incremented x7 (from 0) exactly 8 times. 7212 ASSERT_EQUAL_64(8, x7); 7213 7214 ASSERT_EQUAL_64(fpcr_core, x8); 7215 7216#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7217 ASSERT_EQUAL_64(fpcr_core, x9); 7218 ASSERT_EQUAL_64(0, x10); 7219#endif 7220 } 7221} 7222 7223 7224TEST(system_pauth_a) { 7225 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 7226 START(); 7227 7228 // Exclude x16 and x17 from the scratch register list so we can use 7229 // Pac/Autia1716 safely. 7230 UseScratchRegisterScope temps(&masm); 7231 temps.Exclude(x16, x17); 7232 temps.Include(x10, x11); 7233 7234 // Backup stack pointer. 7235 __ Mov(x20, sp); 7236 7237 // Modifiers 7238 __ Mov(x16, 0x477d469dec0b8760); 7239 __ Mov(sp, 0x477d469dec0b8760); 7240 7241 // Generate PACs using the 3 system instructions. 7242 __ Mov(x17, 0x0000000012345678); 7243 __ Pacia1716(); 7244 __ Mov(x0, x17); 7245 7246 __ Mov(lr, 0x0000000012345678); 7247 __ Paciaz(); 7248 __ Mov(x1, lr); 7249 7250 __ Mov(lr, 0x0000000012345678); 7251 __ Paciasp(); 7252 __ Mov(x2, lr); 7253 7254 // Authenticate the pointers above. 7255 __ Mov(x17, x0); 7256 __ Autia1716(); 7257 __ Mov(x3, x17); 7258 7259 __ Mov(lr, x1); 7260 __ Autiaz(); 7261 __ Mov(x4, lr); 7262 7263 __ Mov(lr, x2); 7264 __ Autiasp(); 7265 __ Mov(x5, lr); 7266 7267 // Attempt to authenticate incorrect pointers. 7268 __ Mov(x17, x1); 7269 __ Autia1716(); 7270 __ Mov(x6, x17); 7271 7272 __ Mov(lr, x0); 7273 __ Autiaz(); 7274 __ Mov(x7, lr); 7275 7276 __ Mov(lr, x1); 7277 __ Autiasp(); 7278 __ Mov(x8, lr); 7279 7280 // Strip the pac code from the pointer in x0. 7281 __ Mov(lr, x0); 7282 __ Xpaclri(); 7283 __ Mov(x9, lr); 7284 7285 // Restore stack pointer. 7286 __ Mov(sp, x20); 7287 7288 // Mask out just the PAC code bits. 7289 // TODO: use Simulator::CalculatePACMask in a nice way. 7290 __ And(x0, x0, 0x007f000000000000); 7291 __ And(x1, x1, 0x007f000000000000); 7292 __ And(x2, x2, 0x007f000000000000); 7293 7294 END(); 7295 7296 if (CAN_RUN()) { 7297 RUN(); 7298 7299 // Check PAC codes have been generated and aren't equal. 7300 // NOTE: with a different ComputePAC implementation, there may be a 7301 // collision. 7302 ASSERT_NOT_EQUAL_64(0, x0); 7303 ASSERT_NOT_EQUAL_64(0, x1); 7304 ASSERT_NOT_EQUAL_64(0, x2); 7305 ASSERT_NOT_EQUAL_64(x0, x1); 7306 ASSERT_EQUAL_64(x0, x2); 7307 7308 // Pointers correctly authenticated. 7309 ASSERT_EQUAL_64(0x0000000012345678, x3); 7310 ASSERT_EQUAL_64(0x0000000012345678, x4); 7311 ASSERT_EQUAL_64(0x0000000012345678, x5); 7312 7313 // Pointers corrupted after failing to authenticate. 7314 ASSERT_EQUAL_64(0x0020000012345678, x6); 7315 ASSERT_EQUAL_64(0x0020000012345678, x7); 7316 ASSERT_EQUAL_64(0x0020000012345678, x8); 7317 7318 // Pointer with code stripped. 7319 ASSERT_EQUAL_64(0x0000000012345678, x9); 7320 } 7321} 7322 7323 7324TEST(system_pauth_b) { 7325 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 7326 START(); 7327 7328 // Exclude x16 and x17 from the scratch register list so we can use 7329 // Pac/Autia1716 safely. 7330 UseScratchRegisterScope temps(&masm); 7331 temps.Exclude(x16, x17); 7332 temps.Include(x10, x11); 7333 7334 // Backup stack pointer. 7335 __ Mov(x20, sp); 7336 7337 // Modifiers 7338 __ Mov(x16, 0x477d469dec0b8760); 7339 __ Mov(sp, 0x477d469dec0b8760); 7340 7341 // Generate PACs using the 3 system instructions. 7342 __ Mov(x17, 0x0000000012345678); 7343 __ Pacib1716(); 7344 __ Mov(x0, x17); 7345 7346 __ Mov(lr, 0x0000000012345678); 7347 __ Pacibz(); 7348 __ Mov(x1, lr); 7349 7350 __ Mov(lr, 0x0000000012345678); 7351 __ Pacibsp(); 7352 __ Mov(x2, lr); 7353 7354 // Authenticate the pointers above. 7355 __ Mov(x17, x0); 7356 __ Autib1716(); 7357 __ Mov(x3, x17); 7358 7359 __ Mov(lr, x1); 7360 __ Autibz(); 7361 __ Mov(x4, lr); 7362 7363 __ Mov(lr, x2); 7364 __ Autibsp(); 7365 __ Mov(x5, lr); 7366 7367 // Attempt to authenticate incorrect pointers. 7368 __ Mov(x17, x1); 7369 __ Autib1716(); 7370 __ Mov(x6, x17); 7371 7372 __ Mov(lr, x0); 7373 __ Autibz(); 7374 __ Mov(x7, lr); 7375 7376 __ Mov(lr, x1); 7377 __ Autibsp(); 7378 __ Mov(x8, lr); 7379 7380 // Strip the pac code from the pointer in x0. 7381 __ Mov(lr, x0); 7382 __ Xpaclri(); 7383 __ Mov(x9, lr); 7384 7385 // Restore stack pointer. 7386 __ Mov(sp, x20); 7387 7388 // Mask out just the PAC code bits. 7389 // TODO: use Simulator::CalculatePACMask in a nice way. 7390 __ And(x0, x0, 0x007f000000000000); 7391 __ And(x1, x1, 0x007f000000000000); 7392 __ And(x2, x2, 0x007f000000000000); 7393 7394 END(); 7395 7396 if (CAN_RUN()) { 7397 RUN(); 7398 7399 // Check PAC codes have been generated and aren't equal. 7400 // NOTE: with a different ComputePAC implementation, there may be a 7401 // collision. 7402 ASSERT_NOT_EQUAL_64(0, x0); 7403 ASSERT_NOT_EQUAL_64(0, x1); 7404 ASSERT_NOT_EQUAL_64(0, x2); 7405 ASSERT_NOT_EQUAL_64(x0, x1); 7406 ASSERT_EQUAL_64(x0, x2); 7407 7408 // Pointers correctly authenticated. 7409 ASSERT_EQUAL_64(0x0000000012345678, x3); 7410 ASSERT_EQUAL_64(0x0000000012345678, x4); 7411 ASSERT_EQUAL_64(0x0000000012345678, x5); 7412 7413 // Pointers corrupted after failing to authenticate. 7414 ASSERT_EQUAL_64(0x0040000012345678, x6); 7415 ASSERT_EQUAL_64(0x0040000012345678, x7); 7416 ASSERT_EQUAL_64(0x0040000012345678, x8); 7417 7418 // Pointer with code stripped. 7419 ASSERT_EQUAL_64(0x0000000012345678, x9); 7420 } 7421} 7422 7423#ifdef VIXL_NEGATIVE_TESTING 7424TEST(system_pauth_negative_test) { 7425 SETUP_WITH_FEATURES(CPUFeatures::kPAuth); 7426 START(); 7427 7428 // Test for an assert (independent of order). 7429 MUST_FAIL_WITH_MESSAGE(__ Pacia1716(), 7430 "Assertion failed " 7431 "(!GetScratchRegisterList()->IncludesAliasOf("); 7432 7433 // Test for x16 assert. 7434 { 7435 UseScratchRegisterScope temps(&masm); 7436 temps.Exclude(x17); 7437 temps.Include(x16); 7438 MUST_FAIL_WITH_MESSAGE(__ Pacia1716(), 7439 "Assertion failed " 7440 "(!GetScratchRegisterList()->IncludesAliasOf(x16))"); 7441 } 7442 7443 // Test for x17 assert. 7444 { 7445 UseScratchRegisterScope temps(&masm); 7446 temps.Exclude(x16); 7447 temps.Include(x17); 7448 MUST_FAIL_WITH_MESSAGE(__ Pacia1716(), 7449 "Assertion failed " 7450 "(!GetScratchRegisterList()->IncludesAliasOf(x17))"); 7451 } 7452 7453 // Repeat first test for other 1716 instructions. 7454 MUST_FAIL_WITH_MESSAGE(__ Pacib1716(), 7455 "Assertion failed " 7456 "(!GetScratchRegisterList()->IncludesAliasOf("); 7457 MUST_FAIL_WITH_MESSAGE(__ Autia1716(), 7458 "Assertion failed " 7459 "(!GetScratchRegisterList()->IncludesAliasOf("); 7460 MUST_FAIL_WITH_MESSAGE(__ Autib1716(), 7461 "Assertion failed " 7462 "(!GetScratchRegisterList()->IncludesAliasOf("); 7463 7464 END(); 7465} 7466#endif // VIXL_NEGATIVE_TESTING 7467 7468 7469TEST(system) { 7470 // RegisterDump::Dump uses NEON. 7471 SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kRAS); 7472 RegisterDump before; 7473 7474 START(); 7475 before.Dump(&masm); 7476 __ Nop(); 7477 __ Esb(); 7478 __ Csdb(); 7479 END(); 7480 7481 if (CAN_RUN()) { 7482 RUN(); 7483 7484 ASSERT_EQUAL_REGISTERS(before); 7485 ASSERT_EQUAL_NZCV(before.flags_nzcv()); 7486 } 7487} 7488 7489static void BtiHelper(Register ipreg) { 7490 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7491 7492 Label jump_target, jump_call_target, call_target, done; 7493 START(); 7494 UseScratchRegisterScope temps(&masm); 7495 temps.Exclude(ipreg); 7496 __ Adr(x0, &jump_target); 7497 __ Br(x0); 7498 __ Nop(); 7499 __ Bind(&jump_target, EmitBTI_j); 7500 __ Adr(x0, &call_target); 7501 __ Blr(x0); 7502 __ Adr(ipreg, &jump_call_target); 7503 __ Blr(ipreg); 7504 __ Adr(lr, &done); // Make Ret return to done label. 7505 __ Br(ipreg); 7506 __ Bind(&call_target, EmitBTI_c); 7507 __ Ret(); 7508 __ Bind(&jump_call_target, EmitBTI_jc); 7509 __ Ret(); 7510 __ Bind(&done); 7511 END(); 7512 7513 if (CAN_RUN()) { 7514#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7515 simulator.SetGuardedPages(true); 7516#else 7517 VIXL_UNIMPLEMENTED(); 7518#endif 7519 RUN(); 7520 } 7521} 7522 7523TEST(bti) { 7524 BtiHelper(x16); 7525 BtiHelper(x17); 7526} 7527 7528TEST(unguarded_bti_is_nop) { 7529 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7530 7531 Label start, none, c, j, jc; 7532 START(); 7533 __ B(&start); 7534 __ Bind(&none, EmitBTI); 7535 __ Bind(&c, EmitBTI_c); 7536 __ Bind(&j, EmitBTI_j); 7537 __ Bind(&jc, EmitBTI_jc); 7538 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&none) == 4 * kInstructionSize); 7539 __ Ret(); 7540 7541 Label jump_to_c, call_to_j; 7542 __ Bind(&start); 7543 __ Adr(x0, &none); 7544 __ Adr(lr, &jump_to_c); 7545 __ Br(x0); 7546 7547 __ Bind(&jump_to_c); 7548 __ Adr(x0, &c); 7549 __ Adr(lr, &call_to_j); 7550 __ Br(x0); 7551 7552 __ Bind(&call_to_j); 7553 __ Adr(x0, &j); 7554 __ Blr(x0); 7555 END(); 7556 7557 if (CAN_RUN()) { 7558#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7559 simulator.SetGuardedPages(false); 7560#else 7561 VIXL_UNIMPLEMENTED(); 7562#endif 7563 RUN(); 7564 } 7565} 7566 7567#ifdef VIXL_NEGATIVE_TESTING 7568TEST(bti_jump_to_ip_unidentified) { 7569 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7570 7571 START(); 7572 UseScratchRegisterScope temps(&masm); 7573 temps.Exclude(x17); 7574 Label l; 7575 __ Adr(x17, &l); 7576 __ Br(x17); 7577 __ Nop(); 7578 __ Bind(&l); 7579 __ Nop(); 7580 END(); 7581 7582 if (CAN_RUN()) { 7583#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7584 simulator.SetGuardedPages(true); 7585#else 7586 VIXL_UNIMPLEMENTED(); 7587#endif 7588 MUST_FAIL_WITH_MESSAGE(RUN(), 7589 "Executing non-BTI instruction with wrong " 7590 "BType."); 7591 } 7592} 7593 7594TEST(bti_jump_to_unidentified) { 7595 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7596 7597 START(); 7598 Label l; 7599 __ Adr(x0, &l); 7600 __ Br(x0); 7601 __ Nop(); 7602 __ Bind(&l); 7603 __ Nop(); 7604 END(); 7605 7606 if (CAN_RUN()) { 7607#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7608 simulator.SetGuardedPages(true); 7609#else 7610 VIXL_UNIMPLEMENTED(); 7611#endif 7612 MUST_FAIL_WITH_MESSAGE(RUN(), 7613 "Executing non-BTI instruction with wrong " 7614 "BType."); 7615 } 7616} 7617 7618TEST(bti_call_to_unidentified) { 7619 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7620 7621 START(); 7622 Label l; 7623 __ Adr(x0, &l); 7624 __ Blr(x0); 7625 __ Nop(); 7626 __ Bind(&l); 7627 __ Nop(); 7628 END(); 7629 7630 if (CAN_RUN()) { 7631#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7632 simulator.SetGuardedPages(true); 7633#else 7634 VIXL_UNIMPLEMENTED(); 7635#endif 7636 MUST_FAIL_WITH_MESSAGE(RUN(), 7637 "Executing non-BTI instruction with wrong " 7638 "BType."); 7639 } 7640} 7641 7642TEST(bti_jump_to_c) { 7643 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7644 7645 START(); 7646 // Jumping to a "BTI c" target must fail. 7647 Label jump_target; 7648 __ Adr(x0, &jump_target); 7649 __ Br(x0); 7650 __ Nop(); 7651 __ Bind(&jump_target, EmitBTI_c); 7652 __ Nop(); 7653 END(); 7654 7655 if (CAN_RUN()) { 7656#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7657 simulator.SetGuardedPages(true); 7658#else 7659 VIXL_UNIMPLEMENTED(); 7660#endif 7661 MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI c with wrong BType."); 7662 } 7663} 7664 7665TEST(bti_call_to_j) { 7666 SETUP_WITH_FEATURES(CPUFeatures::kBTI); 7667 7668 START(); 7669 // Calling a "BTI j" target must fail. 7670 Label call_target; 7671 __ Adr(x0, &call_target); 7672 __ Blr(x0); 7673 __ Nop(); 7674 __ Bind(&call_target, EmitBTI_j); 7675 __ Nop(); 7676 END(); 7677 7678 if (CAN_RUN()) { 7679#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7680 simulator.SetGuardedPages(true); 7681#else 7682 VIXL_UNIMPLEMENTED(); 7683#endif 7684 MUST_FAIL_WITH_MESSAGE(RUN(), "Executing BTI j with wrong BType."); 7685 } 7686} 7687#endif // VIXL_NEGATIVE_TESTING 7688 7689TEST(fall_through_bti) { 7690 SETUP_WITH_FEATURES(CPUFeatures::kBTI, CPUFeatures::kPAuth); 7691 7692 START(); 7693 Label target, target_j, target_c, target_jc; 7694 __ Mov(x0, 0); // 'Normal' instruction sets BTYPE to zero. 7695 __ Bind(&target, EmitBTI); 7696 __ Add(x0, x0, 1); 7697 __ Bind(&target_j, EmitBTI_j); 7698 __ Add(x0, x0, 1); 7699 __ Bind(&target_c, EmitBTI_c); 7700 __ Add(x0, x0, 1); 7701 __ Bind(&target_jc, EmitBTI_jc); 7702 __ Add(x0, x0, 1); 7703 __ Paciasp(); 7704 END(); 7705 7706 if (CAN_RUN()) { 7707#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 7708 simulator.SetGuardedPages(true); 7709#else 7710 VIXL_UNIMPLEMENTED(); 7711#endif 7712 RUN(); 7713 7714 ASSERT_EQUAL_64(4, x0); 7715 } 7716} 7717 7718TEST(zero_dest) { 7719 // RegisterDump::Dump uses NEON. 7720 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 7721 RegisterDump before; 7722 7723 START(); 7724 // Preserve the stack pointer, in case we clobber it. 7725 __ Mov(x30, sp); 7726 // Initialize the other registers used in this test. 7727 uint64_t literal_base = 0x0100001000100101; 7728 __ Mov(x0, 0); 7729 __ Mov(x1, literal_base); 7730 for (unsigned i = 2; i < x30.GetCode(); i++) { 7731 __ Add(XRegister(i), XRegister(i - 1), x1); 7732 } 7733 before.Dump(&masm); 7734 7735 // All of these instructions should be NOPs in these forms, but have 7736 // alternate forms which can write into the stack pointer. 7737 { 7738 ExactAssemblyScope scope(&masm, 3 * 7 * kInstructionSize); 7739 __ add(xzr, x0, x1); 7740 __ add(xzr, x1, xzr); 7741 __ add(xzr, xzr, x1); 7742 7743 __ and_(xzr, x0, x2); 7744 __ and_(xzr, x2, xzr); 7745 __ and_(xzr, xzr, x2); 7746 7747 __ bic(xzr, x0, x3); 7748 __ bic(xzr, x3, xzr); 7749 __ bic(xzr, xzr, x3); 7750 7751 __ eon(xzr, x0, x4); 7752 __ eon(xzr, x4, xzr); 7753 __ eon(xzr, xzr, x4); 7754 7755 __ eor(xzr, x0, x5); 7756 __ eor(xzr, x5, xzr); 7757 __ eor(xzr, xzr, x5); 7758 7759 __ orr(xzr, x0, x6); 7760 __ orr(xzr, x6, xzr); 7761 __ orr(xzr, xzr, x6); 7762 7763 __ sub(xzr, x0, x7); 7764 __ sub(xzr, x7, xzr); 7765 __ sub(xzr, xzr, x7); 7766 } 7767 7768 // Swap the saved stack pointer with the real one. If sp was written 7769 // during the test, it will show up in x30. This is done because the test 7770 // framework assumes that sp will be valid at the end of the test. 7771 __ Mov(x29, x30); 7772 __ Mov(x30, sp); 7773 __ Mov(sp, x29); 7774 // We used x29 as a scratch register, so reset it to make sure it doesn't 7775 // trigger a test failure. 7776 __ Add(x29, x28, x1); 7777 END(); 7778 7779 if (CAN_RUN()) { 7780 RUN(); 7781 7782 ASSERT_EQUAL_REGISTERS(before); 7783 ASSERT_EQUAL_NZCV(before.flags_nzcv()); 7784 } 7785} 7786 7787 7788TEST(zero_dest_setflags) { 7789 // RegisterDump::Dump uses NEON. 7790 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 7791 RegisterDump before; 7792 7793 START(); 7794 // Preserve the stack pointer, in case we clobber it. 7795 __ Mov(x30, sp); 7796 // Initialize the other registers used in this test. 7797 uint64_t literal_base = 0x0100001000100101; 7798 __ Mov(x0, 0); 7799 __ Mov(x1, literal_base); 7800 for (int i = 2; i < 30; i++) { 7801 __ Add(XRegister(i), XRegister(i - 1), x1); 7802 } 7803 before.Dump(&masm); 7804 7805 // All of these instructions should only write to the flags in these forms, 7806 // but have alternate forms which can write into the stack pointer. 7807 { 7808 ExactAssemblyScope scope(&masm, 6 * kInstructionSize); 7809 __ adds(xzr, x0, Operand(x1, UXTX)); 7810 __ adds(xzr, x1, Operand(xzr, UXTX)); 7811 __ adds(xzr, x1, 1234); 7812 __ adds(xzr, x0, x1); 7813 __ adds(xzr, x1, xzr); 7814 __ adds(xzr, xzr, x1); 7815 } 7816 7817 { 7818 ExactAssemblyScope scope(&masm, 5 * kInstructionSize); 7819 __ ands(xzr, x2, ~0xf); 7820 __ ands(xzr, xzr, ~0xf); 7821 __ ands(xzr, x0, x2); 7822 __ ands(xzr, x2, xzr); 7823 __ ands(xzr, xzr, x2); 7824 } 7825 7826 { 7827 ExactAssemblyScope scope(&masm, 5 * kInstructionSize); 7828 __ bics(xzr, x3, ~0xf); 7829 __ bics(xzr, xzr, ~0xf); 7830 __ bics(xzr, x0, x3); 7831 __ bics(xzr, x3, xzr); 7832 __ bics(xzr, xzr, x3); 7833 } 7834 7835 { 7836 ExactAssemblyScope scope(&masm, 6 * kInstructionSize); 7837 __ subs(xzr, x0, Operand(x3, UXTX)); 7838 __ subs(xzr, x3, Operand(xzr, UXTX)); 7839 __ subs(xzr, x3, 1234); 7840 __ subs(xzr, x0, x3); 7841 __ subs(xzr, x3, xzr); 7842 __ subs(xzr, xzr, x3); 7843 } 7844 7845 // Swap the saved stack pointer with the real one. If sp was written 7846 // during the test, it will show up in x30. This is done because the test 7847 // framework assumes that sp will be valid at the end of the test. 7848 __ Mov(x29, x30); 7849 __ Mov(x30, sp); 7850 __ Mov(sp, x29); 7851 // We used x29 as a scratch register, so reset it to make sure it doesn't 7852 // trigger a test failure. 7853 __ Add(x29, x28, x1); 7854 END(); 7855 7856 if (CAN_RUN()) { 7857 RUN(); 7858 7859 ASSERT_EQUAL_REGISTERS(before); 7860 } 7861} 7862 7863 7864TEST(stack_pointer_override) { 7865 // This test generates some stack maintenance code, but the test only checks 7866 // the reported state. 7867 SETUP(); 7868 START(); 7869 7870 // The default stack pointer in VIXL is sp. 7871 VIXL_CHECK(sp.Is(__ StackPointer())); 7872 __ SetStackPointer(x0); 7873 VIXL_CHECK(x0.Is(__ StackPointer())); 7874 __ SetStackPointer(x28); 7875 VIXL_CHECK(x28.Is(__ StackPointer())); 7876 __ SetStackPointer(sp); 7877 VIXL_CHECK(sp.Is(__ StackPointer())); 7878 7879 END(); 7880 if (CAN_RUN()) { 7881 RUN(); 7882 } 7883} 7884 7885 7886TEST(peek_poke_simple) { 7887 SETUP(); 7888 START(); 7889 7890 static const RegList x0_to_x3 = 7891 x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit(); 7892 static const RegList x10_to_x13 = 7893 x10.GetBit() | x11.GetBit() | x12.GetBit() | x13.GetBit(); 7894 7895 // The literal base is chosen to have two useful properties: 7896 // * When multiplied by small values (such as a register index), this value 7897 // is clearly readable in the result. 7898 // * The value is not formed from repeating fixed-size smaller values, so it 7899 // can be used to detect endianness-related errors. 7900 uint64_t literal_base = 0x0100001000100101; 7901 7902 // Initialize the registers. 7903 __ Mov(x0, literal_base); 7904 __ Add(x1, x0, x0); 7905 __ Add(x2, x1, x0); 7906 __ Add(x3, x2, x0); 7907 7908 __ Claim(32); 7909 7910 // Simple exchange. 7911 // After this test: 7912 // x0-x3 should be unchanged. 7913 // w10-w13 should contain the lower words of x0-x3. 7914 __ Poke(x0, 0); 7915 __ Poke(x1, 8); 7916 __ Poke(x2, 16); 7917 __ Poke(x3, 24); 7918 Clobber(&masm, x0_to_x3); 7919 __ Peek(x0, 0); 7920 __ Peek(x1, 8); 7921 __ Peek(x2, 16); 7922 __ Peek(x3, 24); 7923 7924 __ Poke(w0, 0); 7925 __ Poke(w1, 4); 7926 __ Poke(w2, 8); 7927 __ Poke(w3, 12); 7928 Clobber(&masm, x10_to_x13); 7929 __ Peek(w10, 0); 7930 __ Peek(w11, 4); 7931 __ Peek(w12, 8); 7932 __ Peek(w13, 12); 7933 7934 __ Drop(32); 7935 7936 END(); 7937 if (CAN_RUN()) { 7938 RUN(); 7939 7940 ASSERT_EQUAL_64(literal_base * 1, x0); 7941 ASSERT_EQUAL_64(literal_base * 2, x1); 7942 ASSERT_EQUAL_64(literal_base * 3, x2); 7943 ASSERT_EQUAL_64(literal_base * 4, x3); 7944 7945 ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10); 7946 ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11); 7947 ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12); 7948 ASSERT_EQUAL_64((literal_base * 4) & 0xffffffff, x13); 7949 } 7950} 7951 7952 7953TEST(peek_poke_unaligned) { 7954 SETUP(); 7955 START(); 7956 7957 // The literal base is chosen to have two useful properties: 7958 // * When multiplied by small values (such as a register index), this value 7959 // is clearly readable in the result. 7960 // * The value is not formed from repeating fixed-size smaller values, so it 7961 // can be used to detect endianness-related errors. 7962 uint64_t literal_base = 0x0100001000100101; 7963 7964 // Initialize the registers. 7965 __ Mov(x0, literal_base); 7966 __ Add(x1, x0, x0); 7967 __ Add(x2, x1, x0); 7968 __ Add(x3, x2, x0); 7969 __ Add(x4, x3, x0); 7970 __ Add(x5, x4, x0); 7971 __ Add(x6, x5, x0); 7972 7973 __ Claim(32); 7974 7975 // Unaligned exchanges. 7976 // After this test: 7977 // x0-x6 should be unchanged. 7978 // w10-w12 should contain the lower words of x0-x2. 7979 __ Poke(x0, 1); 7980 Clobber(&masm, x0.GetBit()); 7981 __ Peek(x0, 1); 7982 __ Poke(x1, 2); 7983 Clobber(&masm, x1.GetBit()); 7984 __ Peek(x1, 2); 7985 __ Poke(x2, 3); 7986 Clobber(&masm, x2.GetBit()); 7987 __ Peek(x2, 3); 7988 __ Poke(x3, 4); 7989 Clobber(&masm, x3.GetBit()); 7990 __ Peek(x3, 4); 7991 __ Poke(x4, 5); 7992 Clobber(&masm, x4.GetBit()); 7993 __ Peek(x4, 5); 7994 __ Poke(x5, 6); 7995 Clobber(&masm, x5.GetBit()); 7996 __ Peek(x5, 6); 7997 __ Poke(x6, 7); 7998 Clobber(&masm, x6.GetBit()); 7999 __ Peek(x6, 7); 8000 8001 __ Poke(w0, 1); 8002 Clobber(&masm, w10.GetBit()); 8003 __ Peek(w10, 1); 8004 __ Poke(w1, 2); 8005 Clobber(&masm, w11.GetBit()); 8006 __ Peek(w11, 2); 8007 __ Poke(w2, 3); 8008 Clobber(&masm, w12.GetBit()); 8009 __ Peek(w12, 3); 8010 8011 __ Drop(32); 8012 8013 END(); 8014 if (CAN_RUN()) { 8015 RUN(); 8016 8017 ASSERT_EQUAL_64(literal_base * 1, x0); 8018 ASSERT_EQUAL_64(literal_base * 2, x1); 8019 ASSERT_EQUAL_64(literal_base * 3, x2); 8020 ASSERT_EQUAL_64(literal_base * 4, x3); 8021 ASSERT_EQUAL_64(literal_base * 5, x4); 8022 ASSERT_EQUAL_64(literal_base * 6, x5); 8023 ASSERT_EQUAL_64(literal_base * 7, x6); 8024 8025 ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10); 8026 ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11); 8027 ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12); 8028 } 8029} 8030 8031 8032TEST(peek_poke_endianness) { 8033 SETUP(); 8034 START(); 8035 8036 // The literal base is chosen to have two useful properties: 8037 // * When multiplied by small values (such as a register index), this value 8038 // is clearly readable in the result. 8039 // * The value is not formed from repeating fixed-size smaller values, so it 8040 // can be used to detect endianness-related errors. 8041 uint64_t literal_base = 0x0100001000100101; 8042 8043 // Initialize the registers. 8044 __ Mov(x0, literal_base); 8045 __ Add(x1, x0, x0); 8046 8047 __ Claim(32); 8048 8049 // Endianness tests. 8050 // After this section: 8051 // x4 should match x0[31:0]:x0[63:32] 8052 // w5 should match w1[15:0]:w1[31:16] 8053 __ Poke(x0, 0); 8054 __ Poke(x0, 8); 8055 __ Peek(x4, 4); 8056 8057 __ Poke(w1, 0); 8058 __ Poke(w1, 4); 8059 __ Peek(w5, 2); 8060 8061 __ Drop(32); 8062 8063 END(); 8064 if (CAN_RUN()) { 8065 RUN(); 8066 8067 uint64_t x0_expected = literal_base * 1; 8068 uint64_t x1_expected = literal_base * 2; 8069 uint64_t x4_expected = (x0_expected << 32) | (x0_expected >> 32); 8070 uint64_t x5_expected = 8071 ((x1_expected << 16) & 0xffff0000) | ((x1_expected >> 16) & 0x0000ffff); 8072 8073 ASSERT_EQUAL_64(x0_expected, x0); 8074 ASSERT_EQUAL_64(x1_expected, x1); 8075 ASSERT_EQUAL_64(x4_expected, x4); 8076 ASSERT_EQUAL_64(x5_expected, x5); 8077 } 8078} 8079 8080 8081TEST(peek_poke_mixed) { 8082 SETUP(); 8083 START(); 8084 8085 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 8086 UseScratchRegisterScope temps(&masm); 8087 temps.ExcludeAll(); 8088 8089 // The literal base is chosen to have two useful properties: 8090 // * When multiplied by small values (such as a register index), this value 8091 // is clearly readable in the result. 8092 // * The value is not formed from repeating fixed-size smaller values, so it 8093 // can be used to detect endianness-related errors. 8094 uint64_t literal_base = 0x0100001000100101; 8095 8096 // Initialize the registers. 8097 __ Mov(x0, literal_base); 8098 __ Add(x1, x0, x0); 8099 __ Add(x2, x1, x0); 8100 __ Add(x3, x2, x0); 8101 8102 __ Claim(32); 8103 8104 // Mix with other stack operations. 8105 // After this section: 8106 // x0-x3 should be unchanged. 8107 // x6 should match x1[31:0]:x0[63:32] 8108 // w7 should match x1[15:0]:x0[63:48] 8109 __ Poke(x1, 8); 8110 __ Poke(x0, 0); 8111 { 8112 VIXL_ASSERT(__ StackPointer().Is(sp)); 8113 __ Mov(x4, __ StackPointer()); 8114 __ SetStackPointer(x4); 8115 8116 __ Poke(wzr, 0); // Clobber the space we're about to drop. 8117 __ Drop(4); 8118 __ Peek(x6, 0); 8119 __ Claim(8); 8120 __ Peek(w7, 10); 8121 __ Poke(x3, 28); 8122 __ Poke(xzr, 0); // Clobber the space we're about to drop. 8123 __ Drop(8); 8124 __ Poke(x2, 12); 8125 __ Push(w0); 8126 8127 __ Mov(sp, __ StackPointer()); 8128 __ SetStackPointer(sp); 8129 } 8130 8131 __ Pop(x0, x1, x2, x3); 8132 8133 END(); 8134 if (CAN_RUN()) { 8135 RUN(); 8136 8137 uint64_t x0_expected = literal_base * 1; 8138 uint64_t x1_expected = literal_base * 2; 8139 uint64_t x2_expected = literal_base * 3; 8140 uint64_t x3_expected = literal_base * 4; 8141 uint64_t x6_expected = (x1_expected << 32) | (x0_expected >> 32); 8142 uint64_t x7_expected = 8143 ((x1_expected << 16) & 0xffff0000) | ((x0_expected >> 48) & 0x0000ffff); 8144 8145 ASSERT_EQUAL_64(x0_expected, x0); 8146 ASSERT_EQUAL_64(x1_expected, x1); 8147 ASSERT_EQUAL_64(x2_expected, x2); 8148 ASSERT_EQUAL_64(x3_expected, x3); 8149 ASSERT_EQUAL_64(x6_expected, x6); 8150 ASSERT_EQUAL_64(x7_expected, x7); 8151 } 8152} 8153 8154 8155TEST(peek_poke_reglist) { 8156 SETUP_WITH_FEATURES(CPUFeatures::kFP); 8157 8158 START(); 8159 8160 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 8161 UseScratchRegisterScope temps(&masm); 8162 temps.ExcludeAll(); 8163 8164 // The literal base is chosen to have two useful properties: 8165 // * When multiplied by small values (such as a register index), this value 8166 // is clearly readable in the result. 8167 // * The value is not formed from repeating fixed-size smaller values, so it 8168 // can be used to detect endianness-related errors. 8169 uint64_t base = 0x0100001000100101; 8170 8171 // Initialize the registers. 8172 __ Mov(x1, base); 8173 __ Add(x2, x1, x1); 8174 __ Add(x3, x2, x1); 8175 __ Add(x4, x3, x1); 8176 8177 CPURegList list_1(x1, x2, x3, x4); 8178 CPURegList list_2(x11, x12, x13, x14); 8179 int list_1_size = list_1.GetTotalSizeInBytes(); 8180 8181 __ Claim(2 * list_1_size); 8182 8183 __ PokeCPURegList(list_1, 0); 8184 __ PokeXRegList(list_1.GetList(), list_1_size); 8185 __ PeekCPURegList(list_2, 2 * kXRegSizeInBytes); 8186 __ PeekXRegList(x15.GetBit(), kWRegSizeInBytes); 8187 __ PeekWRegList(w16.GetBit() | w17.GetBit(), 3 * kXRegSizeInBytes); 8188 8189 __ Drop(2 * list_1_size); 8190 8191 8192 uint64_t base_d = 0x1010010001000010; 8193 8194 // Initialize the registers. 8195 __ Mov(x1, base_d); 8196 __ Add(x2, x1, x1); 8197 __ Add(x3, x2, x1); 8198 __ Add(x4, x3, x1); 8199 __ Fmov(d1, x1); 8200 __ Fmov(d2, x2); 8201 __ Fmov(d3, x3); 8202 __ Fmov(d4, x4); 8203 8204 CPURegList list_d_1(d1, d2, d3, d4); 8205 CPURegList list_d_2(d11, d12, d13, d14); 8206 int list_d_1_size = list_d_1.GetTotalSizeInBytes(); 8207 8208 __ Claim(2 * list_d_1_size); 8209 8210 __ PokeCPURegList(list_d_1, 0); 8211 __ PokeDRegList(list_d_1.GetList(), list_d_1_size); 8212 __ PeekCPURegList(list_d_2, 2 * kDRegSizeInBytes); 8213 __ PeekDRegList(d15.GetBit(), kSRegSizeInBytes); 8214 __ PeekSRegList(s16.GetBit() | s17.GetBit(), 3 * kDRegSizeInBytes); 8215 8216 __ Drop(2 * list_d_1_size); 8217 8218 8219 END(); 8220 if (CAN_RUN()) { 8221 RUN(); 8222 8223 ASSERT_EQUAL_64(3 * base, x11); 8224 ASSERT_EQUAL_64(4 * base, x12); 8225 ASSERT_EQUAL_64(1 * base, x13); 8226 ASSERT_EQUAL_64(2 * base, x14); 8227 ASSERT_EQUAL_64(((1 * base) >> kWRegSize) | ((2 * base) << kWRegSize), x15); 8228 ASSERT_EQUAL_64(2 * base, x14); 8229 ASSERT_EQUAL_32((4 * base) & kWRegMask, w16); 8230 ASSERT_EQUAL_32((4 * base) >> kWRegSize, w17); 8231 8232 ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base_d), d11); 8233 ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base_d), d12); 8234 ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base_d), d13); 8235 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14); 8236 ASSERT_EQUAL_FP64(RawbitsToDouble((base_d >> kSRegSize) | 8237 ((2 * base_d) << kSRegSize)), 8238 d15); 8239 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base_d), d14); 8240 ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) & kSRegMask), s16); 8241 ASSERT_EQUAL_FP32(RawbitsToFloat((4 * base_d) >> kSRegSize), s17); 8242 } 8243} 8244 8245 8246TEST(load_store_reglist) { 8247 SETUP_WITH_FEATURES(CPUFeatures::kFP); 8248 8249 START(); 8250 8251 // The literal base is chosen to have two useful properties: 8252 // * When multiplied by small values (such as a register index), this value 8253 // is clearly readable in the result. 8254 // * The value is not formed from repeating fixed-size smaller values, so it 8255 // can be used to detect endianness-related errors. 8256 uint64_t high_base = UINT32_C(0x01000010); 8257 uint64_t low_base = UINT32_C(0x00100101); 8258 uint64_t base = (high_base << 32) | low_base; 8259 uint64_t array[21]; 8260 memset(array, 0, sizeof(array)); 8261 8262 // Initialize the registers. 8263 __ Mov(x1, base); 8264 __ Add(x2, x1, x1); 8265 __ Add(x3, x2, x1); 8266 __ Add(x4, x3, x1); 8267 __ Fmov(d1, x1); 8268 __ Fmov(d2, x2); 8269 __ Fmov(d3, x3); 8270 __ Fmov(d4, x4); 8271 __ Fmov(d5, x1); 8272 __ Fmov(d6, x2); 8273 __ Fmov(d7, x3); 8274 __ Fmov(d8, x4); 8275 8276 Register reg_base = x20; 8277 Register reg_index = x21; 8278 int size_stored = 0; 8279 8280 __ Mov(reg_base, reinterpret_cast<uintptr_t>(&array)); 8281 8282 // Test aligned accesses. 8283 CPURegList list_src(w1, w2, w3, w4); 8284 CPURegList list_dst(w11, w12, w13, w14); 8285 CPURegList list_fp_src_1(d1, d2, d3, d4); 8286 CPURegList list_fp_dst_1(d11, d12, d13, d14); 8287 8288 __ StoreCPURegList(list_src, MemOperand(reg_base, 0 * sizeof(uint64_t))); 8289 __ LoadCPURegList(list_dst, MemOperand(reg_base, 0 * sizeof(uint64_t))); 8290 size_stored += 4 * kWRegSizeInBytes; 8291 8292 __ Mov(reg_index, size_stored); 8293 __ StoreCPURegList(list_src, MemOperand(reg_base, reg_index)); 8294 __ LoadCPURegList(list_dst, MemOperand(reg_base, reg_index)); 8295 size_stored += 4 * kWRegSizeInBytes; 8296 8297 __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, size_stored)); 8298 __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, size_stored)); 8299 size_stored += 4 * kDRegSizeInBytes; 8300 8301 __ Mov(reg_index, size_stored); 8302 __ StoreCPURegList(list_fp_src_1, MemOperand(reg_base, reg_index)); 8303 __ LoadCPURegList(list_fp_dst_1, MemOperand(reg_base, reg_index)); 8304 size_stored += 4 * kDRegSizeInBytes; 8305 8306 // Test unaligned accesses. 8307 CPURegList list_fp_src_2(d5, d6, d7, d8); 8308 CPURegList list_fp_dst_2(d15, d16, d17, d18); 8309 8310 __ Str(wzr, MemOperand(reg_base, size_stored)); 8311 size_stored += 1 * kWRegSizeInBytes; 8312 __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, size_stored)); 8313 __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, size_stored)); 8314 size_stored += 4 * kDRegSizeInBytes; 8315 8316 __ Mov(reg_index, size_stored); 8317 __ StoreCPURegList(list_fp_src_2, MemOperand(reg_base, reg_index)); 8318 __ LoadCPURegList(list_fp_dst_2, MemOperand(reg_base, reg_index)); 8319 8320 END(); 8321 if (CAN_RUN()) { 8322 RUN(); 8323 8324 VIXL_CHECK(array[0] == (1 * low_base) + (2 * low_base << kWRegSize)); 8325 VIXL_CHECK(array[1] == (3 * low_base) + (4 * low_base << kWRegSize)); 8326 VIXL_CHECK(array[2] == (1 * low_base) + (2 * low_base << kWRegSize)); 8327 VIXL_CHECK(array[3] == (3 * low_base) + (4 * low_base << kWRegSize)); 8328 VIXL_CHECK(array[4] == 1 * base); 8329 VIXL_CHECK(array[5] == 2 * base); 8330 VIXL_CHECK(array[6] == 3 * base); 8331 VIXL_CHECK(array[7] == 4 * base); 8332 VIXL_CHECK(array[8] == 1 * base); 8333 VIXL_CHECK(array[9] == 2 * base); 8334 VIXL_CHECK(array[10] == 3 * base); 8335 VIXL_CHECK(array[11] == 4 * base); 8336 VIXL_CHECK(array[12] == ((1 * low_base) << kSRegSize)); 8337 VIXL_CHECK(array[13] == (((2 * low_base) << kSRegSize) | (1 * high_base))); 8338 VIXL_CHECK(array[14] == (((3 * low_base) << kSRegSize) | (2 * high_base))); 8339 VIXL_CHECK(array[15] == (((4 * low_base) << kSRegSize) | (3 * high_base))); 8340 VIXL_CHECK(array[16] == (((1 * low_base) << kSRegSize) | (4 * high_base))); 8341 VIXL_CHECK(array[17] == (((2 * low_base) << kSRegSize) | (1 * high_base))); 8342 VIXL_CHECK(array[18] == (((3 * low_base) << kSRegSize) | (2 * high_base))); 8343 VIXL_CHECK(array[19] == (((4 * low_base) << kSRegSize) | (3 * high_base))); 8344 VIXL_CHECK(array[20] == (4 * high_base)); 8345 8346 ASSERT_EQUAL_64(1 * low_base, x11); 8347 ASSERT_EQUAL_64(2 * low_base, x12); 8348 ASSERT_EQUAL_64(3 * low_base, x13); 8349 ASSERT_EQUAL_64(4 * low_base, x14); 8350 ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d11); 8351 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d12); 8352 ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d13); 8353 ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d14); 8354 ASSERT_EQUAL_FP64(RawbitsToDouble(1 * base), d15); 8355 ASSERT_EQUAL_FP64(RawbitsToDouble(2 * base), d16); 8356 ASSERT_EQUAL_FP64(RawbitsToDouble(3 * base), d17); 8357 ASSERT_EQUAL_FP64(RawbitsToDouble(4 * base), d18); 8358 } 8359} 8360 8361 8362// This enum is used only as an argument to the push-pop test helpers. 8363enum PushPopMethod { 8364 // Push or Pop using the Push and Pop methods, with blocks of up to four 8365 // registers. (Smaller blocks will be used if necessary.) 8366 PushPopByFour, 8367 8368 // Use Push<Size>RegList and Pop<Size>RegList to transfer the registers. 8369 PushPopRegList 8370}; 8371 8372 8373// For the PushPop* tests, use the maximum number of registers that the test 8374// supports (where a reg_count argument would otherwise be provided). 8375static int const kPushPopUseMaxRegCount = -1; 8376 8377// Test a simple push-pop pattern: 8378// * Claim <claim> bytes to set the stack alignment. 8379// * Push <reg_count> registers with size <reg_size>. 8380// * Clobber the register contents. 8381// * Pop <reg_count> registers to restore the original contents. 8382// * Drop <claim> bytes to restore the original stack pointer. 8383// 8384// Different push and pop methods can be specified independently to test for 8385// proper word-endian behaviour. 8386static void PushPopSimpleHelper(int reg_count, 8387 int claim, 8388 int reg_size, 8389 PushPopMethod push_method, 8390 PushPopMethod pop_method) { 8391 SETUP(); 8392 8393 START(); 8394 8395 // Arbitrarily pick a register to use as a stack pointer. 8396 const Register& stack_pointer = x20; 8397 const RegList allowed = ~stack_pointer.GetBit(); 8398 if (reg_count == kPushPopUseMaxRegCount) { 8399 reg_count = CountSetBits(allowed, kNumberOfRegisters); 8400 } 8401 // Work out which registers to use, based on reg_size. 8402 Register r[kNumberOfRegisters]; 8403 Register x[kNumberOfRegisters]; 8404 RegList list = 8405 PopulateRegisterArray(NULL, x, r, reg_size, reg_count, allowed); 8406 8407 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 8408 UseScratchRegisterScope temps(&masm); 8409 temps.ExcludeAll(); 8410 8411 // The literal base is chosen to have two useful properties: 8412 // * When multiplied by small values (such as a register index), this value 8413 // is clearly readable in the result. 8414 // * The value is not formed from repeating fixed-size smaller values, so it 8415 // can be used to detect endianness-related errors. 8416 uint64_t literal_base = 0x0100001000100101; 8417 8418 { 8419 VIXL_ASSERT(__ StackPointer().Is(sp)); 8420 __ Mov(stack_pointer, __ StackPointer()); 8421 __ SetStackPointer(stack_pointer); 8422 8423 int i; 8424 8425 // Initialize the registers. 8426 for (i = 0; i < reg_count; i++) { 8427 // Always write into the X register, to ensure that the upper word is 8428 // properly ignored by Push when testing W registers. 8429 __ Mov(x[i], literal_base * i); 8430 } 8431 8432 // Claim memory first, as requested. 8433 __ Claim(claim); 8434 8435 switch (push_method) { 8436 case PushPopByFour: 8437 // Push high-numbered registers first (to the highest addresses). 8438 for (i = reg_count; i >= 4; i -= 4) { 8439 __ Push(r[i - 1], r[i - 2], r[i - 3], r[i - 4]); 8440 } 8441 // Finish off the leftovers. 8442 switch (i) { 8443 case 3: 8444 __ Push(r[2], r[1], r[0]); 8445 break; 8446 case 2: 8447 __ Push(r[1], r[0]); 8448 break; 8449 case 1: 8450 __ Push(r[0]); 8451 break; 8452 default: 8453 VIXL_ASSERT(i == 0); 8454 break; 8455 } 8456 break; 8457 case PushPopRegList: 8458 __ PushSizeRegList(list, reg_size); 8459 break; 8460 } 8461 8462 // Clobber all the registers, to ensure that they get repopulated by Pop. 8463 Clobber(&masm, list); 8464 8465 switch (pop_method) { 8466 case PushPopByFour: 8467 // Pop low-numbered registers first (from the lowest addresses). 8468 for (i = 0; i <= (reg_count - 4); i += 4) { 8469 __ Pop(r[i], r[i + 1], r[i + 2], r[i + 3]); 8470 } 8471 // Finish off the leftovers. 8472 switch (reg_count - i) { 8473 case 3: 8474 __ Pop(r[i], r[i + 1], r[i + 2]); 8475 break; 8476 case 2: 8477 __ Pop(r[i], r[i + 1]); 8478 break; 8479 case 1: 8480 __ Pop(r[i]); 8481 break; 8482 default: 8483 VIXL_ASSERT(i == reg_count); 8484 break; 8485 } 8486 break; 8487 case PushPopRegList: 8488 __ PopSizeRegList(list, reg_size); 8489 break; 8490 } 8491 8492 // Drop memory to restore stack_pointer. 8493 __ Drop(claim); 8494 8495 __ Mov(sp, __ StackPointer()); 8496 __ SetStackPointer(sp); 8497 } 8498 8499 END(); 8500 8501 if (CAN_RUN()) { 8502 RUN(); 8503 8504 // Check that the register contents were preserved. 8505 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test 8506 // that the upper word was properly cleared by Pop. 8507 literal_base &= (0xffffffffffffffff >> (64 - reg_size)); 8508 for (int i = 0; i < reg_count; i++) { 8509 if (x[i].Is(xzr)) { 8510 ASSERT_EQUAL_64(0, x[i]); 8511 } else { 8512 ASSERT_EQUAL_64(literal_base * i, x[i]); 8513 } 8514 } 8515 } 8516} 8517 8518 8519TEST(push_pop_xreg_simple_32) { 8520 for (int claim = 0; claim <= 8; claim++) { 8521 for (int count = 0; count <= 8; count++) { 8522 PushPopSimpleHelper(count, 8523 claim, 8524 kWRegSize, 8525 PushPopByFour, 8526 PushPopByFour); 8527 PushPopSimpleHelper(count, 8528 claim, 8529 kWRegSize, 8530 PushPopByFour, 8531 PushPopRegList); 8532 PushPopSimpleHelper(count, 8533 claim, 8534 kWRegSize, 8535 PushPopRegList, 8536 PushPopByFour); 8537 PushPopSimpleHelper(count, 8538 claim, 8539 kWRegSize, 8540 PushPopRegList, 8541 PushPopRegList); 8542 } 8543 // Test with the maximum number of registers. 8544 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8545 claim, 8546 kWRegSize, 8547 PushPopByFour, 8548 PushPopByFour); 8549 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8550 claim, 8551 kWRegSize, 8552 PushPopByFour, 8553 PushPopRegList); 8554 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8555 claim, 8556 kWRegSize, 8557 PushPopRegList, 8558 PushPopByFour); 8559 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8560 claim, 8561 kWRegSize, 8562 PushPopRegList, 8563 PushPopRegList); 8564 } 8565} 8566 8567 8568TEST(push_pop_xreg_simple_64) { 8569 for (int claim = 0; claim <= 8; claim++) { 8570 for (int count = 0; count <= 8; count++) { 8571 PushPopSimpleHelper(count, 8572 claim, 8573 kXRegSize, 8574 PushPopByFour, 8575 PushPopByFour); 8576 PushPopSimpleHelper(count, 8577 claim, 8578 kXRegSize, 8579 PushPopByFour, 8580 PushPopRegList); 8581 PushPopSimpleHelper(count, 8582 claim, 8583 kXRegSize, 8584 PushPopRegList, 8585 PushPopByFour); 8586 PushPopSimpleHelper(count, 8587 claim, 8588 kXRegSize, 8589 PushPopRegList, 8590 PushPopRegList); 8591 } 8592 // Test with the maximum number of registers. 8593 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8594 claim, 8595 kXRegSize, 8596 PushPopByFour, 8597 PushPopByFour); 8598 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8599 claim, 8600 kXRegSize, 8601 PushPopByFour, 8602 PushPopRegList); 8603 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8604 claim, 8605 kXRegSize, 8606 PushPopRegList, 8607 PushPopByFour); 8608 PushPopSimpleHelper(kPushPopUseMaxRegCount, 8609 claim, 8610 kXRegSize, 8611 PushPopRegList, 8612 PushPopRegList); 8613 } 8614} 8615 8616// For the PushPopFP* tests, use the maximum number of registers that the test 8617// supports (where a reg_count argument would otherwise be provided). 8618static int const kPushPopFPUseMaxRegCount = -1; 8619 8620// Test a simple push-pop pattern: 8621// * Claim <claim> bytes to set the stack alignment. 8622// * Push <reg_count> FP registers with size <reg_size>. 8623// * Clobber the register contents. 8624// * Pop <reg_count> FP registers to restore the original contents. 8625// * Drop <claim> bytes to restore the original stack pointer. 8626// 8627// Different push and pop methods can be specified independently to test for 8628// proper word-endian behaviour. 8629static void PushPopFPSimpleHelper(int reg_count, 8630 int claim, 8631 int reg_size, 8632 PushPopMethod push_method, 8633 PushPopMethod pop_method) { 8634 SETUP_WITH_FEATURES((reg_count == 0) ? CPUFeatures::kNone : CPUFeatures::kFP); 8635 8636 START(); 8637 8638 // We can use any floating-point register. None of them are reserved for 8639 // debug code, for example. 8640 static RegList const allowed = ~0; 8641 if (reg_count == kPushPopFPUseMaxRegCount) { 8642 reg_count = CountSetBits(allowed, kNumberOfVRegisters); 8643 } 8644 // Work out which registers to use, based on reg_size. 8645 VRegister v[kNumberOfRegisters]; 8646 VRegister d[kNumberOfRegisters]; 8647 RegList list = 8648 PopulateVRegisterArray(NULL, d, v, reg_size, reg_count, allowed); 8649 8650 // Arbitrarily pick a register to use as a stack pointer. 8651 const Register& stack_pointer = x10; 8652 8653 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 8654 UseScratchRegisterScope temps(&masm); 8655 temps.ExcludeAll(); 8656 8657 // The literal base is chosen to have two useful properties: 8658 // * When multiplied (using an integer) by small values (such as a register 8659 // index), this value is clearly readable in the result. 8660 // * The value is not formed from repeating fixed-size smaller values, so it 8661 // can be used to detect endianness-related errors. 8662 // * It is never a floating-point NaN, and will therefore always compare 8663 // equal to itself. 8664 uint64_t literal_base = 0x0100001000100101; 8665 8666 { 8667 VIXL_ASSERT(__ StackPointer().Is(sp)); 8668 __ Mov(stack_pointer, __ StackPointer()); 8669 __ SetStackPointer(stack_pointer); 8670 8671 int i; 8672 8673 // Initialize the registers, using X registers to load the literal. 8674 __ Mov(x0, 0); 8675 __ Mov(x1, literal_base); 8676 for (i = 0; i < reg_count; i++) { 8677 // Always write into the D register, to ensure that the upper word is 8678 // properly ignored by Push when testing S registers. 8679 __ Fmov(d[i], x0); 8680 // Calculate the next literal. 8681 __ Add(x0, x0, x1); 8682 } 8683 8684 // Claim memory first, as requested. 8685 __ Claim(claim); 8686 8687 switch (push_method) { 8688 case PushPopByFour: 8689 // Push high-numbered registers first (to the highest addresses). 8690 for (i = reg_count; i >= 4; i -= 4) { 8691 __ Push(v[i - 1], v[i - 2], v[i - 3], v[i - 4]); 8692 } 8693 // Finish off the leftovers. 8694 switch (i) { 8695 case 3: 8696 __ Push(v[2], v[1], v[0]); 8697 break; 8698 case 2: 8699 __ Push(v[1], v[0]); 8700 break; 8701 case 1: 8702 __ Push(v[0]); 8703 break; 8704 default: 8705 VIXL_ASSERT(i == 0); 8706 break; 8707 } 8708 break; 8709 case PushPopRegList: 8710 __ PushSizeRegList(list, reg_size, CPURegister::kVRegister); 8711 break; 8712 } 8713 8714 // Clobber all the registers, to ensure that they get repopulated by Pop. 8715 ClobberFP(&masm, list); 8716 8717 switch (pop_method) { 8718 case PushPopByFour: 8719 // Pop low-numbered registers first (from the lowest addresses). 8720 for (i = 0; i <= (reg_count - 4); i += 4) { 8721 __ Pop(v[i], v[i + 1], v[i + 2], v[i + 3]); 8722 } 8723 // Finish off the leftovers. 8724 switch (reg_count - i) { 8725 case 3: 8726 __ Pop(v[i], v[i + 1], v[i + 2]); 8727 break; 8728 case 2: 8729 __ Pop(v[i], v[i + 1]); 8730 break; 8731 case 1: 8732 __ Pop(v[i]); 8733 break; 8734 default: 8735 VIXL_ASSERT(i == reg_count); 8736 break; 8737 } 8738 break; 8739 case PushPopRegList: 8740 __ PopSizeRegList(list, reg_size, CPURegister::kVRegister); 8741 break; 8742 } 8743 8744 // Drop memory to restore the stack pointer. 8745 __ Drop(claim); 8746 8747 __ Mov(sp, __ StackPointer()); 8748 __ SetStackPointer(sp); 8749 } 8750 8751 END(); 8752 8753 if (CAN_RUN()) { 8754 RUN(); 8755 8756 // Check that the register contents were preserved. 8757 // Always use ASSERT_EQUAL_FP64, even when testing S registers, so we can 8758 // test that the upper word was properly cleared by Pop. 8759 literal_base &= (0xffffffffffffffff >> (64 - reg_size)); 8760 for (int i = 0; i < reg_count; i++) { 8761 uint64_t literal = literal_base * i; 8762 double expected; 8763 memcpy(&expected, &literal, sizeof(expected)); 8764 ASSERT_EQUAL_FP64(expected, d[i]); 8765 } 8766 } 8767} 8768 8769 8770TEST(push_pop_fp_xreg_simple_32) { 8771 for (int claim = 0; claim <= 8; claim++) { 8772 for (int count = 0; count <= 8; count++) { 8773 PushPopFPSimpleHelper(count, 8774 claim, 8775 kSRegSize, 8776 PushPopByFour, 8777 PushPopByFour); 8778 PushPopFPSimpleHelper(count, 8779 claim, 8780 kSRegSize, 8781 PushPopByFour, 8782 PushPopRegList); 8783 PushPopFPSimpleHelper(count, 8784 claim, 8785 kSRegSize, 8786 PushPopRegList, 8787 PushPopByFour); 8788 PushPopFPSimpleHelper(count, 8789 claim, 8790 kSRegSize, 8791 PushPopRegList, 8792 PushPopRegList); 8793 } 8794 // Test with the maximum number of registers. 8795 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8796 claim, 8797 kSRegSize, 8798 PushPopByFour, 8799 PushPopByFour); 8800 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8801 claim, 8802 kSRegSize, 8803 PushPopByFour, 8804 PushPopRegList); 8805 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8806 claim, 8807 kSRegSize, 8808 PushPopRegList, 8809 PushPopByFour); 8810 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8811 claim, 8812 kSRegSize, 8813 PushPopRegList, 8814 PushPopRegList); 8815 } 8816} 8817 8818 8819TEST(push_pop_fp_xreg_simple_64) { 8820 for (int claim = 0; claim <= 8; claim++) { 8821 for (int count = 0; count <= 8; count++) { 8822 PushPopFPSimpleHelper(count, 8823 claim, 8824 kDRegSize, 8825 PushPopByFour, 8826 PushPopByFour); 8827 PushPopFPSimpleHelper(count, 8828 claim, 8829 kDRegSize, 8830 PushPopByFour, 8831 PushPopRegList); 8832 PushPopFPSimpleHelper(count, 8833 claim, 8834 kDRegSize, 8835 PushPopRegList, 8836 PushPopByFour); 8837 PushPopFPSimpleHelper(count, 8838 claim, 8839 kDRegSize, 8840 PushPopRegList, 8841 PushPopRegList); 8842 } 8843 // Test with the maximum number of registers. 8844 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8845 claim, 8846 kDRegSize, 8847 PushPopByFour, 8848 PushPopByFour); 8849 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8850 claim, 8851 kDRegSize, 8852 PushPopByFour, 8853 PushPopRegList); 8854 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8855 claim, 8856 kDRegSize, 8857 PushPopRegList, 8858 PushPopByFour); 8859 PushPopFPSimpleHelper(kPushPopFPUseMaxRegCount, 8860 claim, 8861 kDRegSize, 8862 PushPopRegList, 8863 PushPopRegList); 8864 } 8865} 8866 8867 8868// Push and pop data using an overlapping combination of Push/Pop and 8869// RegList-based methods. 8870static void PushPopMixedMethodsHelper(int claim, int reg_size) { 8871 SETUP(); 8872 8873 // Arbitrarily pick a register to use as a stack pointer. 8874 const Register& stack_pointer = x5; 8875 const RegList allowed = ~stack_pointer.GetBit(); 8876 // Work out which registers to use, based on reg_size. 8877 Register r[10]; 8878 Register x[10]; 8879 PopulateRegisterArray(NULL, x, r, reg_size, 10, allowed); 8880 8881 // Calculate some handy register lists. 8882 RegList r0_to_r3 = 0; 8883 for (int i = 0; i <= 3; i++) { 8884 r0_to_r3 |= x[i].GetBit(); 8885 } 8886 RegList r4_to_r5 = 0; 8887 for (int i = 4; i <= 5; i++) { 8888 r4_to_r5 |= x[i].GetBit(); 8889 } 8890 RegList r6_to_r9 = 0; 8891 for (int i = 6; i <= 9; i++) { 8892 r6_to_r9 |= x[i].GetBit(); 8893 } 8894 8895 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 8896 UseScratchRegisterScope temps(&masm); 8897 temps.ExcludeAll(); 8898 8899 // The literal base is chosen to have two useful properties: 8900 // * When multiplied by small values (such as a register index), this value 8901 // is clearly readable in the result. 8902 // * The value is not formed from repeating fixed-size smaller values, so it 8903 // can be used to detect endianness-related errors. 8904 uint64_t literal_base = 0x0100001000100101; 8905 8906 START(); 8907 { 8908 VIXL_ASSERT(__ StackPointer().Is(sp)); 8909 __ Mov(stack_pointer, __ StackPointer()); 8910 __ SetStackPointer(stack_pointer); 8911 8912 // Claim memory first, as requested. 8913 __ Claim(claim); 8914 8915 __ Mov(x[3], literal_base * 3); 8916 __ Mov(x[2], literal_base * 2); 8917 __ Mov(x[1], literal_base * 1); 8918 __ Mov(x[0], literal_base * 0); 8919 8920 __ PushSizeRegList(r0_to_r3, reg_size); 8921 __ Push(r[3], r[2]); 8922 8923 Clobber(&masm, r0_to_r3); 8924 __ PopSizeRegList(r0_to_r3, reg_size); 8925 8926 __ Push(r[2], r[1], r[3], r[0]); 8927 8928 Clobber(&masm, r4_to_r5); 8929 __ Pop(r[4], r[5]); 8930 Clobber(&masm, r6_to_r9); 8931 __ Pop(r[6], r[7], r[8], r[9]); 8932 8933 // Drop memory to restore stack_pointer. 8934 __ Drop(claim); 8935 8936 __ Mov(sp, __ StackPointer()); 8937 __ SetStackPointer(sp); 8938 } 8939 8940 END(); 8941 8942 if (CAN_RUN()) { 8943 RUN(); 8944 8945 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test 8946 // that the upper word was properly cleared by Pop. 8947 literal_base &= (0xffffffffffffffff >> (64 - reg_size)); 8948 8949 ASSERT_EQUAL_64(literal_base * 3, x[9]); 8950 ASSERT_EQUAL_64(literal_base * 2, x[8]); 8951 ASSERT_EQUAL_64(literal_base * 0, x[7]); 8952 ASSERT_EQUAL_64(literal_base * 3, x[6]); 8953 ASSERT_EQUAL_64(literal_base * 1, x[5]); 8954 ASSERT_EQUAL_64(literal_base * 2, x[4]); 8955 } 8956} 8957 8958 8959TEST(push_pop_xreg_mixed_methods_64) { 8960 for (int claim = 0; claim <= 8; claim++) { 8961 PushPopMixedMethodsHelper(claim, kXRegSize); 8962 } 8963} 8964 8965 8966TEST(push_pop_xreg_mixed_methods_32) { 8967 for (int claim = 0; claim <= 8; claim++) { 8968 PushPopMixedMethodsHelper(claim, kWRegSize); 8969 } 8970} 8971 8972 8973// Push and pop data using overlapping X- and W-sized quantities. 8974static void PushPopWXOverlapHelper(int reg_count, int claim) { 8975 SETUP(); 8976 8977 // Arbitrarily pick a register to use as a stack pointer. 8978 const Register& stack_pointer = x10; 8979 const RegList allowed = ~stack_pointer.GetBit(); 8980 if (reg_count == kPushPopUseMaxRegCount) { 8981 reg_count = CountSetBits(allowed, kNumberOfRegisters); 8982 } 8983 // Work out which registers to use, based on reg_size. 8984 Register w[kNumberOfRegisters]; 8985 Register x[kNumberOfRegisters]; 8986 RegList list = PopulateRegisterArray(w, x, NULL, 0, reg_count, allowed); 8987 8988 // The number of W-sized slots we expect to pop. When we pop, we alternate 8989 // between W and X registers, so we need reg_count*1.5 W-sized slots. 8990 int const requested_w_slots = reg_count + reg_count / 2; 8991 8992 // Track what _should_ be on the stack, using W-sized slots. 8993 static int const kMaxWSlots = kNumberOfRegisters + kNumberOfRegisters / 2; 8994 uint32_t stack[kMaxWSlots]; 8995 for (int i = 0; i < kMaxWSlots; i++) { 8996 stack[i] = 0xdeadbeef; 8997 } 8998 8999 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 9000 UseScratchRegisterScope temps(&masm); 9001 temps.ExcludeAll(); 9002 9003 // The literal base is chosen to have two useful properties: 9004 // * When multiplied by small values (such as a register index), this value 9005 // is clearly readable in the result. 9006 // * The value is not formed from repeating fixed-size smaller values, so it 9007 // can be used to detect endianness-related errors. 9008 static uint64_t const literal_base = 0x0100001000100101; 9009 static uint64_t const literal_base_hi = literal_base >> 32; 9010 static uint64_t const literal_base_lo = literal_base & 0xffffffff; 9011 static uint64_t const literal_base_w = literal_base & 0xffffffff; 9012 9013 START(); 9014 { 9015 VIXL_ASSERT(__ StackPointer().Is(sp)); 9016 __ Mov(stack_pointer, __ StackPointer()); 9017 __ SetStackPointer(stack_pointer); 9018 9019 // Initialize the registers. 9020 for (int i = 0; i < reg_count; i++) { 9021 // Always write into the X register, to ensure that the upper word is 9022 // properly ignored by Push when testing W registers. 9023 __ Mov(x[i], literal_base * i); 9024 } 9025 9026 // Claim memory first, as requested. 9027 __ Claim(claim); 9028 9029 // The push-pop pattern is as follows: 9030 // Push: Pop: 9031 // x[0](hi) -> w[0] 9032 // x[0](lo) -> x[1](hi) 9033 // w[1] -> x[1](lo) 9034 // w[1] -> w[2] 9035 // x[2](hi) -> x[2](hi) 9036 // x[2](lo) -> x[2](lo) 9037 // x[2](hi) -> w[3] 9038 // x[2](lo) -> x[4](hi) 9039 // x[2](hi) -> x[4](lo) 9040 // x[2](lo) -> w[5] 9041 // w[3] -> x[5](hi) 9042 // w[3] -> x[6](lo) 9043 // w[3] -> w[7] 9044 // w[3] -> x[8](hi) 9045 // x[4](hi) -> x[8](lo) 9046 // x[4](lo) -> w[9] 9047 // ... pattern continues ... 9048 // 9049 // That is, registers are pushed starting with the lower numbers, 9050 // alternating between x and w registers, and pushing i%4+1 copies of each, 9051 // where i is the register number. 9052 // Registers are popped starting with the higher numbers one-by-one, 9053 // alternating between x and w registers, but only popping one at a time. 9054 // 9055 // This pattern provides a wide variety of alignment effects and overlaps. 9056 9057 // ---- Push ---- 9058 9059 int active_w_slots = 0; 9060 for (int i = 0; active_w_slots < requested_w_slots; i++) { 9061 VIXL_ASSERT(i < reg_count); 9062 // In order to test various arguments to PushMultipleTimes, and to try to 9063 // exercise different alignment and overlap effects, we push each 9064 // register a different number of times. 9065 int times = i % 4 + 1; 9066 if (i & 1) { 9067 // Push odd-numbered registers as W registers. 9068 __ PushMultipleTimes(times, w[i]); 9069 // Fill in the expected stack slots. 9070 for (int j = 0; j < times; j++) { 9071 if (w[i].Is(wzr)) { 9072 // The zero register always writes zeroes. 9073 stack[active_w_slots++] = 0; 9074 } else { 9075 stack[active_w_slots++] = literal_base_w * i; 9076 } 9077 } 9078 } else { 9079 // Push even-numbered registers as X registers. 9080 __ PushMultipleTimes(times, x[i]); 9081 // Fill in the expected stack slots. 9082 for (int j = 0; j < times; j++) { 9083 if (x[i].Is(xzr)) { 9084 // The zero register always writes zeroes. 9085 stack[active_w_slots++] = 0; 9086 stack[active_w_slots++] = 0; 9087 } else { 9088 stack[active_w_slots++] = literal_base_hi * i; 9089 stack[active_w_slots++] = literal_base_lo * i; 9090 } 9091 } 9092 } 9093 } 9094 // Because we were pushing several registers at a time, we probably pushed 9095 // more than we needed to. 9096 if (active_w_slots > requested_w_slots) { 9097 __ Drop((active_w_slots - requested_w_slots) * kWRegSizeInBytes); 9098 // Bump the number of active W-sized slots back to where it should be, 9099 // and fill the empty space with a placeholder value. 9100 do { 9101 stack[active_w_slots--] = 0xdeadbeef; 9102 } while (active_w_slots > requested_w_slots); 9103 } 9104 9105 // ---- Pop ---- 9106 9107 Clobber(&masm, list); 9108 9109 // If popping an even number of registers, the first one will be X-sized. 9110 // Otherwise, the first one will be W-sized. 9111 bool next_is_64 = !(reg_count & 1); 9112 for (int i = reg_count - 1; i >= 0; i--) { 9113 if (next_is_64) { 9114 __ Pop(x[i]); 9115 active_w_slots -= 2; 9116 } else { 9117 __ Pop(w[i]); 9118 active_w_slots -= 1; 9119 } 9120 next_is_64 = !next_is_64; 9121 } 9122 VIXL_ASSERT(active_w_slots == 0); 9123 9124 // Drop memory to restore stack_pointer. 9125 __ Drop(claim); 9126 9127 __ Mov(sp, __ StackPointer()); 9128 __ SetStackPointer(sp); 9129 } 9130 9131 END(); 9132 9133 if (CAN_RUN()) { 9134 RUN(); 9135 9136 int slot = 0; 9137 for (int i = 0; i < reg_count; i++) { 9138 // Even-numbered registers were written as W registers. 9139 // Odd-numbered registers were written as X registers. 9140 bool expect_64 = (i & 1); 9141 uint64_t expected; 9142 9143 if (expect_64) { 9144 uint64_t hi = stack[slot++]; 9145 uint64_t lo = stack[slot++]; 9146 expected = (hi << 32) | lo; 9147 } else { 9148 expected = stack[slot++]; 9149 } 9150 9151 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can 9152 // test that the upper word was properly cleared by Pop. 9153 if (x[i].Is(xzr)) { 9154 ASSERT_EQUAL_64(0, x[i]); 9155 } else { 9156 ASSERT_EQUAL_64(expected, x[i]); 9157 } 9158 } 9159 VIXL_ASSERT(slot == requested_w_slots); 9160 } 9161} 9162 9163 9164TEST(push_pop_xreg_wx_overlap) { 9165 for (int claim = 0; claim <= 8; claim++) { 9166 for (int count = 1; count <= 8; count++) { 9167 PushPopWXOverlapHelper(count, claim); 9168 } 9169 // Test with the maximum number of registers. 9170 PushPopWXOverlapHelper(kPushPopUseMaxRegCount, claim); 9171 } 9172} 9173 9174 9175TEST(push_pop_sp) { 9176 SETUP(); 9177 9178 START(); 9179 9180 VIXL_ASSERT(sp.Is(__ StackPointer())); 9181 9182 // Acquire all temps from the MacroAssembler. They are used arbitrarily below. 9183 UseScratchRegisterScope temps(&masm); 9184 temps.ExcludeAll(); 9185 9186 __ Mov(x3, 0x3333333333333333); 9187 __ Mov(x2, 0x2222222222222222); 9188 __ Mov(x1, 0x1111111111111111); 9189 __ Mov(x0, 0x0000000000000000); 9190 __ Claim(2 * kXRegSizeInBytes); 9191 __ PushXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit()); 9192 __ Push(x3, x2); 9193 __ PopXRegList(x0.GetBit() | x1.GetBit() | x2.GetBit() | x3.GetBit()); 9194 __ Push(x2, x1, x3, x0); 9195 __ Pop(x4, x5); 9196 __ Pop(x6, x7, x8, x9); 9197 9198 __ Claim(2 * kXRegSizeInBytes); 9199 __ PushWRegList(w0.GetBit() | w1.GetBit() | w2.GetBit() | w3.GetBit()); 9200 __ Push(w3, w1, w2, w0); 9201 __ PopWRegList(w10.GetBit() | w11.GetBit() | w12.GetBit() | w13.GetBit()); 9202 __ Pop(w14, w15, w16, w17); 9203 9204 __ Claim(2 * kXRegSizeInBytes); 9205 __ Push(w2, w2, w1, w1); 9206 __ Push(x3, x3); 9207 __ Pop(w18, w19, w20, w21); 9208 __ Pop(x22, x23); 9209 9210 __ Claim(2 * kXRegSizeInBytes); 9211 __ PushXRegList(x1.GetBit() | x22.GetBit()); 9212 __ PopXRegList(x24.GetBit() | x26.GetBit()); 9213 9214 __ Claim(2 * kXRegSizeInBytes); 9215 __ PushWRegList(w1.GetBit() | w2.GetBit() | w4.GetBit() | w22.GetBit()); 9216 __ PopWRegList(w25.GetBit() | w27.GetBit() | w28.GetBit() | w29.GetBit()); 9217 9218 __ Claim(2 * kXRegSizeInBytes); 9219 __ PushXRegList(0); 9220 __ PopXRegList(0); 9221 __ PushXRegList(0xffffffff); 9222 __ PopXRegList(0xffffffff); 9223 __ Drop(12 * kXRegSizeInBytes); 9224 END(); 9225 9226 if (CAN_RUN()) { 9227 RUN(); 9228 9229 ASSERT_EQUAL_64(0x1111111111111111, x3); 9230 ASSERT_EQUAL_64(0x0000000000000000, x2); 9231 ASSERT_EQUAL_64(0x3333333333333333, x1); 9232 ASSERT_EQUAL_64(0x2222222222222222, x0); 9233 ASSERT_EQUAL_64(0x3333333333333333, x9); 9234 ASSERT_EQUAL_64(0x2222222222222222, x8); 9235 ASSERT_EQUAL_64(0x0000000000000000, x7); 9236 ASSERT_EQUAL_64(0x3333333333333333, x6); 9237 ASSERT_EQUAL_64(0x1111111111111111, x5); 9238 ASSERT_EQUAL_64(0x2222222222222222, x4); 9239 9240 ASSERT_EQUAL_32(0x11111111U, w13); 9241 ASSERT_EQUAL_32(0x33333333U, w12); 9242 ASSERT_EQUAL_32(0x00000000U, w11); 9243 ASSERT_EQUAL_32(0x22222222U, w10); 9244 ASSERT_EQUAL_32(0x11111111U, w17); 9245 ASSERT_EQUAL_32(0x00000000U, w16); 9246 ASSERT_EQUAL_32(0x33333333U, w15); 9247 ASSERT_EQUAL_32(0x22222222U, w14); 9248 9249 ASSERT_EQUAL_32(0x11111111U, w18); 9250 ASSERT_EQUAL_32(0x11111111U, w19); 9251 ASSERT_EQUAL_32(0x11111111U, w20); 9252 ASSERT_EQUAL_32(0x11111111U, w21); 9253 ASSERT_EQUAL_64(0x3333333333333333, x22); 9254 ASSERT_EQUAL_64(0x0000000000000000, x23); 9255 9256 ASSERT_EQUAL_64(0x3333333333333333, x24); 9257 ASSERT_EQUAL_64(0x3333333333333333, x26); 9258 9259 ASSERT_EQUAL_32(0x33333333U, w25); 9260 ASSERT_EQUAL_32(0x00000000U, w27); 9261 ASSERT_EQUAL_32(0x22222222U, w28); 9262 ASSERT_EQUAL_32(0x33333333U, w29); 9263 } 9264} 9265 9266 9267TEST(printf) { 9268 // RegisterDump::Dump uses NEON. 9269 // Printf uses FP to cast FP arguments to doubles. 9270 SETUP_WITH_FEATURES(CPUFeatures::kNEON, CPUFeatures::kFP); 9271 9272 START(); 9273 9274 char const* test_plain_string = "Printf with no arguments.\n"; 9275 char const* test_substring = "'This is a substring.'"; 9276 RegisterDump before; 9277 9278 // Initialize x29 to the value of the stack pointer. We will use x29 as a 9279 // temporary stack pointer later, and initializing it in this way allows the 9280 // RegisterDump check to pass. 9281 __ Mov(x29, __ StackPointer()); 9282 9283 // Test simple integer arguments. 9284 __ Mov(x0, 1234); 9285 __ Mov(x1, 0x1234); 9286 9287 // Test simple floating-point arguments. 9288 __ Fmov(d0, 1.234); 9289 9290 // Test pointer (string) arguments. 9291 __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring)); 9292 9293 // Test the maximum number of arguments, and sign extension. 9294 __ Mov(w3, 0xffffffff); 9295 __ Mov(w4, 0xffffffff); 9296 __ Mov(x5, 0xffffffffffffffff); 9297 __ Mov(x6, 0xffffffffffffffff); 9298 __ Fmov(s1, 1.234); 9299 __ Fmov(s2, 2.345); 9300 __ Fmov(d3, 3.456); 9301 __ Fmov(d4, 4.567); 9302 9303 // Test printing callee-saved registers. 9304 __ Mov(x28, 0x123456789abcdef); 9305 __ Fmov(d10, 42.0); 9306 9307 // Test with three arguments. 9308 __ Mov(x10, 3); 9309 __ Mov(x11, 40); 9310 __ Mov(x12, 500); 9311 9312 // A single character. 9313 __ Mov(w13, 'x'); 9314 9315 // Check that we don't clobber any registers. 9316 before.Dump(&masm); 9317 9318 __ Printf(test_plain_string); // NOLINT(runtime/printf) 9319 __ Printf("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1); 9320 __ Printf("w5: %" PRId32 ", x5: %" PRId64 "\n", w5, x5); 9321 __ Printf("d0: %f\n", d0); 9322 __ Printf("Test %%s: %s\n", x2); 9323 __ Printf("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32 9324 "\n" 9325 "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n", 9326 w3, 9327 w4, 9328 x5, 9329 x6); 9330 __ Printf("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4); 9331 __ Printf("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28); 9332 __ Printf("%g\n", d10); 9333 __ Printf("%%%%%s%%%c%%\n", x2, w13); 9334 9335 // Print the stack pointer (sp). 9336 __ Printf("StackPointer(sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n", 9337 __ StackPointer(), 9338 __ StackPointer().W()); 9339 9340 // Test with a different stack pointer. 9341 const Register old_stack_pointer = __ StackPointer(); 9342 __ Mov(x29, old_stack_pointer); 9343 __ SetStackPointer(x29); 9344 // Print the stack pointer (not sp). 9345 __ Printf("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n", 9346 __ StackPointer(), 9347 __ StackPointer().W()); 9348 __ Mov(old_stack_pointer, __ StackPointer()); 9349 __ SetStackPointer(old_stack_pointer); 9350 9351 // Test with three arguments. 9352 __ Printf("3=%u, 4=%u, 5=%u\n", x10, x11, x12); 9353 9354 // Mixed argument types. 9355 __ Printf("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n", 9356 w3, 9357 s1, 9358 x5, 9359 d3); 9360 __ Printf("s1: %f, d3: %f, w3: %" PRId32 ", x5: %" PRId64 "\n", 9361 s1, 9362 d3, 9363 w3, 9364 x5); 9365 9366 END(); 9367 if (CAN_RUN()) { 9368 RUN(); 9369 9370 // We cannot easily test the output of the Printf sequences, and because 9371 // Printf preserves all registers by default, we can't look at the number of 9372 // bytes that were printed. However, the printf_no_preserve test should 9373 // check 9374 // that, and here we just test that we didn't clobber any registers. 9375 ASSERT_EQUAL_REGISTERS(before); 9376 } 9377} 9378 9379 9380TEST(printf_no_preserve) { 9381 // PrintfNoPreserve uses FP to cast FP arguments to doubles. 9382 SETUP_WITH_FEATURES(CPUFeatures::kFP); 9383 9384 START(); 9385 9386 char const* test_plain_string = "Printf with no arguments.\n"; 9387 char const* test_substring = "'This is a substring.'"; 9388 9389 __ PrintfNoPreserve(test_plain_string); 9390 __ Mov(x19, x0); 9391 9392 // Test simple integer arguments. 9393 __ Mov(x0, 1234); 9394 __ Mov(x1, 0x1234); 9395 __ PrintfNoPreserve("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1); 9396 __ Mov(x20, x0); 9397 9398 // Test simple floating-point arguments. 9399 __ Fmov(d0, 1.234); 9400 __ PrintfNoPreserve("d0: %f\n", d0); 9401 __ Mov(x21, x0); 9402 9403 // Test pointer (string) arguments. 9404 __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring)); 9405 __ PrintfNoPreserve("Test %%s: %s\n", x2); 9406 __ Mov(x22, x0); 9407 9408 // Test the maximum number of arguments, and sign extension. 9409 __ Mov(w3, 0xffffffff); 9410 __ Mov(w4, 0xffffffff); 9411 __ Mov(x5, 0xffffffffffffffff); 9412 __ Mov(x6, 0xffffffffffffffff); 9413 __ PrintfNoPreserve("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32 9414 "\n" 9415 "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n", 9416 w3, 9417 w4, 9418 x5, 9419 x6); 9420 __ Mov(x23, x0); 9421 9422 __ Fmov(s1, 1.234); 9423 __ Fmov(s2, 2.345); 9424 __ Fmov(d3, 3.456); 9425 __ Fmov(d4, 4.567); 9426 __ PrintfNoPreserve("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4); 9427 __ Mov(x24, x0); 9428 9429 // Test printing callee-saved registers. 9430 __ Mov(x28, 0x123456789abcdef); 9431 __ PrintfNoPreserve("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28); 9432 __ Mov(x25, x0); 9433 9434 __ Fmov(d10, 42.0); 9435 __ PrintfNoPreserve("%g\n", d10); 9436 __ Mov(x26, x0); 9437 9438 // Test with a different stack pointer. 9439 const Register old_stack_pointer = __ StackPointer(); 9440 __ Mov(x29, old_stack_pointer); 9441 __ SetStackPointer(x29); 9442 // Print the stack pointer (not sp). 9443 __ PrintfNoPreserve("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 9444 "\n", 9445 __ StackPointer(), 9446 __ StackPointer().W()); 9447 __ Mov(x27, x0); 9448 __ Mov(old_stack_pointer, __ StackPointer()); 9449 __ SetStackPointer(old_stack_pointer); 9450 9451 // Test with three arguments. 9452 __ Mov(x3, 3); 9453 __ Mov(x4, 40); 9454 __ Mov(x5, 500); 9455 __ PrintfNoPreserve("3=%u, 4=%u, 5=%u\n", x3, x4, x5); 9456 __ Mov(x28, x0); 9457 9458 // Mixed argument types. 9459 __ Mov(w3, 0xffffffff); 9460 __ Fmov(s1, 1.234); 9461 __ Mov(x5, 0xffffffffffffffff); 9462 __ Fmov(d3, 3.456); 9463 __ PrintfNoPreserve("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n", 9464 w3, 9465 s1, 9466 x5, 9467 d3); 9468 __ Mov(x29, x0); 9469 9470 END(); 9471 if (CAN_RUN()) { 9472 RUN(); 9473 9474 // We cannot easily test the exact output of the Printf sequences, but we 9475 // can 9476 // use the return code to check that the string length was correct. 9477 9478 // Printf with no arguments. 9479 ASSERT_EQUAL_64(strlen(test_plain_string), x19); 9480 // x0: 1234, x1: 0x00001234 9481 ASSERT_EQUAL_64(25, x20); 9482 // d0: 1.234000 9483 ASSERT_EQUAL_64(13, x21); 9484 // Test %s: 'This is a substring.' 9485 ASSERT_EQUAL_64(32, x22); 9486 // w3(uint32): 4294967295 9487 // w4(int32): -1 9488 // x5(uint64): 18446744073709551615 9489 // x6(int64): -1 9490 ASSERT_EQUAL_64(23 + 14 + 33 + 14, x23); 9491 // %f: 1.234000 9492 // %g: 2.345 9493 // %e: 3.456000e+00 9494 // %E: 4.567000E+00 9495 ASSERT_EQUAL_64(13 + 10 + 17 + 17, x24); 9496 // 0x89abcdef, 0x123456789abcdef 9497 ASSERT_EQUAL_64(30, x25); 9498 // 42 9499 ASSERT_EQUAL_64(3, x26); 9500 // StackPointer(not sp): 0x00007fb037ae2370, 0x37ae2370 9501 // Note: This is an example value, but the field width is fixed here so the 9502 // string length is still predictable. 9503 ASSERT_EQUAL_64(53, x27); 9504 // 3=3, 4=40, 5=500 9505 ASSERT_EQUAL_64(17, x28); 9506 // w3: 4294967295, s1: 1.234000, x5: 18446744073709551615, d3: 3.456000 9507 ASSERT_EQUAL_64(69, x29); 9508 } 9509} 9510 9511 9512TEST(trace) { 9513 // The Trace helper should not generate any code unless the simulator is being 9514 // used. 9515 SETUP(); 9516 START(); 9517 9518 Label start; 9519 __ Bind(&start); 9520 __ Trace(LOG_ALL, TRACE_ENABLE); 9521 __ Trace(LOG_ALL, TRACE_DISABLE); 9522 if (masm.GenerateSimulatorCode()) { 9523 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0); 9524 } else { 9525 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0); 9526 } 9527 9528 END(); 9529} 9530 9531 9532TEST(log) { 9533 // The Log helper should not generate any code unless the simulator is being 9534 // used. 9535 SETUP(); 9536 START(); 9537 9538 Label start; 9539 __ Bind(&start); 9540 __ Log(LOG_ALL); 9541 if (masm.GenerateSimulatorCode()) { 9542 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) > 0); 9543 } else { 9544 VIXL_CHECK(__ GetSizeOfCodeGeneratedSince(&start) == 0); 9545 } 9546 9547 END(); 9548} 9549 9550 9551TEST(blr_lr) { 9552 // A simple test to check that the simulator correctly handle "blr lr". 9553 SETUP(); 9554 9555 START(); 9556 Label target; 9557 Label end; 9558 9559 __ Mov(x0, 0x0); 9560 __ Adr(lr, &target); 9561 9562 __ Blr(lr); 9563 __ Mov(x0, 0xdeadbeef); 9564 __ B(&end); 9565 9566 __ Bind(&target); 9567 __ Mov(x0, 0xc001c0de); 9568 9569 __ Bind(&end); 9570 END(); 9571 9572 if (CAN_RUN()) { 9573 RUN(); 9574 9575 ASSERT_EQUAL_64(0xc001c0de, x0); 9576 } 9577} 9578 9579 9580TEST(barriers) { 9581 // Generate all supported barriers, this is just a smoke test 9582 SETUP(); 9583 9584 START(); 9585 9586 // DMB 9587 __ Dmb(FullSystem, BarrierAll); 9588 __ Dmb(FullSystem, BarrierReads); 9589 __ Dmb(FullSystem, BarrierWrites); 9590 __ Dmb(FullSystem, BarrierOther); 9591 9592 __ Dmb(InnerShareable, BarrierAll); 9593 __ Dmb(InnerShareable, BarrierReads); 9594 __ Dmb(InnerShareable, BarrierWrites); 9595 __ Dmb(InnerShareable, BarrierOther); 9596 9597 __ Dmb(NonShareable, BarrierAll); 9598 __ Dmb(NonShareable, BarrierReads); 9599 __ Dmb(NonShareable, BarrierWrites); 9600 __ Dmb(NonShareable, BarrierOther); 9601 9602 __ Dmb(OuterShareable, BarrierAll); 9603 __ Dmb(OuterShareable, BarrierReads); 9604 __ Dmb(OuterShareable, BarrierWrites); 9605 __ Dmb(OuterShareable, BarrierOther); 9606 9607 // DSB 9608 __ Dsb(FullSystem, BarrierAll); 9609 __ Dsb(FullSystem, BarrierReads); 9610 __ Dsb(FullSystem, BarrierWrites); 9611 __ Dsb(FullSystem, BarrierOther); 9612 9613 __ Dsb(InnerShareable, BarrierAll); 9614 __ Dsb(InnerShareable, BarrierReads); 9615 __ Dsb(InnerShareable, BarrierWrites); 9616 __ Dsb(InnerShareable, BarrierOther); 9617 9618 __ Dsb(NonShareable, BarrierAll); 9619 __ Dsb(NonShareable, BarrierReads); 9620 __ Dsb(NonShareable, BarrierWrites); 9621 __ Dsb(NonShareable, BarrierOther); 9622 9623 __ Dsb(OuterShareable, BarrierAll); 9624 __ Dsb(OuterShareable, BarrierReads); 9625 __ Dsb(OuterShareable, BarrierWrites); 9626 __ Dsb(OuterShareable, BarrierOther); 9627 9628 // ISB 9629 __ Isb(); 9630 9631 END(); 9632 9633 if (CAN_RUN()) { 9634 RUN(); 9635 } 9636} 9637 9638 9639TEST(ldar_stlr) { 9640 // The middle value is read, modified, and written. The padding exists only to 9641 // check for over-write. 9642 uint8_t b[] = {0, 0x12, 0}; 9643 uint16_t h[] = {0, 0x1234, 0}; 9644 uint32_t w[] = {0, 0x12345678, 0}; 9645 uint64_t x[] = {0, 0x123456789abcdef0, 0}; 9646 9647 SETUP(); 9648 START(); 9649 9650 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1])); 9651 __ Ldarb(w0, MemOperand(x10)); 9652 __ Add(w0, w0, 1); 9653 __ Stlrb(w0, MemOperand(x10)); 9654 9655 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1])); 9656 __ Ldarh(w0, MemOperand(x10)); 9657 __ Add(w0, w0, 1); 9658 __ Stlrh(w0, MemOperand(x10)); 9659 9660 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1])); 9661 __ Ldar(w0, MemOperand(x10)); 9662 __ Add(w0, w0, 1); 9663 __ Stlr(w0, MemOperand(x10)); 9664 9665 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1])); 9666 __ Ldar(x0, MemOperand(x10)); 9667 __ Add(x0, x0, 1); 9668 __ Stlr(x0, MemOperand(x10)); 9669 9670 END(); 9671 if (CAN_RUN()) { 9672 RUN(); 9673 9674 ASSERT_EQUAL_32(0x13, b[1]); 9675 ASSERT_EQUAL_32(0x1235, h[1]); 9676 ASSERT_EQUAL_32(0x12345679, w[1]); 9677 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]); 9678 9679 // Check for over-write. 9680 ASSERT_EQUAL_32(0, b[0]); 9681 ASSERT_EQUAL_32(0, b[2]); 9682 ASSERT_EQUAL_32(0, h[0]); 9683 ASSERT_EQUAL_32(0, h[2]); 9684 ASSERT_EQUAL_32(0, w[0]); 9685 ASSERT_EQUAL_32(0, w[2]); 9686 ASSERT_EQUAL_64(0, x[0]); 9687 ASSERT_EQUAL_64(0, x[2]); 9688 } 9689} 9690 9691 9692TEST(ldlar_stllr) { 9693 // The middle value is read, modified, and written. The padding exists only to 9694 // check for over-write. 9695 uint8_t b[] = {0, 0x12, 0}; 9696 uint16_t h[] = {0, 0x1234, 0}; 9697 uint32_t w[] = {0, 0x12345678, 0}; 9698 uint64_t x[] = {0, 0x123456789abcdef0, 0}; 9699 9700 SETUP_WITH_FEATURES(CPUFeatures::kLORegions); 9701 9702 START(); 9703 9704 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1])); 9705 __ Ldlarb(w0, MemOperand(x10)); 9706 __ Add(w0, w0, 1); 9707 __ Stllrb(w0, MemOperand(x10)); 9708 9709 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1])); 9710 __ Ldlarh(w0, MemOperand(x10)); 9711 __ Add(w0, w0, 1); 9712 __ Stllrh(w0, MemOperand(x10)); 9713 9714 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1])); 9715 __ Ldlar(w0, MemOperand(x10)); 9716 __ Add(w0, w0, 1); 9717 __ Stllr(w0, MemOperand(x10)); 9718 9719 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1])); 9720 __ Ldlar(x0, MemOperand(x10)); 9721 __ Add(x0, x0, 1); 9722 __ Stllr(x0, MemOperand(x10)); 9723 9724 END(); 9725 9726 if (CAN_RUN()) { 9727 RUN(); 9728 9729 ASSERT_EQUAL_32(0x13, b[1]); 9730 ASSERT_EQUAL_32(0x1235, h[1]); 9731 ASSERT_EQUAL_32(0x12345679, w[1]); 9732 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]); 9733 9734 // Check for over-write. 9735 ASSERT_EQUAL_32(0, b[0]); 9736 ASSERT_EQUAL_32(0, b[2]); 9737 ASSERT_EQUAL_32(0, h[0]); 9738 ASSERT_EQUAL_32(0, h[2]); 9739 ASSERT_EQUAL_32(0, w[0]); 9740 ASSERT_EQUAL_32(0, w[2]); 9741 ASSERT_EQUAL_64(0, x[0]); 9742 ASSERT_EQUAL_64(0, x[2]); 9743 } 9744} 9745 9746 9747TEST(ldxr_stxr) { 9748 // The middle value is read, modified, and written. The padding exists only to 9749 // check for over-write. 9750 uint8_t b[] = {0, 0x12, 0}; 9751 uint16_t h[] = {0, 0x1234, 0}; 9752 uint32_t w[] = {0, 0x12345678, 0}; 9753 uint64_t x[] = {0, 0x123456789abcdef0, 0}; 9754 9755 // As above, but get suitably-aligned values for ldxp and stxp. 9756 uint32_t wp_data[] = {0, 0, 0, 0, 0}; 9757 uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1; 9758 wp[1] = 0x12345678; // wp[1] is 64-bit-aligned. 9759 wp[2] = 0x87654321; 9760 uint64_t xp_data[] = {0, 0, 0, 0, 0}; 9761 uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1; 9762 xp[1] = 0x123456789abcdef0; // xp[1] is 128-bit-aligned. 9763 xp[2] = 0x0fedcba987654321; 9764 9765 SETUP(); 9766 START(); 9767 9768 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1])); 9769 Label try_b; 9770 __ Bind(&try_b); 9771 __ Ldxrb(w0, MemOperand(x10)); 9772 __ Add(w0, w0, 1); 9773 __ Stxrb(w5, w0, MemOperand(x10)); 9774 __ Cbnz(w5, &try_b); 9775 9776 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1])); 9777 Label try_h; 9778 __ Bind(&try_h); 9779 __ Ldxrh(w0, MemOperand(x10)); 9780 __ Add(w0, w0, 1); 9781 __ Stxrh(w5, w0, MemOperand(x10)); 9782 __ Cbnz(w5, &try_h); 9783 9784 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1])); 9785 Label try_w; 9786 __ Bind(&try_w); 9787 __ Ldxr(w0, MemOperand(x10)); 9788 __ Add(w0, w0, 1); 9789 __ Stxr(w5, w0, MemOperand(x10)); 9790 __ Cbnz(w5, &try_w); 9791 9792 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1])); 9793 Label try_x; 9794 __ Bind(&try_x); 9795 __ Ldxr(x0, MemOperand(x10)); 9796 __ Add(x0, x0, 1); 9797 __ Stxr(w5, x0, MemOperand(x10)); 9798 __ Cbnz(w5, &try_x); 9799 9800 __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1])); 9801 Label try_wp; 9802 __ Bind(&try_wp); 9803 __ Ldxp(w0, w1, MemOperand(x10)); 9804 __ Add(w0, w0, 1); 9805 __ Add(w1, w1, 1); 9806 __ Stxp(w5, w0, w1, MemOperand(x10)); 9807 __ Cbnz(w5, &try_wp); 9808 9809 __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1])); 9810 Label try_xp; 9811 __ Bind(&try_xp); 9812 __ Ldxp(x0, x1, MemOperand(x10)); 9813 __ Add(x0, x0, 1); 9814 __ Add(x1, x1, 1); 9815 __ Stxp(w5, x0, x1, MemOperand(x10)); 9816 __ Cbnz(w5, &try_xp); 9817 9818 END(); 9819 if (CAN_RUN()) { 9820 RUN(); 9821 9822 ASSERT_EQUAL_32(0x13, b[1]); 9823 ASSERT_EQUAL_32(0x1235, h[1]); 9824 ASSERT_EQUAL_32(0x12345679, w[1]); 9825 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]); 9826 ASSERT_EQUAL_32(0x12345679, wp[1]); 9827 ASSERT_EQUAL_32(0x87654322, wp[2]); 9828 ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]); 9829 ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]); 9830 9831 // Check for over-write. 9832 ASSERT_EQUAL_32(0, b[0]); 9833 ASSERT_EQUAL_32(0, b[2]); 9834 ASSERT_EQUAL_32(0, h[0]); 9835 ASSERT_EQUAL_32(0, h[2]); 9836 ASSERT_EQUAL_32(0, w[0]); 9837 ASSERT_EQUAL_32(0, w[2]); 9838 ASSERT_EQUAL_64(0, x[0]); 9839 ASSERT_EQUAL_64(0, x[2]); 9840 ASSERT_EQUAL_32(0, wp[0]); 9841 ASSERT_EQUAL_32(0, wp[3]); 9842 ASSERT_EQUAL_64(0, xp[0]); 9843 ASSERT_EQUAL_64(0, xp[3]); 9844 } 9845} 9846 9847 9848TEST(ldaxr_stlxr) { 9849 // The middle value is read, modified, and written. The padding exists only to 9850 // check for over-write. 9851 uint8_t b[] = {0, 0x12, 0}; 9852 uint16_t h[] = {0, 0x1234, 0}; 9853 uint32_t w[] = {0, 0x12345678, 0}; 9854 uint64_t x[] = {0, 0x123456789abcdef0, 0}; 9855 9856 // As above, but get suitably-aligned values for ldxp and stxp. 9857 uint32_t wp_data[] = {0, 0, 0, 0, 0}; 9858 uint32_t* wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1; 9859 wp[1] = 0x12345678; // wp[1] is 64-bit-aligned. 9860 wp[2] = 0x87654321; 9861 uint64_t xp_data[] = {0, 0, 0, 0, 0}; 9862 uint64_t* xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1; 9863 xp[1] = 0x123456789abcdef0; // xp[1] is 128-bit-aligned. 9864 xp[2] = 0x0fedcba987654321; 9865 9866 SETUP(); 9867 START(); 9868 9869 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1])); 9870 Label try_b; 9871 __ Bind(&try_b); 9872 __ Ldaxrb(w0, MemOperand(x10)); 9873 __ Add(w0, w0, 1); 9874 __ Stlxrb(w5, w0, MemOperand(x10)); 9875 __ Cbnz(w5, &try_b); 9876 9877 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1])); 9878 Label try_h; 9879 __ Bind(&try_h); 9880 __ Ldaxrh(w0, MemOperand(x10)); 9881 __ Add(w0, w0, 1); 9882 __ Stlxrh(w5, w0, MemOperand(x10)); 9883 __ Cbnz(w5, &try_h); 9884 9885 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1])); 9886 Label try_w; 9887 __ Bind(&try_w); 9888 __ Ldaxr(w0, MemOperand(x10)); 9889 __ Add(w0, w0, 1); 9890 __ Stlxr(w5, w0, MemOperand(x10)); 9891 __ Cbnz(w5, &try_w); 9892 9893 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1])); 9894 Label try_x; 9895 __ Bind(&try_x); 9896 __ Ldaxr(x0, MemOperand(x10)); 9897 __ Add(x0, x0, 1); 9898 __ Stlxr(w5, x0, MemOperand(x10)); 9899 __ Cbnz(w5, &try_x); 9900 9901 __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1])); 9902 Label try_wp; 9903 __ Bind(&try_wp); 9904 __ Ldaxp(w0, w1, MemOperand(x10)); 9905 __ Add(w0, w0, 1); 9906 __ Add(w1, w1, 1); 9907 __ Stlxp(w5, w0, w1, MemOperand(x10)); 9908 __ Cbnz(w5, &try_wp); 9909 9910 __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1])); 9911 Label try_xp; 9912 __ Bind(&try_xp); 9913 __ Ldaxp(x0, x1, MemOperand(x10)); 9914 __ Add(x0, x0, 1); 9915 __ Add(x1, x1, 1); 9916 __ Stlxp(w5, x0, x1, MemOperand(x10)); 9917 __ Cbnz(w5, &try_xp); 9918 9919 END(); 9920 if (CAN_RUN()) { 9921 RUN(); 9922 9923 ASSERT_EQUAL_32(0x13, b[1]); 9924 ASSERT_EQUAL_32(0x1235, h[1]); 9925 ASSERT_EQUAL_32(0x12345679, w[1]); 9926 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]); 9927 ASSERT_EQUAL_32(0x12345679, wp[1]); 9928 ASSERT_EQUAL_32(0x87654322, wp[2]); 9929 ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]); 9930 ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]); 9931 9932 // Check for over-write. 9933 ASSERT_EQUAL_32(0, b[0]); 9934 ASSERT_EQUAL_32(0, b[2]); 9935 ASSERT_EQUAL_32(0, h[0]); 9936 ASSERT_EQUAL_32(0, h[2]); 9937 ASSERT_EQUAL_32(0, w[0]); 9938 ASSERT_EQUAL_32(0, w[2]); 9939 ASSERT_EQUAL_64(0, x[0]); 9940 ASSERT_EQUAL_64(0, x[2]); 9941 ASSERT_EQUAL_32(0, wp[0]); 9942 ASSERT_EQUAL_32(0, wp[3]); 9943 ASSERT_EQUAL_64(0, xp[0]); 9944 ASSERT_EQUAL_64(0, xp[3]); 9945 } 9946} 9947 9948 9949TEST(clrex) { 9950 // This data should never be written. 9951 uint64_t data[] = {0, 0, 0}; 9952 uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2); 9953 9954 SETUP(); 9955 START(); 9956 9957 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned)); 9958 __ Mov(w6, 0); 9959 9960 __ Ldxrb(w0, MemOperand(x10)); 9961 __ Clrex(); 9962 __ Add(w0, w0, 1); 9963 __ Stxrb(w5, w0, MemOperand(x10)); 9964 __ Add(w6, w6, w5); 9965 9966 __ Ldxrh(w0, MemOperand(x10)); 9967 __ Clrex(); 9968 __ Add(w0, w0, 1); 9969 __ Stxrh(w5, w0, MemOperand(x10)); 9970 __ Add(w6, w6, w5); 9971 9972 __ Ldxr(w0, MemOperand(x10)); 9973 __ Clrex(); 9974 __ Add(w0, w0, 1); 9975 __ Stxr(w5, w0, MemOperand(x10)); 9976 __ Add(w6, w6, w5); 9977 9978 __ Ldxr(x0, MemOperand(x10)); 9979 __ Clrex(); 9980 __ Add(x0, x0, 1); 9981 __ Stxr(w5, x0, MemOperand(x10)); 9982 __ Add(w6, w6, w5); 9983 9984 __ Ldxp(w0, w1, MemOperand(x10)); 9985 __ Clrex(); 9986 __ Add(w0, w0, 1); 9987 __ Add(w1, w1, 1); 9988 __ Stxp(w5, w0, w1, MemOperand(x10)); 9989 __ Add(w6, w6, w5); 9990 9991 __ Ldxp(x0, x1, MemOperand(x10)); 9992 __ Clrex(); 9993 __ Add(x0, x0, 1); 9994 __ Add(x1, x1, 1); 9995 __ Stxp(w5, x0, x1, MemOperand(x10)); 9996 __ Add(w6, w6, w5); 9997 9998 // Acquire-release variants. 9999 10000 __ Ldaxrb(w0, MemOperand(x10)); 10001 __ Clrex(); 10002 __ Add(w0, w0, 1); 10003 __ Stlxrb(w5, w0, MemOperand(x10)); 10004 __ Add(w6, w6, w5); 10005 10006 __ Ldaxrh(w0, MemOperand(x10)); 10007 __ Clrex(); 10008 __ Add(w0, w0, 1); 10009 __ Stlxrh(w5, w0, MemOperand(x10)); 10010 __ Add(w6, w6, w5); 10011 10012 __ Ldaxr(w0, MemOperand(x10)); 10013 __ Clrex(); 10014 __ Add(w0, w0, 1); 10015 __ Stlxr(w5, w0, MemOperand(x10)); 10016 __ Add(w6, w6, w5); 10017 10018 __ Ldaxr(x0, MemOperand(x10)); 10019 __ Clrex(); 10020 __ Add(x0, x0, 1); 10021 __ Stlxr(w5, x0, MemOperand(x10)); 10022 __ Add(w6, w6, w5); 10023 10024 __ Ldaxp(w0, w1, MemOperand(x10)); 10025 __ Clrex(); 10026 __ Add(w0, w0, 1); 10027 __ Add(w1, w1, 1); 10028 __ Stlxp(w5, w0, w1, MemOperand(x10)); 10029 __ Add(w6, w6, w5); 10030 10031 __ Ldaxp(x0, x1, MemOperand(x10)); 10032 __ Clrex(); 10033 __ Add(x0, x0, 1); 10034 __ Add(x1, x1, 1); 10035 __ Stlxp(w5, x0, x1, MemOperand(x10)); 10036 __ Add(w6, w6, w5); 10037 10038 END(); 10039 if (CAN_RUN()) { 10040 RUN(); 10041 10042 // None of the 12 store-exclusives should have succeeded. 10043 ASSERT_EQUAL_32(12, w6); 10044 10045 ASSERT_EQUAL_64(0, data[0]); 10046 ASSERT_EQUAL_64(0, data[1]); 10047 ASSERT_EQUAL_64(0, data[2]); 10048 } 10049} 10050 10051 10052#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 10053// Check that the simulator occasionally makes store-exclusive fail. 10054TEST(ldxr_stxr_fail) { 10055 uint64_t data[] = {0, 0, 0}; 10056 uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2); 10057 10058 // Impose a hard limit on the number of attempts, so the test cannot hang. 10059 static const uint64_t kWatchdog = 10000; 10060 Label done; 10061 10062 SETUP(); 10063 START(); 10064 10065 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned)); 10066 __ Mov(x11, kWatchdog); 10067 10068 // This loop is the opposite of what we normally do with ldxr and stxr; we 10069 // keep trying until we fail (or the watchdog counter runs out). 10070 Label try_b; 10071 __ Bind(&try_b); 10072 __ Ldxrb(w0, MemOperand(x10)); 10073 __ Stxrb(w5, w0, MemOperand(x10)); 10074 // Check the watchdog counter. 10075 __ Sub(x11, x11, 1); 10076 __ Cbz(x11, &done); 10077 // Check the exclusive-store result. 10078 __ Cbz(w5, &try_b); 10079 10080 Label try_h; 10081 __ Bind(&try_h); 10082 __ Ldxrh(w0, MemOperand(x10)); 10083 __ Stxrh(w5, w0, MemOperand(x10)); 10084 __ Sub(x11, x11, 1); 10085 __ Cbz(x11, &done); 10086 __ Cbz(w5, &try_h); 10087 10088 Label try_w; 10089 __ Bind(&try_w); 10090 __ Ldxr(w0, MemOperand(x10)); 10091 __ Stxr(w5, w0, MemOperand(x10)); 10092 __ Sub(x11, x11, 1); 10093 __ Cbz(x11, &done); 10094 __ Cbz(w5, &try_w); 10095 10096 Label try_x; 10097 __ Bind(&try_x); 10098 __ Ldxr(x0, MemOperand(x10)); 10099 __ Stxr(w5, x0, MemOperand(x10)); 10100 __ Sub(x11, x11, 1); 10101 __ Cbz(x11, &done); 10102 __ Cbz(w5, &try_x); 10103 10104 Label try_wp; 10105 __ Bind(&try_wp); 10106 __ Ldxp(w0, w1, MemOperand(x10)); 10107 __ Stxp(w5, w0, w1, MemOperand(x10)); 10108 __ Sub(x11, x11, 1); 10109 __ Cbz(x11, &done); 10110 __ Cbz(w5, &try_wp); 10111 10112 Label try_xp; 10113 __ Bind(&try_xp); 10114 __ Ldxp(x0, x1, MemOperand(x10)); 10115 __ Stxp(w5, x0, x1, MemOperand(x10)); 10116 __ Sub(x11, x11, 1); 10117 __ Cbz(x11, &done); 10118 __ Cbz(w5, &try_xp); 10119 10120 __ Bind(&done); 10121 // Trigger an error if x11 (watchdog) is zero. 10122 __ Cmp(x11, 0); 10123 __ Cset(x12, eq); 10124 10125 END(); 10126 if (CAN_RUN()) { 10127 RUN(); 10128 10129 // Check that the watchdog counter didn't run out. 10130 ASSERT_EQUAL_64(0, x12); 10131 } 10132} 10133#endif 10134 10135 10136#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 10137// Check that the simulator occasionally makes store-exclusive fail. 10138TEST(ldaxr_stlxr_fail) { 10139 uint64_t data[] = {0, 0, 0}; 10140 uint64_t* data_aligned = AlignUp(data, kXRegSizeInBytes * 2); 10141 10142 // Impose a hard limit on the number of attempts, so the test cannot hang. 10143 static const uint64_t kWatchdog = 10000; 10144 Label done; 10145 10146 SETUP(); 10147 START(); 10148 10149 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned)); 10150 __ Mov(x11, kWatchdog); 10151 10152 // This loop is the opposite of what we normally do with ldxr and stxr; we 10153 // keep trying until we fail (or the watchdog counter runs out). 10154 Label try_b; 10155 __ Bind(&try_b); 10156 __ Ldxrb(w0, MemOperand(x10)); 10157 __ Stxrb(w5, w0, MemOperand(x10)); 10158 // Check the watchdog counter. 10159 __ Sub(x11, x11, 1); 10160 __ Cbz(x11, &done); 10161 // Check the exclusive-store result. 10162 __ Cbz(w5, &try_b); 10163 10164 Label try_h; 10165 __ Bind(&try_h); 10166 __ Ldaxrh(w0, MemOperand(x10)); 10167 __ Stlxrh(w5, w0, MemOperand(x10)); 10168 __ Sub(x11, x11, 1); 10169 __ Cbz(x11, &done); 10170 __ Cbz(w5, &try_h); 10171 10172 Label try_w; 10173 __ Bind(&try_w); 10174 __ Ldaxr(w0, MemOperand(x10)); 10175 __ Stlxr(w5, w0, MemOperand(x10)); 10176 __ Sub(x11, x11, 1); 10177 __ Cbz(x11, &done); 10178 __ Cbz(w5, &try_w); 10179 10180 Label try_x; 10181 __ Bind(&try_x); 10182 __ Ldaxr(x0, MemOperand(x10)); 10183 __ Stlxr(w5, x0, MemOperand(x10)); 10184 __ Sub(x11, x11, 1); 10185 __ Cbz(x11, &done); 10186 __ Cbz(w5, &try_x); 10187 10188 Label try_wp; 10189 __ Bind(&try_wp); 10190 __ Ldaxp(w0, w1, MemOperand(x10)); 10191 __ Stlxp(w5, w0, w1, MemOperand(x10)); 10192 __ Sub(x11, x11, 1); 10193 __ Cbz(x11, &done); 10194 __ Cbz(w5, &try_wp); 10195 10196 Label try_xp; 10197 __ Bind(&try_xp); 10198 __ Ldaxp(x0, x1, MemOperand(x10)); 10199 __ Stlxp(w5, x0, x1, MemOperand(x10)); 10200 __ Sub(x11, x11, 1); 10201 __ Cbz(x11, &done); 10202 __ Cbz(w5, &try_xp); 10203 10204 __ Bind(&done); 10205 // Trigger an error if x11 (watchdog) is zero. 10206 __ Cmp(x11, 0); 10207 __ Cset(x12, eq); 10208 10209 END(); 10210 if (CAN_RUN()) { 10211 RUN(); 10212 10213 // Check that the watchdog counter didn't run out. 10214 ASSERT_EQUAL_64(0, x12); 10215 } 10216} 10217#endif 10218 10219TEST(cas_casa_casl_casal_w) { 10220 uint64_t data1 = 0x0123456789abcdef; 10221 uint64_t data2 = 0x0123456789abcdef; 10222 uint64_t data3 = 0x0123456789abcdef; 10223 uint64_t data4 = 0x0123456789abcdef; 10224 uint64_t data5 = 0x0123456789abcdef; 10225 uint64_t data6 = 0x0123456789abcdef; 10226 uint64_t data7 = 0x0123456789abcdef; 10227 uint64_t data8 = 0x0123456789abcdef; 10228 10229 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10230 10231 START(); 10232 10233 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0); 10234 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0); 10235 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 4); 10236 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 4); 10237 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 0); 10238 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 0); 10239 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 4); 10240 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 4); 10241 10242 __ Mov(x0, 0xffffffff); 10243 10244 __ Mov(x1, 0xfedcba9876543210); 10245 __ Mov(x2, 0x0123456789abcdef); 10246 __ Mov(x3, 0xfedcba9876543210); 10247 __ Mov(x4, 0x89abcdef01234567); 10248 __ Mov(x5, 0xfedcba9876543210); 10249 __ Mov(x6, 0x0123456789abcdef); 10250 __ Mov(x7, 0xfedcba9876543210); 10251 __ Mov(x8, 0x89abcdef01234567); 10252 10253 __ Cas(w1, w0, MemOperand(x21)); 10254 __ Cas(w2, w0, MemOperand(x22)); 10255 __ Casa(w3, w0, MemOperand(x23)); 10256 __ Casa(w4, w0, MemOperand(x24)); 10257 __ Casl(w5, w0, MemOperand(x25)); 10258 __ Casl(w6, w0, MemOperand(x26)); 10259 __ Casal(w7, w0, MemOperand(x27)); 10260 __ Casal(w8, w0, MemOperand(x28)); 10261 10262 END(); 10263 10264 if (CAN_RUN()) { 10265 RUN(); 10266 10267 ASSERT_EQUAL_64(0x89abcdef, x1); 10268 ASSERT_EQUAL_64(0x89abcdef, x2); 10269 ASSERT_EQUAL_64(0x01234567, x3); 10270 ASSERT_EQUAL_64(0x01234567, x4); 10271 ASSERT_EQUAL_64(0x89abcdef, x5); 10272 ASSERT_EQUAL_64(0x89abcdef, x6); 10273 ASSERT_EQUAL_64(0x01234567, x7); 10274 ASSERT_EQUAL_64(0x01234567, x8); 10275 10276 ASSERT_EQUAL_64(0x0123456789abcdef, data1); 10277 ASSERT_EQUAL_64(0x01234567ffffffff, data2); 10278 ASSERT_EQUAL_64(0x0123456789abcdef, data3); 10279 ASSERT_EQUAL_64(0xffffffff89abcdef, data4); 10280 ASSERT_EQUAL_64(0x0123456789abcdef, data5); 10281 ASSERT_EQUAL_64(0x01234567ffffffff, data6); 10282 ASSERT_EQUAL_64(0x0123456789abcdef, data7); 10283 ASSERT_EQUAL_64(0xffffffff89abcdef, data8); 10284 } 10285} 10286 10287TEST(cas_casa_casl_casal_x) { 10288 uint64_t data1 = 0x0123456789abcdef; 10289 uint64_t data2 = 0x0123456789abcdef; 10290 uint64_t data3 = 0x0123456789abcdef; 10291 uint64_t data4 = 0x0123456789abcdef; 10292 uint64_t data5 = 0x0123456789abcdef; 10293 uint64_t data6 = 0x0123456789abcdef; 10294 uint64_t data7 = 0x0123456789abcdef; 10295 uint64_t data8 = 0x0123456789abcdef; 10296 10297 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10298 10299 START(); 10300 10301 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1)); 10302 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2)); 10303 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3)); 10304 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4)); 10305 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5)); 10306 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6)); 10307 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7)); 10308 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8)); 10309 10310 __ Mov(x0, 0xffffffffffffffff); 10311 10312 __ Mov(x1, 0xfedcba9876543210); 10313 __ Mov(x2, 0x0123456789abcdef); 10314 __ Mov(x3, 0xfedcba9876543210); 10315 __ Mov(x4, 0x0123456789abcdef); 10316 __ Mov(x5, 0xfedcba9876543210); 10317 __ Mov(x6, 0x0123456789abcdef); 10318 __ Mov(x7, 0xfedcba9876543210); 10319 __ Mov(x8, 0x0123456789abcdef); 10320 10321 __ Cas(x1, x0, MemOperand(x21)); 10322 __ Cas(x2, x0, MemOperand(x22)); 10323 __ Casa(x3, x0, MemOperand(x23)); 10324 __ Casa(x4, x0, MemOperand(x24)); 10325 __ Casl(x5, x0, MemOperand(x25)); 10326 __ Casl(x6, x0, MemOperand(x26)); 10327 __ Casal(x7, x0, MemOperand(x27)); 10328 __ Casal(x8, x0, MemOperand(x28)); 10329 10330 END(); 10331 10332 if (CAN_RUN()) { 10333 RUN(); 10334 10335 ASSERT_EQUAL_64(0x0123456789abcdef, x1); 10336 ASSERT_EQUAL_64(0x0123456789abcdef, x2); 10337 ASSERT_EQUAL_64(0x0123456789abcdef, x3); 10338 ASSERT_EQUAL_64(0x0123456789abcdef, x4); 10339 ASSERT_EQUAL_64(0x0123456789abcdef, x5); 10340 ASSERT_EQUAL_64(0x0123456789abcdef, x6); 10341 ASSERT_EQUAL_64(0x0123456789abcdef, x7); 10342 ASSERT_EQUAL_64(0x0123456789abcdef, x8); 10343 10344 ASSERT_EQUAL_64(0x0123456789abcdef, data1); 10345 ASSERT_EQUAL_64(0xffffffffffffffff, data2); 10346 ASSERT_EQUAL_64(0x0123456789abcdef, data3); 10347 ASSERT_EQUAL_64(0xffffffffffffffff, data4); 10348 ASSERT_EQUAL_64(0x0123456789abcdef, data5); 10349 ASSERT_EQUAL_64(0xffffffffffffffff, data6); 10350 ASSERT_EQUAL_64(0x0123456789abcdef, data7); 10351 ASSERT_EQUAL_64(0xffffffffffffffff, data8); 10352 } 10353} 10354 10355TEST(casb_casab_caslb_casalb) { 10356 uint32_t data1 = 0x01234567; 10357 uint32_t data2 = 0x01234567; 10358 uint32_t data3 = 0x01234567; 10359 uint32_t data4 = 0x01234567; 10360 uint32_t data5 = 0x01234567; 10361 uint32_t data6 = 0x01234567; 10362 uint32_t data7 = 0x01234567; 10363 uint32_t data8 = 0x01234567; 10364 10365 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10366 10367 START(); 10368 10369 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0); 10370 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0); 10371 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 1); 10372 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 1); 10373 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 2); 10374 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 2); 10375 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 3); 10376 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 3); 10377 10378 __ Mov(x0, 0xff); 10379 10380 __ Mov(x1, 0x76543210); 10381 __ Mov(x2, 0x01234567); 10382 __ Mov(x3, 0x76543210); 10383 __ Mov(x4, 0x67012345); 10384 __ Mov(x5, 0x76543210); 10385 __ Mov(x6, 0x45670123); 10386 __ Mov(x7, 0x76543210); 10387 __ Mov(x8, 0x23456701); 10388 10389 __ Casb(w1, w0, MemOperand(x21)); 10390 __ Casb(w2, w0, MemOperand(x22)); 10391 __ Casab(w3, w0, MemOperand(x23)); 10392 __ Casab(w4, w0, MemOperand(x24)); 10393 __ Caslb(w5, w0, MemOperand(x25)); 10394 __ Caslb(w6, w0, MemOperand(x26)); 10395 __ Casalb(w7, w0, MemOperand(x27)); 10396 __ Casalb(w8, w0, MemOperand(x28)); 10397 10398 END(); 10399 10400 if (CAN_RUN()) { 10401 RUN(); 10402 10403 ASSERT_EQUAL_64(0x00000067, x1); 10404 ASSERT_EQUAL_64(0x00000067, x2); 10405 ASSERT_EQUAL_64(0x00000045, x3); 10406 ASSERT_EQUAL_64(0x00000045, x4); 10407 ASSERT_EQUAL_64(0x00000023, x5); 10408 ASSERT_EQUAL_64(0x00000023, x6); 10409 ASSERT_EQUAL_64(0x00000001, x7); 10410 ASSERT_EQUAL_64(0x00000001, x8); 10411 10412 ASSERT_EQUAL_64(0x01234567, data1); 10413 ASSERT_EQUAL_64(0x012345ff, data2); 10414 ASSERT_EQUAL_64(0x01234567, data3); 10415 ASSERT_EQUAL_64(0x0123ff67, data4); 10416 ASSERT_EQUAL_64(0x01234567, data5); 10417 ASSERT_EQUAL_64(0x01ff4567, data6); 10418 ASSERT_EQUAL_64(0x01234567, data7); 10419 ASSERT_EQUAL_64(0xff234567, data8); 10420 } 10421} 10422 10423TEST(cash_casah_caslh_casalh) { 10424 uint64_t data1 = 0x0123456789abcdef; 10425 uint64_t data2 = 0x0123456789abcdef; 10426 uint64_t data3 = 0x0123456789abcdef; 10427 uint64_t data4 = 0x0123456789abcdef; 10428 uint64_t data5 = 0x0123456789abcdef; 10429 uint64_t data6 = 0x0123456789abcdef; 10430 uint64_t data7 = 0x0123456789abcdef; 10431 uint64_t data8 = 0x0123456789abcdef; 10432 10433 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10434 10435 START(); 10436 10437 __ Mov(x21, reinterpret_cast<uintptr_t>(&data1) + 0); 10438 __ Mov(x22, reinterpret_cast<uintptr_t>(&data2) + 0); 10439 __ Mov(x23, reinterpret_cast<uintptr_t>(&data3) + 2); 10440 __ Mov(x24, reinterpret_cast<uintptr_t>(&data4) + 2); 10441 __ Mov(x25, reinterpret_cast<uintptr_t>(&data5) + 4); 10442 __ Mov(x26, reinterpret_cast<uintptr_t>(&data6) + 4); 10443 __ Mov(x27, reinterpret_cast<uintptr_t>(&data7) + 6); 10444 __ Mov(x28, reinterpret_cast<uintptr_t>(&data8) + 6); 10445 10446 __ Mov(x0, 0xffff); 10447 10448 __ Mov(x1, 0xfedcba9876543210); 10449 __ Mov(x2, 0x0123456789abcdef); 10450 __ Mov(x3, 0xfedcba9876543210); 10451 __ Mov(x4, 0xcdef0123456789ab); 10452 __ Mov(x5, 0xfedcba9876543210); 10453 __ Mov(x6, 0x89abcdef01234567); 10454 __ Mov(x7, 0xfedcba9876543210); 10455 __ Mov(x8, 0x456789abcdef0123); 10456 10457 __ Cash(w1, w0, MemOperand(x21)); 10458 __ Cash(w2, w0, MemOperand(x22)); 10459 __ Casah(w3, w0, MemOperand(x23)); 10460 __ Casah(w4, w0, MemOperand(x24)); 10461 __ Caslh(w5, w0, MemOperand(x25)); 10462 __ Caslh(w6, w0, MemOperand(x26)); 10463 __ Casalh(w7, w0, MemOperand(x27)); 10464 __ Casalh(w8, w0, MemOperand(x28)); 10465 10466 END(); 10467 10468 if (CAN_RUN()) { 10469 RUN(); 10470 10471 ASSERT_EQUAL_64(0x0000cdef, x1); 10472 ASSERT_EQUAL_64(0x0000cdef, x2); 10473 ASSERT_EQUAL_64(0x000089ab, x3); 10474 ASSERT_EQUAL_64(0x000089ab, x4); 10475 ASSERT_EQUAL_64(0x00004567, x5); 10476 ASSERT_EQUAL_64(0x00004567, x6); 10477 ASSERT_EQUAL_64(0x00000123, x7); 10478 ASSERT_EQUAL_64(0x00000123, x8); 10479 10480 ASSERT_EQUAL_64(0x0123456789abcdef, data1); 10481 ASSERT_EQUAL_64(0x0123456789abffff, data2); 10482 ASSERT_EQUAL_64(0x0123456789abcdef, data3); 10483 ASSERT_EQUAL_64(0x01234567ffffcdef, data4); 10484 ASSERT_EQUAL_64(0x0123456789abcdef, data5); 10485 ASSERT_EQUAL_64(0x0123ffff89abcdef, data6); 10486 ASSERT_EQUAL_64(0x0123456789abcdef, data7); 10487 ASSERT_EQUAL_64(0xffff456789abcdef, data8); 10488 } 10489} 10490 10491TEST(casp_caspa_caspl_caspal_w) { 10492 uint64_t data1[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10493 uint64_t data2[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10494 uint64_t data3[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10495 uint64_t data4[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10496 uint64_t data5[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10497 uint64_t data6[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10498 uint64_t data7[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10499 uint64_t data8[] = {0x7766554433221100, 0xffeeddccbbaa9988}; 10500 10501 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10502 10503 START(); 10504 10505 __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0); 10506 __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0); 10507 __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 8); 10508 __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 8); 10509 __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 8); 10510 __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 8); 10511 __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0); 10512 __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0); 10513 10514 __ Mov(x0, 0xfff00fff); 10515 __ Mov(x1, 0xfff11fff); 10516 10517 __ Mov(x2, 0x77665544); 10518 __ Mov(x3, 0x33221100); 10519 __ Mov(x4, 0x33221100); 10520 __ Mov(x5, 0x77665544); 10521 10522 __ Mov(x6, 0xffeeddcc); 10523 __ Mov(x7, 0xbbaa9988); 10524 __ Mov(x8, 0xbbaa9988); 10525 __ Mov(x9, 0xffeeddcc); 10526 10527 __ Mov(x10, 0xffeeddcc); 10528 __ Mov(x11, 0xbbaa9988); 10529 __ Mov(x12, 0xbbaa9988); 10530 __ Mov(x13, 0xffeeddcc); 10531 10532 __ Mov(x14, 0x77665544); 10533 __ Mov(x15, 0x33221100); 10534 __ Mov(x16, 0x33221100); 10535 __ Mov(x17, 0x77665544); 10536 10537 __ Casp(w2, w3, w0, w1, MemOperand(x21)); 10538 __ Casp(w4, w5, w0, w1, MemOperand(x22)); 10539 __ Caspa(w6, w7, w0, w1, MemOperand(x23)); 10540 __ Caspa(w8, w9, w0, w1, MemOperand(x24)); 10541 __ Caspl(w10, w11, w0, w1, MemOperand(x25)); 10542 __ Caspl(w12, w13, w0, w1, MemOperand(x26)); 10543 __ Caspal(w14, w15, w0, w1, MemOperand(x27)); 10544 __ Caspal(w16, w17, w0, w1, MemOperand(x28)); 10545 10546 END(); 10547 10548 if (CAN_RUN()) { 10549 RUN(); 10550 10551 ASSERT_EQUAL_64(0x33221100, x2); 10552 ASSERT_EQUAL_64(0x77665544, x3); 10553 ASSERT_EQUAL_64(0x33221100, x4); 10554 ASSERT_EQUAL_64(0x77665544, x5); 10555 ASSERT_EQUAL_64(0xbbaa9988, x6); 10556 ASSERT_EQUAL_64(0xffeeddcc, x7); 10557 ASSERT_EQUAL_64(0xbbaa9988, x8); 10558 ASSERT_EQUAL_64(0xffeeddcc, x9); 10559 ASSERT_EQUAL_64(0xbbaa9988, x10); 10560 ASSERT_EQUAL_64(0xffeeddcc, x11); 10561 ASSERT_EQUAL_64(0xbbaa9988, x12); 10562 ASSERT_EQUAL_64(0xffeeddcc, x13); 10563 ASSERT_EQUAL_64(0x33221100, x14); 10564 ASSERT_EQUAL_64(0x77665544, x15); 10565 ASSERT_EQUAL_64(0x33221100, x16); 10566 ASSERT_EQUAL_64(0x77665544, x17); 10567 10568 ASSERT_EQUAL_64(0x7766554433221100, data1[0]); 10569 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]); 10570 ASSERT_EQUAL_64(0xfff11ffffff00fff, data2[0]); 10571 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data2[1]); 10572 ASSERT_EQUAL_64(0x7766554433221100, data3[0]); 10573 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]); 10574 ASSERT_EQUAL_64(0x7766554433221100, data4[0]); 10575 ASSERT_EQUAL_64(0xfff11ffffff00fff, data4[1]); 10576 ASSERT_EQUAL_64(0x7766554433221100, data5[0]); 10577 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]); 10578 ASSERT_EQUAL_64(0x7766554433221100, data6[0]); 10579 ASSERT_EQUAL_64(0xfff11ffffff00fff, data6[1]); 10580 ASSERT_EQUAL_64(0x7766554433221100, data7[0]); 10581 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]); 10582 ASSERT_EQUAL_64(0xfff11ffffff00fff, data8[0]); 10583 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data8[1]); 10584 } 10585} 10586 10587TEST(casp_caspa_caspl_caspal_x) { 10588 alignas(kXRegSizeInBytes * 2) uint64_t data1[] = {0x7766554433221100, 10589 0xffeeddccbbaa9988, 10590 0xfedcba9876543210, 10591 0x0123456789abcdef}; 10592 alignas(kXRegSizeInBytes * 2) uint64_t data2[] = {0x7766554433221100, 10593 0xffeeddccbbaa9988, 10594 0xfedcba9876543210, 10595 0x0123456789abcdef}; 10596 alignas(kXRegSizeInBytes * 2) uint64_t data3[] = {0x7766554433221100, 10597 0xffeeddccbbaa9988, 10598 0xfedcba9876543210, 10599 0x0123456789abcdef}; 10600 alignas(kXRegSizeInBytes * 2) uint64_t data4[] = {0x7766554433221100, 10601 0xffeeddccbbaa9988, 10602 0xfedcba9876543210, 10603 0x0123456789abcdef}; 10604 alignas(kXRegSizeInBytes * 2) uint64_t data5[] = {0x7766554433221100, 10605 0xffeeddccbbaa9988, 10606 0xfedcba9876543210, 10607 0x0123456789abcdef}; 10608 alignas(kXRegSizeInBytes * 2) uint64_t data6[] = {0x7766554433221100, 10609 0xffeeddccbbaa9988, 10610 0xfedcba9876543210, 10611 0x0123456789abcdef}; 10612 alignas(kXRegSizeInBytes * 2) uint64_t data7[] = {0x7766554433221100, 10613 0xffeeddccbbaa9988, 10614 0xfedcba9876543210, 10615 0x0123456789abcdef}; 10616 alignas(kXRegSizeInBytes * 2) uint64_t data8[] = {0x7766554433221100, 10617 0xffeeddccbbaa9988, 10618 0xfedcba9876543210, 10619 0x0123456789abcdef}; 10620 10621 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10622 10623 START(); 10624 10625 __ Mov(x21, reinterpret_cast<uintptr_t>(data1) + 0); 10626 __ Mov(x22, reinterpret_cast<uintptr_t>(data2) + 0); 10627 __ Mov(x23, reinterpret_cast<uintptr_t>(data3) + 16); 10628 __ Mov(x24, reinterpret_cast<uintptr_t>(data4) + 16); 10629 __ Mov(x25, reinterpret_cast<uintptr_t>(data5) + 16); 10630 __ Mov(x26, reinterpret_cast<uintptr_t>(data6) + 16); 10631 __ Mov(x27, reinterpret_cast<uintptr_t>(data7) + 0); 10632 __ Mov(x28, reinterpret_cast<uintptr_t>(data8) + 0); 10633 10634 __ Mov(x0, 0xfffffff00fffffff); 10635 __ Mov(x1, 0xfffffff11fffffff); 10636 10637 __ Mov(x2, 0xffeeddccbbaa9988); 10638 __ Mov(x3, 0x7766554433221100); 10639 __ Mov(x4, 0x7766554433221100); 10640 __ Mov(x5, 0xffeeddccbbaa9988); 10641 10642 __ Mov(x6, 0x0123456789abcdef); 10643 __ Mov(x7, 0xfedcba9876543210); 10644 __ Mov(x8, 0xfedcba9876543210); 10645 __ Mov(x9, 0x0123456789abcdef); 10646 10647 __ Mov(x10, 0x0123456789abcdef); 10648 __ Mov(x11, 0xfedcba9876543210); 10649 __ Mov(x12, 0xfedcba9876543210); 10650 __ Mov(x13, 0x0123456789abcdef); 10651 10652 __ Mov(x14, 0xffeeddccbbaa9988); 10653 __ Mov(x15, 0x7766554433221100); 10654 __ Mov(x16, 0x7766554433221100); 10655 __ Mov(x17, 0xffeeddccbbaa9988); 10656 10657 __ Casp(x2, x3, x0, x1, MemOperand(x21)); 10658 __ Casp(x4, x5, x0, x1, MemOperand(x22)); 10659 __ Caspa(x6, x7, x0, x1, MemOperand(x23)); 10660 __ Caspa(x8, x9, x0, x1, MemOperand(x24)); 10661 __ Caspl(x10, x11, x0, x1, MemOperand(x25)); 10662 __ Caspl(x12, x13, x0, x1, MemOperand(x26)); 10663 __ Caspal(x14, x15, x0, x1, MemOperand(x27)); 10664 __ Caspal(x16, x17, x0, x1, MemOperand(x28)); 10665 10666 END(); 10667 10668 if (CAN_RUN()) { 10669 RUN(); 10670 10671 ASSERT_EQUAL_64(0x7766554433221100, x2); 10672 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x3); 10673 ASSERT_EQUAL_64(0x7766554433221100, x4); 10674 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5); 10675 10676 ASSERT_EQUAL_64(0xfedcba9876543210, x6); 10677 ASSERT_EQUAL_64(0x0123456789abcdef, x7); 10678 ASSERT_EQUAL_64(0xfedcba9876543210, x8); 10679 ASSERT_EQUAL_64(0x0123456789abcdef, x9); 10680 10681 ASSERT_EQUAL_64(0xfedcba9876543210, x10); 10682 ASSERT_EQUAL_64(0x0123456789abcdef, x11); 10683 ASSERT_EQUAL_64(0xfedcba9876543210, x12); 10684 ASSERT_EQUAL_64(0x0123456789abcdef, x13); 10685 10686 ASSERT_EQUAL_64(0x7766554433221100, x14); 10687 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x15); 10688 ASSERT_EQUAL_64(0x7766554433221100, x16); 10689 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x17); 10690 10691 ASSERT_EQUAL_64(0x7766554433221100, data1[0]); 10692 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data1[1]); 10693 ASSERT_EQUAL_64(0xfedcba9876543210, data1[2]); 10694 ASSERT_EQUAL_64(0x0123456789abcdef, data1[3]); 10695 10696 ASSERT_EQUAL_64(0xfffffff00fffffff, data2[0]); 10697 ASSERT_EQUAL_64(0xfffffff11fffffff, data2[1]); 10698 ASSERT_EQUAL_64(0xfedcba9876543210, data2[2]); 10699 ASSERT_EQUAL_64(0x0123456789abcdef, data2[3]); 10700 10701 ASSERT_EQUAL_64(0x7766554433221100, data3[0]); 10702 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data3[1]); 10703 ASSERT_EQUAL_64(0xfedcba9876543210, data3[2]); 10704 ASSERT_EQUAL_64(0x0123456789abcdef, data3[3]); 10705 10706 ASSERT_EQUAL_64(0x7766554433221100, data4[0]); 10707 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data4[1]); 10708 ASSERT_EQUAL_64(0xfffffff00fffffff, data4[2]); 10709 ASSERT_EQUAL_64(0xfffffff11fffffff, data4[3]); 10710 10711 ASSERT_EQUAL_64(0x7766554433221100, data5[0]); 10712 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data5[1]); 10713 ASSERT_EQUAL_64(0xfedcba9876543210, data5[2]); 10714 ASSERT_EQUAL_64(0x0123456789abcdef, data5[3]); 10715 10716 ASSERT_EQUAL_64(0x7766554433221100, data6[0]); 10717 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data6[1]); 10718 ASSERT_EQUAL_64(0xfffffff00fffffff, data6[2]); 10719 ASSERT_EQUAL_64(0xfffffff11fffffff, data6[3]); 10720 10721 ASSERT_EQUAL_64(0x7766554433221100, data7[0]); 10722 ASSERT_EQUAL_64(0xffeeddccbbaa9988, data7[1]); 10723 ASSERT_EQUAL_64(0xfedcba9876543210, data7[2]); 10724 ASSERT_EQUAL_64(0x0123456789abcdef, data7[3]); 10725 10726 ASSERT_EQUAL_64(0xfffffff00fffffff, data8[0]); 10727 ASSERT_EQUAL_64(0xfffffff11fffffff, data8[1]); 10728 ASSERT_EQUAL_64(0xfedcba9876543210, data8[2]); 10729 ASSERT_EQUAL_64(0x0123456789abcdef, data8[3]); 10730 } 10731} 10732 10733 10734typedef void (MacroAssembler::*AtomicMemoryLoadSignature)( 10735 const Register& rs, const Register& rt, const MemOperand& src); 10736typedef void (MacroAssembler::*AtomicMemoryStoreSignature)( 10737 const Register& rs, const MemOperand& src); 10738 10739void AtomicMemoryWHelper(AtomicMemoryLoadSignature* load_funcs, 10740 AtomicMemoryStoreSignature* store_funcs, 10741 uint64_t arg1, 10742 uint64_t arg2, 10743 uint64_t expected, 10744 uint64_t result_mask) { 10745 uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10746 uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10747 uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10748 uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10749 uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10750 uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10751 10752 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10753 START(); 10754 10755 __ Mov(x20, reinterpret_cast<uintptr_t>(data0)); 10756 __ Mov(x21, reinterpret_cast<uintptr_t>(data1)); 10757 __ Mov(x22, reinterpret_cast<uintptr_t>(data2)); 10758 __ Mov(x23, reinterpret_cast<uintptr_t>(data3)); 10759 10760 __ Mov(x0, arg1); 10761 __ Mov(x1, arg1); 10762 __ Mov(x2, arg1); 10763 __ Mov(x3, arg1); 10764 10765 (masm.*(load_funcs[0]))(w0, w10, MemOperand(x20)); 10766 (masm.*(load_funcs[1]))(w1, w11, MemOperand(x21)); 10767 (masm.*(load_funcs[2]))(w2, w12, MemOperand(x22)); 10768 (masm.*(load_funcs[3]))(w3, w13, MemOperand(x23)); 10769 10770 if (store_funcs != NULL) { 10771 __ Mov(x24, reinterpret_cast<uintptr_t>(data4)); 10772 __ Mov(x25, reinterpret_cast<uintptr_t>(data5)); 10773 __ Mov(x4, arg1); 10774 __ Mov(x5, arg1); 10775 10776 (masm.*(store_funcs[0]))(w4, MemOperand(x24)); 10777 (masm.*(store_funcs[1]))(w5, MemOperand(x25)); 10778 } 10779 10780 END(); 10781 10782 if (CAN_RUN()) { 10783 RUN(); 10784 10785 uint64_t stored_value = arg2 & result_mask; 10786 ASSERT_EQUAL_64(stored_value, x10); 10787 ASSERT_EQUAL_64(stored_value, x11); 10788 ASSERT_EQUAL_64(stored_value, x12); 10789 ASSERT_EQUAL_64(stored_value, x13); 10790 10791 // The data fields contain arg2 already then only the bits masked by 10792 // result_mask are overwritten. 10793 uint64_t final_expected = (arg2 & ~result_mask) | (expected & result_mask); 10794 ASSERT_EQUAL_64(final_expected, data0[0]); 10795 ASSERT_EQUAL_64(final_expected, data1[0]); 10796 ASSERT_EQUAL_64(final_expected, data2[0]); 10797 ASSERT_EQUAL_64(final_expected, data3[0]); 10798 10799 if (store_funcs != NULL) { 10800 ASSERT_EQUAL_64(final_expected, data4[0]); 10801 ASSERT_EQUAL_64(final_expected, data5[0]); 10802 } 10803 } 10804} 10805 10806void AtomicMemoryXHelper(AtomicMemoryLoadSignature* load_funcs, 10807 AtomicMemoryStoreSignature* store_funcs, 10808 uint64_t arg1, 10809 uint64_t arg2, 10810 uint64_t expected) { 10811 uint64_t data0[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10812 uint64_t data1[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10813 uint64_t data2[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10814 uint64_t data3[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10815 uint64_t data4[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10816 uint64_t data5[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {arg2, 0}; 10817 10818 SETUP_WITH_FEATURES(CPUFeatures::kAtomics); 10819 START(); 10820 10821 __ Mov(x20, reinterpret_cast<uintptr_t>(data0)); 10822 __ Mov(x21, reinterpret_cast<uintptr_t>(data1)); 10823 __ Mov(x22, reinterpret_cast<uintptr_t>(data2)); 10824 __ Mov(x23, reinterpret_cast<uintptr_t>(data3)); 10825 10826 __ Mov(x0, arg1); 10827 __ Mov(x1, arg1); 10828 __ Mov(x2, arg1); 10829 __ Mov(x3, arg1); 10830 10831 (masm.*(load_funcs[0]))(x0, x10, MemOperand(x20)); 10832 (masm.*(load_funcs[1]))(x1, x11, MemOperand(x21)); 10833 (masm.*(load_funcs[2]))(x2, x12, MemOperand(x22)); 10834 (masm.*(load_funcs[3]))(x3, x13, MemOperand(x23)); 10835 10836 if (store_funcs != NULL) { 10837 __ Mov(x24, reinterpret_cast<uintptr_t>(data4)); 10838 __ Mov(x25, reinterpret_cast<uintptr_t>(data5)); 10839 __ Mov(x4, arg1); 10840 __ Mov(x5, arg1); 10841 10842 (masm.*(store_funcs[0]))(x4, MemOperand(x24)); 10843 (masm.*(store_funcs[1]))(x5, MemOperand(x25)); 10844 } 10845 10846 END(); 10847 10848 if (CAN_RUN()) { 10849 RUN(); 10850 10851 ASSERT_EQUAL_64(arg2, x10); 10852 ASSERT_EQUAL_64(arg2, x11); 10853 ASSERT_EQUAL_64(arg2, x12); 10854 ASSERT_EQUAL_64(arg2, x13); 10855 10856 ASSERT_EQUAL_64(expected, data0[0]); 10857 ASSERT_EQUAL_64(expected, data1[0]); 10858 ASSERT_EQUAL_64(expected, data2[0]); 10859 ASSERT_EQUAL_64(expected, data3[0]); 10860 10861 if (store_funcs != NULL) { 10862 ASSERT_EQUAL_64(expected, data4[0]); 10863 ASSERT_EQUAL_64(expected, data5[0]); 10864 } 10865 } 10866} 10867 10868// clang-format off 10869#define MAKE_LOADS(NAME) \ 10870 {&MacroAssembler::Ld##NAME, \ 10871 &MacroAssembler::Ld##NAME##a, \ 10872 &MacroAssembler::Ld##NAME##l, \ 10873 &MacroAssembler::Ld##NAME##al} 10874#define MAKE_STORES(NAME) \ 10875 {&MacroAssembler::St##NAME, &MacroAssembler::St##NAME##l} 10876 10877#define MAKE_B_LOADS(NAME) \ 10878 {&MacroAssembler::Ld##NAME##b, \ 10879 &MacroAssembler::Ld##NAME##ab, \ 10880 &MacroAssembler::Ld##NAME##lb, \ 10881 &MacroAssembler::Ld##NAME##alb} 10882#define MAKE_B_STORES(NAME) \ 10883 {&MacroAssembler::St##NAME##b, &MacroAssembler::St##NAME##lb} 10884 10885#define MAKE_H_LOADS(NAME) \ 10886 {&MacroAssembler::Ld##NAME##h, \ 10887 &MacroAssembler::Ld##NAME##ah, \ 10888 &MacroAssembler::Ld##NAME##lh, \ 10889 &MacroAssembler::Ld##NAME##alh} 10890#define MAKE_H_STORES(NAME) \ 10891 {&MacroAssembler::St##NAME##h, &MacroAssembler::St##NAME##lh} 10892// clang-format on 10893 10894TEST(atomic_memory_add) { 10895 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(add); 10896 AtomicMemoryStoreSignature stores[] = MAKE_STORES(add); 10897 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(add); 10898 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(add); 10899 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(add); 10900 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(add); 10901 10902 // The arguments are chosen to have two useful properties: 10903 // * When multiplied by small values (such as a register index), this value 10904 // is clearly readable in the result. 10905 // * The value is not formed from repeating fixed-size smaller values, so it 10906 // can be used to detect endianness-related errors. 10907 uint64_t arg1 = 0x0100001000100101; 10908 uint64_t arg2 = 0x0200002000200202; 10909 uint64_t expected = arg1 + arg2; 10910 10911 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 10912 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 10913 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 10914 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 10915} 10916 10917TEST(atomic_memory_clr) { 10918 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(clr); 10919 AtomicMemoryStoreSignature stores[] = MAKE_STORES(clr); 10920 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(clr); 10921 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(clr); 10922 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(clr); 10923 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(clr); 10924 10925 uint64_t arg1 = 0x0300003000300303; 10926 uint64_t arg2 = 0x0500005000500505; 10927 uint64_t expected = arg2 & ~arg1; 10928 10929 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 10930 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 10931 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 10932 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 10933} 10934 10935TEST(atomic_memory_eor) { 10936 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(eor); 10937 AtomicMemoryStoreSignature stores[] = MAKE_STORES(eor); 10938 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(eor); 10939 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(eor); 10940 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(eor); 10941 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(eor); 10942 10943 uint64_t arg1 = 0x0300003000300303; 10944 uint64_t arg2 = 0x0500005000500505; 10945 uint64_t expected = arg1 ^ arg2; 10946 10947 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 10948 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 10949 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 10950 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 10951} 10952 10953TEST(atomic_memory_set) { 10954 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(set); 10955 AtomicMemoryStoreSignature stores[] = MAKE_STORES(set); 10956 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(set); 10957 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(set); 10958 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(set); 10959 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(set); 10960 10961 uint64_t arg1 = 0x0300003000300303; 10962 uint64_t arg2 = 0x0500005000500505; 10963 uint64_t expected = arg1 | arg2; 10964 10965 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 10966 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 10967 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 10968 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 10969} 10970 10971TEST(atomic_memory_smax) { 10972 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smax); 10973 AtomicMemoryStoreSignature stores[] = MAKE_STORES(smax); 10974 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smax); 10975 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smax); 10976 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smax); 10977 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smax); 10978 10979 uint64_t arg1 = 0x8100000080108181; 10980 uint64_t arg2 = 0x0100001000100101; 10981 uint64_t expected = 0x0100001000100101; 10982 10983 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 10984 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 10985 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 10986 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 10987} 10988 10989TEST(atomic_memory_smin) { 10990 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(smin); 10991 AtomicMemoryStoreSignature stores[] = MAKE_STORES(smin); 10992 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(smin); 10993 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(smin); 10994 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(smin); 10995 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(smin); 10996 10997 uint64_t arg1 = 0x8100000080108181; 10998 uint64_t arg2 = 0x0100001000100101; 10999 uint64_t expected = 0x8100000080108181; 11000 11001 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 11002 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 11003 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 11004 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 11005} 11006 11007TEST(atomic_memory_umax) { 11008 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umax); 11009 AtomicMemoryStoreSignature stores[] = MAKE_STORES(umax); 11010 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umax); 11011 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umax); 11012 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umax); 11013 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umax); 11014 11015 uint64_t arg1 = 0x8100000080108181; 11016 uint64_t arg2 = 0x0100001000100101; 11017 uint64_t expected = 0x8100000080108181; 11018 11019 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 11020 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 11021 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 11022 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 11023} 11024 11025TEST(atomic_memory_umin) { 11026 AtomicMemoryLoadSignature loads[] = MAKE_LOADS(umin); 11027 AtomicMemoryStoreSignature stores[] = MAKE_STORES(umin); 11028 AtomicMemoryLoadSignature b_loads[] = MAKE_B_LOADS(umin); 11029 AtomicMemoryStoreSignature b_stores[] = MAKE_B_STORES(umin); 11030 AtomicMemoryLoadSignature h_loads[] = MAKE_H_LOADS(umin); 11031 AtomicMemoryStoreSignature h_stores[] = MAKE_H_STORES(umin); 11032 11033 uint64_t arg1 = 0x8100000080108181; 11034 uint64_t arg2 = 0x0100001000100101; 11035 uint64_t expected = 0x0100001000100101; 11036 11037 AtomicMemoryWHelper(b_loads, b_stores, arg1, arg2, expected, kByteMask); 11038 AtomicMemoryWHelper(h_loads, h_stores, arg1, arg2, expected, kHalfWordMask); 11039 AtomicMemoryWHelper(loads, stores, arg1, arg2, expected, kWordMask); 11040 AtomicMemoryXHelper(loads, stores, arg1, arg2, expected); 11041} 11042 11043TEST(atomic_memory_swp) { 11044 AtomicMemoryLoadSignature loads[] = {&MacroAssembler::Swp, 11045 &MacroAssembler::Swpa, 11046 &MacroAssembler::Swpl, 11047 &MacroAssembler::Swpal}; 11048 AtomicMemoryLoadSignature b_loads[] = {&MacroAssembler::Swpb, 11049 &MacroAssembler::Swpab, 11050 &MacroAssembler::Swplb, 11051 &MacroAssembler::Swpalb}; 11052 AtomicMemoryLoadSignature h_loads[] = {&MacroAssembler::Swph, 11053 &MacroAssembler::Swpah, 11054 &MacroAssembler::Swplh, 11055 &MacroAssembler::Swpalh}; 11056 11057 uint64_t arg1 = 0x0100001000100101; 11058 uint64_t arg2 = 0x0200002000200202; 11059 uint64_t expected = 0x0100001000100101; 11060 11061 // SWP functions have equivalent signatures to the Atomic Memory LD functions 11062 // so we can use the same helper but without the ST aliases. 11063 AtomicMemoryWHelper(b_loads, NULL, arg1, arg2, expected, kByteMask); 11064 AtomicMemoryWHelper(h_loads, NULL, arg1, arg2, expected, kHalfWordMask); 11065 AtomicMemoryWHelper(loads, NULL, arg1, arg2, expected, kWordMask); 11066 AtomicMemoryXHelper(loads, NULL, arg1, arg2, expected); 11067} 11068 11069 11070TEST(ldaprb_ldaprh_ldapr) { 11071 uint64_t data0[] = {0x1010101010101010, 0x1010101010101010}; 11072 uint64_t data1[] = {0x1010101010101010, 0x1010101010101010}; 11073 uint64_t data2[] = {0x1010101010101010, 0x1010101010101010}; 11074 uint64_t data3[] = {0x1010101010101010, 0x1010101010101010}; 11075 11076 uint64_t* data0_aligned = AlignUp(data0, kXRegSizeInBytes * 2); 11077 uint64_t* data1_aligned = AlignUp(data1, kXRegSizeInBytes * 2); 11078 uint64_t* data2_aligned = AlignUp(data2, kXRegSizeInBytes * 2); 11079 uint64_t* data3_aligned = AlignUp(data3, kXRegSizeInBytes * 2); 11080 11081 SETUP_WITH_FEATURES(CPUFeatures::kRCpc); 11082 START(); 11083 11084 __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned)); 11085 __ Mov(x21, reinterpret_cast<uintptr_t>(data1_aligned)); 11086 __ Mov(x22, reinterpret_cast<uintptr_t>(data2_aligned)); 11087 __ Mov(x23, reinterpret_cast<uintptr_t>(data3_aligned)); 11088 11089 __ Ldaprb(w0, MemOperand(x20)); 11090 __ Ldaprh(w1, MemOperand(x21)); 11091 __ Ldapr(w2, MemOperand(x22)); 11092 __ Ldapr(x3, MemOperand(x23)); 11093 11094 END(); 11095 11096 if (CAN_RUN()) { 11097 RUN(); 11098 ASSERT_EQUAL_64(0x10, x0); 11099 ASSERT_EQUAL_64(0x1010, x1); 11100 ASSERT_EQUAL_64(0x10101010, x2); 11101 ASSERT_EQUAL_64(0x1010101010101010, x3); 11102 } 11103} 11104 11105 11106TEST(ldapurb_ldapurh_ldapur) { 11107 uint64_t data[] 11108 __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef, 11109 0xfedcba9876543210}; 11110 11111 uintptr_t data_base = reinterpret_cast<uintptr_t>(data); 11112 11113 SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm); 11114 START(); 11115 11116 __ Mov(x20, data_base); 11117 __ Mov(x21, data_base + 2 * sizeof(data[0])); 11118 11119 __ Ldaprb(w0, MemOperand(x20)); 11120 __ Ldaprh(w1, MemOperand(x20)); 11121 __ Ldapr(w2, MemOperand(x20)); 11122 __ Ldapr(x3, MemOperand(x20)); 11123 __ Ldaprb(w4, MemOperand(x20, 12)); 11124 __ Ldaprh(w5, MemOperand(x20, 8)); 11125 __ Ldapr(w6, MemOperand(x20, 10)); 11126 __ Ldapr(x7, MemOperand(x20, 7)); 11127 __ Ldaprb(w8, MemOperand(x21, -1)); 11128 __ Ldaprh(w9, MemOperand(x21, -3)); 11129 __ Ldapr(w10, MemOperand(x21, -9)); 11130 __ Ldapr(x11, MemOperand(x21, -12)); 11131 11132 END(); 11133 11134 if (CAN_RUN()) { 11135 RUN(); 11136 ASSERT_EQUAL_64(0xef, x0); 11137 ASSERT_EQUAL_64(0xcdef, x1); 11138 ASSERT_EQUAL_64(0x89abcdef, x2); 11139 ASSERT_EQUAL_64(0x0123456789abcdef, x3); 11140 ASSERT_EQUAL_64(0x98, x4); 11141 ASSERT_EQUAL_64(0x3210, x5); 11142 ASSERT_EQUAL_64(0xba987654, x6); 11143 ASSERT_EQUAL_64(0xdcba987654321001, x7); 11144 ASSERT_EQUAL_64(0xfe, x8); 11145 ASSERT_EQUAL_64(0xdcba, x9); 11146 ASSERT_EQUAL_64(0x54321001, x10); 11147 ASSERT_EQUAL_64(0x7654321001234567, x11); 11148 } 11149} 11150 11151 11152TEST(ldapursb_ldapursh_ldapursw) { 11153 uint64_t data[] 11154 __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0123456789abcdef, 11155 0xfedcba9876543210}; 11156 11157 uintptr_t data_base = reinterpret_cast<uintptr_t>(data); 11158 11159 SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm); 11160 START(); 11161 11162 __ Mov(x20, data_base); 11163 __ Mov(x21, data_base + 2 * sizeof(data[0])); 11164 11165 __ Ldapursb(w0, MemOperand(x20)); 11166 __ Ldapursb(x1, MemOperand(x20)); 11167 __ Ldapursh(w2, MemOperand(x20)); 11168 __ Ldapursh(x3, MemOperand(x20)); 11169 __ Ldapursw(x4, MemOperand(x20)); 11170 __ Ldapursb(w5, MemOperand(x20, 12)); 11171 __ Ldapursb(x6, MemOperand(x20, 12)); 11172 __ Ldapursh(w7, MemOperand(x20, 13)); 11173 __ Ldapursh(x8, MemOperand(x20, 13)); 11174 __ Ldapursw(x9, MemOperand(x20, 10)); 11175 __ Ldapursb(w10, MemOperand(x21, -1)); 11176 __ Ldapursb(x11, MemOperand(x21, -1)); 11177 __ Ldapursh(w12, MemOperand(x21, -4)); 11178 __ Ldapursh(x13, MemOperand(x21, -4)); 11179 __ Ldapursw(x14, MemOperand(x21, -5)); 11180 11181 __ Ldapursb(x15, MemOperand(x20, 8)); 11182 __ Ldapursh(x16, MemOperand(x20, 8)); 11183 __ Ldapursw(x17, MemOperand(x20, 8)); 11184 11185 END(); 11186 11187 if (CAN_RUN()) { 11188 RUN(); 11189 ASSERT_EQUAL_64(0xffffffef, x0); 11190 ASSERT_EQUAL_64(0xffffffffffffffef, x1); 11191 ASSERT_EQUAL_64(0xffffcdef, x2); 11192 ASSERT_EQUAL_64(0xffffffffffffcdef, x3); 11193 ASSERT_EQUAL_64(0xffffffff89abcdef, x4); 11194 ASSERT_EQUAL_64(0xffffff98, x5); 11195 ASSERT_EQUAL_64(0xffffffffffffff98, x6); 11196 ASSERT_EQUAL_64(0xffffdcba, x7); 11197 ASSERT_EQUAL_64(0xffffffffffffdcba, x8); 11198 ASSERT_EQUAL_64(0xffffffffba987654, x9); 11199 ASSERT_EQUAL_64(0xfffffffe, x10); 11200 ASSERT_EQUAL_64(0xfffffffffffffffe, x11); 11201 ASSERT_EQUAL_64(0xffffba98, x12); 11202 ASSERT_EQUAL_64(0xffffffffffffba98, x13); 11203 ASSERT_EQUAL_64(0xffffffffdcba9876, x14); 11204 11205 ASSERT_EQUAL_64(0x0000000000000010, x15); 11206 ASSERT_EQUAL_64(0x0000000000003210, x16); 11207 ASSERT_EQUAL_64(0x0000000076543210, x17); 11208 } 11209} 11210 11211 11212TEST(stlurb_stlurh_strlur) { 11213 uint64_t data[] __attribute__((aligned(kXRegSizeInBytes * 2))) = {0x0, 0x0}; 11214 11215 uintptr_t data_base = reinterpret_cast<uintptr_t>(data); 11216 11217 SETUP_WITH_FEATURES(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm); 11218 START(); 11219 11220 __ Mov(x0, 0x0011223344556677); 11221 __ Mov(x20, data_base); 11222 __ Mov(x21, data_base + 2 * sizeof(data[0])); 11223 11224 __ Stlrb(w0, MemOperand(x20)); 11225 __ Stlrh(w0, MemOperand(x20, 1)); 11226 __ Stlr(w0, MemOperand(x20, 3)); 11227 __ Stlr(x0, MemOperand(x21, -8)); 11228 11229 END(); 11230 11231 if (CAN_RUN()) { 11232 RUN(); 11233 ASSERT_EQUAL_64(0x0044556677667777, data[0]); 11234 ASSERT_EQUAL_64(0x0011223344556677, data[1]); 11235 } 11236} 11237 11238 11239#define SIMPLE_ATOMIC_OPS(V, DEF) \ 11240 V(DEF, add) \ 11241 V(DEF, clr) \ 11242 V(DEF, eor) \ 11243 V(DEF, set) \ 11244 V(DEF, smax) \ 11245 V(DEF, smin) \ 11246 V(DEF, umax) \ 11247 V(DEF, umin) 11248 11249#define SIMPLE_ATOMIC_STORE_MODES(V, NAME) \ 11250 V(NAME) \ 11251 V(NAME##l) 11252 11253#define SIMPLE_ATOMIC_LOAD_MODES(V, NAME) \ 11254 SIMPLE_ATOMIC_STORE_MODES(V, NAME) \ 11255 V(NAME##a) \ 11256 V(NAME##al) 11257 11258 11259TEST(unaligned_single_copy_atomicity) { 11260 uint64_t data0[] = {0x1010101010101010, 0x1010101010101010}; 11261 uint64_t dst[] = {0x0000000000000000, 0x0000000000000000}; 11262 11263 uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule); 11264 uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule); 11265 11266 CPUFeatures features(CPUFeatures::kAtomics, 11267 CPUFeatures::kLORegions, 11268 CPUFeatures::kRCpc, 11269 CPUFeatures::kRCpcImm); 11270 features.Combine(CPUFeatures::kUSCAT); 11271 SETUP_WITH_FEATURES(features); 11272 START(); 11273 11274 __ Mov(x0, 0x0123456789abcdef); 11275 __ Mov(x1, 0x456789abcdef0123); 11276 __ Mov(x2, 0x89abcdef01234567); 11277 __ Mov(x3, 0xcdef0123456789ab); 11278 __ Mov(x18, reinterpret_cast<uintptr_t>(data0_aligned)); 11279 __ Mov(x19, reinterpret_cast<uintptr_t>(dst_aligned)); 11280 __ Mov(x20, x18); 11281 __ Mov(x21, x19); 11282 11283 for (unsigned i = 0; i < kAtomicAccessGranule; i++) { 11284 __ Stxrb(w0, w1, MemOperand(x20)); 11285 __ Stlxrb(w0, w1, MemOperand(x20)); 11286 __ Ldxrb(w0, MemOperand(x20)); 11287 __ Ldaxrb(w0, MemOperand(x20)); 11288 __ Stllrb(w0, MemOperand(x20)); 11289 __ Stlrb(w0, MemOperand(x20)); 11290 __ Casb(w0, w1, MemOperand(x20)); 11291 __ Caslb(w0, w1, MemOperand(x20)); 11292 __ Ldlarb(w0, MemOperand(x20)); 11293 __ Ldarb(w0, MemOperand(x20)); 11294 __ Casab(w0, w1, MemOperand(x20)); 11295 __ Casalb(w0, w1, MemOperand(x20)); 11296 11297 __ Swpb(w0, w1, MemOperand(x20)); 11298 __ Swplb(w0, w1, MemOperand(x20)); 11299 __ Swpab(w0, w1, MemOperand(x20)); 11300 __ Swpalb(w0, w1, MemOperand(x20)); 11301 __ Ldaprb(w0, MemOperand(x20)); 11302 // Use offset instead of Add to test Stlurb and Ldapurb. 11303 __ Stlrb(w0, MemOperand(x19, i)); 11304 __ Ldaprb(w0, MemOperand(x19, i)); 11305 __ Ldapursb(w0, MemOperand(x20)); 11306 __ Ldapursb(x0, MemOperand(x20)); 11307 11308#define ATOMIC_LOAD_B(NAME) __ Ld##NAME##b(w0, w1, MemOperand(x20)); 11309#define ATOMIC_STORE_B(NAME) __ St##NAME##b(w0, MemOperand(x20)); 11310 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_B) 11311 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_B) 11312#undef ATOMIC_LOAD_B 11313#undef ATOMIC_STORE_B 11314 11315 if (i <= (kAtomicAccessGranule - kHRegSizeInBytes)) { 11316 __ Stxrh(w0, w1, MemOperand(x20)); 11317 __ Stlxrh(w0, w1, MemOperand(x20)); 11318 __ Ldxrh(w0, MemOperand(x20)); 11319 __ Ldaxrh(w0, MemOperand(x20)); 11320 __ Stllrh(w0, MemOperand(x20)); 11321 __ Stlrh(w0, MemOperand(x20)); 11322 __ Cash(w0, w1, MemOperand(x20)); 11323 __ Caslh(w0, w1, MemOperand(x20)); 11324 __ Ldlarh(w0, MemOperand(x20)); 11325 __ Ldarh(w0, MemOperand(x20)); 11326 __ Casah(w0, w1, MemOperand(x20)); 11327 __ Casalh(w0, w1, MemOperand(x20)); 11328 11329 __ Swph(w0, w1, MemOperand(x20)); 11330 __ Swplh(w0, w1, MemOperand(x20)); 11331 __ Swpah(w0, w1, MemOperand(x20)); 11332 __ Swpalh(w0, w1, MemOperand(x20)); 11333 __ Ldaprh(w0, MemOperand(x20)); 11334 // Use offset instead of Add to test Stlurh and Ldapurh. 11335 __ Stlrh(w0, MemOperand(x19, i)); 11336 __ Ldaprh(w0, MemOperand(x19, i)); 11337 __ Ldapursh(w0, MemOperand(x20)); 11338 __ Ldapursh(x0, MemOperand(x20)); 11339 11340#define ATOMIC_LOAD_H(NAME) __ Ld##NAME##h(w0, w1, MemOperand(x20)); 11341#define ATOMIC_STORE_H(NAME) __ St##NAME##h(w0, MemOperand(x20)); 11342 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H) 11343 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H) 11344#undef ATOMIC_LOAD_H 11345#undef ATOMIC_STORE_H 11346 } 11347 11348 if (i <= (kAtomicAccessGranule - kWRegSizeInBytes)) { 11349 __ Stxr(w0, w1, MemOperand(x20)); 11350 __ Stlxr(w0, w1, MemOperand(x20)); 11351 __ Ldxr(w0, MemOperand(x20)); 11352 __ Ldaxr(w0, MemOperand(x20)); 11353 __ Stllr(w0, MemOperand(x20)); 11354 __ Stlr(w0, MemOperand(x20)); 11355 __ Cas(w0, w1, MemOperand(x20)); 11356 __ Casl(w0, w1, MemOperand(x20)); 11357 __ Ldlar(w0, MemOperand(x20)); 11358 __ Ldar(w0, MemOperand(x20)); 11359 __ Casa(w0, w1, MemOperand(x20)); 11360 __ Casal(w0, w1, MemOperand(x20)); 11361 11362 __ Swp(w0, w1, MemOperand(x20)); 11363 __ Swpl(w0, w1, MemOperand(x20)); 11364 __ Swpa(w0, w1, MemOperand(x20)); 11365 __ Swpal(w0, w1, MemOperand(x20)); 11366 __ Ldapr(w0, MemOperand(x20)); 11367 // Use offset instead of Add to test Stlur and Ldapur. 11368 __ Stlr(w0, MemOperand(x19, i)); 11369 __ Ldapr(w0, MemOperand(x19, i)); 11370 __ Ldapursw(x0, MemOperand(x20)); 11371 11372#define ATOMIC_LOAD_W(NAME) __ Ld##NAME(w0, w1, MemOperand(x20)); 11373#define ATOMIC_STORE_W(NAME) __ St##NAME(w0, MemOperand(x20)); 11374 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W) 11375 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W) 11376#undef ATOMIC_LOAD_W 11377#undef ATOMIC_STORE_W 11378 } 11379 11380 if (i <= (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) { 11381 __ Casp(w0, w1, w2, w3, MemOperand(x20)); 11382 __ Caspl(w0, w1, w2, w3, MemOperand(x20)); 11383 __ Caspa(w0, w1, w2, w3, MemOperand(x20)); 11384 __ Caspal(w0, w1, w2, w3, MemOperand(x20)); 11385 __ Stxp(w0, w1, w2, MemOperand(x20)); 11386 __ Stlxp(w0, w1, w2, MemOperand(x20)); 11387 __ Ldxp(w0, w1, MemOperand(x20)); 11388 __ Ldaxp(w0, w1, MemOperand(x20)); 11389 } 11390 11391 if (i <= (kAtomicAccessGranule - kXRegSizeInBytes)) { 11392 __ Stxr(x0, x1, MemOperand(x20)); 11393 __ Stlxr(x0, x1, MemOperand(x20)); 11394 __ Ldxr(x0, MemOperand(x20)); 11395 __ Ldaxr(x0, MemOperand(x20)); 11396 __ Stllr(x0, MemOperand(x20)); 11397 __ Stlr(x0, MemOperand(x20)); 11398 __ Cas(x0, x1, MemOperand(x20)); 11399 __ Casl(x0, x1, MemOperand(x20)); 11400 __ Ldlar(x0, MemOperand(x20)); 11401 __ Ldar(x0, MemOperand(x20)); 11402 __ Casa(x0, x1, MemOperand(x20)); 11403 __ Casal(x0, x1, MemOperand(x20)); 11404 11405 __ Swp(x0, x1, MemOperand(x20)); 11406 __ Swpl(x0, x1, MemOperand(x20)); 11407 __ Swpa(x0, x1, MemOperand(x20)); 11408 __ Swpal(x0, x1, MemOperand(x20)); 11409 __ Ldapr(x0, MemOperand(x20)); 11410 // Use offset instead of Add to test Stlur and Ldapur. 11411 __ Stlr(x0, MemOperand(x19, i)); 11412 __ Ldapr(x0, MemOperand(x19, i)); 11413 11414#define ATOMIC_LOAD_X(NAME) __ Ld##NAME(x0, x1, MemOperand(x20)); 11415#define ATOMIC_STORE_X(NAME) __ St##NAME(x0, MemOperand(x20)); 11416 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X) 11417 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X) 11418#undef ATOMIC_LOAD_X 11419#undef ATOMIC_STORE_X 11420 } 11421 11422 if (i <= (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) { 11423 __ Casp(x0, x1, x2, x3, MemOperand(x20)); 11424 __ Caspl(x0, x1, x2, x3, MemOperand(x20)); 11425 __ Caspa(x0, x1, x2, x3, MemOperand(x20)); 11426 __ Caspal(x0, x1, x2, x3, MemOperand(x20)); 11427 __ Stxp(x0, x1, x2, MemOperand(x20)); 11428 __ Stlxp(x0, x1, x2, MemOperand(x20)); 11429 __ Ldxp(x0, x1, MemOperand(x20)); 11430 __ Ldaxp(x0, x1, MemOperand(x20)); 11431 } 11432 11433 __ Add(x20, x20, 1); 11434 __ Add(x21, x21, 1); 11435 } 11436 END(); 11437 11438 if (CAN_RUN()) { 11439 // We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the seen 11440 // check. 11441 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 11442 } 11443} 11444 11445 11446#if defined(VIXL_NEGATIVE_TESTING) && defined(VIXL_INCLUDE_SIMULATOR_AARCH64) 11447 11448#define CHECK_ALIGN_FAIL(i, expr) \ 11449 { \ 11450 CPUFeatures features(CPUFeatures::kAtomics, \ 11451 CPUFeatures::kLORegions, \ 11452 CPUFeatures::kRCpc, \ 11453 CPUFeatures::kRCpcImm); \ 11454 features.Combine(CPUFeatures::kUSCAT); \ 11455 SETUP_WITH_FEATURES(features); \ 11456 START(); \ 11457 __ Mov(x0, 0x0123456789abcdef); \ 11458 __ Mov(x1, 0x456789abcdef0123); \ 11459 __ Mov(x2, 0x89abcdef01234567); \ 11460 __ Mov(x3, 0xcdef0123456789ab); \ 11461 __ Mov(x20, reinterpret_cast<uintptr_t>(data0_aligned)); \ 11462 __ Mov(x21, reinterpret_cast<uintptr_t>(dst_aligned)); \ 11463 __ Add(x20, x20, i); \ 11464 __ Add(x21, x21, i); \ 11465 expr; \ 11466 END(); \ 11467 if (CAN_RUN()) { \ 11468 /* We can't detect kUSCAT with the CPUFeaturesAuditor so it fails the */ \ 11469 /* seen check. */ \ 11470 MUST_FAIL_WITH_MESSAGE(RUN_WITHOUT_SEEN_FEATURE_CHECK(), \ 11471 "ALIGNMENT EXCEPTION"); \ 11472 } \ 11473 } 11474 11475TEST(unaligned_single_copy_atomicity_negative_test) { 11476 uint64_t data0[] = {0x1010101010101010, 0x1010101010101010}; 11477 uint64_t dst[] = {0x0000000000000000, 0x0000000000000000}; 11478 11479 uint64_t* data0_aligned = AlignUp(data0, kAtomicAccessGranule); 11480 uint64_t* dst_aligned = AlignUp(dst, kAtomicAccessGranule); 11481 11482 for (unsigned i = 0; i < kAtomicAccessGranule; i++) { 11483 if (i > (kAtomicAccessGranule - kHRegSizeInBytes)) { 11484 CHECK_ALIGN_FAIL(i, __ Stxrh(w0, w1, MemOperand(x20))); 11485 CHECK_ALIGN_FAIL(i, __ Stlxrh(w0, w1, MemOperand(x20))); 11486 CHECK_ALIGN_FAIL(i, __ Ldxrh(w0, MemOperand(x20))); 11487 CHECK_ALIGN_FAIL(i, __ Ldaxrh(w0, MemOperand(x20))); 11488 CHECK_ALIGN_FAIL(i, __ Stllrh(w0, MemOperand(x20))); 11489 CHECK_ALIGN_FAIL(i, __ Stlrh(w0, MemOperand(x20))); 11490 CHECK_ALIGN_FAIL(i, __ Cash(w0, w1, MemOperand(x20))); 11491 CHECK_ALIGN_FAIL(i, __ Caslh(w0, w1, MemOperand(x20))); 11492 CHECK_ALIGN_FAIL(i, __ Ldlarh(w0, MemOperand(x20))); 11493 CHECK_ALIGN_FAIL(i, __ Ldarh(w0, MemOperand(x20))); 11494 CHECK_ALIGN_FAIL(i, __ Casah(w0, w1, MemOperand(x20))); 11495 CHECK_ALIGN_FAIL(i, __ Casalh(w0, w1, MemOperand(x20))); 11496 11497 CHECK_ALIGN_FAIL(i, __ Swph(w0, w1, MemOperand(x20))); 11498 CHECK_ALIGN_FAIL(i, __ Swplh(w0, w1, MemOperand(x20))); 11499 CHECK_ALIGN_FAIL(i, __ Swpah(w0, w1, MemOperand(x20))); 11500 CHECK_ALIGN_FAIL(i, __ Swpalh(w0, w1, MemOperand(x20))); 11501 CHECK_ALIGN_FAIL(i, __ Ldaprh(w0, MemOperand(x20))); 11502 // Use offset instead of Add to test Stlurh and Ldapurh. 11503 CHECK_ALIGN_FAIL(0, __ Stlrh(w0, MemOperand(x20, i))); 11504 CHECK_ALIGN_FAIL(0, __ Ldaprh(w0, MemOperand(x20, i))); 11505 CHECK_ALIGN_FAIL(i, __ Ldapursh(w0, MemOperand(x20))); 11506 CHECK_ALIGN_FAIL(i, __ Ldapursh(x0, MemOperand(x20))); 11507 11508#define ATOMIC_LOAD_H(NAME) \ 11509 CHECK_ALIGN_FAIL(i, __ Ld##NAME##h(w0, w1, MemOperand(x20))); 11510#define ATOMIC_STORE_H(NAME) \ 11511 CHECK_ALIGN_FAIL(i, __ St##NAME##h(w0, MemOperand(x20))); 11512 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_H) 11513 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_H) 11514#undef ATOMIC_LOAD_H 11515#undef ATOMIC_STORE_H 11516 } 11517 11518 if (i > (kAtomicAccessGranule - kWRegSizeInBytes)) { 11519 CHECK_ALIGN_FAIL(i, __ Stxr(w0, w1, MemOperand(x20))); 11520 CHECK_ALIGN_FAIL(i, __ Stlxr(w0, w1, MemOperand(x20))); 11521 CHECK_ALIGN_FAIL(i, __ Ldxr(w0, MemOperand(x20))); 11522 CHECK_ALIGN_FAIL(i, __ Ldaxr(w0, MemOperand(x20))); 11523 CHECK_ALIGN_FAIL(i, __ Stllr(w0, MemOperand(x20))); 11524 CHECK_ALIGN_FAIL(i, __ Stlr(w0, MemOperand(x20))); 11525 CHECK_ALIGN_FAIL(i, __ Cas(w0, w1, MemOperand(x20))); 11526 CHECK_ALIGN_FAIL(i, __ Casl(w0, w1, MemOperand(x20))); 11527 CHECK_ALIGN_FAIL(i, __ Ldlar(w0, MemOperand(x20))); 11528 CHECK_ALIGN_FAIL(i, __ Ldar(w0, MemOperand(x20))); 11529 CHECK_ALIGN_FAIL(i, __ Casa(w0, w1, MemOperand(x20))); 11530 CHECK_ALIGN_FAIL(i, __ Casal(w0, w1, MemOperand(x20))); 11531 11532 CHECK_ALIGN_FAIL(i, __ Swp(w0, w1, MemOperand(x20))); 11533 CHECK_ALIGN_FAIL(i, __ Swpl(w0, w1, MemOperand(x20))); 11534 CHECK_ALIGN_FAIL(i, __ Swpa(w0, w1, MemOperand(x20))); 11535 CHECK_ALIGN_FAIL(i, __ Swpal(w0, w1, MemOperand(x20))); 11536 CHECK_ALIGN_FAIL(i, __ Ldapr(w0, MemOperand(x20))); 11537 // Use offset instead of add to test Stlur and Ldapur. 11538 CHECK_ALIGN_FAIL(0, __ Stlr(w0, MemOperand(x20, i))); 11539 CHECK_ALIGN_FAIL(0, __ Ldapr(w0, MemOperand(x20, i))); 11540 CHECK_ALIGN_FAIL(i, __ Ldapursw(x0, MemOperand(x20))); 11541 11542#define ATOMIC_LOAD_W(NAME) \ 11543 CHECK_ALIGN_FAIL(i, __ Ld##NAME(w0, w1, MemOperand(x20))); 11544#define ATOMIC_STORE_W(NAME) \ 11545 CHECK_ALIGN_FAIL(i, __ St##NAME(w0, MemOperand(x20))); 11546 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_W) 11547 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_W) 11548#undef ATOMIC_LOAD_W 11549#undef ATOMIC_STORE_W 11550 } 11551 11552 if (i > (kAtomicAccessGranule - (kWRegSizeInBytes * 2))) { 11553 CHECK_ALIGN_FAIL(i, __ Casp(w0, w1, w2, w3, MemOperand(x20))); 11554 CHECK_ALIGN_FAIL(i, __ Caspl(w0, w1, w2, w3, MemOperand(x20))); 11555 CHECK_ALIGN_FAIL(i, __ Caspa(w0, w1, w2, w3, MemOperand(x20))); 11556 CHECK_ALIGN_FAIL(i, __ Caspal(w0, w1, w2, w3, MemOperand(x20))); 11557 CHECK_ALIGN_FAIL(i, __ Stxp(w0, w1, w2, MemOperand(x20))); 11558 CHECK_ALIGN_FAIL(i, __ Stlxp(w0, w1, w2, MemOperand(x20))); 11559 CHECK_ALIGN_FAIL(i, __ Ldxp(w0, w1, MemOperand(x20))); 11560 CHECK_ALIGN_FAIL(i, __ Ldaxp(w0, w1, MemOperand(x20))); 11561 } 11562 11563 if (i > (kAtomicAccessGranule - kXRegSizeInBytes)) { 11564 CHECK_ALIGN_FAIL(i, __ Stxr(x0, x1, MemOperand(x20))); 11565 CHECK_ALIGN_FAIL(i, __ Stlxr(x0, x1, MemOperand(x20))); 11566 CHECK_ALIGN_FAIL(i, __ Ldxr(x0, MemOperand(x20))); 11567 CHECK_ALIGN_FAIL(i, __ Ldaxr(x0, MemOperand(x20))); 11568 CHECK_ALIGN_FAIL(i, __ Stllr(x0, MemOperand(x20))); 11569 CHECK_ALIGN_FAIL(i, __ Stlr(x0, MemOperand(x20))); 11570 CHECK_ALIGN_FAIL(i, __ Cas(x0, x1, MemOperand(x20))); 11571 CHECK_ALIGN_FAIL(i, __ Casl(x0, x1, MemOperand(x20))); 11572 CHECK_ALIGN_FAIL(i, __ Ldlar(x0, MemOperand(x20))); 11573 CHECK_ALIGN_FAIL(i, __ Ldar(x0, MemOperand(x20))); 11574 CHECK_ALIGN_FAIL(i, __ Casa(x0, x1, MemOperand(x20))); 11575 CHECK_ALIGN_FAIL(i, __ Casal(x0, x1, MemOperand(x20))); 11576 11577 CHECK_ALIGN_FAIL(i, __ Swp(x0, x1, MemOperand(x20))); 11578 CHECK_ALIGN_FAIL(i, __ Swpl(x0, x1, MemOperand(x20))); 11579 CHECK_ALIGN_FAIL(i, __ Swpa(x0, x1, MemOperand(x20))); 11580 CHECK_ALIGN_FAIL(i, __ Swpal(x0, x1, MemOperand(x20))); 11581 CHECK_ALIGN_FAIL(i, __ Ldapr(x0, MemOperand(x20))); 11582 // Use offset instead of add to test Stlur and Ldapur. 11583 CHECK_ALIGN_FAIL(0, __ Stlr(x0, MemOperand(x20, i))); 11584 CHECK_ALIGN_FAIL(0, __ Ldapr(x0, MemOperand(x20, i))); 11585 11586#define ATOMIC_LOAD_X(NAME) \ 11587 CHECK_ALIGN_FAIL(i, __ Ld##NAME(x0, x1, MemOperand(x20))); 11588#define ATOMIC_STORE_X(NAME) \ 11589 CHECK_ALIGN_FAIL(i, __ St##NAME(x0, MemOperand(x20))); 11590 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_LOAD_MODES, ATOMIC_LOAD_X) 11591 SIMPLE_ATOMIC_OPS(SIMPLE_ATOMIC_STORE_MODES, ATOMIC_STORE_X) 11592#undef ATOMIC_LOAD_X 11593#undef ATOMIC_STORE_X 11594 } 11595 11596 if (i > (kAtomicAccessGranule - (kXRegSizeInBytes * 2))) { 11597 CHECK_ALIGN_FAIL(i, __ Casp(x0, x1, x2, x3, MemOperand(x20))); 11598 CHECK_ALIGN_FAIL(i, __ Caspl(x0, x1, x2, x3, MemOperand(x20))); 11599 CHECK_ALIGN_FAIL(i, __ Caspa(x0, x1, x2, x3, MemOperand(x20))); 11600 CHECK_ALIGN_FAIL(i, __ Caspal(x0, x1, x2, x3, MemOperand(x20))); 11601 CHECK_ALIGN_FAIL(i, __ Stxp(x0, x1, x2, MemOperand(x20))); 11602 CHECK_ALIGN_FAIL(i, __ Stlxp(x0, x1, x2, MemOperand(x20))); 11603 CHECK_ALIGN_FAIL(i, __ Ldxp(x0, x1, MemOperand(x20))); 11604 CHECK_ALIGN_FAIL(i, __ Ldaxp(x0, x1, MemOperand(x20))); 11605 } 11606 } 11607} 11608 11609TEST(unaligned_single_copy_atomicity_negative_test_2) { 11610 uint64_t data[] = {0x1010101010101010, 0x1010101010101010}; 11611 11612 uint64_t* data_aligned = AlignUp(data, kAtomicAccessGranule); 11613 11614 // Check that the same code doesn't fail with USCAT enabled but does 11615 // fail when not enabled. 11616 { 11617 SETUP_WITH_FEATURES(CPUFeatures::kUSCAT); 11618 START(); 11619 __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned)); 11620 __ Add(x0, x0, 1); 11621 __ Ldxrh(w1, MemOperand(x0)); 11622 END(); 11623 if (CAN_RUN()) { 11624 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 11625 } 11626 } 11627 { 11628 SETUP(); 11629 START(); 11630 __ Mov(x0, reinterpret_cast<uintptr_t>(data_aligned)); 11631 __ Add(x0, x0, 1); 11632 __ Ldxrh(w1, MemOperand(x0)); 11633 END(); 11634 if (CAN_RUN()) { 11635 MUST_FAIL_WITH_MESSAGE(RUN(), "ALIGNMENT EXCEPTION"); 11636 } 11637 } 11638} 11639#endif // VIXL_NEGATIVE_TESTING && VIXL_INCLUDE_SIMULATOR_AARCH64 11640 11641 11642TEST(load_store_tagged_immediate_offset) { 11643 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff}; 11644 int tag_count = sizeof(tags) / sizeof(tags[0]); 11645 11646 const int kMaxDataLength = 160; 11647 11648 for (int i = 0; i < tag_count; i++) { 11649 unsigned char src[kMaxDataLength]; 11650 uint64_t src_raw = reinterpret_cast<uint64_t>(src); 11651 uint64_t src_tag = tags[i]; 11652 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag); 11653 11654 for (int k = 0; k < kMaxDataLength; k++) { 11655 src[k] = k + 1; 11656 } 11657 11658 for (int j = 0; j < tag_count; j++) { 11659 unsigned char dst[kMaxDataLength]; 11660 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst); 11661 uint64_t dst_tag = tags[j]; 11662 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag); 11663 11664 memset(dst, 0, kMaxDataLength); 11665 11666 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 11667 START(); 11668 11669 __ Mov(x0, src_tagged); 11670 __ Mov(x1, dst_tagged); 11671 11672 int offset = 0; 11673 11674 // Scaled-immediate offsets. 11675 { 11676 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11677 __ ldp(q0, q1, MemOperand(x0, offset)); 11678 __ stp(q0, q1, MemOperand(x1, offset)); 11679 } 11680 offset += 2 * kQRegSizeInBytes; 11681 11682 { 11683 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11684 __ ldp(x2, x3, MemOperand(x0, offset)); 11685 __ stp(x2, x3, MemOperand(x1, offset)); 11686 } 11687 offset += 2 * kXRegSizeInBytes; 11688 11689 { 11690 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11691 __ ldpsw(x2, x3, MemOperand(x0, offset)); 11692 __ stp(w2, w3, MemOperand(x1, offset)); 11693 } 11694 offset += 2 * kWRegSizeInBytes; 11695 11696 { 11697 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11698 __ ldp(d0, d1, MemOperand(x0, offset)); 11699 __ stp(d0, d1, MemOperand(x1, offset)); 11700 } 11701 offset += 2 * kDRegSizeInBytes; 11702 11703 { 11704 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11705 __ ldp(w2, w3, MemOperand(x0, offset)); 11706 __ stp(w2, w3, MemOperand(x1, offset)); 11707 } 11708 offset += 2 * kWRegSizeInBytes; 11709 11710 { 11711 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11712 __ ldp(s0, s1, MemOperand(x0, offset)); 11713 __ stp(s0, s1, MemOperand(x1, offset)); 11714 } 11715 offset += 2 * kSRegSizeInBytes; 11716 11717 { 11718 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11719 __ ldr(x2, MemOperand(x0, offset), RequireScaledOffset); 11720 __ str(x2, MemOperand(x1, offset), RequireScaledOffset); 11721 } 11722 offset += kXRegSizeInBytes; 11723 11724 { 11725 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11726 __ ldr(d0, MemOperand(x0, offset), RequireScaledOffset); 11727 __ str(d0, MemOperand(x1, offset), RequireScaledOffset); 11728 } 11729 offset += kDRegSizeInBytes; 11730 11731 { 11732 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11733 __ ldr(w2, MemOperand(x0, offset), RequireScaledOffset); 11734 __ str(w2, MemOperand(x1, offset), RequireScaledOffset); 11735 } 11736 offset += kWRegSizeInBytes; 11737 11738 { 11739 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11740 __ ldr(s0, MemOperand(x0, offset), RequireScaledOffset); 11741 __ str(s0, MemOperand(x1, offset), RequireScaledOffset); 11742 } 11743 offset += kSRegSizeInBytes; 11744 11745 { 11746 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11747 __ ldrh(w2, MemOperand(x0, offset), RequireScaledOffset); 11748 __ strh(w2, MemOperand(x1, offset), RequireScaledOffset); 11749 } 11750 offset += 2; 11751 11752 { 11753 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11754 __ ldrsh(w2, MemOperand(x0, offset), RequireScaledOffset); 11755 __ strh(w2, MemOperand(x1, offset), RequireScaledOffset); 11756 } 11757 offset += 2; 11758 11759 { 11760 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11761 __ ldrb(w2, MemOperand(x0, offset), RequireScaledOffset); 11762 __ strb(w2, MemOperand(x1, offset), RequireScaledOffset); 11763 } 11764 offset += 1; 11765 11766 { 11767 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11768 __ ldrsb(w2, MemOperand(x0, offset), RequireScaledOffset); 11769 __ strb(w2, MemOperand(x1, offset), RequireScaledOffset); 11770 } 11771 offset += 1; 11772 11773 // Unscaled-immediate offsets. 11774 11775 { 11776 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11777 __ ldur(x2, MemOperand(x0, offset), RequireUnscaledOffset); 11778 __ stur(x2, MemOperand(x1, offset), RequireUnscaledOffset); 11779 } 11780 offset += kXRegSizeInBytes; 11781 11782 { 11783 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11784 __ ldur(d0, MemOperand(x0, offset), RequireUnscaledOffset); 11785 __ stur(d0, MemOperand(x1, offset), RequireUnscaledOffset); 11786 } 11787 offset += kDRegSizeInBytes; 11788 11789 { 11790 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11791 __ ldur(w2, MemOperand(x0, offset), RequireUnscaledOffset); 11792 __ stur(w2, MemOperand(x1, offset), RequireUnscaledOffset); 11793 } 11794 offset += kWRegSizeInBytes; 11795 11796 { 11797 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11798 __ ldur(s0, MemOperand(x0, offset), RequireUnscaledOffset); 11799 __ stur(s0, MemOperand(x1, offset), RequireUnscaledOffset); 11800 } 11801 offset += kSRegSizeInBytes; 11802 11803 { 11804 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11805 __ ldurh(w2, MemOperand(x0, offset), RequireUnscaledOffset); 11806 __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset); 11807 } 11808 offset += 2; 11809 11810 { 11811 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11812 __ ldursh(w2, MemOperand(x0, offset), RequireUnscaledOffset); 11813 __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset); 11814 } 11815 offset += 2; 11816 11817 { 11818 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11819 __ ldurb(w2, MemOperand(x0, offset), RequireUnscaledOffset); 11820 __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset); 11821 } 11822 offset += 1; 11823 11824 { 11825 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11826 __ ldursb(w2, MemOperand(x0, offset), RequireUnscaledOffset); 11827 __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset); 11828 } 11829 offset += 1; 11830 11831 // Extract the tag (so we can test that it was preserved correctly). 11832 __ Ubfx(x0, x0, kAddressTagOffset, kAddressTagWidth); 11833 __ Ubfx(x1, x1, kAddressTagOffset, kAddressTagWidth); 11834 11835 VIXL_ASSERT(kMaxDataLength >= offset); 11836 11837 END(); 11838 if (CAN_RUN()) { 11839 RUN(); 11840 11841 ASSERT_EQUAL_64(src_tag, x0); 11842 ASSERT_EQUAL_64(dst_tag, x1); 11843 11844 for (int k = 0; k < offset; k++) { 11845 VIXL_CHECK(src[k] == dst[k]); 11846 } 11847 } 11848 } 11849 } 11850} 11851 11852 11853TEST(load_store_tagged_immediate_preindex) { 11854 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff}; 11855 int tag_count = sizeof(tags) / sizeof(tags[0]); 11856 11857 const int kMaxDataLength = 128; 11858 11859 for (int i = 0; i < tag_count; i++) { 11860 unsigned char src[kMaxDataLength]; 11861 uint64_t src_raw = reinterpret_cast<uint64_t>(src); 11862 uint64_t src_tag = tags[i]; 11863 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag); 11864 11865 for (int k = 0; k < kMaxDataLength; k++) { 11866 src[k] = k + 1; 11867 } 11868 11869 for (int j = 0; j < tag_count; j++) { 11870 unsigned char dst[kMaxDataLength]; 11871 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst); 11872 uint64_t dst_tag = tags[j]; 11873 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag); 11874 11875 for (int k = 0; k < kMaxDataLength; k++) { 11876 dst[k] = 0; 11877 } 11878 11879 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 11880 START(); 11881 11882 // Each MemOperand must apply a pre-index equal to the size of the 11883 // previous access. 11884 11885 // Start with a non-zero preindex. 11886 int preindex = 62 * kXRegSizeInBytes; 11887 int data_length = 0; 11888 11889 __ Mov(x0, src_tagged - preindex); 11890 __ Mov(x1, dst_tagged - preindex); 11891 11892 { 11893 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11894 __ ldp(q0, q1, MemOperand(x0, preindex, PreIndex)); 11895 __ stp(q0, q1, MemOperand(x1, preindex, PreIndex)); 11896 } 11897 preindex = 2 * kQRegSizeInBytes; 11898 data_length = preindex; 11899 11900 { 11901 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11902 __ ldp(x2, x3, MemOperand(x0, preindex, PreIndex)); 11903 __ stp(x2, x3, MemOperand(x1, preindex, PreIndex)); 11904 } 11905 preindex = 2 * kXRegSizeInBytes; 11906 data_length += preindex; 11907 11908 { 11909 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11910 __ ldpsw(x2, x3, MemOperand(x0, preindex, PreIndex)); 11911 __ stp(w2, w3, MemOperand(x1, preindex, PreIndex)); 11912 } 11913 preindex = 2 * kWRegSizeInBytes; 11914 data_length += preindex; 11915 11916 { 11917 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11918 __ ldp(d0, d1, MemOperand(x0, preindex, PreIndex)); 11919 __ stp(d0, d1, MemOperand(x1, preindex, PreIndex)); 11920 } 11921 preindex = 2 * kDRegSizeInBytes; 11922 data_length += preindex; 11923 11924 { 11925 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11926 __ ldp(w2, w3, MemOperand(x0, preindex, PreIndex)); 11927 __ stp(w2, w3, MemOperand(x1, preindex, PreIndex)); 11928 } 11929 preindex = 2 * kWRegSizeInBytes; 11930 data_length += preindex; 11931 11932 { 11933 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11934 __ ldp(s0, s1, MemOperand(x0, preindex, PreIndex)); 11935 __ stp(s0, s1, MemOperand(x1, preindex, PreIndex)); 11936 } 11937 preindex = 2 * kSRegSizeInBytes; 11938 data_length += preindex; 11939 11940 { 11941 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11942 __ ldr(x2, MemOperand(x0, preindex, PreIndex)); 11943 __ str(x2, MemOperand(x1, preindex, PreIndex)); 11944 } 11945 preindex = kXRegSizeInBytes; 11946 data_length += preindex; 11947 11948 { 11949 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11950 __ ldr(d0, MemOperand(x0, preindex, PreIndex)); 11951 __ str(d0, MemOperand(x1, preindex, PreIndex)); 11952 } 11953 preindex = kDRegSizeInBytes; 11954 data_length += preindex; 11955 11956 { 11957 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11958 __ ldr(w2, MemOperand(x0, preindex, PreIndex)); 11959 __ str(w2, MemOperand(x1, preindex, PreIndex)); 11960 } 11961 preindex = kWRegSizeInBytes; 11962 data_length += preindex; 11963 11964 { 11965 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11966 __ ldr(s0, MemOperand(x0, preindex, PreIndex)); 11967 __ str(s0, MemOperand(x1, preindex, PreIndex)); 11968 } 11969 preindex = kSRegSizeInBytes; 11970 data_length += preindex; 11971 11972 { 11973 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11974 __ ldrh(w2, MemOperand(x0, preindex, PreIndex)); 11975 __ strh(w2, MemOperand(x1, preindex, PreIndex)); 11976 } 11977 preindex = 2; 11978 data_length += preindex; 11979 11980 { 11981 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11982 __ ldrsh(w2, MemOperand(x0, preindex, PreIndex)); 11983 __ strh(w2, MemOperand(x1, preindex, PreIndex)); 11984 } 11985 preindex = 2; 11986 data_length += preindex; 11987 11988 { 11989 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11990 __ ldrb(w2, MemOperand(x0, preindex, PreIndex)); 11991 __ strb(w2, MemOperand(x1, preindex, PreIndex)); 11992 } 11993 preindex = 1; 11994 data_length += preindex; 11995 11996 { 11997 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 11998 __ ldrsb(w2, MemOperand(x0, preindex, PreIndex)); 11999 __ strb(w2, MemOperand(x1, preindex, PreIndex)); 12000 } 12001 preindex = 1; 12002 data_length += preindex; 12003 12004 VIXL_ASSERT(kMaxDataLength >= data_length); 12005 12006 END(); 12007 if (CAN_RUN()) { 12008 RUN(); 12009 12010 // Check that the preindex was correctly applied in each operation, and 12011 // that the tag was preserved. 12012 ASSERT_EQUAL_64(src_tagged + data_length - preindex, x0); 12013 ASSERT_EQUAL_64(dst_tagged + data_length - preindex, x1); 12014 12015 for (int k = 0; k < data_length; k++) { 12016 VIXL_CHECK(src[k] == dst[k]); 12017 } 12018 } 12019 } 12020 } 12021} 12022 12023 12024TEST(load_store_tagged_immediate_postindex) { 12025 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff}; 12026 int tag_count = sizeof(tags) / sizeof(tags[0]); 12027 12028 const int kMaxDataLength = 128; 12029 12030 for (int i = 0; i < tag_count; i++) { 12031 unsigned char src[kMaxDataLength]; 12032 uint64_t src_raw = reinterpret_cast<uint64_t>(src); 12033 uint64_t src_tag = tags[i]; 12034 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag); 12035 12036 for (int k = 0; k < kMaxDataLength; k++) { 12037 src[k] = k + 1; 12038 } 12039 12040 for (int j = 0; j < tag_count; j++) { 12041 unsigned char dst[kMaxDataLength]; 12042 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst); 12043 uint64_t dst_tag = tags[j]; 12044 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag); 12045 12046 for (int k = 0; k < kMaxDataLength; k++) { 12047 dst[k] = 0; 12048 } 12049 12050 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 12051 START(); 12052 12053 int postindex = 2 * kXRegSizeInBytes; 12054 int data_length = 0; 12055 12056 __ Mov(x0, src_tagged); 12057 __ Mov(x1, dst_tagged); 12058 12059 { 12060 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12061 __ ldp(x2, x3, MemOperand(x0, postindex, PostIndex)); 12062 __ stp(x2, x3, MemOperand(x1, postindex, PostIndex)); 12063 } 12064 data_length = postindex; 12065 12066 postindex = 2 * kQRegSizeInBytes; 12067 { 12068 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12069 __ ldp(q0, q1, MemOperand(x0, postindex, PostIndex)); 12070 __ stp(q0, q1, MemOperand(x1, postindex, PostIndex)); 12071 } 12072 data_length += postindex; 12073 12074 postindex = 2 * kWRegSizeInBytes; 12075 { 12076 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12077 __ ldpsw(x2, x3, MemOperand(x0, postindex, PostIndex)); 12078 __ stp(w2, w3, MemOperand(x1, postindex, PostIndex)); 12079 } 12080 data_length += postindex; 12081 12082 postindex = 2 * kDRegSizeInBytes; 12083 { 12084 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12085 __ ldp(d0, d1, MemOperand(x0, postindex, PostIndex)); 12086 __ stp(d0, d1, MemOperand(x1, postindex, PostIndex)); 12087 } 12088 data_length += postindex; 12089 12090 postindex = 2 * kWRegSizeInBytes; 12091 { 12092 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12093 __ ldp(w2, w3, MemOperand(x0, postindex, PostIndex)); 12094 __ stp(w2, w3, MemOperand(x1, postindex, PostIndex)); 12095 } 12096 data_length += postindex; 12097 12098 postindex = 2 * kSRegSizeInBytes; 12099 { 12100 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12101 __ ldp(s0, s1, MemOperand(x0, postindex, PostIndex)); 12102 __ stp(s0, s1, MemOperand(x1, postindex, PostIndex)); 12103 } 12104 data_length += postindex; 12105 12106 postindex = kXRegSizeInBytes; 12107 { 12108 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12109 __ ldr(x2, MemOperand(x0, postindex, PostIndex)); 12110 __ str(x2, MemOperand(x1, postindex, PostIndex)); 12111 } 12112 data_length += postindex; 12113 12114 postindex = kDRegSizeInBytes; 12115 { 12116 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12117 __ ldr(d0, MemOperand(x0, postindex, PostIndex)); 12118 __ str(d0, MemOperand(x1, postindex, PostIndex)); 12119 } 12120 data_length += postindex; 12121 12122 postindex = kWRegSizeInBytes; 12123 { 12124 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12125 __ ldr(w2, MemOperand(x0, postindex, PostIndex)); 12126 __ str(w2, MemOperand(x1, postindex, PostIndex)); 12127 } 12128 data_length += postindex; 12129 12130 postindex = kSRegSizeInBytes; 12131 { 12132 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12133 __ ldr(s0, MemOperand(x0, postindex, PostIndex)); 12134 __ str(s0, MemOperand(x1, postindex, PostIndex)); 12135 } 12136 data_length += postindex; 12137 12138 postindex = 2; 12139 { 12140 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12141 __ ldrh(w2, MemOperand(x0, postindex, PostIndex)); 12142 __ strh(w2, MemOperand(x1, postindex, PostIndex)); 12143 } 12144 data_length += postindex; 12145 12146 postindex = 2; 12147 { 12148 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12149 __ ldrsh(w2, MemOperand(x0, postindex, PostIndex)); 12150 __ strh(w2, MemOperand(x1, postindex, PostIndex)); 12151 } 12152 data_length += postindex; 12153 12154 postindex = 1; 12155 { 12156 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12157 __ ldrb(w2, MemOperand(x0, postindex, PostIndex)); 12158 __ strb(w2, MemOperand(x1, postindex, PostIndex)); 12159 } 12160 data_length += postindex; 12161 12162 postindex = 1; 12163 { 12164 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12165 __ ldrsb(w2, MemOperand(x0, postindex, PostIndex)); 12166 __ strb(w2, MemOperand(x1, postindex, PostIndex)); 12167 } 12168 data_length += postindex; 12169 12170 VIXL_ASSERT(kMaxDataLength >= data_length); 12171 12172 END(); 12173 if (CAN_RUN()) { 12174 RUN(); 12175 12176 // Check that the postindex was correctly applied in each operation, and 12177 // that the tag was preserved. 12178 ASSERT_EQUAL_64(src_tagged + data_length, x0); 12179 ASSERT_EQUAL_64(dst_tagged + data_length, x1); 12180 12181 for (int k = 0; k < data_length; k++) { 12182 VIXL_CHECK(src[k] == dst[k]); 12183 } 12184 } 12185 } 12186 } 12187} 12188 12189 12190TEST(load_store_tagged_register_offset) { 12191 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff}; 12192 int tag_count = sizeof(tags) / sizeof(tags[0]); 12193 12194 const int kMaxDataLength = 128; 12195 12196 for (int i = 0; i < tag_count; i++) { 12197 unsigned char src[kMaxDataLength]; 12198 uint64_t src_raw = reinterpret_cast<uint64_t>(src); 12199 uint64_t src_tag = tags[i]; 12200 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag); 12201 12202 for (int k = 0; k < kMaxDataLength; k++) { 12203 src[k] = k + 1; 12204 } 12205 12206 for (int j = 0; j < tag_count; j++) { 12207 unsigned char dst[kMaxDataLength]; 12208 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst); 12209 uint64_t dst_tag = tags[j]; 12210 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag); 12211 12212 // Also tag the offset register; the operation should still succeed. 12213 for (int o = 0; o < tag_count; o++) { 12214 uint64_t offset_base = CPU::SetPointerTag(UINT64_C(0), tags[o]); 12215 int data_length = 0; 12216 12217 for (int k = 0; k < kMaxDataLength; k++) { 12218 dst[k] = 0; 12219 } 12220 12221 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 12222 START(); 12223 12224 __ Mov(x0, src_tagged); 12225 __ Mov(x1, dst_tagged); 12226 12227 __ Mov(x10, offset_base + data_length); 12228 { 12229 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12230 __ ldr(x2, MemOperand(x0, x10)); 12231 __ str(x2, MemOperand(x1, x10)); 12232 } 12233 data_length += kXRegSizeInBytes; 12234 12235 __ Mov(x10, offset_base + data_length); 12236 { 12237 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12238 __ ldr(d0, MemOperand(x0, x10)); 12239 __ str(d0, MemOperand(x1, x10)); 12240 } 12241 data_length += kDRegSizeInBytes; 12242 12243 __ Mov(x10, offset_base + data_length); 12244 { 12245 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12246 __ ldr(w2, MemOperand(x0, x10)); 12247 __ str(w2, MemOperand(x1, x10)); 12248 } 12249 data_length += kWRegSizeInBytes; 12250 12251 __ Mov(x10, offset_base + data_length); 12252 { 12253 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12254 __ ldr(s0, MemOperand(x0, x10)); 12255 __ str(s0, MemOperand(x1, x10)); 12256 } 12257 data_length += kSRegSizeInBytes; 12258 12259 __ Mov(x10, offset_base + data_length); 12260 { 12261 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12262 __ ldrh(w2, MemOperand(x0, x10)); 12263 __ strh(w2, MemOperand(x1, x10)); 12264 } 12265 data_length += 2; 12266 12267 __ Mov(x10, offset_base + data_length); 12268 { 12269 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12270 __ ldrsh(w2, MemOperand(x0, x10)); 12271 __ strh(w2, MemOperand(x1, x10)); 12272 } 12273 data_length += 2; 12274 12275 __ Mov(x10, offset_base + data_length); 12276 { 12277 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12278 __ ldrb(w2, MemOperand(x0, x10)); 12279 __ strb(w2, MemOperand(x1, x10)); 12280 } 12281 data_length += 1; 12282 12283 __ Mov(x10, offset_base + data_length); 12284 { 12285 ExactAssemblyScope scope(&masm, 2 * kInstructionSize); 12286 __ ldrsb(w2, MemOperand(x0, x10)); 12287 __ strb(w2, MemOperand(x1, x10)); 12288 } 12289 data_length += 1; 12290 12291 VIXL_ASSERT(kMaxDataLength >= data_length); 12292 12293 END(); 12294 if (CAN_RUN()) { 12295 RUN(); 12296 12297 // Check that the postindex was correctly applied in each operation, 12298 // and that the tag was preserved. 12299 ASSERT_EQUAL_64(src_tagged, x0); 12300 ASSERT_EQUAL_64(dst_tagged, x1); 12301 ASSERT_EQUAL_64(offset_base + data_length - 1, x10); 12302 12303 for (int k = 0; k < data_length; k++) { 12304 VIXL_CHECK(src[k] == dst[k]); 12305 } 12306 } 12307 } 12308 } 12309 } 12310} 12311 12312 12313TEST(load_store_tagged_register_postindex) { 12314 uint64_t src[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908}; 12315 uint64_t tags[] = {0x00, 0x1, 0x55, 0xff}; 12316 int tag_count = sizeof(tags) / sizeof(tags[0]); 12317 12318 for (int j = 0; j < tag_count; j++) { 12319 for (int i = 0; i < tag_count; i++) { 12320 SETUP_WITH_FEATURES(CPUFeatures::kNEON); 12321 12322 uint64_t src_base = reinterpret_cast<uint64_t>(src); 12323 uint64_t src_tagged = CPU::SetPointerTag(src_base, tags[i]); 12324 uint64_t offset_tagged = CPU::SetPointerTag(UINT64_C(0), tags[j]); 12325 12326 START(); 12327 __ Mov(x10, src_tagged); 12328 __ Mov(x11, offset_tagged); 12329 __ Ld1(v0.V16B(), MemOperand(x10, x11, PostIndex)); 12330 // TODO: add other instructions (ld2-4, st1-4) as they become available. 12331 END(); 12332 12333 if (CAN_RUN()) { 12334 RUN(); 12335 12336 ASSERT_EQUAL_128(0x0f0e0d0c0b0a0908, 0x0706050403020100, q0); 12337 ASSERT_EQUAL_64(src_tagged + offset_tagged, x10); 12338 } 12339 } 12340 } 12341} 12342 12343 12344TEST(branch_tagged) { 12345 SETUP(); 12346 START(); 12347 12348 Label loop, loop_entry, done; 12349 __ Adr(x0, &loop); 12350 __ Mov(x1, 0); 12351 __ B(&loop_entry); 12352 12353 __ Bind(&loop); 12354 __ Add(x1, x1, 1); // Count successful jumps. 12355 12356 // Advance to the next tag, then bail out if we've come back around to tag 0. 12357 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset); 12358 __ Tst(x0, kAddressTagMask); 12359 __ B(eq, &done); 12360 12361 __ Bind(&loop_entry); 12362 __ Br(x0); 12363 12364 __ Bind(&done); 12365 12366 END(); 12367 if (CAN_RUN()) { 12368 RUN(); 12369 12370 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1); 12371 } 12372} 12373 12374 12375TEST(branch_and_link_tagged) { 12376 SETUP(); 12377 START(); 12378 12379 Label loop, loop_entry, done; 12380 __ Adr(x0, &loop); 12381 __ Mov(x1, 0); 12382 __ B(&loop_entry); 12383 12384 __ Bind(&loop); 12385 12386 // Bail out (before counting a successful jump) if lr appears to be tagged. 12387 __ Tst(lr, kAddressTagMask); 12388 __ B(ne, &done); 12389 12390 __ Add(x1, x1, 1); // Count successful jumps. 12391 12392 // Advance to the next tag, then bail out if we've come back around to tag 0. 12393 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset); 12394 __ Tst(x0, kAddressTagMask); 12395 __ B(eq, &done); 12396 12397 __ Bind(&loop_entry); 12398 __ Blr(x0); 12399 12400 __ Bind(&done); 12401 12402 END(); 12403 if (CAN_RUN()) { 12404 RUN(); 12405 12406 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1); 12407 } 12408} 12409 12410 12411TEST(branch_tagged_and_adr_adrp) { 12412 SETUP_CUSTOM(kPageSize, PageOffsetDependentCode); 12413 START(); 12414 12415 Label loop, loop_entry, done; 12416 __ Adr(x0, &loop); 12417 __ Mov(x1, 0); 12418 __ B(&loop_entry); 12419 12420 __ Bind(&loop); 12421 12422 // Bail out (before counting a successful jump) if `adr x10, ...` is tagged. 12423 __ Adr(x10, &done); 12424 __ Tst(x10, kAddressTagMask); 12425 __ B(ne, &done); 12426 12427 // Bail out (before counting a successful jump) if `adrp x11, ...` is tagged. 12428 __ Adrp(x11, &done); 12429 __ Tst(x11, kAddressTagMask); 12430 __ B(ne, &done); 12431 12432 __ Add(x1, x1, 1); // Count successful iterations. 12433 12434 // Advance to the next tag, then bail out if we've come back around to tag 0. 12435 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset); 12436 __ Tst(x0, kAddressTagMask); 12437 __ B(eq, &done); 12438 12439 __ Bind(&loop_entry); 12440 __ Br(x0); 12441 12442 __ Bind(&done); 12443 12444 END(); 12445 if (CAN_RUN()) { 12446 RUN(); 12447 12448 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1); 12449 } 12450} 12451 12452TEST(system_sys) { 12453 SETUP(); 12454 const char* msg = "SYS test!"; 12455 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); 12456 12457 START(); 12458 __ Mov(x4, msg_addr); 12459 __ Sys(3, 0x7, 0x5, 1, x4); 12460 __ Mov(x3, x4); 12461 __ Sys(3, 0x7, 0xa, 1, x3); 12462 __ Mov(x2, x3); 12463 __ Sys(3, 0x7, 0xb, 1, x2); 12464 __ Mov(x1, x2); 12465 __ Sys(3, 0x7, 0xe, 1, x1); 12466 // TODO: Add tests to check ZVA equivalent. 12467 END(); 12468 12469 if (CAN_RUN()) { 12470 RUN(); 12471 } 12472} 12473 12474 12475TEST(system_ic) { 12476 SETUP(); 12477 const char* msg = "IC test!"; 12478 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); 12479 12480 START(); 12481 __ Mov(x11, msg_addr); 12482 __ Ic(IVAU, x11); 12483 END(); 12484 12485 if (CAN_RUN()) { 12486 RUN(); 12487 } 12488} 12489 12490 12491TEST(system_dc) { 12492 SETUP(); 12493 const char* msg = "DC test!"; 12494 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); 12495 12496 START(); 12497 __ Mov(x20, msg_addr); 12498 __ Dc(CVAC, x20); 12499 __ Mov(x21, msg_addr); 12500 __ Dc(CVAU, x21); 12501 __ Mov(x22, msg_addr); 12502 __ Dc(CIVAC, x22); 12503 // TODO: Add tests to check ZVA. 12504 END(); 12505 12506 if (CAN_RUN()) { 12507 RUN(); 12508 ASSERT_EQUAL_64(msg_addr, x20); 12509 ASSERT_EQUAL_64(msg_addr, x21); 12510 ASSERT_EQUAL_64(msg_addr, x22); 12511 } 12512} 12513 12514 12515TEST(system_dcpop) { 12516 SETUP_WITH_FEATURES(CPUFeatures::kDCPoP); 12517 const char* msg = "DCPoP test!"; 12518 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); 12519 12520 START(); 12521 __ Mov(x20, msg_addr); 12522 __ Dc(CVAP, x20); 12523 END(); 12524 12525 if (CAN_RUN()) { 12526 RUN(); 12527 ASSERT_EQUAL_64(msg_addr, x20); 12528 } 12529} 12530 12531TEST(system_dccvadp) { 12532 SETUP_WITH_FEATURES(CPUFeatures::kDCCVADP); 12533 const char* msg = "DCCVADP test!"; 12534 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); 12535 12536 START(); 12537 __ Mov(x20, msg_addr); 12538 __ Dc(CVADP, x20); 12539 END(); 12540 12541 if (CAN_RUN()) { 12542 RUN(); 12543 ASSERT_EQUAL_64(msg_addr, x20); 12544 } 12545} 12546 12547TEST(system_dc_mte) { 12548 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 12549 const char* msg = "DC MTE test!"; 12550 uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); 12551 12552 START(); 12553 __ Mov(x20, msg_addr); 12554 __ Dc(CGVAC, x20); 12555 __ Dc(CGDVAC, x20); 12556 __ Dc(CGVAP, x20); 12557 __ Dc(CGDVAP, x20); 12558 __ Dc(CIGVAC, x20); 12559 __ Dc(CIGDVAC, x20); 12560 END(); 12561 12562 if (CAN_RUN()) { 12563 RUN(); 12564 ASSERT_EQUAL_64(msg_addr, x20); 12565 } 12566} 12567 12568// We currently disable tests for CRC32 instructions when running natively. 12569// Support for this family of instruction is optional, and so native platforms 12570// may simply fail to execute the test. 12571TEST(crc32b) { 12572 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12573 12574 START(); 12575 12576 __ Mov(w0, 0); 12577 __ Mov(w1, 0); 12578 __ Crc32b(w10, w0, w1); 12579 12580 __ Mov(w0, 0x1); 12581 __ Mov(w1, 0x138); 12582 __ Crc32b(w11, w0, w1); 12583 12584 __ Mov(w0, 0x1); 12585 __ Mov(w1, 0x38); 12586 __ Crc32b(w12, w0, w1); 12587 12588 __ Mov(w0, 0); 12589 __ Mov(w1, 128); 12590 __ Crc32b(w13, w0, w1); 12591 12592 __ Mov(w0, UINT32_MAX); 12593 __ Mov(w1, 255); 12594 __ Crc32b(w14, w0, w1); 12595 12596 __ Mov(w0, 0x00010001); 12597 __ Mov(w1, 0x10001000); 12598 __ Crc32b(w15, w0, w1); 12599 12600 END(); 12601 12602 if (CAN_RUN()) { 12603 RUN(); 12604 12605 ASSERT_EQUAL_64(0x0, x10); 12606 ASSERT_EQUAL_64(0x5f058808, x11); 12607 ASSERT_EQUAL_64(0x5f058808, x12); 12608 ASSERT_EQUAL_64(0xedb88320, x13); 12609 ASSERT_EQUAL_64(0x00ffffff, x14); 12610 ASSERT_EQUAL_64(0x77073196, x15); 12611 } 12612} 12613 12614 12615TEST(crc32h) { 12616 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12617 12618 START(); 12619 12620 __ Mov(w0, 0); 12621 __ Mov(w1, 0); 12622 __ Crc32h(w10, w0, w1); 12623 12624 __ Mov(w0, 0x1); 12625 __ Mov(w1, 0x10038); 12626 __ Crc32h(w11, w0, w1); 12627 12628 __ Mov(w0, 0x1); 12629 __ Mov(w1, 0x38); 12630 __ Crc32h(w12, w0, w1); 12631 12632 __ Mov(w0, 0); 12633 __ Mov(w1, 128); 12634 __ Crc32h(w13, w0, w1); 12635 12636 __ Mov(w0, UINT32_MAX); 12637 __ Mov(w1, 255); 12638 __ Crc32h(w14, w0, w1); 12639 12640 __ Mov(w0, 0x00010001); 12641 __ Mov(w1, 0x10001000); 12642 __ Crc32h(w15, w0, w1); 12643 12644 END(); 12645 12646 if (CAN_RUN()) { 12647 RUN(); 12648 12649 ASSERT_EQUAL_64(0x0, x10); 12650 ASSERT_EQUAL_64(0x0e848dba, x11); 12651 ASSERT_EQUAL_64(0x0e848dba, x12); 12652 ASSERT_EQUAL_64(0x3b83984b, x13); 12653 ASSERT_EQUAL_64(0x2d021072, x14); 12654 ASSERT_EQUAL_64(0x04ac2124, x15); 12655 } 12656} 12657 12658 12659TEST(crc32w) { 12660 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12661 12662 START(); 12663 12664 __ Mov(w0, 0); 12665 __ Mov(w1, 0); 12666 __ Crc32w(w10, w0, w1); 12667 12668 __ Mov(w0, 0x1); 12669 __ Mov(w1, 0x80000031); 12670 __ Crc32w(w11, w0, w1); 12671 12672 __ Mov(w0, 0); 12673 __ Mov(w1, 128); 12674 __ Crc32w(w13, w0, w1); 12675 12676 __ Mov(w0, UINT32_MAX); 12677 __ Mov(w1, 255); 12678 __ Crc32w(w14, w0, w1); 12679 12680 __ Mov(w0, 0x00010001); 12681 __ Mov(w1, 0x10001000); 12682 __ Crc32w(w15, w0, w1); 12683 12684 END(); 12685 12686 if (CAN_RUN()) { 12687 RUN(); 12688 12689 ASSERT_EQUAL_64(0x0, x10); 12690 ASSERT_EQUAL_64(0x1d937b81, x11); 12691 ASSERT_EQUAL_64(0xed59b63b, x13); 12692 ASSERT_EQUAL_64(0x00be2612, x14); 12693 ASSERT_EQUAL_64(0xa036e530, x15); 12694 } 12695} 12696 12697 12698TEST(crc32x) { 12699 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12700 12701 START(); 12702 12703 __ Mov(w0, 0); 12704 __ Mov(x1, 0); 12705 __ Crc32x(w10, w0, x1); 12706 12707 __ Mov(w0, 0x1); 12708 __ Mov(x1, UINT64_C(0x0000000800000031)); 12709 __ Crc32x(w11, w0, x1); 12710 12711 __ Mov(w0, 0); 12712 __ Mov(x1, 128); 12713 __ Crc32x(w13, w0, x1); 12714 12715 __ Mov(w0, UINT32_MAX); 12716 __ Mov(x1, 255); 12717 __ Crc32x(w14, w0, x1); 12718 12719 __ Mov(w0, 0x00010001); 12720 __ Mov(x1, UINT64_C(0x1000100000000000)); 12721 __ Crc32x(w15, w0, x1); 12722 12723 END(); 12724 12725 if (CAN_RUN()) { 12726 RUN(); 12727 12728 ASSERT_EQUAL_64(0x0, x10); 12729 ASSERT_EQUAL_64(0x40797b92, x11); 12730 ASSERT_EQUAL_64(0x533b85da, x13); 12731 ASSERT_EQUAL_64(0xbc962670, x14); 12732 ASSERT_EQUAL_64(0x0667602f, x15); 12733 } 12734} 12735 12736 12737TEST(crc32cb) { 12738 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12739 12740 START(); 12741 12742 __ Mov(w0, 0); 12743 __ Mov(w1, 0); 12744 __ Crc32cb(w10, w0, w1); 12745 12746 __ Mov(w0, 0x1); 12747 __ Mov(w1, 0x138); 12748 __ Crc32cb(w11, w0, w1); 12749 12750 __ Mov(w0, 0x1); 12751 __ Mov(w1, 0x38); 12752 __ Crc32cb(w12, w0, w1); 12753 12754 __ Mov(w0, 0); 12755 __ Mov(w1, 128); 12756 __ Crc32cb(w13, w0, w1); 12757 12758 __ Mov(w0, UINT32_MAX); 12759 __ Mov(w1, 255); 12760 __ Crc32cb(w14, w0, w1); 12761 12762 __ Mov(w0, 0x00010001); 12763 __ Mov(w1, 0x10001000); 12764 __ Crc32cb(w15, w0, w1); 12765 12766 END(); 12767 12768 if (CAN_RUN()) { 12769 RUN(); 12770 12771 ASSERT_EQUAL_64(0x0, x10); 12772 ASSERT_EQUAL_64(0x4851927d, x11); 12773 ASSERT_EQUAL_64(0x4851927d, x12); 12774 ASSERT_EQUAL_64(0x82f63b78, x13); 12775 ASSERT_EQUAL_64(0x00ffffff, x14); 12776 ASSERT_EQUAL_64(0xf26b8203, x15); 12777 } 12778} 12779 12780 12781TEST(crc32ch) { 12782 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12783 12784 START(); 12785 12786 __ Mov(w0, 0); 12787 __ Mov(w1, 0); 12788 __ Crc32ch(w10, w0, w1); 12789 12790 __ Mov(w0, 0x1); 12791 __ Mov(w1, 0x10038); 12792 __ Crc32ch(w11, w0, w1); 12793 12794 __ Mov(w0, 0x1); 12795 __ Mov(w1, 0x38); 12796 __ Crc32ch(w12, w0, w1); 12797 12798 __ Mov(w0, 0); 12799 __ Mov(w1, 128); 12800 __ Crc32ch(w13, w0, w1); 12801 12802 __ Mov(w0, UINT32_MAX); 12803 __ Mov(w1, 255); 12804 __ Crc32ch(w14, w0, w1); 12805 12806 __ Mov(w0, 0x00010001); 12807 __ Mov(w1, 0x10001000); 12808 __ Crc32ch(w15, w0, w1); 12809 12810 END(); 12811 12812 if (CAN_RUN()) { 12813 RUN(); 12814 12815 ASSERT_EQUAL_64(0x0, x10); 12816 ASSERT_EQUAL_64(0xcef8494c, x11); 12817 ASSERT_EQUAL_64(0xcef8494c, x12); 12818 ASSERT_EQUAL_64(0xfbc3faf9, x13); 12819 ASSERT_EQUAL_64(0xad7dacae, x14); 12820 ASSERT_EQUAL_64(0x03fc5f19, x15); 12821 } 12822} 12823 12824 12825TEST(crc32cw) { 12826 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12827 12828 START(); 12829 12830 __ Mov(w0, 0); 12831 __ Mov(w1, 0); 12832 __ Crc32cw(w10, w0, w1); 12833 12834 __ Mov(w0, 0x1); 12835 __ Mov(w1, 0x80000031); 12836 __ Crc32cw(w11, w0, w1); 12837 12838 __ Mov(w0, 0); 12839 __ Mov(w1, 128); 12840 __ Crc32cw(w13, w0, w1); 12841 12842 __ Mov(w0, UINT32_MAX); 12843 __ Mov(w1, 255); 12844 __ Crc32cw(w14, w0, w1); 12845 12846 __ Mov(w0, 0x00010001); 12847 __ Mov(w1, 0x10001000); 12848 __ Crc32cw(w15, w0, w1); 12849 12850 END(); 12851 12852 if (CAN_RUN()) { 12853 RUN(); 12854 12855 ASSERT_EQUAL_64(0x0, x10); 12856 ASSERT_EQUAL_64(0xbcb79ece, x11); 12857 ASSERT_EQUAL_64(0x52a0c93f, x13); 12858 ASSERT_EQUAL_64(0x9f9b5c7a, x14); 12859 ASSERT_EQUAL_64(0xae1b882a, x15); 12860 } 12861} 12862 12863 12864TEST(crc32cx) { 12865 SETUP_WITH_FEATURES(CPUFeatures::kCRC32); 12866 12867 START(); 12868 12869 __ Mov(w0, 0); 12870 __ Mov(x1, 0); 12871 __ Crc32cx(w10, w0, x1); 12872 12873 __ Mov(w0, 0x1); 12874 __ Mov(x1, UINT64_C(0x0000000800000031)); 12875 __ Crc32cx(w11, w0, x1); 12876 12877 __ Mov(w0, 0); 12878 __ Mov(x1, 128); 12879 __ Crc32cx(w13, w0, x1); 12880 12881 __ Mov(w0, UINT32_MAX); 12882 __ Mov(x1, 255); 12883 __ Crc32cx(w14, w0, x1); 12884 12885 __ Mov(w0, 0x00010001); 12886 __ Mov(x1, UINT64_C(0x1000100000000000)); 12887 __ Crc32cx(w15, w0, x1); 12888 12889 END(); 12890 12891 if (CAN_RUN()) { 12892 RUN(); 12893 12894 ASSERT_EQUAL_64(0x0, x10); 12895 ASSERT_EQUAL_64(0x7f320fcb, x11); 12896 ASSERT_EQUAL_64(0x34019664, x13); 12897 ASSERT_EQUAL_64(0x6cc27dd0, x14); 12898 ASSERT_EQUAL_64(0xc6f0acdb, x15); 12899 } 12900} 12901 12902TEST(regress_cmp_shift_imm) { 12903 SETUP(); 12904 12905 START(); 12906 12907 __ Mov(x0, 0x3d720c8d); 12908 __ Cmp(x0, Operand(0x3d720c8d)); 12909 12910 END(); 12911 if (CAN_RUN()) { 12912 RUN(); 12913 12914 ASSERT_EQUAL_NZCV(ZCFlag); 12915 } 12916} 12917 12918 12919TEST(compute_address) { 12920 SETUP(); 12921 12922 START(); 12923 int64_t base_address = INT64_C(0x123000000abc); 12924 int64_t reg_offset = INT64_C(0x1087654321); 12925 Register base = x0; 12926 Register offset = x1; 12927 12928 __ Mov(base, base_address); 12929 __ Mov(offset, reg_offset); 12930 12931 12932 __ ComputeAddress(x2, MemOperand(base, 0)); 12933 __ ComputeAddress(x3, MemOperand(base, 8)); 12934 __ ComputeAddress(x4, MemOperand(base, -100)); 12935 12936 __ ComputeAddress(x5, MemOperand(base, offset)); 12937 __ ComputeAddress(x6, MemOperand(base, offset, LSL, 2)); 12938 __ ComputeAddress(x7, MemOperand(base, offset, LSL, 4)); 12939 __ ComputeAddress(x8, MemOperand(base, offset, LSL, 8)); 12940 12941 __ ComputeAddress(x9, MemOperand(base, offset, SXTW)); 12942 __ ComputeAddress(x10, MemOperand(base, offset, UXTW, 1)); 12943 __ ComputeAddress(x11, MemOperand(base, offset, SXTW, 2)); 12944 __ ComputeAddress(x12, MemOperand(base, offset, UXTW, 3)); 12945 12946 END(); 12947 12948 if (CAN_RUN()) { 12949 RUN(); 12950 12951 ASSERT_EQUAL_64(base_address, base); 12952 12953 ASSERT_EQUAL_64(INT64_C(0x123000000abc), x2); 12954 ASSERT_EQUAL_64(INT64_C(0x123000000ac4), x3); 12955 ASSERT_EQUAL_64(INT64_C(0x123000000a58), x4); 12956 12957 ASSERT_EQUAL_64(INT64_C(0x124087654ddd), x5); 12958 ASSERT_EQUAL_64(INT64_C(0x12721d951740), x6); 12959 ASSERT_EQUAL_64(INT64_C(0x133876543ccc), x7); 12960 ASSERT_EQUAL_64(INT64_C(0x22b765432bbc), x8); 12961 12962 ASSERT_EQUAL_64(INT64_C(0x122f87654ddd), x9); 12963 ASSERT_EQUAL_64(INT64_C(0x12310eca90fe), x10); 12964 ASSERT_EQUAL_64(INT64_C(0x122e1d951740), x11); 12965 ASSERT_EQUAL_64(INT64_C(0x12343b2a23c4), x12); 12966 } 12967} 12968 12969 12970TEST(far_branch_backward) { 12971 // Test that the MacroAssembler correctly resolves backward branches to labels 12972 // that are outside the immediate range of branch instructions. 12973 // Take into account that backward branches can reach one instruction further 12974 // than forward branches. 12975 const int overflow_size = 12976 kInstructionSize + 12977 std::max(Instruction::GetImmBranchForwardRange(TestBranchType), 12978 std::max(Instruction::GetImmBranchForwardRange( 12979 CompareBranchType), 12980 Instruction::GetImmBranchForwardRange(CondBranchType))); 12981 12982 SETUP(); 12983 START(); 12984 12985 Label done, fail; 12986 Label test_tbz, test_cbz, test_bcond; 12987 Label success_tbz, success_cbz, success_bcond; 12988 12989 __ Mov(x0, 0); 12990 __ Mov(x1, 1); 12991 __ Mov(x10, 0); 12992 12993 __ B(&test_tbz); 12994 __ Bind(&success_tbz); 12995 __ Orr(x0, x0, 1 << 0); 12996 __ B(&test_cbz); 12997 __ Bind(&success_cbz); 12998 __ Orr(x0, x0, 1 << 1); 12999 __ B(&test_bcond); 13000 __ Bind(&success_bcond); 13001 __ Orr(x0, x0, 1 << 2); 13002 13003 __ B(&done); 13004 13005 // Generate enough code to overflow the immediate range of the three types of 13006 // branches below. 13007 for (unsigned i = 0; i < overflow_size / kInstructionSize; ++i) { 13008 if (i % 100 == 0) { 13009 // If we do land in this code, we do not want to execute so many nops 13010 // before reaching the end of test (especially if tracing is activated). 13011 __ B(&fail); 13012 } else { 13013 __ Nop(); 13014 } 13015 } 13016 __ B(&fail); 13017 13018 __ Bind(&test_tbz); 13019 __ Tbz(x10, 7, &success_tbz); 13020 __ Bind(&test_cbz); 13021 __ Cbz(x10, &success_cbz); 13022 __ Bind(&test_bcond); 13023 __ Cmp(x10, 0); 13024 __ B(eq, &success_bcond); 13025 13026 // For each out-of-range branch instructions, at least two instructions should 13027 // have been generated. 13028 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&test_tbz) >= 13029 7 * kInstructionSize); 13030 13031 __ Bind(&fail); 13032 __ Mov(x1, 0); 13033 __ Bind(&done); 13034 13035 END(); 13036 if (CAN_RUN()) { 13037 RUN(); 13038 13039 ASSERT_EQUAL_64(0x7, x0); 13040 ASSERT_EQUAL_64(0x1, x1); 13041 } 13042} 13043 13044 13045TEST(single_veneer) { 13046 SETUP(); 13047 START(); 13048 13049 const int max_range = Instruction::GetImmBranchForwardRange(TestBranchType); 13050 13051 Label success, fail, done; 13052 13053 __ Mov(x0, 0); 13054 __ Mov(x1, 1); 13055 __ Mov(x10, 0); 13056 13057 __ Tbz(x10, 7, &success); 13058 13059 // Generate enough code to overflow the immediate range of the `tbz`. 13060 for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) { 13061 if (i % 100 == 0) { 13062 // If we do land in this code, we do not want to execute so many nops 13063 // before reaching the end of test (especially if tracing is activated). 13064 __ B(&fail); 13065 } else { 13066 __ Nop(); 13067 } 13068 } 13069 __ B(&fail); 13070 13071 __ Bind(&success); 13072 __ Mov(x0, 1); 13073 13074 __ B(&done); 13075 __ Bind(&fail); 13076 __ Mov(x1, 0); 13077 __ Bind(&done); 13078 13079 END(); 13080 if (CAN_RUN()) { 13081 RUN(); 13082 13083 ASSERT_EQUAL_64(1, x0); 13084 ASSERT_EQUAL_64(1, x1); 13085 } 13086} 13087 13088 13089TEST(simple_veneers) { 13090 // Test that the MacroAssembler correctly emits veneers for forward branches 13091 // to labels that are outside the immediate range of branch instructions. 13092 const int max_range = 13093 std::max(Instruction::GetImmBranchForwardRange(TestBranchType), 13094 std::max(Instruction::GetImmBranchForwardRange( 13095 CompareBranchType), 13096 Instruction::GetImmBranchForwardRange(CondBranchType))); 13097 13098 SETUP(); 13099 START(); 13100 13101 Label done, fail; 13102 Label test_tbz, test_cbz, test_bcond; 13103 Label success_tbz, success_cbz, success_bcond; 13104 13105 __ Mov(x0, 0); 13106 __ Mov(x1, 1); 13107 __ Mov(x10, 0); 13108 13109 __ Bind(&test_tbz); 13110 __ Tbz(x10, 7, &success_tbz); 13111 __ Bind(&test_cbz); 13112 __ Cbz(x10, &success_cbz); 13113 __ Bind(&test_bcond); 13114 __ Cmp(x10, 0); 13115 __ B(eq, &success_bcond); 13116 13117 // Generate enough code to overflow the immediate range of the three types of 13118 // branches below. 13119 for (unsigned i = 0; i < max_range / kInstructionSize + 1; ++i) { 13120 if (i % 100 == 0) { 13121 // If we do land in this code, we do not want to execute so many nops 13122 // before reaching the end of test (especially if tracing is activated). 13123 __ B(&fail); 13124 } else { 13125 __ Nop(); 13126 } 13127 } 13128 __ B(&fail); 13129 13130 __ Bind(&success_tbz); 13131 __ Orr(x0, x0, 1 << 0); 13132 __ B(&test_cbz); 13133 __ Bind(&success_cbz); 13134 __ Orr(x0, x0, 1 << 1); 13135 __ B(&test_bcond); 13136 __ Bind(&success_bcond); 13137 __ Orr(x0, x0, 1 << 2); 13138 13139 __ B(&done); 13140 __ Bind(&fail); 13141 __ Mov(x1, 0); 13142 __ Bind(&done); 13143 13144 END(); 13145 if (CAN_RUN()) { 13146 RUN(); 13147 13148 ASSERT_EQUAL_64(0x7, x0); 13149 ASSERT_EQUAL_64(0x1, x1); 13150 } 13151} 13152 13153 13154TEST(veneers_stress) { 13155 SETUP(); 13156 START(); 13157 13158 // This is a code generation test stressing the emission of veneers. The code 13159 // generated is not executed. 13160 13161 Label target; 13162 const unsigned max_range = 13163 Instruction::GetImmBranchForwardRange(CondBranchType); 13164 const unsigned iterations = 13165 (max_range + max_range / 4) / (4 * kInstructionSize); 13166 for (unsigned i = 0; i < iterations; i++) { 13167 __ B(&target); 13168 __ B(eq, &target); 13169 __ Cbz(x0, &target); 13170 __ Tbz(x0, 0, &target); 13171 } 13172 __ Bind(&target); 13173 13174 END(); 13175} 13176 13177 13178TEST(veneers_two_out_of_range) { 13179 SETUP(); 13180 START(); 13181 13182 // This is a code generation test. The code generated is not executed. 13183 // Ensure that the MacroAssembler considers unresolved branches to chose when 13184 // a veneer pool should be emitted. We generate two branches that go out of 13185 // range at the same offset. When the MacroAssembler decides to emit the 13186 // veneer pool, the emission of a first veneer should not cause the other 13187 // branch to go out of range. 13188 13189 int range_cbz = Instruction::GetImmBranchForwardRange(CompareBranchType); 13190 int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType); 13191 int max_target = static_cast<int>(masm.GetCursorOffset()) + range_cbz; 13192 13193 Label done; 13194 13195 // We use different labels to prevent the MacroAssembler from sharing veneers. 13196 Label target_cbz, target_tbz; 13197 13198 __ Cbz(x0, &target_cbz); 13199 while (masm.GetCursorOffset() < max_target - range_tbz) { 13200 __ Nop(); 13201 } 13202 __ Tbz(x0, 0, &target_tbz); 13203 while (masm.GetCursorOffset() < max_target) { 13204 __ Nop(); 13205 } 13206 13207 // This additional nop makes the branches go out of range. 13208 __ Nop(); 13209 13210 __ Bind(&target_cbz); 13211 __ Bind(&target_tbz); 13212 13213 END(); 13214} 13215 13216 13217TEST(veneers_hanging) { 13218 SETUP(); 13219 START(); 13220 13221 // This is a code generation test. The code generated is not executed. 13222 // Ensure that the MacroAssembler considers unresolved branches to chose when 13223 // a veneer pool should be emitted. This is similar to the 13224 // 'veneers_two_out_of_range' test. We try to trigger the following situation: 13225 // b.eq label 13226 // b.eq label 13227 // ... 13228 // nop 13229 // ... 13230 // cbz x0, label 13231 // cbz x0, label 13232 // ... 13233 // tbz x0, 0 label 13234 // nop 13235 // ... 13236 // nop <- From here the `b.eq` and `cbz` instructions run out of range, 13237 // so a literal pool is required. 13238 // veneer 13239 // veneer 13240 // veneer <- The `tbz` runs out of range somewhere in the middle of the 13241 // veneer veneer pool. 13242 // veneer 13243 13244 const int range_bcond = Instruction::GetImmBranchForwardRange(CondBranchType); 13245 const int range_cbz = 13246 Instruction::GetImmBranchForwardRange(CompareBranchType); 13247 const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType); 13248 const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_bcond; 13249 13250 Label done; 13251 const int n_bcond = 100; 13252 const int n_cbz = 100; 13253 const int n_tbz = 1; 13254 const int kNTotalBranches = n_bcond + n_cbz + n_tbz; 13255 13256 // We use different labels to prevent the MacroAssembler from sharing veneers. 13257 Label labels[kNTotalBranches]; 13258 for (int i = 0; i < kNTotalBranches; i++) { 13259 new (&labels[i]) Label(); 13260 } 13261 13262 for (int i = 0; i < n_bcond; i++) { 13263 __ B(eq, &labels[i]); 13264 } 13265 13266 while (masm.GetCursorOffset() < max_target - range_cbz) { 13267 __ Nop(); 13268 } 13269 13270 for (int i = 0; i < n_cbz; i++) { 13271 __ Cbz(x0, &labels[n_bcond + i]); 13272 } 13273 13274 // Ensure the 'tbz' will go out of range after some of the previously 13275 // generated branches. 13276 int margin = (n_bcond / 2) * kInstructionSize; 13277 while (masm.GetCursorOffset() < max_target - range_tbz + margin) { 13278 __ Nop(); 13279 } 13280 13281 __ Tbz(x0, 0, &labels[n_bcond + n_cbz]); 13282 13283 while (masm.GetCursorOffset() < max_target) { 13284 __ Nop(); 13285 } 13286 13287 // This additional nop makes the 'b.eq' and 'cbz' instructions go out of range 13288 // and forces the emission of a veneer pool. The 'tbz' is not yet out of 13289 // range, but will go out of range while veneers are emitted for the other 13290 // branches. 13291 // The MacroAssembler should ensure that veneers are correctly emitted for all 13292 // the branches, including the 'tbz'. Checks will fail if the target of a 13293 // branch is out of range. 13294 __ Nop(); 13295 13296 for (int i = 0; i < kNTotalBranches; i++) { 13297 __ Bind(&labels[i]); 13298 } 13299 13300 END(); 13301} 13302 13303 13304TEST(collision_literal_veneer_pools) { 13305 SETUP_WITH_FEATURES(CPUFeatures::kFP); 13306 START(); 13307 13308 // This is a code generation test. The code generated is not executed. 13309 13310 // Make sure the literal pool is empty; 13311 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13312 ASSERT_LITERAL_POOL_SIZE(0); 13313 13314 // We chose the offsets below to (try to) trigger the following situation: 13315 // buffer offset 13316 // 0: tbz x0, 0, target_tbz ----------------------------------. 13317 // 4: nop | 13318 // ... | 13319 // nop | 13320 // literal gen: ldr s0, [pc + ...] ; load from `pool start + 0` | 13321 // ldr s0, [pc + ...] ; load from `pool start + 4` | 13322 // ... | 13323 // ldr s0, [pc + ...] | 13324 // pool start: floating-point literal (0.1) | 13325 // floating-point literal (1.1) | 13326 // ... | 13327 // floating-point literal (<n>.1) <-----tbz-max-range--' 13328 // floating-point literal (<n+1>.1) 13329 // ... 13330 13331 const int range_tbz = Instruction::GetImmBranchForwardRange(TestBranchType); 13332 const int max_target = static_cast<int>(masm.GetCursorOffset()) + range_tbz; 13333 13334 const size_t target_literal_pool_size = 100 * kInstructionSize; 13335 const int offset_start_literal_gen = 13336 target_literal_pool_size + target_literal_pool_size / 2; 13337 13338 13339 Label target_tbz; 13340 13341 __ Tbz(x0, 0, &target_tbz); 13342 VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1); 13343 while (masm.GetCursorOffset() < max_target - offset_start_literal_gen) { 13344 __ Nop(); 13345 } 13346 VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 1); 13347 13348 for (int i = 0; i < 100; i++) { 13349 // Use a different value to force one literal pool entry per iteration. 13350 __ Ldr(s0, i + 0.1); 13351 } 13352 VIXL_CHECK(masm.GetLiteralPoolSize() >= target_literal_pool_size); 13353 13354 // Force emission of a literal pool. 13355 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13356 ASSERT_LITERAL_POOL_SIZE(0); 13357 13358 // The branch should not have gone out of range during the emission of the 13359 // literal pool. 13360 __ Bind(&target_tbz); 13361 13362 VIXL_CHECK(masm.GetNumberOfPotentialVeneers() == 0); 13363 13364 END(); 13365} 13366 13367 13368TEST(ldr_literal_explicit) { 13369 SETUP(); 13370 13371 START(); 13372 Literal<int64_t> automatically_placed_literal(1, masm.GetLiteralPool()); 13373 Literal<int64_t> manually_placed_literal(2); 13374 { 13375 ExactAssemblyScope scope(&masm, kInstructionSize + sizeof(int64_t)); 13376 Label over_literal; 13377 __ b(&over_literal); 13378 __ place(&manually_placed_literal); 13379 __ bind(&over_literal); 13380 } 13381 __ Ldr(x1, &manually_placed_literal); 13382 __ Ldr(x2, &automatically_placed_literal); 13383 __ Add(x0, x1, x2); 13384 END(); 13385 13386 if (CAN_RUN()) { 13387 RUN(); 13388 13389 ASSERT_EQUAL_64(3, x0); 13390 } 13391} 13392 13393 13394TEST(ldr_literal_automatically_placed) { 13395 SETUP_WITH_FEATURES(CPUFeatures::kFP); 13396 13397 START(); 13398 13399 // We start with an empty literal pool. 13400 ASSERT_LITERAL_POOL_SIZE(0); 13401 13402 // Create a literal that should be placed by the literal pool. 13403 Literal<int64_t> explicit_literal(2, masm.GetLiteralPool()); 13404 // It should not appear in the literal pool until its first use. 13405 ASSERT_LITERAL_POOL_SIZE(0); 13406 13407 // Check that using standard literals does not break the use of explicitly 13408 // created literals. 13409 __ Ldr(d1, 1.1); 13410 ASSERT_LITERAL_POOL_SIZE(8); 13411 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13412 ASSERT_LITERAL_POOL_SIZE(0); 13413 13414 __ Ldr(x2, &explicit_literal); 13415 ASSERT_LITERAL_POOL_SIZE(8); 13416 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13417 ASSERT_LITERAL_POOL_SIZE(0); 13418 13419 __ Ldr(d3, 3.3); 13420 ASSERT_LITERAL_POOL_SIZE(8); 13421 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13422 ASSERT_LITERAL_POOL_SIZE(0); 13423 13424 // Re-use our explicitly created literal. It has already been placed, so it 13425 // should not impact the literal pool. 13426 __ Ldr(x4, &explicit_literal); 13427 ASSERT_LITERAL_POOL_SIZE(0); 13428 13429 END(); 13430 13431 if (CAN_RUN()) { 13432 RUN(); 13433 13434 ASSERT_EQUAL_FP64(1.1, d1); 13435 ASSERT_EQUAL_64(2, x2); 13436 ASSERT_EQUAL_FP64(3.3, d3); 13437 ASSERT_EQUAL_64(2, x4); 13438 } 13439} 13440 13441 13442TEST(literal_update_overwrite) { 13443 SETUP(); 13444 13445 START(); 13446 13447 ASSERT_LITERAL_POOL_SIZE(0); 13448 LiteralPool* literal_pool = masm.GetLiteralPool(); 13449 13450 Literal<int32_t> lit_32_update_before_pool(0xbad, literal_pool); 13451 Literal<int32_t> lit_32_update_after_pool(0xbad, literal_pool); 13452 Literal<int64_t> lit_64_update_before_pool(0xbad, literal_pool); 13453 Literal<int64_t> lit_64_update_after_pool(0xbad, literal_pool); 13454 13455 ASSERT_LITERAL_POOL_SIZE(0); 13456 13457 lit_32_update_before_pool.UpdateValue(32); 13458 lit_64_update_before_pool.UpdateValue(64); 13459 13460 __ Ldr(w1, &lit_32_update_before_pool); 13461 __ Ldr(x2, &lit_64_update_before_pool); 13462 __ Ldr(w3, &lit_32_update_after_pool); 13463 __ Ldr(x4, &lit_64_update_after_pool); 13464 13465 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13466 13467 VIXL_ASSERT(lit_32_update_after_pool.IsPlaced()); 13468 VIXL_ASSERT(lit_64_update_after_pool.IsPlaced()); 13469 lit_32_update_after_pool.UpdateValue(128, &masm); 13470 lit_64_update_after_pool.UpdateValue(256, &masm); 13471 13472 END(); 13473 13474 if (CAN_RUN()) { 13475 RUN(); 13476 13477 ASSERT_EQUAL_64(32, x1); 13478 ASSERT_EQUAL_64(64, x2); 13479 ASSERT_EQUAL_64(128, x3); 13480 ASSERT_EQUAL_64(256, x4); 13481 } 13482} 13483 13484 13485TEST(literal_deletion_policies) { 13486 SETUP(); 13487 13488 START(); 13489 13490 // We cannot check exactly when the deletion of the literals occur, but we 13491 // check that usage of the deletion policies is not broken. 13492 13493 ASSERT_LITERAL_POOL_SIZE(0); 13494 LiteralPool* literal_pool = masm.GetLiteralPool(); 13495 13496 Literal<int32_t> lit_manual(0xbad, literal_pool); 13497 Literal<int32_t>* lit_deleted_on_placement = 13498 new Literal<int32_t>(0xbad, 13499 literal_pool, 13500 RawLiteral::kDeletedOnPlacementByPool); 13501 Literal<int32_t>* lit_deleted_on_pool_destruction = 13502 new Literal<int32_t>(0xbad, 13503 literal_pool, 13504 RawLiteral::kDeletedOnPoolDestruction); 13505 13506 ASSERT_LITERAL_POOL_SIZE(0); 13507 13508 lit_manual.UpdateValue(32); 13509 lit_deleted_on_placement->UpdateValue(64); 13510 13511 __ Ldr(w1, &lit_manual); 13512 __ Ldr(w2, lit_deleted_on_placement); 13513 __ Ldr(w3, lit_deleted_on_pool_destruction); 13514 13515 masm.EmitLiteralPool(LiteralPool::kBranchRequired); 13516 13517 VIXL_ASSERT(lit_manual.IsPlaced()); 13518 VIXL_ASSERT(lit_deleted_on_pool_destruction->IsPlaced()); 13519 lit_deleted_on_pool_destruction->UpdateValue(128, &masm); 13520 13521 END(); 13522 13523 if (CAN_RUN()) { 13524 RUN(); 13525 13526 ASSERT_EQUAL_64(32, x1); 13527 ASSERT_EQUAL_64(64, x2); 13528 ASSERT_EQUAL_64(128, x3); 13529 } 13530} 13531 13532 13533TEST(generic_operand) { 13534 SETUP_WITH_FEATURES(CPUFeatures::kFP); 13535 13536 int32_t data_32_array[5] = {0xbadbeef, 13537 0x11111111, 13538 0xbadbeef, 13539 0x33333333, 13540 0xbadbeef}; 13541 int64_t data_64_array[5] = {INT64_C(0xbadbadbadbeef), 13542 INT64_C(0x1111111111111111), 13543 INT64_C(0xbadbadbadbeef), 13544 INT64_C(0x3333333333333333), 13545 INT64_C(0xbadbadbadbeef)}; 13546 size_t size_32 = sizeof(data_32_array[0]); 13547 size_t size_64 = sizeof(data_64_array[0]); 13548 13549 START(); 13550 13551 intptr_t data_32_address = reinterpret_cast<intptr_t>(&data_32_array[0]); 13552 intptr_t data_64_address = reinterpret_cast<intptr_t>(&data_64_array[0]); 13553 Register data_32 = x27; 13554 Register data_64 = x28; 13555 __ Mov(data_32, data_32_address); 13556 __ Mov(data_64, data_64_address); 13557 13558 __ Move(GenericOperand(w0), 13559 GenericOperand(MemOperand(data_32, 1 * size_32), size_32)); 13560 __ Move(GenericOperand(s0), 13561 GenericOperand(MemOperand(data_32, 3 * size_32), size_32)); 13562 __ Move(GenericOperand(x10), 13563 GenericOperand(MemOperand(data_64, 1 * size_64), size_64)); 13564 __ Move(GenericOperand(d10), 13565 GenericOperand(MemOperand(data_64, 3 * size_64), size_64)); 13566 13567 __ Move(GenericOperand(w1), GenericOperand(w0)); 13568 __ Move(GenericOperand(s1), GenericOperand(s0)); 13569 __ Move(GenericOperand(x11), GenericOperand(x10)); 13570 __ Move(GenericOperand(d11), GenericOperand(d10)); 13571 13572 __ Move(GenericOperand(MemOperand(data_32, 0 * size_32), size_32), 13573 GenericOperand(w1)); 13574 __ Move(GenericOperand(MemOperand(data_32, 2 * size_32), size_32), 13575 GenericOperand(s1)); 13576 __ Move(GenericOperand(MemOperand(data_64, 0 * size_64), size_64), 13577 GenericOperand(x11)); 13578 __ Move(GenericOperand(MemOperand(data_64, 2 * size_64), size_64), 13579 GenericOperand(d11)); 13580 13581 __ Move(GenericOperand(MemOperand(data_32, 4 * size_32), size_32), 13582 GenericOperand(MemOperand(data_32, 0 * size_32), size_32)); 13583 __ Move(GenericOperand(MemOperand(data_64, 4 * size_64), size_64), 13584 GenericOperand(MemOperand(data_64, 0 * size_64), size_64)); 13585 END(); 13586 13587 if (CAN_RUN()) { 13588 RUN(); 13589 13590 ASSERT_EQUAL_64(data_32_address, data_32); 13591 ASSERT_EQUAL_64(data_64_address, data_64); 13592 13593 ASSERT_EQUAL_32(0x11111111, w0); 13594 ASSERT_EQUAL_32(0x33333333, core.sreg_bits(0)); 13595 ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x10); 13596 ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(10)); 13597 13598 ASSERT_EQUAL_32(0x11111111, w1); 13599 ASSERT_EQUAL_32(0x33333333, core.sreg_bits(1)); 13600 ASSERT_EQUAL_64(INT64_C(0x1111111111111111), x11); 13601 ASSERT_EQUAL_64(INT64_C(0x3333333333333333), core.dreg_bits(11)); 13602 13603 VIXL_CHECK(data_32_array[0] == 0x11111111); 13604 VIXL_CHECK(data_32_array[1] == 0x11111111); 13605 VIXL_CHECK(data_32_array[2] == 0x33333333); 13606 VIXL_CHECK(data_32_array[3] == 0x33333333); 13607 VIXL_CHECK(data_32_array[4] == 0x11111111); 13608 13609 VIXL_CHECK(data_64_array[0] == INT64_C(0x1111111111111111)); 13610 VIXL_CHECK(data_64_array[1] == INT64_C(0x1111111111111111)); 13611 VIXL_CHECK(data_64_array[2] == INT64_C(0x3333333333333333)); 13612 VIXL_CHECK(data_64_array[3] == INT64_C(0x3333333333333333)); 13613 VIXL_CHECK(data_64_array[4] == INT64_C(0x1111111111111111)); 13614 } 13615} 13616 13617 13618// Test feature detection of calls to runtime functions. 13619 13620// C++11 should be sufficient to provide simulated runtime calls, except for a 13621// GCC bug before 4.9.1. 13622#if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && (__cplusplus >= 201103L) && \ 13623 (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1)) && \ 13624 !defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) 13625#error \ 13626 "C++11 should be sufficient to provide support for simulated runtime calls." 13627#endif // #if defined(VIXL_INCLUDE_SIMULATOR_AARCH64) && ... 13628 13629#if (__cplusplus >= 201103L) && \ 13630 !defined(VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT) 13631#error \ 13632 "C++11 should be sufficient to provide support for `MacroAssembler::CallRuntime()`." 13633#endif // #if (__cplusplus >= 201103L) && ... 13634 13635#ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 13636int32_t runtime_call_add_one(int32_t a) { return a + 1; } 13637 13638double runtime_call_add_doubles(double a, double b, double c) { 13639 return a + b + c; 13640} 13641 13642int64_t runtime_call_one_argument_on_stack(int64_t arg1 __attribute__((unused)), 13643 int64_t arg2 __attribute__((unused)), 13644 int64_t arg3 __attribute__((unused)), 13645 int64_t arg4 __attribute__((unused)), 13646 int64_t arg5 __attribute__((unused)), 13647 int64_t arg6 __attribute__((unused)), 13648 int64_t arg7 __attribute__((unused)), 13649 int64_t arg8 __attribute__((unused)), 13650 int64_t arg9) { 13651 return arg9; 13652} 13653 13654double runtime_call_two_arguments_on_stack(int64_t arg1 __attribute__((unused)), 13655 int64_t arg2 __attribute__((unused)), 13656 int64_t arg3 __attribute__((unused)), 13657 int64_t arg4 __attribute__((unused)), 13658 int64_t arg5 __attribute__((unused)), 13659 int64_t arg6 __attribute__((unused)), 13660 int64_t arg7 __attribute__((unused)), 13661 int64_t arg8 __attribute__((unused)), 13662 double arg9, 13663 double arg10) { 13664 return arg9 - arg10; 13665} 13666 13667void runtime_call_store_at_address(int64_t* address) { *address = 0xf00d; } 13668 13669int32_t runtime_call_no_args() { return 1; } 13670 13671enum RuntimeCallTestEnum { Enum0 }; 13672 13673RuntimeCallTestEnum runtime_call_enum(RuntimeCallTestEnum e) { return e; } 13674 13675enum class RuntimeCallTestEnumClass { Enum0 }; 13676 13677RuntimeCallTestEnumClass runtime_call_enum_class(RuntimeCallTestEnumClass e) { 13678 return e; 13679} 13680 13681int8_t test_int8_t(int8_t x) { return x; } 13682uint8_t test_uint8_t(uint8_t x) { return x; } 13683int16_t test_int16_t(int16_t x) { return x; } 13684uint16_t test_uint16_t(uint16_t x) { return x; } 13685 13686TEST(runtime_calls) { 13687 SETUP_WITH_FEATURES(CPUFeatures::kFP); 13688 13689#ifndef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT 13690 if (masm.GenerateSimulatorCode()) { 13691 // This configuration is unsupported and a `VIXL_UNREACHABLE()` would fire 13692 // while trying to generate `CallRuntime`. This configuration should only be 13693 // reachable with C++11 and a (buggy) version of GCC pre-4.9.1. 13694 return; 13695 } 13696#endif 13697 13698 START(); 13699 13700 // Test `CallRuntime`. 13701 13702 __ Mov(w0, 0); 13703 __ CallRuntime(runtime_call_add_one); 13704 __ Mov(w20, w0); 13705 13706 __ Fmov(d0, 0.0); 13707 __ Fmov(d1, 1.5); 13708 __ Fmov(d2, 2.5); 13709 __ CallRuntime(runtime_call_add_doubles); 13710 __ Fmov(d20, d0); 13711 13712 __ Mov(x0, 0x123); 13713 __ Push(x0, x0); 13714 __ CallRuntime(runtime_call_one_argument_on_stack); 13715 __ Mov(x21, x0); 13716 __ Pop(x0, x1); 13717 13718 __ Fmov(d0, 314.0); 13719 __ Fmov(d1, 4.0); 13720 __ Push(d1, d0); 13721 __ CallRuntime(runtime_call_two_arguments_on_stack); 13722 __ Fmov(d21, d0); 13723 __ Pop(d1, d0); 13724 13725 // Test that the template mechanisms don't break with enums. 13726 __ Mov(w0, 0); 13727 __ CallRuntime(runtime_call_enum); 13728 __ Mov(w0, 0); 13729 __ CallRuntime(runtime_call_enum_class); 13730 13731 // Test `TailCallRuntime`. 13732 13733 Label function, after_function; 13734 __ B(&after_function); 13735 __ Bind(&function); 13736 __ Mov(x22, 0); 13737 __ Mov(w0, 123); 13738 __ TailCallRuntime(runtime_call_add_one); 13739 // Control should not fall through. 13740 __ Mov(x22, 0xbad); 13741 __ Ret(); 13742 __ Bind(&after_function); 13743 13744 // Call our placeholder function, taking care to preserve the link register. 13745 __ Push(ip0, lr); 13746 __ Bl(&function); 13747 __ Pop(lr, ip0); 13748 // Save the result. 13749 __ Mov(w23, w0); 13750 13751 __ Mov(x24, 0); 13752 int test_values[] = {static_cast<int8_t>(-1), 13753 static_cast<uint8_t>(-1), 13754 static_cast<int16_t>(-1), 13755 static_cast<uint16_t>(-1), 13756 -256, 13757 -1, 13758 0, 13759 1, 13760 256}; 13761 for (size_t i = 0; i < sizeof(test_values) / sizeof(test_values[0]); ++i) { 13762 Label pass_int8, pass_uint8, pass_int16, pass_uint16; 13763 int x = test_values[i]; 13764 __ Mov(w0, x); 13765 __ CallRuntime(test_int8_t); 13766 __ Sxtb(w0, w0); 13767 __ Cmp(w0, ExtractSignedBitfield32(7, 0, x)); 13768 __ Cinc(x24, x24, ne); 13769 __ Mov(w0, x); 13770 __ CallRuntime(test_uint8_t); 13771 __ Uxtb(w0, w0); 13772 __ Cmp(w0, ExtractUnsignedBitfield32(7, 0, x)); 13773 __ Cinc(x24, x24, ne); 13774 __ Mov(w0, x); 13775 __ CallRuntime(test_int16_t); 13776 __ Sxth(w0, w0); 13777 __ Cmp(w0, ExtractSignedBitfield32(15, 0, x)); 13778 __ Cinc(x24, x24, ne); 13779 __ Mov(w0, x); 13780 __ CallRuntime(test_uint16_t); 13781 __ Uxth(w0, w0); 13782 __ Cmp(w0, ExtractUnsignedBitfield32(15, 0, x)); 13783 __ Cinc(x24, x24, ne); 13784 } 13785 13786 13787 int64_t value = 0xbadbeef; 13788 __ Mov(x0, reinterpret_cast<uint64_t>(&value)); 13789 __ CallRuntime(runtime_call_store_at_address); 13790 13791 __ Mov(w0, 0); 13792 __ CallRuntime(runtime_call_no_args); 13793 __ Mov(w25, w0); 13794 13795 END(); 13796 13797#if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || \ 13798 !defined(VIXL_INCLUDE_SIMULATOR_AARCH64) 13799 if (CAN_RUN()) { 13800 RUN(); 13801 13802 ASSERT_EQUAL_32(1, w20); 13803 ASSERT_EQUAL_FP64(4.0, d20); 13804 ASSERT_EQUAL_64(0x123, x21); 13805 ASSERT_EQUAL_FP64(310.0, d21); 13806 VIXL_CHECK(value == 0xf00d); 13807 ASSERT_EQUAL_64(0, x22); 13808 ASSERT_EQUAL_32(124, w23); 13809 ASSERT_EQUAL_64(0, x24); 13810 ASSERT_EQUAL_32(1, w25); 13811 } 13812#endif // #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) || ... 13813} 13814 13815#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 13816void void_func() {} 13817uint32_t uint32_func() { return 2; } 13818void void_param_func(uint32_t x) { USE(x); } 13819uint32_t uint32_param_func(uint32_t x) { return ++x; } 13820 13821void void_placeholder() {} 13822uint32_t uint32_placeholder() { return 4; } 13823void void_param_placeholder(uint32_t x) { USE(x); } 13824uint32_t uint32_param_placeholder(uint32_t x) { return ++x; } 13825 13826#define DO_TEST_BRANCH_INTERCEPTION(func) \ 13827 __ Mov(x16, reinterpret_cast<uint64_t>(func)); \ 13828 __ Blr(x16); 13829 13830TEST(branch_interception) { 13831 SETUP(); 13832 START(); 13833 13834 // Test default branch interception, i.e: do a runtime call to the function. 13835 DO_TEST_BRANCH_INTERCEPTION(void_func); 13836 DO_TEST_BRANCH_INTERCEPTION(uint32_func); 13837 __ Mov(w20, w0); 13838 DO_TEST_BRANCH_INTERCEPTION(void_param_func); 13839 __ Mov(w0, 2); 13840 DO_TEST_BRANCH_INTERCEPTION(uint32_param_func); 13841 __ Mov(w21, w0); 13842 13843 // Test interceptions with callbacks. 13844 DO_TEST_BRANCH_INTERCEPTION(void_placeholder); 13845 __ Mov(w22, w0); 13846 DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder); 13847 __ Mov(w23, w0); 13848 __ Mov(w0, 4); 13849 DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder); 13850 __ Mov(w24, w0); 13851 DO_TEST_BRANCH_INTERCEPTION(uint32_placeholder); 13852 __ Mov(w25, w0); 13853 13854 END(); 13855 13856 simulator.RegisterBranchInterception(void_func); 13857 simulator.RegisterBranchInterception(uint32_func); 13858 simulator.RegisterBranchInterception(void_param_func); 13859 simulator.RegisterBranchInterception(uint32_param_func); 13860 13861 auto callback = [&simulator](uint64_t original_target) { 13862 USE(original_target); 13863 simulator.WriteWRegister(0, 1); 13864 }; 13865 13866 simulator.RegisterBranchInterception(void_placeholder, callback); 13867 simulator.RegisterBranchInterception(uint32_placeholder, callback); 13868 simulator.RegisterBranchInterception(void_param_placeholder, callback); 13869 simulator.RegisterBranchInterception(uint32_param_placeholder, callback); 13870 13871 if (CAN_RUN()) { 13872 RUN(); 13873 13874 ASSERT_EQUAL_32(2, w20); 13875 ASSERT_EQUAL_32(3, w21); 13876 ASSERT_EQUAL_32(1, w22); 13877 ASSERT_EQUAL_32(1, w23); 13878 ASSERT_EQUAL_32(1, w24); 13879 ASSERT_EQUAL_32(1, w25); 13880 } 13881} 13882#endif // #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 13883#endif // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 13884 13885 13886TEST(optimised_mov_register) { 13887 SETUP(); 13888 13889 START(); 13890 Label start; 13891 __ Bind(&start); 13892 __ Mov(x0, x0); 13893 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0); 13894 __ Mov(w0, w0, kDiscardForSameWReg); 13895 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == 0); 13896 __ Mov(w0, w0); 13897 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) == kInstructionSize); 13898 13899 END(); 13900 13901 if (CAN_RUN()) { 13902 RUN(); 13903 } 13904} 13905 13906 13907TEST(nop) { 13908 MacroAssembler masm; 13909 13910 Label start; 13911 __ Bind(&start); 13912 __ Nop(); 13913 // `MacroAssembler::Nop` must generate at least one nop. 13914 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= kInstructionSize); 13915 13916 masm.FinalizeCode(); 13917} 13918 13919 13920TEST(mte_addg_subg) { 13921 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 13922 13923 START(); 13924 __ Mov(x0, 0x5555000055555555); 13925 13926 // Add/subtract an address offset, changing tag each time. 13927 __ Addg(x1, x0, 16, 2); 13928 __ Subg(x2, x1, 16, 1); 13929 13930 // Add/subtract address offsets, keep tag. 13931 __ Addg(x3, x0, 1008, 0); 13932 __ Subg(x4, x3, 1008, 0); 13933 13934 // Change tag only. Check wraparound. 13935 __ Addg(x5, x0, 0, 15); 13936 __ Subg(x6, x0, 0, 14); 13937 13938 // Do nothing. 13939 __ Addg(x7, x0, 0, 0); 13940 __ Subg(x8, x0, 0, 0); 13941 13942 // Use stack pointer as source/destination. 13943 __ Mov(x20, sp); // Store original sp. 13944 13945 __ Subg(sp, sp, 32, 0); // Claim 32 bytes. 13946 __ Sub(x9, sp, x20); // Subtract original sp and store difference. 13947 13948 __ Mov(sp, x20); // Restore original sp. 13949 __ Claim(32); 13950 __ Addg(sp, sp, 32, 0); // Drop 32 bytes. 13951 __ Sub(x10, sp, x20); // Subtract original sp and store difference. 13952 13953 __ Mov(sp, x20); // Restore sp (should be no-op) 13954 __ Addg(sp, sp, 0, 1); // Tag the sp. 13955 __ Sub(x11, sp, x20); // Subtract original sp and store for later comparison. 13956 __ Mov(sp, x20); // Restore sp. 13957 13958 END(); 13959 13960 if (CAN_RUN()) { 13961 RUN(); 13962 13963 ASSERT_EQUAL_64(0x5755000055555565, x1); 13964 ASSERT_EQUAL_64(0x5855000055555555, x2); 13965 ASSERT_EQUAL_64(0x5555000055555945, x3); 13966 ASSERT_EQUAL_64(0x5555000055555555, x4); 13967 ASSERT_EQUAL_64(0x5455000055555555, x5); 13968 ASSERT_EQUAL_64(0x5355000055555555, x6); 13969 ASSERT_EQUAL_64(0x5555000055555555, x7); 13970 ASSERT_EQUAL_64(0x5555000055555555, x8); 13971 ASSERT_EQUAL_64(-32, x9); 13972 ASSERT_EQUAL_64(0, x10); 13973 ASSERT_EQUAL_64(UINT64_C(1) << 56, x11); 13974 } 13975} 13976 13977TEST(mte_subp) { 13978 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 13979 13980 START(); 13981 __ Mov(x0, 0x5555555555555555); 13982 __ Mov(x1, -42); 13983 13984 // Test subp with equivalent sbfx/sub(s) operations. 13985 __ Sbfx(x10, x0, 0, 56); 13986 __ Sbfx(x11, x1, 0, 56); 13987 13988 __ Subp(x4, x0, x1); 13989 __ Sub(x5, x10, x11); 13990 13991 __ Subp(x6, x1, x0); 13992 __ Sub(x7, x11, x10); 13993 13994 __ Subps(x8, x0, x1); 13995 __ Mrs(x18, NZCV); 13996 __ Subs(x9, x10, x11); 13997 __ Mrs(x19, NZCV); 13998 13999 __ Cmpp(x1, x0); 14000 __ Mrs(x20, NZCV); 14001 __ Cmp(x11, x10); 14002 __ Mrs(x21, NZCV); 14003 14004 // Test equal pointers with mismatched tags compare equal and produce a zero 14005 // difference with subps. 14006 __ Mov(x2, 0x20); // Exclude tag 5. 14007 __ Irg(x3, x0, x2); 14008 __ Subps(x22, x0, x3); 14009 14010 END(); 14011 14012 if (CAN_RUN()) { 14013 RUN(); 14014 14015 ASSERT_EQUAL_64(x5, x4); 14016 ASSERT_EQUAL_64(x7, x6); 14017 ASSERT_EQUAL_64(x9, x8); 14018 ASSERT_EQUAL_64(x19, x18); 14019 ASSERT_EQUAL_64(x20, x21); 14020 ASSERT_EQUAL_64(0, x22); 14021 ASSERT_EQUAL_NZCV(ZCFlag); 14022 } 14023} 14024 14025TEST(mte_gmi) { 14026 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 14027 14028 START(); 14029 __ Mov(x0, 0xaaaa); 14030 __ Mov(x20, 0x12345678); 14031 14032 __ Gmi(x0, x20, x0); // Add mask bit 0. 14033 __ Addg(x20, x20, 0, 1); 14034 __ Gmi(x1, x20, x0); // No effect. 14035 __ Addg(x20, x20, 0, 1); 14036 __ Gmi(x2, x20, x1); // Add mask bit 2. 14037 __ Addg(x20, x20, 0, 1); 14038 __ Gmi(x3, x20, x2); // No effect. 14039 __ Addg(x20, x20, 0, 1); 14040 __ Gmi(x4, x20, x3); // Add mask bit 4. 14041 __ Addg(x20, x20, 0, 1); 14042 __ Gmi(x5, x20, x4); // No effect. 14043 __ Addg(x20, x20, 0, 9); 14044 __ Gmi(x6, x20, x5); // Add mask bit 14. 14045 __ Gmi(x7, x20, xzr); // Only mask bit 14. 14046 END(); 14047 14048 if (CAN_RUN()) { 14049 RUN(); 14050 14051 ASSERT_EQUAL_64(0xaaab, x0); 14052 ASSERT_EQUAL_64(0xaaab, x1); 14053 ASSERT_EQUAL_64(0xaaaf, x2); 14054 ASSERT_EQUAL_64(0xaaaf, x3); 14055 ASSERT_EQUAL_64(0xaabf, x4); 14056 ASSERT_EQUAL_64(0xaabf, x5); 14057 ASSERT_EQUAL_64(0xeabf, x6); 14058 ASSERT_EQUAL_64(0x4000, x7); 14059 } 14060} 14061 14062TEST(mte_irg) { 14063 SETUP_WITH_FEATURES(CPUFeatures::kMTE); 14064 14065 START(); 14066 __ Mov(x10, 8); 14067 __ Mov(x0, 0x5555555555555555); 14068 // Insert a random tag repeatedly. If the loop doesn't exit in the expected 14069 // way, it's statistically likely that a random tag was never inserted. 14070 Label loop, failed, done; 14071 __ Bind(&loop); 14072 __ Irg(x1, x0); 14073 __ Sub(x10, x10, 1); 14074 __ Cbz(x10, &failed); // Exit if loop count exceeded. 14075 __ Cmp(x1, 0x5555555555555555); 14076 __ B(eq, &loop); // Loop if the tag hasn't changed. 14077 14078 // Check non-tag bits have not changed. 14079 __ Bic(x1, x1, 0x0f00000000000000); 14080 __ Subs(x1, x1, 0x5055555555555555); 14081 __ B(&done); 14082 14083 __ Bind(&failed); 14084 __ Mov(x1, 1); 14085 14086 __ Bind(&done); 14087 14088 // Insert random tags, excluding oddly-numbered tags, then orr them together. 14089 // After 128 rounds, it's statistically likely that all but the least 14090 // significant bit will be set. 14091 __ Mov(x3, 0); 14092 __ Mov(x10, 128); 14093 __ Mov(x11, 0xaaaa); 14094 14095 Label loop2; 14096 __ Bind(&loop2); 14097 __ Irg(x2, x1, x11); 14098 __ Orr(x3, x3, x2); 14099 __ Subs(x10, x10, 1); 14100 __ B(ne, &loop2); 14101 __ Lsr(x2, x3, 56); 14102 14103 // Check that excluding all tags results in zero tag insertion. 14104 __ Mov(x3, 0xffffffffffffffff); 14105 __ Irg(x3, x3, x3); 14106 END(); 14107 14108 if (CAN_RUN()) { 14109 RUN(); 14110 14111 ASSERT_EQUAL_64(0, x1); 14112 ASSERT_EQUAL_64(0xe, x2); 14113 ASSERT_EQUAL_64(0xf0ffffffffffffff, x3); 14114 } 14115} 14116 14117TEST(mops_set) { 14118 SETUP_WITH_FEATURES(CPUFeatures::kMOPS); 14119 14120 uint8_t dst[16]; 14121 memset(dst, 0x55, ArrayLength(dst)); 14122 uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst); 14123 14124 START(); 14125 __ Mov(x0, dst_addr); 14126 __ Add(x1, x0, 1); 14127 __ Mov(x2, 13); 14128 __ Mov(x3, 0x1234aa); 14129 14130 // Set 13 bytes dst[1] onwards to 0xaa. 14131 __ Setp(x1, x2, x3); 14132 __ Setm(x1, x2, x3); 14133 __ Sete(x1, x2, x3); 14134 14135 // x2 is now zero, so this should do nothing. 14136 __ Setp(x1, x2, x3); 14137 __ Setm(x1, x2, x3); 14138 __ Sete(x1, x2, x3); 14139 14140 // Set dst[15] to zero using the masm helper. 14141 __ Add(x1, x0, 15); 14142 __ Mov(x2, 1); 14143 __ Set(x1, x2, xzr); 14144 14145 // Load dst for comparison. 14146 __ Ldp(x10, x11, MemOperand(x0)); 14147 END(); 14148 14149 if (CAN_RUN()) { 14150 RUN(); 14151 ASSERT_EQUAL_64(dst_addr + 16, x1); 14152 ASSERT_EQUAL_64(0, x2); 14153 ASSERT_EQUAL_64(0x1234aa, x3); 14154 ASSERT_EQUAL_64(0xaaaa'aaaa'aaaa'aa55, x10); 14155 ASSERT_EQUAL_64(0x0055'aaaa'aaaa'aaaa, x11); 14156 } 14157} 14158 14159TEST(mops_setn) { 14160 SETUP_WITH_FEATURES(CPUFeatures::kMOPS); 14161 14162 // In simulation, non-temporal set is handled by the same code as normal set, 14163 // so only a basic test is required beyond that already provided above. 14164 14165 uint8_t dst[16] = {0x55}; 14166 uintptr_t dst_addr = reinterpret_cast<uintptr_t>(dst); 14167 14168 START(); 14169 __ Mov(x0, dst_addr); 14170 __ Mov(x1, x0); 14171 __ Mov(x2, 16); 14172 __ Mov(x3, 0x42); 14173 __ Setn(x1, x2, x3); 14174 __ Ldp(x10, x11, MemOperand(x0)); 14175 END(); 14176 14177 if (CAN_RUN()) { 14178 RUN(); 14179 ASSERT_EQUAL_64(dst_addr + 16, x1); 14180 ASSERT_EQUAL_64(0, x2); 14181 ASSERT_EQUAL_64(0x42, x3); 14182 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x10); 14183 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x11); 14184 } 14185} 14186 14187TEST(mops_setg) { 14188 SETUP_WITH_FEATURES(CPUFeatures::kMOPS, CPUFeatures::kMTE); 14189 14190 uint8_t* dst_addr = nullptr; 14191#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 14192 const int dst_size = 32; 14193 dst_addr = reinterpret_cast<uint8_t*>( 14194 simulator.Mmap(NULL, 14195 dst_size * sizeof(uint8_t), 14196 PROT_READ | PROT_WRITE | PROT_MTE, 14197 MAP_PRIVATE | MAP_ANONYMOUS, 14198 -1, 14199 0)); 14200 14201 VIXL_ASSERT(dst_addr != nullptr); 14202 uint8_t* untagged_ptr = AddressUntag(dst_addr); 14203 memset(untagged_ptr, 0xc9, dst_size); 14204#else 14205// TODO: Port the memory allocation to work on MTE supported platform natively. 14206// Note that `CAN_RUN` prevents running in MTE-unsupported environments. 14207#endif 14208 14209 START(); 14210 __ Mov(x0, reinterpret_cast<uint64_t>(dst_addr)); 14211 __ Gmi(x2, x0, xzr); 14212 __ Irg(x1, x0, x2); // Choose new tag for setg destination. 14213 __ Mov(x2, 16); 14214 __ Mov(x3, 0x42); 14215 __ Setg(x1, x2, x3); 14216 14217 __ Ubfx(x4, x1, 56, 4); // Extract new tag. 14218 __ Bfi(x0, x4, 56, 4); // Tag dst_addr so set region can be loaded. 14219 __ Ldp(x10, x11, MemOperand(x0)); 14220 14221 __ Mov(x0, reinterpret_cast<uint64_t>(dst_addr)); 14222 __ Ldp(x12, x13, MemOperand(x0, 16)); // Unset region has original tag. 14223 END(); 14224 14225 if (CAN_RUN()) { 14226 RUN(); 14227 ASSERT_EQUAL_64(0, x2); 14228 ASSERT_EQUAL_64(0x42, x3); 14229 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x10); 14230 ASSERT_EQUAL_64(0x4242'4242'4242'4242, x11); 14231 ASSERT_EQUAL_64(0xc9c9'c9c9'c9c9'c9c9, x12); 14232 ASSERT_EQUAL_64(0xc9c9'c9c9'c9c9'c9c9, x13); 14233 } 14234 14235#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 14236 simulator.Munmap(dst_addr, dst_size, PROT_MTE); 14237#endif 14238} 14239 14240TEST(mops_cpy) { 14241 SETUP_WITH_FEATURES(CPUFeatures::kMOPS); 14242 14243 uint8_t buf[16]; 14244 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf); 14245 14246 for (unsigned i = 0; i < ArrayLength(buf); i++) { 14247 buf[i] = i; 14248 } 14249 14250 START(); 14251 __ Mov(x0, buf_addr); 14252 14253 // Copy first eight bytes into second eight. 14254 __ Mov(x2, x0); // src = &buf[0] 14255 __ Add(x3, x0, 8); // dst = &buf[8] 14256 __ Mov(x4, 8); // count = 8 14257 __ Cpyp(x3, x2, x4); 14258 __ Cpym(x3, x2, x4); 14259 __ Cpye(x3, x2, x4); 14260 __ Ldp(x10, x11, MemOperand(x0)); 14261 __ Mrs(x20, NZCV); 14262 14263 // Copy first eight bytes to overlapping offset, causing reverse copy. 14264 __ Mov(x5, x0); // src = &buf[0] 14265 __ Add(x6, x0, 4); // dst = &buf[4] 14266 __ Mov(x7, 8); // count = 8 14267 __ Cpy(x6, x5, x7); 14268 __ Ldp(x12, x13, MemOperand(x0)); 14269 END(); 14270 14271 if (CAN_RUN()) { 14272 RUN(); 14273 ASSERT_EQUAL_64(buf_addr + 8, x2); 14274 ASSERT_EQUAL_64(buf_addr + 16, x3); 14275 ASSERT_EQUAL_64(0, x4); 14276 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x10); 14277 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x11); 14278 ASSERT_EQUAL_64(CFlag, x20); 14279 14280 ASSERT_EQUAL_64(buf_addr, x5); 14281 ASSERT_EQUAL_64(buf_addr + 4, x6); 14282 ASSERT_EQUAL_64(0, x7); 14283 ASSERT_EQUAL_64(0x0302'0100'0302'0100, x12); 14284 ASSERT_EQUAL_64(0x0706'0504'0706'0504, x13); 14285 ASSERT_EQUAL_NZCV(NCFlag); 14286 } 14287} 14288 14289TEST(mops_cpyn) { 14290 SETUP_WITH_FEATURES(CPUFeatures::kMOPS); 14291 14292 // In simulation, non-temporal cpy is handled by the same code as normal cpy, 14293 // so only a basic test is required beyond that already provided above. 14294 14295 uint8_t buf[16]; 14296 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf); 14297 14298 for (unsigned i = 0; i < ArrayLength(buf); i++) { 14299 buf[i] = i; 14300 } 14301 14302 START(); 14303 __ Mov(x0, buf_addr); 14304 14305 __ Add(x2, x0, 1); // src = &buf[1] 14306 __ Mov(x3, x0); // dst = &buf[0] 14307 __ Mov(x4, 15); // count = 15 14308 __ Cpyn(x3, x2, x4); 14309 __ Ldp(x10, x11, MemOperand(x0)); 14310 14311 __ Add(x5, x0, 1); // src = &buf[1] 14312 __ Mov(x6, x0); // dst = &buf[0] 14313 __ Mov(x4, 15); // count = 15 14314 __ Cpyrn(x6, x5, x4); 14315 __ Ldp(x12, x13, MemOperand(x0)); 14316 14317 __ Add(x7, x0, 1); // src = &buf[1] 14318 __ Mov(x8, x0); // dst = &buf[0] 14319 __ Mov(x4, 15); // count = 15 14320 __ Cpywn(x8, x7, x4); 14321 __ Ldp(x14, x15, MemOperand(x0)); 14322 END(); 14323 14324 if (CAN_RUN()) { 14325 RUN(); 14326 ASSERT_EQUAL_64(buf_addr + 16, x2); 14327 ASSERT_EQUAL_64(buf_addr + 15, x3); 14328 ASSERT_EQUAL_64(0x0807'0605'0403'0201, x10); 14329 ASSERT_EQUAL_64(0x0f0f'0e0d'0c0b'0a09, x11); 14330 14331 ASSERT_EQUAL_64(buf_addr + 16, x5); 14332 ASSERT_EQUAL_64(buf_addr + 15, x6); 14333 ASSERT_EQUAL_64(0x0908'0706'0504'0302, x12); 14334 ASSERT_EQUAL_64(0x0f0f'0f0e'0d0c'0b0a, x13); 14335 14336 ASSERT_EQUAL_64(buf_addr + 16, x7); 14337 ASSERT_EQUAL_64(buf_addr + 15, x8); 14338 ASSERT_EQUAL_64(0x0a09'0807'0605'0403, x14); 14339 ASSERT_EQUAL_64(0x0f0f'0f0f'0e0d'0c0b, x15); 14340 14341 ASSERT_EQUAL_64(0, x4); 14342 ASSERT_EQUAL_NZCV(CFlag); 14343 } 14344} 14345 14346TEST(mops_cpyf) { 14347 SETUP_WITH_FEATURES(CPUFeatures::kMOPS); 14348 14349 uint8_t buf[16]; 14350 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf); 14351 14352 for (unsigned i = 0; i < ArrayLength(buf); i++) { 14353 buf[i] = i; 14354 } 14355 14356 // This test matches the cpy variant above, but using cpyf will result in a 14357 // different answer for the overlapping copy. 14358 START(); 14359 __ Mov(x0, buf_addr); 14360 14361 // Copy first eight bytes into second eight. 14362 __ Mov(x2, x0); // src = &buf[0] 14363 __ Add(x3, x0, 8); // dst = &buf[8] 14364 __ Mov(x4, 8); // count = 8 14365 __ Cpyf(x3, x2, x4); 14366 __ Ldp(x10, x11, MemOperand(x0)); 14367 __ Mrs(x20, NZCV); 14368 14369 // Copy first eight bytes to overlapping offset. 14370 __ Mov(x5, x0); // src = &buf[0] 14371 __ Add(x6, x0, 4); // dst = &buf[4] 14372 __ Mov(x7, 8); // count = 8 14373 __ Cpyf(x6, x5, x7); 14374 __ Ldp(x12, x13, MemOperand(x0)); 14375 END(); 14376 14377 if (CAN_RUN()) { 14378 RUN(); 14379 ASSERT_EQUAL_64(buf_addr + 8, x2); 14380 ASSERT_EQUAL_64(buf_addr + 16, x3); 14381 ASSERT_EQUAL_64(0, x4); 14382 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x10); 14383 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x11); 14384 ASSERT_EQUAL_64(CFlag, x20); 14385 14386 ASSERT_EQUAL_64(buf_addr + 8, x5); 14387 ASSERT_EQUAL_64(buf_addr + 12, x6); 14388 ASSERT_EQUAL_64(0, x7); 14389 ASSERT_EQUAL_NZCV(CFlag); 14390 14391 // These results are not architecturally defined. They may change if the 14392 // simulator is implemented in a different, but still architecturally 14393 // correct, way. 14394 ASSERT_EQUAL_64(0x0302'0100'0302'0100, x12); 14395 ASSERT_EQUAL_64(0x0706'0504'0302'0100, x13); 14396 } 14397} 14398 14399TEST(mops_cpyfn) { 14400 SETUP_WITH_FEATURES(CPUFeatures::kMOPS); 14401 14402 // In simulation, non-temporal cpy is handled by the same code as normal cpy, 14403 // so only a basic test is required beyond that already provided above. 14404 14405 uint8_t buf[16]; 14406 uintptr_t buf_addr = reinterpret_cast<uintptr_t>(buf); 14407 14408 for (unsigned i = 0; i < ArrayLength(buf); i++) { 14409 buf[i] = i; 14410 } 14411 14412 START(); 14413 __ Mov(x0, buf_addr); 14414 14415 __ Add(x2, x0, 1); // src = &buf[1] 14416 __ Mov(x3, x0); // dst = &buf[0] 14417 __ Mov(x4, 15); // count = 15 14418 __ Cpyfn(x3, x2, x4); 14419 __ Ldp(x10, x11, MemOperand(x0)); 14420 14421 __ Add(x5, x0, 1); // src = &buf[1] 14422 __ Mov(x6, x0); // dst = &buf[0] 14423 __ Mov(x4, 15); // count = 15 14424 __ Cpyfrn(x6, x5, x4); 14425 __ Ldp(x12, x13, MemOperand(x0)); 14426 14427 __ Add(x7, x0, 1); // src = &buf[1] 14428 __ Mov(x8, x0); // dst = &buf[0] 14429 __ Mov(x4, 15); // count = 15 14430 __ Cpyfwn(x8, x7, x4); 14431 __ Ldp(x14, x15, MemOperand(x0)); 14432 END(); 14433 14434 if (CAN_RUN()) { 14435 RUN(); 14436 ASSERT_EQUAL_64(buf_addr + 16, x2); 14437 ASSERT_EQUAL_64(buf_addr + 15, x3); 14438 ASSERT_EQUAL_64(0x0807'0605'0403'0201, x10); 14439 ASSERT_EQUAL_64(0x0f0f'0e0d'0c0b'0a09, x11); 14440 14441 ASSERT_EQUAL_64(buf_addr + 16, x5); 14442 ASSERT_EQUAL_64(buf_addr + 15, x6); 14443 ASSERT_EQUAL_64(0x0908'0706'0504'0302, x12); 14444 ASSERT_EQUAL_64(0x0f0f'0f0e'0d0c'0b0a, x13); 14445 14446 ASSERT_EQUAL_64(buf_addr + 16, x7); 14447 ASSERT_EQUAL_64(buf_addr + 15, x8); 14448 ASSERT_EQUAL_64(0x0a09'0807'0605'0403, x14); 14449 ASSERT_EQUAL_64(0x0f0f'0f0f'0e0d'0c0b, x15); 14450 14451 ASSERT_EQUAL_64(0, x4); 14452 ASSERT_EQUAL_NZCV(CFlag); 14453 } 14454} 14455 14456TEST(cssc_abs) { 14457 SETUP_WITH_FEATURES(CPUFeatures::kCSSC); 14458 14459 START(); 14460 __ Mov(x0, -1); 14461 __ Mov(x1, 1); 14462 __ Mov(x2, 0); 14463 __ Mov(x3, 0x7fff'ffff); 14464 __ Mov(x4, 0x8000'0000); 14465 __ Mov(x5, 0x8000'0001); 14466 __ Mov(x6, 0x7fff'ffff'ffff'ffff); 14467 __ Mov(x7, 0x8000'0000'0000'0000); 14468 __ Mov(x8, 0x8000'0000'0000'0001); 14469 14470 __ Abs(w10, w0); 14471 __ Abs(x11, x0); 14472 __ Abs(w12, w1); 14473 __ Abs(x13, x1); 14474 __ Abs(w14, w2); 14475 __ Abs(x15, x2); 14476 14477 __ Abs(w19, w3); 14478 __ Abs(x20, x3); 14479 __ Abs(w21, w4); 14480 __ Abs(x22, x4); 14481 __ Abs(w23, w5); 14482 __ Abs(x24, x5); 14483 __ Abs(w25, w6); 14484 __ Abs(x26, x6); 14485 __ Abs(w27, w7); 14486 __ Abs(x28, x7); 14487 __ Abs(w29, w8); 14488 __ Abs(x30, x8); 14489 END(); 14490 14491 if (CAN_RUN()) { 14492 RUN(); 14493 14494 ASSERT_EQUAL_64(1, x10); 14495 ASSERT_EQUAL_64(1, x11); 14496 ASSERT_EQUAL_64(1, x12); 14497 ASSERT_EQUAL_64(1, x13); 14498 ASSERT_EQUAL_64(0, x14); 14499 ASSERT_EQUAL_64(0, x15); 14500 ASSERT_EQUAL_64(0x7fff'ffff, x19); 14501 ASSERT_EQUAL_64(0x7fff'ffff, x20); 14502 ASSERT_EQUAL_64(0x8000'0000, x21); 14503 ASSERT_EQUAL_64(0x8000'0000, x22); 14504 ASSERT_EQUAL_64(0x7fff'ffff, x23); 14505 ASSERT_EQUAL_64(0x8000'0001, x24); 14506 ASSERT_EQUAL_64(1, x25); 14507 ASSERT_EQUAL_64(0x7fff'ffff'ffff'ffff, x26); 14508 ASSERT_EQUAL_64(0, x27); 14509 ASSERT_EQUAL_64(0x8000'0000'0000'0000, x28); 14510 ASSERT_EQUAL_64(1, x29); 14511 ASSERT_EQUAL_64(0x7fff'ffff'ffff'ffff, x30); 14512 } 14513} 14514 14515TEST(cssc_cnt) { 14516 SETUP_WITH_FEATURES(CPUFeatures::kCSSC); 14517 14518 START(); 14519 __ Mov(x0, -1); 14520 __ Mov(x1, 1); 14521 __ Mov(x2, 0); 14522 __ Mov(x3, 0x7fff'ffff); 14523 __ Mov(x4, 0x8000'0000); 14524 __ Mov(x5, 0x8000'0001); 14525 __ Mov(x6, 0x7fff'ffff'ffff'ffff); 14526 __ Mov(x7, 0x4242'4242'aaaa'aaaa); 14527 14528 __ Cnt(w10, w0); 14529 __ Cnt(x11, x0); 14530 __ Cnt(w12, w1); 14531 __ Cnt(x13, x1); 14532 __ Cnt(w14, w2); 14533 __ Cnt(x15, x2); 14534 __ Cnt(w19, w3); 14535 __ Cnt(x20, x3); 14536 __ Cnt(w21, w4); 14537 __ Cnt(x22, x4); 14538 __ Cnt(w23, w5); 14539 __ Cnt(x24, x5); 14540 __ Cnt(w25, w6); 14541 __ Cnt(x26, x6); 14542 __ Cnt(w27, w7); 14543 __ Cnt(x28, x7); 14544 END(); 14545 14546 if (CAN_RUN()) { 14547 RUN(); 14548 14549 ASSERT_EQUAL_64(32, x10); 14550 ASSERT_EQUAL_64(64, x11); 14551 ASSERT_EQUAL_64(1, x12); 14552 ASSERT_EQUAL_64(1, x13); 14553 ASSERT_EQUAL_64(0, x14); 14554 ASSERT_EQUAL_64(0, x15); 14555 ASSERT_EQUAL_64(31, x19); 14556 ASSERT_EQUAL_64(31, x20); 14557 ASSERT_EQUAL_64(1, x21); 14558 ASSERT_EQUAL_64(1, x22); 14559 ASSERT_EQUAL_64(2, x23); 14560 ASSERT_EQUAL_64(2, x24); 14561 ASSERT_EQUAL_64(32, x25); 14562 ASSERT_EQUAL_64(63, x26); 14563 ASSERT_EQUAL_64(16, x27); 14564 ASSERT_EQUAL_64(24, x28); 14565 } 14566} 14567 14568TEST(cssc_ctz) { 14569 SETUP_WITH_FEATURES(CPUFeatures::kCSSC); 14570 14571 START(); 14572 __ Mov(x0, -1); 14573 __ Mov(x1, 1); 14574 __ Mov(x2, 2); 14575 __ Mov(x3, 0x7fff'ff00); 14576 __ Mov(x4, 0x8000'4000); 14577 __ Mov(x5, 0x4000'0001); 14578 __ Mov(x6, 0x0000'0001'0000'0000); 14579 __ Mov(x7, 0x4200'0000'0000'0000); 14580 14581 __ Ctz(w10, w0); 14582 __ Ctz(x11, x0); 14583 __ Ctz(w12, w1); 14584 __ Ctz(x13, x1); 14585 __ Ctz(w14, w2); 14586 __ Ctz(x15, x2); 14587 __ Ctz(w19, w3); 14588 __ Ctz(x20, x3); 14589 __ Ctz(w21, w4); 14590 __ Ctz(x22, x4); 14591 __ Ctz(w23, w5); 14592 __ Ctz(x24, x5); 14593 __ Ctz(w25, w6); 14594 __ Ctz(x26, x6); 14595 __ Ctz(w27, w7); 14596 __ Ctz(x28, x7); 14597 END(); 14598 14599 if (CAN_RUN()) { 14600 RUN(); 14601 14602 ASSERT_EQUAL_64(0, x10); 14603 ASSERT_EQUAL_64(0, x11); 14604 ASSERT_EQUAL_64(0, x12); 14605 ASSERT_EQUAL_64(0, x13); 14606 ASSERT_EQUAL_64(1, x14); 14607 ASSERT_EQUAL_64(1, x15); 14608 ASSERT_EQUAL_64(8, x19); 14609 ASSERT_EQUAL_64(8, x20); 14610 ASSERT_EQUAL_64(14, x21); 14611 ASSERT_EQUAL_64(14, x22); 14612 ASSERT_EQUAL_64(0, x23); 14613 ASSERT_EQUAL_64(0, x24); 14614 ASSERT_EQUAL_64(32, x25); 14615 ASSERT_EQUAL_64(32, x26); 14616 ASSERT_EQUAL_64(32, x27); 14617 ASSERT_EQUAL_64(57, x28); 14618 } 14619} 14620 14621using MinMaxOp = void (MacroAssembler::*)(const Register&, 14622 const Register&, 14623 const Operand&); 14624 14625static void MinMaxHelper(MinMaxOp op, 14626 bool is_signed, 14627 uint64_t a, 14628 uint64_t b, 14629 uint32_t wexp, 14630 uint64_t xexp) { 14631 SETUP_WITH_FEATURES(CPUFeatures::kCSSC); 14632 14633 START(); 14634 __ Mov(x0, a); 14635 __ Mov(x1, b); 14636 if ((is_signed && IsInt8(b)) || (!is_signed && IsUint8(b))) { 14637 (masm.*op)(w10, w0, b); 14638 (masm.*op)(x11, x0, b); 14639 } else { 14640 (masm.*op)(w10, w0, w1); 14641 (masm.*op)(x11, x0, x1); 14642 } 14643 END(); 14644 14645 if (CAN_RUN()) { 14646 RUN(); 14647 ASSERT_EQUAL_64(wexp, x10); 14648 ASSERT_EQUAL_64(xexp, x11); 14649 } 14650} 14651 14652TEST(cssc_umin) { 14653 MinMaxOp op = &MacroAssembler::Umin; 14654 uint32_t s32min = 0x8000'0000; 14655 uint32_t s32max = 0x7fff'ffff; 14656 uint64_t s64min = 0x8000'0000'0000'0000; 14657 uint64_t s64max = 0x7fff'ffff'ffff'ffff; 14658 14659 MinMaxHelper(op, false, 0, 0, 0, 0); 14660 MinMaxHelper(op, false, 128, 255, 128, 128); 14661 MinMaxHelper(op, false, 0, 0xffff'ffff'ffff'ffff, 0, 0); 14662 MinMaxHelper(op, false, s32max, s32min, s32max, s32max); 14663 MinMaxHelper(op, false, s32min, s32max, s32max, s32max); 14664 MinMaxHelper(op, false, s64max, s32min, s32min, s32min); 14665 MinMaxHelper(op, false, s64min, s64max, 0, s64max); 14666} 14667 14668TEST(cssc_umax) { 14669 MinMaxOp op = &MacroAssembler::Umax; 14670 uint32_t s32min = 0x8000'0000; 14671 uint32_t s32max = 0x7fff'ffff; 14672 uint64_t s64min = 0x8000'0000'0000'0000; 14673 uint64_t s64max = 0x7fff'ffff'ffff'ffff; 14674 14675 MinMaxHelper(op, false, 0, 0, 0, 0); 14676 MinMaxHelper(op, false, 128, 255, 255, 255); 14677 MinMaxHelper(op, 14678 false, 14679 0, 14680 0xffff'ffff'ffff'ffff, 14681 0xffff'ffff, 14682 0xffff'ffff'ffff'ffff); 14683 MinMaxHelper(op, false, s32max, s32min, s32min, s32min); 14684 MinMaxHelper(op, false, s32min, s32max, s32min, s32min); 14685 MinMaxHelper(op, false, s64max, s32min, 0xffff'ffff, s64max); 14686 MinMaxHelper(op, false, s64min, s64max, 0xffff'ffff, s64min); 14687} 14688 14689TEST(cssc_smin) { 14690 MinMaxOp op = &MacroAssembler::Smin; 14691 uint32_t s32min = 0x8000'0000; 14692 uint32_t s32max = 0x7fff'ffff; 14693 uint64_t s64min = 0x8000'0000'0000'0000; 14694 uint64_t s64max = 0x7fff'ffff'ffff'ffff; 14695 14696 MinMaxHelper(op, true, 0, 0, 0, 0); 14697 MinMaxHelper(op, true, 128, 255, 128, 128); 14698 MinMaxHelper(op, 14699 true, 14700 0, 14701 0xffff'ffff'ffff'ffff, 14702 0xffff'ffff, 14703 0xffff'ffff'ffff'ffff); 14704 MinMaxHelper(op, true, s32max, s32min, s32min, s32max); 14705 MinMaxHelper(op, true, s32min, s32max, s32min, s32max); 14706 MinMaxHelper(op, true, s64max, s32min, s32min, s32min); 14707 MinMaxHelper(op, true, s64min, s64max, 0xffff'ffff, s64min); 14708} 14709 14710TEST(cssc_smax) { 14711 MinMaxOp op = &MacroAssembler::Smax; 14712 uint32_t s32min = 0x8000'0000; 14713 uint32_t s32max = 0x7fff'ffff; 14714 uint64_t s64min = 0x8000'0000'0000'0000; 14715 uint64_t s64max = 0x7fff'ffff'ffff'ffff; 14716 14717 MinMaxHelper(op, true, 0, 0, 0, 0); 14718 MinMaxHelper(op, true, 128, 255, 255, 255); 14719 MinMaxHelper(op, true, 0, 0xffff'ffff'ffff'ffff, 0, 0); 14720 MinMaxHelper(op, true, s32max, s32min, s32max, s32min); 14721 MinMaxHelper(op, true, s32min, s32max, s32max, s32min); 14722 MinMaxHelper(op, true, s64max, s32min, 0xffff'ffff, s64max); 14723 MinMaxHelper(op, true, s64min, s64max, 0, s64max); 14724} 14725 14726#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 14727// Test the pseudo-instructions that control CPUFeatures dynamically in the 14728// Simulator. These are used by the test infrastructure itself, but in a fairly 14729// limited way. 14730 14731static void RunHelperWithFeatureCombinations( 14732 void (*helper)(const CPUFeatures& base, const CPUFeatures& f)) { 14733 // Iterate, testing the first n features in this list. 14734 CPUFeatures::Feature features[] = { 14735 // Put kNone first, so that the first iteration uses an empty feature set. 14736 CPUFeatures::kNone, 14737 // The remaining features used are arbitrary. 14738 CPUFeatures::kIDRegisterEmulation, 14739 CPUFeatures::kDCPoP, 14740 CPUFeatures::kPAuth, 14741 CPUFeatures::kFcma, 14742 CPUFeatures::kAES, 14743 CPUFeatures::kNEON, 14744 CPUFeatures::kCRC32, 14745 CPUFeatures::kFP, 14746 CPUFeatures::kPmull1Q, 14747 CPUFeatures::kSM4, 14748 CPUFeatures::kSM3, 14749 CPUFeatures::kDotProduct, 14750 }; 14751 VIXL_ASSERT(CPUFeatures(CPUFeatures::kNone) == CPUFeatures::None()); 14752 // The features are not necessarily encoded in kInstructionSize-sized slots, 14753 // so the MacroAssembler must pad the list to align the following instruction. 14754 // Ensure that we have enough features in the list to cover all interesting 14755 // alignment cases, even if the highest common factor of kInstructionSize and 14756 // an encoded feature is one. 14757 VIXL_STATIC_ASSERT(ARRAY_SIZE(features) > kInstructionSize); 14758 14759 CPUFeatures base = CPUFeatures::None(); 14760 for (size_t i = 0; i < ARRAY_SIZE(features); i++) { 14761 base.Combine(features[i]); 14762 CPUFeatures f = CPUFeatures::None(); 14763 for (size_t j = 0; j < ARRAY_SIZE(features); j++) { 14764 f.Combine(features[j]); 14765 helper(base, f); 14766 } 14767 } 14768} 14769 14770static void SetSimulatorCPUFeaturesHelper(const CPUFeatures& base, 14771 const CPUFeatures& f) { 14772 SETUP_WITH_FEATURES(base); 14773 START(); 14774 14775 __ SetSimulatorCPUFeatures(f); 14776 14777 END(); 14778 if (CAN_RUN()) { 14779 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 14780 VIXL_CHECK(*(simulator.GetCPUFeatures()) == f); 14781 } 14782} 14783 14784TEST(configure_cpu_features_set) { 14785 RunHelperWithFeatureCombinations(SetSimulatorCPUFeaturesHelper); 14786} 14787 14788static void EnableSimulatorCPUFeaturesHelper(const CPUFeatures& base, 14789 const CPUFeatures& f) { 14790 SETUP_WITH_FEATURES(base); 14791 START(); 14792 14793 __ EnableSimulatorCPUFeatures(f); 14794 14795 END(); 14796 if (CAN_RUN()) { 14797 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 14798 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.With(f)); 14799 } 14800} 14801 14802TEST(configure_cpu_features_enable) { 14803 RunHelperWithFeatureCombinations(EnableSimulatorCPUFeaturesHelper); 14804} 14805 14806static void DisableSimulatorCPUFeaturesHelper(const CPUFeatures& base, 14807 const CPUFeatures& f) { 14808 SETUP_WITH_FEATURES(base); 14809 START(); 14810 14811 __ DisableSimulatorCPUFeatures(f); 14812 14813 END(); 14814 if (CAN_RUN()) { 14815 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 14816 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base.Without(f)); 14817 } 14818} 14819 14820TEST(configure_cpu_features_disable) { 14821 RunHelperWithFeatureCombinations(DisableSimulatorCPUFeaturesHelper); 14822} 14823 14824static void SaveRestoreSimulatorCPUFeaturesHelper(const CPUFeatures& base, 14825 const CPUFeatures& f) { 14826 SETUP_WITH_FEATURES(base); 14827 START(); 14828 14829 { 14830 __ SaveSimulatorCPUFeatures(); 14831 __ SetSimulatorCPUFeatures(f); 14832 { 14833 __ SaveSimulatorCPUFeatures(); 14834 __ SetSimulatorCPUFeatures(CPUFeatures::All()); 14835 __ RestoreSimulatorCPUFeatures(); 14836 } 14837 __ RestoreSimulatorCPUFeatures(); 14838 } 14839 14840 END(); 14841 if (CAN_RUN()) { 14842 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 14843 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base); 14844 } 14845} 14846 14847TEST(configure_cpu_features_save_restore) { 14848 RunHelperWithFeatureCombinations(SaveRestoreSimulatorCPUFeaturesHelper); 14849} 14850 14851static void SimulationCPUFeaturesScopeHelper(const CPUFeatures& base, 14852 const CPUFeatures& f) { 14853 SETUP_WITH_FEATURES(base); 14854 START(); 14855 14856 { 14857 SimulationCPUFeaturesScope scope_a(&masm, f); 14858 { 14859 SimulationCPUFeaturesScope scope_b(&masm, CPUFeatures::All()); 14860 { 14861 SimulationCPUFeaturesScope scope_c(&masm, CPUFeatures::None()); 14862 // The scope arguments should combine with 'Enable', so we should be 14863 // able to use any CPUFeatures here. 14864 __ Fadd(v0.V4S(), v1.V4S(), v2.V4S()); // Requires {FP, NEON}. 14865 } 14866 } 14867 } 14868 14869 END(); 14870 if (CAN_RUN()) { 14871 RUN_WITHOUT_SEEN_FEATURE_CHECK(); 14872 VIXL_CHECK(*(simulator.GetCPUFeatures()) == base); 14873 } 14874} 14875 14876TEST(configure_cpu_features_scope) { 14877 RunHelperWithFeatureCombinations(SimulationCPUFeaturesScopeHelper); 14878} 14879#endif 14880 14881 14882#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 14883TEST(large_sim_stack) { 14884 SimStack builder; 14885 builder.SetUsableSize(16 * 1024); // The default is 8kB. 14886 SimStack::Allocated stack = builder.Allocate(); 14887 uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase()); 14888 uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit()); 14889 SETUP_CUSTOM_SIM(std::move(stack)); 14890 START(); 14891 14892 // Check that we can access the extremes of the stack. 14893 __ Mov(x0, base); 14894 __ Mov(x1, limit); 14895 __ Mov(x2, sp); 14896 __ Add(sp, x1, 1); // Avoid accessing memory below `sp`. 14897 14898 __ Mov(x10, 42); 14899 __ Poke(x10, 0); 14900 __ Peek(x10, base - limit - kXRegSizeInBytes - 1); 14901 14902 __ Mov(sp, x2); 14903 14904 END(); 14905 if (CAN_RUN()) { 14906 RUN(); 14907 } 14908} 14909 14910#ifdef VIXL_NEGATIVE_TESTING 14911TEST(sim_stack_limit_guard_read) { 14912 SimStack builder; 14913 SimStack::Allocated stack = builder.Allocate(); 14914 uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit()); 14915 SETUP_CUSTOM_SIM(std::move(stack)); 14916 START(); 14917 14918 __ Mov(x1, limit); 14919 __ Mov(x2, sp); 14920 __ Add(sp, x1, 1); // Avoid accessing memory below `sp`. 14921 14922 // `sp` points to the lowest usable byte of the stack. 14923 __ Mov(w10, 42); 14924 __ Ldrb(w10, MemOperand(sp, -1)); 14925 14926 __ Mov(sp, x2); 14927 14928 END(); 14929 if (CAN_RUN()) { 14930 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region"); 14931 } 14932} 14933 14934TEST(sim_stack_limit_guard_write) { 14935 SimStack builder; 14936 SimStack::Allocated stack = builder.Allocate(); 14937 uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit()); 14938 SETUP_CUSTOM_SIM(std::move(stack)); 14939 START(); 14940 14941 __ Mov(x1, limit); 14942 __ Mov(x2, sp); 14943 __ Add(sp, x1, 1); // Avoid accessing memory below `sp`. 14944 14945 // `sp` points to the lowest usable byte of the stack. 14946 __ Mov(w10, 42); 14947 __ Strb(w10, MemOperand(sp, -1)); 14948 14949 __ Mov(sp, x2); 14950 14951 END(); 14952 if (CAN_RUN()) { 14953 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region"); 14954 } 14955} 14956 14957TEST(sim_stack_base_guard_read) { 14958 SimStack builder; 14959 SimStack::Allocated stack = builder.Allocate(); 14960 uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase()); 14961 SETUP_CUSTOM_SIM(std::move(stack)); 14962 START(); 14963 14964 __ Mov(x0, base); 14965 // `base` (x0) is the byte after the highest usable byte of the stack. 14966 // The last byte of this access will hit the guard region. 14967 __ Mov(x10, 42); 14968 __ Ldr(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1)); 14969 14970 END(); 14971 if (CAN_RUN()) { 14972 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region"); 14973 } 14974} 14975 14976TEST(sim_stack_base_guard_write) { 14977 SimStack builder; 14978 SimStack::Allocated stack = builder.Allocate(); 14979 uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase()); 14980 SETUP_CUSTOM_SIM(std::move(stack)); 14981 START(); 14982 14983 __ Mov(x0, base); 14984 // `base` (x0) is the byte after the highest usable byte of the stack. 14985 // The last byte of this access will hit the guard region. 14986 __ Mov(x10, 42); 14987 __ Str(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1)); 14988 14989 END(); 14990 if (CAN_RUN()) { 14991 MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region"); 14992 } 14993} 14994#endif 14995#endif 14996 14997TEST(scalar_movi) { 14998 SETUP_WITH_FEATURES(CPUFeatures::kFP, CPUFeatures::kNEON); 14999 START(); 15000 15001 // Make sure that V0 is initialized to a non-zero value. 15002 __ Movi(v0.V16B(), 0xFF); 15003 // This constant value can't be encoded in a MOVI instruction, 15004 // so the program would use a fallback path that must set the 15005 // upper 64 bits of the destination vector to 0. 15006 __ Movi(v0.V1D(), 0xDECAFC0FFEE); 15007 __ Mov(x0, v0.V2D(), 1); 15008 15009 END(); 15010 15011 if (CAN_RUN()) { 15012 RUN(); 15013 15014 ASSERT_EQUAL_64(0, x0); 15015 } 15016} 15017 15018} // namespace aarch64 15019} // namespace vixl 15020