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 <cstdio> 28 #include <string> 29 #include <iostream> 30 31 #include "test-runner.h" 32 #include "test-utils.h" 33 #include "aarch32/test-utils-aarch32.h" 34 35 #include "aarch32/macro-assembler-aarch32.h" 36 #include "aarch32/disasm-aarch32.h" 37 38 namespace vixl { 39 namespace aarch32 { 40 41 #define STRINGIFY(x) #x 42 43 #ifdef VIXL_INCLUDE_TARGET_A32_ONLY 44 #define TEST_T32(Name) \ 45 void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 46 #else 47 // Tests declared with this macro will only target T32. 48 #define TEST_T32(Name) \ 49 void Test##Name##Impl(InstructionSet isa); \ 50 void Test##Name() { Test##Name##Impl(T32); } \ 51 Test test_##Name(STRINGIFY(AARCH32_T32_##Name), &Test##Name); \ 52 void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 53 #endif 54 55 #ifdef VIXL_INCLUDE_TARGET_T32_ONLY 56 #define TEST_A32(Name) \ 57 void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 58 #else 59 // Test declared with this macro will only target A32. 60 #define TEST_A32(Name) \ 61 void Test##Name##Impl(InstructionSet isa); \ 62 void Test##Name() { Test##Name##Impl(A32); } \ 63 Test test_##Name(STRINGIFY(AARCH32_A32_##Name), &Test##Name); \ 64 void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 65 #endif 66 67 // Tests declared with this macro will be run twice: once targeting A32 and 68 // once targeting T32. 69 #if defined(VIXL_INCLUDE_TARGET_A32_ONLY) 70 #define TEST(Name) TEST_A32(Name) 71 #elif defined(VIXL_INCLUDE_TARGET_T32_ONLY) 72 #define TEST(Name) TEST_T32(Name) 73 #else 74 #define TEST(Name) \ 75 void Test##Name##Impl(InstructionSet isa); \ 76 void Test##Name() { \ 77 Test##Name##Impl(A32); \ 78 printf(" > A32 done\n"); \ 79 Test##Name##Impl(T32); \ 80 printf(" > T32 done\n"); \ 81 } \ 82 Test test_##Name(STRINGIFY(AARCH32_ASM_##Name), &Test##Name); \ 83 void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 84 #endif 85 86 // Tests declared with this macro are not expected to use any provided test 87 // helpers such as SETUP, RUN, etc. 88 #define TEST_NOASM(Name) \ 89 void Test##Name(); \ 90 Test test_##Name(STRINGIFY(AARCH32_##Name), &Test##Name); \ 91 void Test##Name() 92 93 #define __ masm. 94 #define BUF_SIZE (4096) 95 96 #define ASSERT_LITERAL_POOL_SIZE(size) \ 97 do { \ 98 VIXL_CHECK(__ GetLiteralPoolSize() == size); \ 99 } while (false) 100 101 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH32 102 // No simulator yet. 103 104 #define SETUP() MacroAssembler masm(BUF_SIZE, isa); 105 106 #define START() masm.GetBuffer()->Reset(); 107 108 #define END() \ 109 __ Hlt(0); \ 110 __ FinalizeCode(); 111 112 #define RUN() DISASSEMBLE(); 113 114 #define TEARDOWN() 115 116 #else // ifdef VIXL_INCLUDE_SIMULATOR_AARCH32. 117 118 #define SETUP() \ 119 RegisterDump core; \ 120 MacroAssembler masm(BUF_SIZE, isa); \ 121 UseScratchRegisterScope harness_scratch(&masm); \ 122 harness_scratch.ExcludeAll(); 123 124 #define START() \ 125 masm.GetBuffer()->Reset(); \ 126 __ Push(r4); \ 127 __ Push(r5); \ 128 __ Push(r6); \ 129 __ Push(r7); \ 130 __ Push(r8); \ 131 __ Push(r9); \ 132 __ Push(r10); \ 133 __ Push(r11); \ 134 __ Push(ip); \ 135 __ Push(lr); \ 136 __ Mov(r0, 0); \ 137 __ Msr(APSR_nzcvq, r0); \ 138 harness_scratch.Include(ip); 139 140 #define END() \ 141 harness_scratch.Exclude(ip); \ 142 core.Dump(&masm); \ 143 __ Pop(lr); \ 144 __ Pop(ip); \ 145 __ Pop(r11); \ 146 __ Pop(r10); \ 147 __ Pop(r9); \ 148 __ Pop(r8); \ 149 __ Pop(r7); \ 150 __ Pop(r6); \ 151 __ Pop(r5); \ 152 __ Pop(r4); \ 153 __ Bx(lr); \ 154 __ FinalizeCode(); 155 156 // Execute the generated code from the MacroAssembler's automatic code buffer. 157 // Note the offset for ExecuteMemory since the PCS requires that 158 // the address be odd in the case of branching to T32 code. 159 #define RUN() \ 160 DISASSEMBLE(); \ 161 { \ 162 int pcs_offset = masm.IsUsingT32() ? 1 : 0; \ 163 masm.GetBuffer()->SetExecutable(); \ 164 ExecuteMemory(masm.GetBuffer()->GetStartAddress<byte*>(), \ 165 masm.GetSizeOfCodeGenerated(), \ 166 pcs_offset); \ 167 masm.GetBuffer()->SetWritable(); \ 168 } 169 170 #define TEARDOWN() harness_scratch.Close(); 171 172 #endif // ifdef VIXL_INCLUDE_SIMULATOR_AARCH32 173 174 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH32 175 // No simulator yet. We can't test the results. 176 177 #define ASSERT_EQUAL_32(expected, result) 178 179 #define ASSERT_EQUAL_64(expected, result) 180 181 #define ASSERT_EQUAL_128(expected_h, expected_l, result) 182 183 #define ASSERT_EQUAL_FP32(expected, result) 184 185 #define ASSERT_EQUAL_FP64(expected, result) 186 187 #define ASSERT_EQUAL_NZCV(expected) 188 189 #else 190 191 #define ASSERT_EQUAL_32(expected, result) \ 192 VIXL_CHECK(Equal32(expected, &core, result)) 193 194 #define ASSERT_EQUAL_64(expected, result) \ 195 VIXL_CHECK(Equal64(expected, &core, result)) 196 197 #define ASSERT_EQUAL_128(expected_h, expected_l, result) \ 198 VIXL_CHECK(Equal128(expected_h, expected_l, &core, result)) 199 200 #define ASSERT_EQUAL_FP32(expected, result) \ 201 VIXL_CHECK(EqualFP32(expected, &core, result)) 202 203 #define ASSERT_EQUAL_FP64(expected, result) \ 204 VIXL_CHECK(EqualFP64(expected, &core, result)) 205 206 #define ASSERT_EQUAL_NZCV(expected) \ 207 VIXL_CHECK(EqualNzcv(expected, core.flags_nzcv())) 208 209 #endif 210 211 #define DISASSEMBLE() \ 212 if (Test::disassemble()) { \ 213 PrintDisassembler dis(std::cout, 0); \ 214 if (masm.IsUsingT32()) { \ 215 dis.DisassembleT32Buffer(masm.GetBuffer()->GetStartAddress<uint16_t*>(), \ 216 masm.GetCursorOffset()); \ 217 } else { \ 218 dis.DisassembleA32Buffer(masm.GetBuffer()->GetStartAddress<uint32_t*>(), \ 219 masm.GetCursorOffset()); \ 220 } \ 221 } 222 223 // TODO: Add SBC to the ADC tests. 224 225 226 TEST(adc_shift) { 227 SETUP(); 228 229 START(); 230 // Initialize registers. 231 __ Mov(r0, 0); 232 __ Mov(r1, 1); 233 __ Mov(r2, 0x01234567); 234 __ Mov(r3, 0xfedcba98); 235 236 // Clear the C flag. 237 __ Adds(r0, r0, 0); 238 239 __ Adc(r4, r2, r3); 240 __ Adc(r5, r0, Operand(r1, LSL, 30)); 241 __ Adc(r6, r0, Operand(r2, LSR, 16)); 242 __ Adc(r7, r2, Operand(r3, ASR, 4)); 243 __ Adc(r8, r2, Operand(r3, ROR, 8)); 244 __ Adc(r9, r2, Operand(r3, RRX)); 245 END(); 246 247 RUN(); 248 249 ASSERT_EQUAL_32(0xffffffff, r4); 250 ASSERT_EQUAL_32(INT32_C(1) << 30, r5); 251 ASSERT_EQUAL_32(0x00000123, r6); 252 ASSERT_EQUAL_32(0x01111110, r7); 253 ASSERT_EQUAL_32(0x9a222221, r8); 254 ASSERT_EQUAL_32(0x8091a2b3, r9); 255 256 START(); 257 // Initialize registers. 258 __ Mov(r0, 0); 259 __ Mov(r1, 1); 260 __ Mov(r2, 0x01234567); 261 __ Mov(r3, 0xfedcba98); 262 __ Mov(r4, 0xffffffff); 263 264 // Set the C flag. 265 __ Adds(r0, r4, r1); 266 267 __ Adc(r5, r2, r3); 268 __ Adc(r6, r0, Operand(r1, LSL, 30)); 269 __ Adc(r7, r0, Operand(r2, LSR, 16)); 270 __ Adc(r8, r2, Operand(r3, ASR, 4)); 271 __ Adc(r9, r2, Operand(r3, ROR, 8)); 272 __ Adc(r10, r2, Operand(r3, RRX)); 273 END(); 274 275 RUN(); 276 277 ASSERT_EQUAL_32(0xffffffff + 1, r5); 278 ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, r6); 279 ASSERT_EQUAL_32(0x00000123 + 1, r7); 280 ASSERT_EQUAL_32(0x01111110 + 1, r8); 281 ASSERT_EQUAL_32(0x9a222221 + 1, r9); 282 ASSERT_EQUAL_32(0x0091a2b3 + 1, r10); 283 284 // Check that adc correctly sets the condition flags. 285 START(); 286 __ Mov(r0, 0); 287 __ Mov(r1, 0xffffffff); 288 __ Mov(r2, 1); 289 290 // Clear the C flag. 291 __ Adds(r0, r0, 0); 292 __ Adcs(r3, r2, r1); 293 END(); 294 295 RUN(); 296 297 ASSERT_EQUAL_NZCV(ZCFlag); 298 ASSERT_EQUAL_32(0, r3); 299 300 START(); 301 __ Mov(r0, 0); 302 __ Mov(r1, 0x80000000); 303 __ Mov(r2, 1); 304 305 // Clear the C flag. 306 __ Adds(r0, r0, 0); 307 __ Adcs(r3, r2, Operand(r1, ASR, 31)); 308 END(); 309 310 RUN(); 311 312 ASSERT_EQUAL_NZCV(ZCFlag); 313 ASSERT_EQUAL_32(0, r3); 314 315 START(); 316 __ Mov(r0, 0); 317 __ Mov(r1, 0x80000000); 318 __ Mov(r2, 0xffffffff); 319 320 // Clear the C flag. 321 __ Adds(r0, r0, 0); 322 __ Adcs(r3, r2, Operand(r1, LSR, 31)); 323 END(); 324 325 RUN(); 326 327 ASSERT_EQUAL_NZCV(ZCFlag); 328 ASSERT_EQUAL_32(0, r3); 329 330 START(); 331 __ Mov(r0, 0); 332 __ Mov(r1, 0x07ffffff); 333 __ Mov(r2, 0x10); 334 335 // Clear the C flag. 336 __ Adds(r0, r0, 0); 337 __ Adcs(r3, r2, Operand(r1, LSL, 4)); 338 END(); 339 340 RUN(); 341 342 ASSERT_EQUAL_NZCV(NVFlag); 343 ASSERT_EQUAL_32(0x080000000, r3); 344 345 START(); 346 __ Mov(r0, 0); 347 __ Mov(r1, 0xffffff00); 348 __ Mov(r2, 0xff000001); 349 350 // Clear the C flag. 351 __ Adds(r0, r0, 0); 352 __ Adcs(r3, r2, Operand(r1, ROR, 8)); 353 END(); 354 355 RUN(); 356 357 ASSERT_EQUAL_NZCV(ZCFlag); 358 ASSERT_EQUAL_32(0, r3); 359 360 START(); 361 __ Mov(r0, 0); 362 __ Mov(r1, 0xffffffff); 363 __ Mov(r2, 0x1); 364 365 // Clear the C flag, forcing RRX to insert 0 in r1's most significant bit. 366 __ Adds(r0, r0, 0); 367 __ Adcs(r3, r2, Operand(r1, RRX)); 368 END(); 369 370 RUN(); 371 372 ASSERT_EQUAL_NZCV(NVFlag); 373 ASSERT_EQUAL_32(0x80000000, r3); 374 375 START(); 376 __ Mov(r0, 0); 377 __ Mov(r1, 0xffffffff); 378 __ Mov(r2, 0x1); 379 380 // Set the C flag, forcing RRX to insert 1 in r1's most significant bit. 381 __ Adds(r0, r1, r2); 382 __ Adcs(r3, r2, Operand(r1, RRX)); 383 END(); 384 385 RUN(); 386 387 ASSERT_EQUAL_NZCV(CFlag); 388 ASSERT_EQUAL_32(1, r3); 389 390 TEARDOWN(); 391 } 392 393 394 TEST(adc_wide_imm) { 395 SETUP(); 396 397 START(); 398 __ Mov(r0, 0); 399 400 // Clear the C flag. 401 __ Adds(r0, r0, 0); 402 403 __ Adc(r1, r0, 0x12345678); 404 __ Adc(r2, r0, 0xffffffff); 405 406 // Set the C flag. 407 __ Cmp(r0, r0); 408 409 __ Adc(r3, r0, 0x12345678); 410 __ Adc(r4, r0, 0xffffffff); 411 END(); 412 413 RUN(); 414 415 ASSERT_EQUAL_32(0x12345678, r1); 416 ASSERT_EQUAL_32(0xffffffff, r2); 417 ASSERT_EQUAL_32(0x12345678 + 1, r3); 418 ASSERT_EQUAL_32(0, r4); 419 420 TEARDOWN(); 421 } 422 423 424 // TODO: Add SUB tests to the ADD tests. 425 426 427 TEST(add_imm) { 428 SETUP(); 429 430 START(); 431 __ Mov(r0, 0); 432 __ Mov(r1, 0x1111); 433 __ Mov(r2, 0xffffffff); 434 __ Mov(r3, 0x80000000); 435 436 __ Add(r4, r0, 0x12); 437 __ Add(r5, r1, 0x120000); 438 __ Add(r6, r0, 0xab << 12); 439 __ Add(r7, r2, 1); 440 441 END(); 442 443 RUN(); 444 445 ASSERT_EQUAL_32(0x12, r4); 446 ASSERT_EQUAL_32(0x121111, r5); 447 ASSERT_EQUAL_32(0xab000, r6); 448 ASSERT_EQUAL_32(0x0, r7); 449 450 TEARDOWN(); 451 } 452 453 454 TEST(add_wide_imm) { 455 SETUP(); 456 457 START(); 458 __ Mov(r0, 0); 459 __ Mov(r1, 1); 460 461 __ Add(r2, r0, 0x12345678); 462 __ Add(r3, r1, 0xffff); 463 END(); 464 465 RUN(); 466 467 ASSERT_EQUAL_32(0x12345678, r2); 468 ASSERT_EQUAL_32(0x00010000, r3); 469 470 TEARDOWN(); 471 } 472 473 474 TEST(add_shifted) { 475 SETUP(); 476 477 START(); 478 __ Mov(r0, 0); 479 __ Mov(r1, 0x01234567); 480 __ Mov(r2, 0x76543210); 481 __ Mov(r3, 0xffffffff); 482 483 __ Add(r4, r1, r2); 484 __ Add(r5, r0, Operand(r1, LSL, 8)); 485 __ Add(r6, r0, Operand(r1, LSR, 8)); 486 __ Add(r7, r0, Operand(r1, ASR, 8)); 487 __ Add(r8, r3, Operand(r1, ROR, 8)); 488 489 // Set the C flag. 490 __ Adds(r0, r3, 1); 491 __ Add(r9, r3, Operand(r1, RRX)); 492 493 // Clear the C flag. 494 __ Adds(r0, r0, 0); 495 __ Add(r10, r3, Operand(r1, RRX)); 496 497 END(); 498 499 RUN(); 500 501 ASSERT_EQUAL_32(0x77777777, r4); 502 ASSERT_EQUAL_32(0x23456700, r5); 503 ASSERT_EQUAL_32(0x00012345, r6); 504 ASSERT_EQUAL_32(0x00012345, r7); 505 ASSERT_EQUAL_32(0x67012344, r8); 506 ASSERT_EQUAL_32(0x8091a2b2, r9); 507 ASSERT_EQUAL_32(0x0091a2b2, r10); 508 509 TEARDOWN(); 510 } 511 512 513 TEST(and_) { 514 SETUP(); 515 516 START(); 517 __ Mov(r0, 0x0000fff0); 518 __ Mov(r1, 0xf00000ff); 519 __ Mov(r2, 0xffffffff); 520 521 __ And(r3, r0, r1); 522 __ And(r4, r0, Operand(r1, LSL, 4)); 523 __ And(r5, r0, Operand(r1, LSR, 1)); 524 __ And(r6, r0, Operand(r1, ASR, 20)); 525 __ And(r7, r0, Operand(r1, ROR, 28)); 526 __ And(r8, r0, 0xff); 527 528 // Set the C flag. 529 __ Adds(r9, r2, 1); 530 __ And(r9, r1, Operand(r1, RRX)); 531 532 // Clear the C flag. 533 __ Adds(r10, r0, 0); 534 __ And(r10, r1, Operand(r1, RRX)); 535 END(); 536 537 RUN(); 538 539 ASSERT_EQUAL_32(0x000000f0, r3); 540 ASSERT_EQUAL_32(0x00000ff0, r4); 541 ASSERT_EQUAL_32(0x00000070, r5); 542 ASSERT_EQUAL_32(0x0000ff00, r6); 543 ASSERT_EQUAL_32(0x00000ff0, r7); 544 ASSERT_EQUAL_32(0x000000f0, r8); 545 ASSERT_EQUAL_32(0xf000007f, r9); 546 ASSERT_EQUAL_32(0x7000007f, r10); 547 548 TEARDOWN(); 549 } 550 551 552 TEST(ands) { 553 SETUP(); 554 555 START(); 556 __ Mov(r0, 0); 557 __ Mov(r1, 0xf00000ff); 558 559 __ Ands(r0, r1, r1); 560 END(); 561 562 RUN(); 563 564 ASSERT_EQUAL_NZCV(NFlag); 565 ASSERT_EQUAL_32(0xf00000ff, r0); 566 567 START(); 568 __ Mov(r0, 0x00fff000); 569 __ Mov(r1, 0xf00000ff); 570 571 __ Ands(r0, r0, Operand(r1, LSL, 4)); 572 END(); 573 574 RUN(); 575 576 ASSERT_EQUAL_NZCV(ZCFlag); 577 ASSERT_EQUAL_32(0x00000000, r0); 578 579 START(); 580 __ Mov(r0, 0x0000fff0); 581 __ Mov(r1, 0xf00000ff); 582 583 __ Ands(r0, r0, Operand(r1, LSR, 4)); 584 END(); 585 586 RUN(); 587 588 ASSERT_EQUAL_NZCV(ZCFlag); 589 ASSERT_EQUAL_32(0x00000000, r0); 590 591 START(); 592 __ Mov(r0, 0xf000fff0); 593 __ Mov(r1, 0xf00000ff); 594 595 __ Ands(r0, r0, Operand(r1, ASR, 4)); 596 END(); 597 598 RUN(); 599 600 ASSERT_EQUAL_NZCV(NCFlag); 601 ASSERT_EQUAL_32(0xf0000000, r0); 602 603 START(); 604 __ Mov(r0, 0x80000000); 605 __ Mov(r1, 0x00000001); 606 607 __ Ands(r0, r0, Operand(r1, ROR, 1)); 608 END(); 609 610 RUN(); 611 612 ASSERT_EQUAL_NZCV(NCFlag); 613 ASSERT_EQUAL_32(0x80000000, r0); 614 615 START(); 616 __ Mov(r0, 0x80000000); 617 __ Mov(r1, 0x80000001); 618 619 // Clear the C flag, forcing RRX to insert 0 in r1's most significant bit. 620 __ Adds(r2, r0, 0); 621 __ Ands(r2, r0, Operand(r1, RRX)); 622 END(); 623 624 RUN(); 625 626 ASSERT_EQUAL_NZCV(ZCFlag); 627 ASSERT_EQUAL_32(0, r2); 628 629 START(); 630 __ Mov(r0, 0x80000000); 631 __ Mov(r1, 0x80000001); 632 __ Mov(r2, 0xffffffff); 633 634 // Set the C flag, forcing RRX to insert 1 in r1's most significant bit. 635 __ Adds(r2, r2, 1); 636 __ Ands(r2, r0, Operand(r1, RRX)); 637 END(); 638 639 RUN(); 640 641 ASSERT_EQUAL_NZCV(NCFlag); 642 ASSERT_EQUAL_32(0x80000000, r2); 643 644 START(); 645 __ Mov(r0, 0xfff0); 646 647 __ Ands(r0, r0, 0xf); 648 END(); 649 650 RUN(); 651 652 ASSERT_EQUAL_NZCV(ZFlag); 653 ASSERT_EQUAL_32(0x00000000, r0); 654 655 START(); 656 __ Mov(r0, 0xff000000); 657 658 __ Ands(r0, r0, 0x80000000); 659 END(); 660 661 RUN(); 662 663 ASSERT_EQUAL_NZCV(NCFlag); 664 ASSERT_EQUAL_32(0x80000000, r0); 665 666 TEARDOWN(); 667 } 668 669 670 TEST(adr_in_range) { 671 SETUP(); 672 673 Label label_1, label_2, label_3, label_4; 674 675 START(); 676 { 677 size_t size_of_generated_code; 678 if (masm.IsUsingA32()) { 679 size_of_generated_code = 18 * kA32InstructionSizeInBytes; 680 } else { 681 size_of_generated_code = 18 * k32BitT32InstructionSizeInBytes + 682 3 * k16BitT32InstructionSizeInBytes; 683 } 684 ExactAssemblyScope scope(&masm, 685 size_of_generated_code, 686 ExactAssemblyScope::kExactSize); 687 688 __ mov(r0, 0x0); // Set to zero to indicate success. 689 __ adr(r1, &label_3); 690 691 __ adr(r2, &label_1); // Multiple forward references to the same label. 692 __ adr(r3, &label_1); 693 __ adr(r4, &label_1); 694 695 __ bind(&label_2); 696 __ eor(r5, r2, r3); // Ensure that r2, r3 and r4 are identical. 697 __ eor(r6, r2, r4); 698 __ orr(r0, r5, r6); 699 if (masm.IsUsingT32()) { 700 // The jump target needs to have its least significant bit set to indicate 701 // that we are jumping into thumb mode. 702 __ orr(r2, r2, 1); 703 } 704 __ bx(r2); // label_1, label_3 705 706 __ bind(&label_3); 707 __ adr(r2, &label_3); // Self-reference (offset 0). 708 __ eor(r1, r1, r2); 709 __ adr(r2, &label_4); // Simple forward reference. 710 if (masm.IsUsingT32()) { 711 // The jump target needs to have its least significant bit set to indicate 712 // that we are jumping into thumb mode. 713 __ orr(r2, r2, 1); 714 } 715 __ bx(r2); // label_4 716 717 __ bind(&label_1); 718 __ adr(r2, &label_3); // Multiple reverse references to the same label. 719 __ adr(r3, &label_3); 720 __ adr(r4, &label_3); 721 __ adr(r5, &label_2); // Simple reverse reference. 722 if (masm.IsUsingT32()) { 723 // The jump target needs to have its least significant bit set to indicate 724 // that we are jumping into thumb mode. 725 __ orr(r5, r5, 1); 726 } 727 __ bx(r5); // label_2 728 729 __ bind(&label_4); 730 } 731 END(); 732 733 RUN(); 734 735 ASSERT_EQUAL_32(0x0, r0); 736 ASSERT_EQUAL_32(0x0, r1); 737 738 TEARDOWN(); 739 } 740 741 742 TEST(shift_imm) { 743 SETUP(); 744 745 START(); 746 __ Mov(r0, 0); 747 __ Mov(r1, 0xfedcba98); 748 __ Mov(r2, 0xffffffff); 749 750 __ Lsl(r3, r1, 4); 751 __ Lsr(r4, r1, 8); 752 __ Asr(r5, r1, 16); 753 __ Ror(r6, r1, 20); 754 END(); 755 756 RUN(); 757 758 ASSERT_EQUAL_32(0xedcba980, r3); 759 ASSERT_EQUAL_32(0x00fedcba, r4); 760 ASSERT_EQUAL_32(0xfffffedc, r5); 761 ASSERT_EQUAL_32(0xcba98fed, r6); 762 763 TEARDOWN(); 764 } 765 766 767 TEST(shift_reg) { 768 SETUP(); 769 770 START(); 771 __ Mov(r0, 0); 772 __ Mov(r1, 0xfedcba98); 773 __ Mov(r2, 0xffffffff); 774 775 __ Add(r9, r0, 4); 776 __ Lsl(r3, r1, r9); 777 778 __ Add(r9, r0, 8); 779 __ Lsr(r4, r1, r9); 780 781 __ Add(r9, r0, 16); 782 __ Asr(r5, r1, r9); 783 784 __ Add(r9, r0, 20); 785 __ Ror(r6, r1, r9); 786 787 // Set the C flag. 788 __ Adds(r7, r2, 1); 789 __ Rrx(r7, r1); 790 791 // Clear the C flag. 792 __ Adds(r8, r0, 0); 793 __ Rrx(r8, r1); 794 END(); 795 796 RUN(); 797 798 ASSERT_EQUAL_32(0xedcba980, r3); 799 ASSERT_EQUAL_32(0x00fedcba, r4); 800 ASSERT_EQUAL_32(0xfffffedc, r5); 801 ASSERT_EQUAL_32(0xcba98fed, r6); 802 ASSERT_EQUAL_32(0xff6e5d4c, r7); 803 ASSERT_EQUAL_32(0x7f6e5d4c, r8); 804 805 TEARDOWN(); 806 } 807 808 809 TEST(branch_cond) { 810 SETUP(); 811 812 Label done, wrong; 813 814 START(); 815 __ Mov(r0, 0x0); 816 __ Mov(r1, 0x1); 817 __ Mov(r2, 0x80000000); 818 // TODO: Use r0 instead of r3 when r0 becomes available. 819 __ Mov(r3, 0x1); 820 821 // For each 'cmp' instruction below, condition codes other than the ones 822 // following it would branch. 823 824 __ Cmp(r1, 0); 825 __ B(eq, &wrong); 826 __ B(lo, &wrong); 827 __ B(mi, &wrong); 828 __ B(vs, &wrong); 829 __ B(ls, &wrong); 830 __ B(lt, &wrong); 831 __ B(le, &wrong); 832 Label ok_1; 833 __ B(ne, &ok_1); 834 // TODO: Use __ Mov(r0, 0x0) instead. 835 __ Add(r3, r0, 0x0); 836 __ Bind(&ok_1); 837 838 __ Cmp(r1, 1); 839 __ B(ne, &wrong); 840 __ B(lo, &wrong); 841 __ B(mi, &wrong); 842 __ B(vs, &wrong); 843 __ B(hi, &wrong); 844 __ B(lt, &wrong); 845 __ B(gt, &wrong); 846 Label ok_2; 847 __ B(pl, &ok_2); 848 // TODO: Use __ Mov(r0, 0x0) instead. 849 __ Add(r3, r0, 0x0); 850 __ Bind(&ok_2); 851 852 __ Cmp(r1, 2); 853 __ B(eq, &wrong); 854 __ B(hs, &wrong); 855 __ B(pl, &wrong); 856 __ B(vs, &wrong); 857 __ B(hi, &wrong); 858 __ B(ge, &wrong); 859 __ B(gt, &wrong); 860 Label ok_3; 861 __ B(vc, &ok_3); 862 // TODO: Use __ Mov(r0, 0x0) instead. 863 __ Add(r3, r0, 0x0); 864 __ Bind(&ok_3); 865 866 __ Cmp(r2, 1); 867 __ B(eq, &wrong); 868 __ B(lo, &wrong); 869 __ B(mi, &wrong); 870 __ B(vc, &wrong); 871 __ B(ls, &wrong); 872 __ B(ge, &wrong); 873 __ B(gt, &wrong); 874 Label ok_4; 875 __ B(le, &ok_4); 876 // TODO: Use __ Mov(r0, 0x0) instead. 877 __ Add(r3, r0, 0x0); 878 __ Bind(&ok_4); 879 880 Label ok_5; 881 __ B(&ok_5); 882 // TODO: Use __ Mov(r0, 0x0) instead. 883 __ Add(r3, r0, 0x0); 884 __ Bind(&ok_5); 885 886 __ B(&done); 887 888 __ Bind(&wrong); 889 // TODO: Use __ Mov(r0, 0x0) instead. 890 __ Add(r3, r0, 0x0); 891 892 __ Bind(&done); 893 END(); 894 895 RUN(); 896 897 // TODO: Use r0. 898 ASSERT_EQUAL_32(0x1, r3); 899 900 TEARDOWN(); 901 } 902 903 904 TEST(bfc_bfi) { 905 SETUP(); 906 907 START(); 908 __ Mov(r0, 0xffffffff); 909 __ Mov(r1, 0x01234567); 910 __ Mov(r2, 0x0); 911 912 __ Bfc(r0, 0, 3); 913 __ Bfc(r0, 16, 5); 914 915 __ Bfi(r2, r1, 0, 8); 916 __ Bfi(r2, r1, 16, 16); 917 END(); 918 919 RUN(); 920 921 ASSERT_EQUAL_32(0xffe0fff8, r0); 922 ASSERT_EQUAL_32(0x45670067, r2); 923 924 TEARDOWN(); 925 } 926 927 928 TEST(bic) { 929 SETUP(); 930 931 START(); 932 __ Mov(r0, 0xfff0); 933 __ Mov(r1, 0xf00000ff); 934 __ Mov(r2, 0xffffffff); 935 936 __ Bic(r3, r0, r1); 937 __ Bic(r4, r0, Operand(r1, LSL, 4)); 938 __ Bic(r5, r0, Operand(r1, LSR, 1)); 939 __ Bic(r6, r0, Operand(r1, ASR, 20)); 940 __ Bic(r7, r0, Operand(r1, ROR, 28)); 941 __ Bic(r8, r0, 0x1f); 942 943 // Set the C flag. 944 __ Adds(r9, r2, 1); 945 __ Bic(r9, r1, Operand(r1, RRX)); 946 947 // Clear the C flag. 948 __ Adds(r10, r0, 0); 949 __ Bic(r10, r1, Operand(r1, RRX)); 950 END(); 951 952 RUN(); 953 954 ASSERT_EQUAL_32(0x0000ff00, r3); 955 ASSERT_EQUAL_32(0x0000f000, r4); 956 ASSERT_EQUAL_32(0x0000ff80, r5); 957 ASSERT_EQUAL_32(0x000000f0, r6); 958 ASSERT_EQUAL_32(0x0000f000, r7); 959 ASSERT_EQUAL_32(0x0000ffe0, r8); 960 ASSERT_EQUAL_32(0x00000080, r9); 961 ASSERT_EQUAL_32(0x80000080, r10); 962 963 TEARDOWN(); 964 } 965 966 967 TEST(bics) { 968 SETUP(); 969 970 START(); 971 __ Mov(r0, 0); 972 __ Mov(r1, 0xf00000ff); 973 974 __ Bics(r0, r1, r1); 975 END(); 976 977 RUN(); 978 979 ASSERT_EQUAL_NZCV(ZFlag); 980 ASSERT_EQUAL_32(0, r0); 981 982 START(); 983 __ Mov(r0, 0x00fff000); 984 __ Mov(r1, 0x0fffff00); 985 986 __ Bics(r0, r0, Operand(r1, LSL, 4)); 987 END(); 988 989 RUN(); 990 991 ASSERT_EQUAL_NZCV(ZFlag); 992 ASSERT_EQUAL_32(0x00000000, r0); 993 994 START(); 995 __ Mov(r0, 0x0000fff0); 996 __ Mov(r1, 0x0fffff00); 997 998 __ Bics(r0, r0, Operand(r1, LSR, 4)); 999 END(); 1000 1001 RUN(); 1002 1003 ASSERT_EQUAL_NZCV(ZFlag); 1004 ASSERT_EQUAL_32(0x00000000, r0); 1005 1006 START(); 1007 __ Mov(r0, 0xf000fff0); 1008 __ Mov(r1, 0x0fffff00); 1009 1010 __ Bics(r0, r0, Operand(r1, ASR, 4)); 1011 END(); 1012 1013 RUN(); 1014 1015 ASSERT_EQUAL_NZCV(NFlag); 1016 ASSERT_EQUAL_32(0xf0000000, r0); 1017 1018 START(); 1019 __ Mov(r0, 0x80000000); 1020 __ Mov(r1, 0xfffffffe); 1021 1022 __ Bics(r0, r0, Operand(r1, ROR, 1)); 1023 END(); 1024 1025 RUN(); 1026 1027 ASSERT_EQUAL_NZCV(NFlag); 1028 ASSERT_EQUAL_32(0x80000000, r0); 1029 1030 START(); 1031 __ Mov(r0, 0x80000000); 1032 __ Mov(r1, 0x80000001); 1033 1034 // Clear the C flag, forcing RRX to insert 0 in r1's most significant bit. 1035 __ Adds(r2, r0, 0); 1036 __ Bics(r2, r0, Operand(r1, RRX)); 1037 END(); 1038 1039 RUN(); 1040 1041 ASSERT_EQUAL_NZCV(NCFlag); 1042 ASSERT_EQUAL_32(0x80000000, r2); 1043 1044 START(); 1045 __ Mov(r0, 0x80000000); 1046 __ Mov(r1, 0x80000001); 1047 __ Mov(r2, 0xffffffff); 1048 1049 // Set the C flag, forcing RRX to insert 1 in r1's most significant bit. 1050 __ Adds(r2, r2, 1); 1051 __ Bics(r2, r0, Operand(r1, RRX)); 1052 END(); 1053 1054 RUN(); 1055 1056 ASSERT_EQUAL_NZCV(ZCFlag); 1057 ASSERT_EQUAL_32(0, r2); 1058 1059 START(); 1060 __ Mov(r0, 0xf000); 1061 1062 __ Bics(r0, r0, 0xf000); 1063 END(); 1064 1065 RUN(); 1066 1067 ASSERT_EQUAL_NZCV(ZFlag); 1068 ASSERT_EQUAL_32(0x00000000, r0); 1069 1070 START(); 1071 __ Mov(r0, 0xff000000); 1072 1073 __ Bics(r0, r0, 0x7fffffff); 1074 END(); 1075 1076 RUN(); 1077 1078 ASSERT_EQUAL_NZCV(NFlag); 1079 ASSERT_EQUAL_32(0x80000000, r0); 1080 1081 TEARDOWN(); 1082 } 1083 1084 1085 // Make sure calling a macro-assembler instruction will generate literal pools 1086 // if needed. 1087 TEST_T32(veneer_pool_generated_by_macro_instruction) { 1088 SETUP(); 1089 1090 START(); 1091 1092 Label start, end; 1093 1094 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1095 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1096 1097 __ Mov(r0, 1); 1098 1099 __ Bind(&start); 1100 __ Cbz(r0, &end); 1101 1102 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 1103 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1104 1105 // Generate enough code so that, after the loop, no instruction can be 1106 // generated before we need to generate the veneer pool. 1107 // Use `ExactAssemblyScope` and the assembler to generate the code. 1108 int32_t space = masm.GetMarginBeforeVeneerEmission(); 1109 { 1110 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1111 while (space > 0) { 1112 __ nop(); 1113 space -= k16BitT32InstructionSizeInBytes; 1114 } 1115 } 1116 1117 // We should not have emitted the veneer pool at this point. 1118 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 1119 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1120 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() == 0); 1121 1122 // Now the pool will need to be generated before we can emit anything. 1123 Label check; 1124 __ Bind(&check); 1125 __ Mov(r0, 0); 1126 // We should have generated 3 wide instructions: 1127 // b.w past_veneer_pool 1128 // b.w end ;; veneer from CBZ to "end". 1129 // past_veneer_pool: 1130 // mov r0, #0 1131 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) == 1132 (3 * k32BitT32InstructionSizeInBytes)); 1133 1134 // Branch back to make sure the veneers work. 1135 __ B(&start); 1136 __ Bind(&end); 1137 1138 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1139 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1140 1141 END(); 1142 1143 RUN(); 1144 1145 ASSERT_EQUAL_32(0, r0); 1146 1147 TEARDOWN(); 1148 } 1149 1150 1151 TEST(emit_reused_load_literal_rewind) { 1152 // This test generates an Ldrd that needs to be rewinded and loads a literal 1153 // that already is in the pool (hence it will be part of the pool that gets 1154 // emitted as part of the rewind). 1155 SETUP(); 1156 1157 START(); 1158 1159 // Make sure the pool is empty. 1160 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1161 ASSERT_LITERAL_POOL_SIZE(0); 1162 1163 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1164 const int string_size = AlignUp(ldrd_range + kMaxInstructionSizeInBytes, 4); 1165 std::string test_string(string_size, 'x'); 1166 StringLiteral big_literal(test_string.c_str()); 1167 __ Adr(r4, &big_literal); 1168 1169 // This load has a wider range than the Ldrd used below for the same 1170 // literal. 1171 Literal<uint64_t> l1(0xcafebeefdeadbaba); 1172 __ Ldr(r0, &l1); 1173 1174 // This Ldrd will be emitted and then rewinded, forcing the pool to be 1175 // emitted before we regenerate the instruction, so l1 will be bound and the 1176 // literal pool empty afterwards. 1177 __ Ldrd(r2, r3, &l1); 1178 ASSERT_LITERAL_POOL_SIZE(0); 1179 1180 __ Ldr(r4, MemOperand(r4)); // Load the first 4 characters in r4. 1181 END(); 1182 1183 RUN(); 1184 1185 // Check that the literals loaded correctly. 1186 ASSERT_EQUAL_32(0xdeadbaba, r0); 1187 ASSERT_EQUAL_32(0xdeadbaba, r2); 1188 ASSERT_EQUAL_32(0xcafebeef, r3); 1189 ASSERT_EQUAL_32(0x78787878, r4); 1190 1191 TEARDOWN(); 1192 } 1193 1194 1195 TEST(emit_reused_load_literal_should_not_rewind) { 1196 // This test checks that we are not conservative when rewinding a load of a 1197 // literal that is already in the literal pool. 1198 SETUP(); 1199 1200 START(); 1201 1202 // Make sure the pool is empty. 1203 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1204 ASSERT_LITERAL_POOL_SIZE(0); 1205 1206 // This load has a wider range than the Ldrd used below for the same 1207 // literal. 1208 Literal<uint64_t> l1(0xcafebeefdeadbaba); 1209 __ Ldr(r0, &l1); 1210 1211 // Add a large string to the literal pool, but only *after* l1, so the 1212 // Ldrd below should not need to rewind. 1213 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1214 const int string_size = AlignUp(ldrd_range + kMaxInstructionSizeInBytes, 4); 1215 std::string test_string(string_size, 'x'); 1216 StringLiteral big_literal(test_string.c_str()); 1217 __ Adr(r4, &big_literal); 1218 __ Ldrd(r2, r3, &l1); 1219 1220 ASSERT_LITERAL_POOL_SIZE(AlignUp(string_size + 1, 4) + l1.GetSize()); 1221 1222 // Make sure the pool is emitted. 1223 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1224 ASSERT_LITERAL_POOL_SIZE(0); 1225 1226 __ Ldr(r4, MemOperand(r4)); // Load the first 4 characters in r4. 1227 END(); 1228 1229 RUN(); 1230 1231 // Check that the literals loaded correctly. 1232 ASSERT_EQUAL_32(0xdeadbaba, r0); 1233 ASSERT_EQUAL_32(0xdeadbaba, r2); 1234 ASSERT_EQUAL_32(0xcafebeef, r3); 1235 ASSERT_EQUAL_32(0x78787878, r4); 1236 1237 TEARDOWN(); 1238 } 1239 1240 1241 void EmitReusedLoadLiteralStressTest(InstructionSet isa, bool conditional) { 1242 // This test stresses loading a literal that is already in the literal pool, 1243 // for 1244 // various positionings on the existing load from that literal. We try to 1245 // exercise 1246 // cases where the two loads result in similar checkpoints for the literal 1247 // pool. 1248 SETUP(); 1249 1250 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1251 const int ldr_range = 4095; 1252 const int nop_size = masm.IsUsingA32() ? 4 : 2; 1253 const int nops = (ldr_range - ldrd_range) / nop_size; 1254 1255 for (int n = nops - 10; n < nops + 10; ++n) { 1256 START(); 1257 1258 // Make sure the pool is empty. 1259 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1260 ASSERT_LITERAL_POOL_SIZE(0); 1261 1262 if (conditional) { 1263 __ Mov(r1, 0); 1264 __ Cmp(r1, 0); 1265 } 1266 1267 // Add a large string to the pool, which will force the Ldrd below to rewind 1268 // (if the pool is not already emitted due to the Ldr). 1269 const int string_size = AlignUp(ldrd_range + kMaxInstructionSizeInBytes, 4); 1270 std::string test_string(string_size, 'x'); 1271 StringLiteral big_literal(test_string.c_str()); 1272 __ Ldr(r4, &big_literal); 1273 1274 // This load has a wider range than the Ldrd used below for the same 1275 // literal. 1276 Literal<uint64_t> l1(0xcafebeefdeadbaba); 1277 __ Ldr(r0, &l1); 1278 1279 // Generate nops, in order to bring the checkpoints of the Ldr and Ldrd 1280 // closer. 1281 { 1282 ExactAssemblyScope scope(&masm, 1283 n * nop_size, 1284 ExactAssemblyScope::kExactSize); 1285 for (int i = 0; i < n; ++i) { 1286 __ nop(); 1287 } 1288 } 1289 1290 if (conditional) { 1291 __ Ldrd(eq, r2, r3, &l1); 1292 } else { 1293 __ Ldrd(r2, r3, &l1); 1294 } 1295 // At this point, the pool will be emitted either because Ldrd needed to 1296 // rewind, or because Ldr reached its range. 1297 ASSERT_LITERAL_POOL_SIZE(0); 1298 1299 END(); 1300 1301 RUN(); 1302 1303 // Check that the literals loaded correctly. 1304 ASSERT_EQUAL_32(0xdeadbaba, r0); 1305 ASSERT_EQUAL_32(0xdeadbaba, r2); 1306 ASSERT_EQUAL_32(0xcafebeef, r3); 1307 ASSERT_EQUAL_32(0x78787878, r4); 1308 } 1309 1310 TEARDOWN(); 1311 } 1312 1313 1314 TEST(emit_reused_load_literal_stress) { 1315 EmitReusedLoadLiteralStressTest(isa, false /*conditional*/); 1316 } 1317 1318 1319 TEST(emit_reused_conditional_load_literal_stress) { 1320 EmitReusedLoadLiteralStressTest(isa, true /*conditional*/); 1321 } 1322 1323 1324 TEST(test_many_loads_from_same_literal) { 1325 // This test generates multiple loads from the same literal in order to 1326 // test that the delegate recursion limit is appropriate for Ldrd with 1327 // large negative offsets. 1328 SETUP(); 1329 1330 START(); 1331 1332 // Make sure the pool is empty. 1333 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1334 ASSERT_LITERAL_POOL_SIZE(0); 1335 1336 Literal<uint64_t> l0(0xcafebeefdeadbaba); 1337 __ Ldrd(r0, r1, &l0); 1338 for (int i = 0; i < 10000; ++i) { 1339 __ Add(r2, r2, i); 1340 __ Ldrd(r4, r5, &l0); 1341 } 1342 1343 __ Ldrd(r2, r3, &l0); 1344 1345 END(); 1346 1347 RUN(); 1348 1349 // Check that the literals loaded correctly. 1350 ASSERT_EQUAL_32(0xdeadbaba, r0); 1351 ASSERT_EQUAL_32(0xcafebeef, r1); 1352 ASSERT_EQUAL_32(0xdeadbaba, r2); 1353 ASSERT_EQUAL_32(0xcafebeef, r3); 1354 ASSERT_EQUAL_32(0xdeadbaba, r4); 1355 ASSERT_EQUAL_32(0xcafebeef, r5); 1356 1357 TEARDOWN(); 1358 } 1359 1360 1361 // Make sure calling a macro-assembler instruction will generate literal pools 1362 // if needed. 1363 TEST_T32(literal_pool_generated_by_macro_instruction) { 1364 SETUP(); 1365 1366 START(); 1367 1368 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1369 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1370 1371 __ Ldrd(r0, r1, 0x1234567890abcdef); 1372 1373 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1374 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1375 1376 // Generate enough code so that, after the loop, no instruction can be 1377 // generated before we need to generate the literal pool. 1378 // Use `ExactAssemblyScope` and the assembler to generate the code. 1379 int32_t space = masm.GetMarginBeforeLiteralEmission(); 1380 { 1381 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1382 while (space > 0) { 1383 __ nop(); 1384 space -= k16BitT32InstructionSizeInBytes; 1385 } 1386 } 1387 1388 // We should not have emitted the literal pool at this point. 1389 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1390 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1391 VIXL_CHECK(masm.GetMarginBeforeLiteralEmission() == 0); 1392 1393 // Now the pool will need to be generated before we emit anything. 1394 Label check; 1395 __ Bind(&check); 1396 __ Mov(r2, 0x12345678); 1397 // We should have generated 3 wide instructions and 8 bytes of data: 1398 // b.w past_literal_pool 1399 // .bytes 0x1234567890abcdef 1400 // past_literal_pool: 1401 // mov r2, #22136 1402 // movt r2, #4660 1403 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) == 1404 (3 * k32BitT32InstructionSizeInBytes + 8)); 1405 1406 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1407 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1408 1409 END(); 1410 1411 RUN(); 1412 1413 ASSERT_EQUAL_32(0x90abcdef, r0); 1414 ASSERT_EQUAL_32(0x12345678, r1); 1415 ASSERT_EQUAL_32(0x12345678, r2); 1416 1417 TEARDOWN(); 1418 } 1419 1420 1421 TEST(emit_single_literal) { 1422 SETUP(); 1423 1424 START(); 1425 // Make sure the pool is empty. 1426 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1427 ASSERT_LITERAL_POOL_SIZE(0); 1428 1429 // Create one literal pool entry. 1430 __ Ldrd(r0, r1, 0x1234567890abcdef); 1431 ASSERT_LITERAL_POOL_SIZE(8); 1432 __ Vldr(s0, 1.0); 1433 __ Vldr(d1, 2.0); 1434 __ Vmov(d2, 4.1); 1435 __ Vmov(s8, 8.2); 1436 ASSERT_LITERAL_POOL_SIZE(20); 1437 END(); 1438 1439 RUN(); 1440 1441 // Check that the literals loaded correctly. 1442 ASSERT_EQUAL_32(0x90abcdef, r0); 1443 ASSERT_EQUAL_32(0x12345678, r1); 1444 ASSERT_EQUAL_FP32(1.0f, s0); 1445 ASSERT_EQUAL_FP64(2.0, d1); 1446 ASSERT_EQUAL_FP64(4.1, d2); 1447 ASSERT_EQUAL_FP32(8.2f, s8); 1448 1449 TEARDOWN(); 1450 } 1451 1452 1453 #undef __ 1454 #define __ masm-> 1455 1456 1457 void EmitLdrdLiteralTest(MacroAssembler* masm) { 1458 const int ldrd_range = masm->IsUsingA32() ? 255 : 1020; 1459 // We want to emit code up to the maximum literal load range and ensure the 1460 // pool has not been emitted. Compute the limit (end). 1461 ptrdiff_t end = AlignDown( 1462 // Align down the PC to 4 bytes as the instruction does when it's 1463 // executed. 1464 // The PC will be the cursor offset plus the architecture state PC 1465 // offset. 1466 AlignDown(masm->GetBuffer()->GetCursorOffset() + 1467 masm->GetArchitectureStatePCOffset(), 1468 4) + 1469 // Maximum range allowed to access the constant. 1470 ldrd_range - 1471 // The literal pool has a two instruction margin. 1472 2 * kMaxInstructionSizeInBytes, 1473 // AlignDown to 4 byte as the literals will be 4 byte aligned. 1474 4); 1475 1476 // Create one literal pool entry. 1477 __ Ldrd(r0, r1, 0x1234567890abcdef); 1478 ASSERT_LITERAL_POOL_SIZE(8); 1479 1480 int32_t margin = masm->GetMarginBeforeLiteralEmission(); 1481 { 1482 ExactAssemblyScope scope(masm, margin, ExactAssemblyScope::kExactSize); 1483 // Opening the scope should not have triggered the emission of the literal 1484 // pool. 1485 VIXL_CHECK(!masm->LiteralPoolIsEmpty()); 1486 while (masm->GetCursorOffset() < end) { 1487 __ nop(); 1488 } 1489 VIXL_CHECK(masm->GetCursorOffset() == end); 1490 } 1491 1492 // Check that the pool has not been emited along the way. 1493 ASSERT_LITERAL_POOL_SIZE(8); 1494 // This extra instruction should trigger an emit of the pool. 1495 __ Nop(); 1496 // The pool should have been emitted. 1497 ASSERT_LITERAL_POOL_SIZE(0); 1498 } 1499 1500 1501 #undef __ 1502 #define __ masm. 1503 1504 1505 TEST(emit_literal_rewind) { 1506 SETUP(); 1507 1508 START(); 1509 1510 // Make sure the pool is empty. 1511 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1512 ASSERT_LITERAL_POOL_SIZE(0); 1513 1514 EmitLdrdLiteralTest(&masm); 1515 1516 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1517 const int string_size = AlignUp(ldrd_range + kMaxInstructionSizeInBytes, 4); 1518 std::string test_string(string_size, 'x'); 1519 StringLiteral big_literal(test_string.c_str()); 1520 __ Adr(r4, &big_literal); 1521 // This adr will overflow the literal pool and force a rewind. 1522 // That means that the string will be generated then, then Ldrd and the 1523 // Ldrd's value will be alone in the pool. 1524 __ Ldrd(r2, r3, 0xcafebeefdeadbaba); 1525 ASSERT_LITERAL_POOL_SIZE(8); 1526 1527 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1528 ASSERT_LITERAL_POOL_SIZE(0); 1529 __ Ldr(r4, MemOperand(r4)); // Load the first 4 characters in r4. 1530 END(); 1531 1532 RUN(); 1533 1534 // Check that the literals loaded correctly. 1535 ASSERT_EQUAL_32(0x90abcdef, r0); 1536 ASSERT_EQUAL_32(0x12345678, r1); 1537 ASSERT_EQUAL_32(0xdeadbaba, r2); 1538 ASSERT_EQUAL_32(0xcafebeef, r3); 1539 ASSERT_EQUAL_32(0x78787878, r4); 1540 1541 TEARDOWN(); 1542 } 1543 1544 TEST(emit_literal_conditional_rewind) { 1545 SETUP(); 1546 1547 START(); 1548 1549 // This test is almost identical to the test above, but the Ldrd instruction 1550 // is conditional and there is a second conditional Ldrd instruction that will 1551 // not be executed. This is to check that reverting the emission of a load 1552 // literal instruction, rewinding, emitting the literal pool and then emitting 1553 // the instruction again works correctly when the load is conditional. 1554 1555 // Make sure the pool is empty. 1556 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1557 ASSERT_LITERAL_POOL_SIZE(0); 1558 1559 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1560 const int string_size = AlignUp(ldrd_range + kMaxInstructionSizeInBytes, 4); 1561 std::string test_string(string_size, 'x'); 1562 StringLiteral big_literal(test_string.c_str()); 1563 __ Adr(r2, &big_literal); 1564 // This adr will overflow the literal pool and force a rewind. 1565 // That means that the string will be generated then, then Ldrd and the 1566 // Ldrd's value will be alone in the pool. 1567 __ Mov(r0, 0); 1568 __ Mov(r1, 0); 1569 __ Mov(r3, 1); 1570 __ Cmp(r3, 1); 1571 __ Ldrd(eq, r0, r1, 0xcafebeefdeadbaba); 1572 __ Ldrd(ne, r0, r1, 0xdeadcafebeefbaba); 1573 ASSERT_LITERAL_POOL_SIZE(16); 1574 1575 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1576 ASSERT_LITERAL_POOL_SIZE(0); 1577 __ Ldr(r2, MemOperand(r2)); // Load the first 4 characters in r2. 1578 END(); 1579 1580 RUN(); 1581 1582 // Check that the literals loaded correctly. 1583 ASSERT_EQUAL_32(0xdeadbaba, r0); 1584 ASSERT_EQUAL_32(0xcafebeef, r1); 1585 ASSERT_EQUAL_32(0x78787878, r2); 1586 1587 TEARDOWN(); 1588 } 1589 1590 enum LiteralStressTestMode { 1591 kUnconditional, 1592 kConditionalTrue, 1593 kConditionalFalse, 1594 kConditionalBoth 1595 }; 1596 1597 // Test loading a literal when the size of the literal pool is close to the 1598 // maximum range of the load, with varying PC values (and alignment, for T32). 1599 // This test is similar to the tests above, with the difference that we allow 1600 // an extra offset to the string size in order to make sure that various pool 1601 // sizes close to the maximum supported offset will produce code that executes 1602 // correctly. As the Ldrd might or might not be rewinded, we do not assert on 1603 // the size of the literal pool in this test. 1604 void EmitLdrdLiteralStressTest(InstructionSet isa, 1605 bool unaligned, 1606 LiteralStressTestMode test_mode) { 1607 SETUP(); 1608 1609 for (int offset = -10; offset <= 10; ++offset) { 1610 START(); 1611 1612 if (unaligned) { 1613 __ Nop(); 1614 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 1615 } 1616 1617 // Make sure the pool is empty. 1618 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1619 ASSERT_LITERAL_POOL_SIZE(0); 1620 1621 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1622 const int string_size = ldrd_range + offset; 1623 std::string test_string(string_size - 1, 'x'); 1624 StringLiteral big_literal(test_string.c_str()); 1625 __ Adr(r2, &big_literal); 1626 __ Mov(r0, 0); 1627 __ Mov(r1, 0); 1628 switch (test_mode) { 1629 case kUnconditional: 1630 __ Ldrd(r0, r1, 0xcafebeefdeadbaba); 1631 break; 1632 case kConditionalTrue: 1633 __ Mov(r0, 0xffffffff); 1634 __ Mov(r1, r0); 1635 __ Mov(r3, 1); 1636 __ Cmp(r3, 1); 1637 __ Ldrd(eq, r0, r1, 0xcafebeefdeadbaba); 1638 break; 1639 case kConditionalFalse: 1640 __ Mov(r0, 0xdeadbaba); 1641 __ Mov(r1, 0xcafebeef); 1642 __ Mov(r3, 1); 1643 __ Cmp(r3, 1); 1644 __ Ldrd(ne, r0, r1, 0xdeadcafebeefbaba); 1645 break; 1646 case kConditionalBoth: 1647 __ Mov(r3, 1); 1648 __ Cmp(r3, 1); 1649 __ Ldrd(eq, r0, r1, 0xcafebeefdeadbaba); 1650 __ Ldrd(ne, r0, r1, 0xdeadcafebeefbaba); 1651 break; 1652 } 1653 1654 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1655 ASSERT_LITERAL_POOL_SIZE(0); 1656 __ Ldr(r2, MemOperand(r2)); // Load the first 4 characters in r2. 1657 END(); 1658 1659 RUN(); 1660 1661 // Check that the literals loaded correctly. 1662 ASSERT_EQUAL_32(0xdeadbaba, r0); 1663 ASSERT_EQUAL_32(0xcafebeef, r1); 1664 ASSERT_EQUAL_32(0x78787878, r2); 1665 } 1666 1667 TEARDOWN(); 1668 } 1669 1670 1671 TEST(emit_literal_rewind_stress) { 1672 EmitLdrdLiteralStressTest(isa, false /*unaligned*/, kUnconditional); 1673 } 1674 1675 1676 TEST_T32(emit_literal_rewind_stress_unaligned) { 1677 EmitLdrdLiteralStressTest(isa, true /*unaligned*/, kUnconditional); 1678 } 1679 1680 1681 TEST(emit_literal_conditional_rewind_stress) { 1682 EmitLdrdLiteralStressTest(isa, false /*unaligned*/, kConditionalTrue); 1683 EmitLdrdLiteralStressTest(isa, false /*unaligned*/, kConditionalFalse); 1684 EmitLdrdLiteralStressTest(isa, false /*unaligned*/, kConditionalBoth); 1685 } 1686 1687 1688 TEST_T32(emit_literal_conditional_rewind_stress_unaligned) { 1689 EmitLdrdLiteralStressTest(isa, true /*unaligned*/, kConditionalTrue); 1690 EmitLdrdLiteralStressTest(isa, true /*unaligned*/, kConditionalFalse); 1691 EmitLdrdLiteralStressTest(isa, true /*unaligned*/, kConditionalBoth); 1692 } 1693 1694 1695 TEST_T32(emit_literal_unaligned) { 1696 SETUP(); 1697 1698 START(); 1699 1700 // Make sure the pool is empty. 1701 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1702 ASSERT_LITERAL_POOL_SIZE(0); 1703 1704 // Generate a nop to break the 4 bytes alignment. 1705 __ Nop(); 1706 1707 EmitLdrdLiteralTest(&masm); 1708 1709 END(); 1710 1711 RUN(); 1712 1713 // Check that the literals loaded correctly. 1714 ASSERT_EQUAL_32(0x90abcdef, r0); 1715 ASSERT_EQUAL_32(0x12345678, r1); 1716 1717 TEARDOWN(); 1718 } 1719 1720 1721 TEST(literal_multiple_uses) { 1722 SETUP(); 1723 1724 START(); 1725 Literal<int32_t> lit(42); 1726 __ Ldr(r0, &lit); 1727 ASSERT_LITERAL_POOL_SIZE(4); 1728 1729 // Multiple uses of the same literal object should not make the 1730 // pool grow. 1731 __ Ldrb(r1, &lit); 1732 __ Ldrsb(r2, &lit); 1733 __ Ldrh(r3, &lit); 1734 __ Ldrsh(r4, &lit); 1735 ASSERT_LITERAL_POOL_SIZE(4); 1736 1737 END(); 1738 1739 RUN(); 1740 1741 ASSERT_EQUAL_32(42, r0); 1742 ASSERT_EQUAL_32(42, r1); 1743 ASSERT_EQUAL_32(42, r2); 1744 ASSERT_EQUAL_32(42, r3); 1745 ASSERT_EQUAL_32(42, r4); 1746 1747 TEARDOWN(); 1748 } 1749 1750 1751 // A test with two loads literal which go out of range at the same time. 1752 TEST_A32(ldr_literal_range_same_time) { 1753 SETUP(); 1754 1755 START(); 1756 const int ldrd_range = 255; 1757 // We need to take into account the jump over the pool. 1758 const int ldrd_padding = ldrd_range - 2 * kA32InstructionSizeInBytes; 1759 const int ldr_range = 4095; 1760 // We need to take into account the ldrd padding and the ldrd instruction. 1761 const int ldr_padding = 1762 ldr_range - ldrd_padding - 2 * kA32InstructionSizeInBytes; 1763 1764 __ Ldr(r1, 0x12121212); 1765 ASSERT_LITERAL_POOL_SIZE(4); 1766 1767 { 1768 int space = AlignDown(ldr_padding, kA32InstructionSizeInBytes); 1769 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1770 int32_t end = masm.GetCursorOffset() + space; 1771 while (masm.GetCursorOffset() < end) { 1772 __ nop(); 1773 } 1774 } 1775 1776 __ Ldrd(r2, r3, 0x1234567890abcdef); 1777 ASSERT_LITERAL_POOL_SIZE(12); 1778 1779 { 1780 int space = AlignDown(ldrd_padding, kA32InstructionSizeInBytes); 1781 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1782 for (int32_t end = masm.GetCursorOffset() + space; 1783 masm.GetCursorOffset() < end;) { 1784 __ nop(); 1785 } 1786 } 1787 ASSERT_LITERAL_POOL_SIZE(12); 1788 1789 // This mov will put the two loads literal out of range and will force 1790 // the literal pool emission. 1791 __ Mov(r0, 0); 1792 ASSERT_LITERAL_POOL_SIZE(0); 1793 END(); 1794 1795 RUN(); 1796 1797 ASSERT_EQUAL_32(0x12121212, r1); 1798 ASSERT_EQUAL_32(0x90abcdef, r2); 1799 ASSERT_EQUAL_32(0x12345678, r3); 1800 1801 TEARDOWN(); 1802 } 1803 1804 1805 TEST(ldr_literal_mix_types) { 1806 SETUP(); 1807 1808 START(); 1809 Literal<uint64_t> l0(0x1234567890abcdef); 1810 Literal<int32_t> l1(0x12345678); 1811 Literal<uint16_t> l2(1234); 1812 Literal<int16_t> l3(-678); 1813 Literal<uint8_t> l4(42); 1814 Literal<int8_t> l5(-12); 1815 1816 __ Ldrd(r0, r1, &l0); 1817 __ Ldr(r2, &l1); 1818 __ Ldrh(r3, &l2); 1819 __ Ldrsh(r4, &l3); 1820 __ Ldrb(r5, &l4); 1821 __ Ldrsb(r6, &l5); 1822 ASSERT_LITERAL_POOL_SIZE(28); 1823 1824 END(); 1825 1826 RUN(); 1827 1828 ASSERT_EQUAL_32(0x90abcdef, r0); 1829 ASSERT_EQUAL_32(0x12345678, r1); 1830 ASSERT_EQUAL_32(0x12345678, r2); 1831 ASSERT_EQUAL_32(1234, r3); 1832 ASSERT_EQUAL_32(-678, r4); 1833 ASSERT_EQUAL_32(42, r5); 1834 ASSERT_EQUAL_32(-12, r6); 1835 1836 TEARDOWN(); 1837 } 1838 1839 1840 TEST(ldr_literal_conditional) { 1841 SETUP(); 1842 1843 START(); 1844 Literal<uint64_t> l0(0x1234567890abcdef); 1845 Literal<uint64_t> l0_not_taken(0x90abcdef12345678); 1846 Literal<int32_t> l1(0x12345678); 1847 Literal<int32_t> l1_not_taken(0x56781234); 1848 Literal<uint16_t> l2(1234); 1849 Literal<uint16_t> l2_not_taken(3412); 1850 Literal<int16_t> l3(-678); 1851 Literal<int16_t> l3_not_taken(678); 1852 Literal<uint8_t> l4(42); 1853 Literal<uint8_t> l4_not_taken(-42); 1854 Literal<int8_t> l5(-12); 1855 Literal<int8_t> l5_not_taken(12); 1856 Literal<float> l6(1.2345f); 1857 Literal<float> l6_not_taken(0.0f); 1858 Literal<double> l7(1.3333); 1859 Literal<double> l7_not_taken(0.0); 1860 1861 // Check that conditionally loading literals of different types works 1862 // correctly for both A32 and T32. 1863 __ Mov(r7, 1); 1864 __ Cmp(r7, 1); 1865 __ Ldrd(eq, r0, r1, &l0); 1866 __ Ldrd(ne, r0, r1, &l0_not_taken); 1867 __ Cmp(r7, 0); 1868 __ Ldr(gt, r2, &l1); 1869 __ Ldr(le, r2, &l1_not_taken); 1870 __ Cmp(r7, 2); 1871 __ Ldrh(lt, r3, &l2); 1872 __ Ldrh(ge, r3, &l2_not_taken); 1873 __ Ldrsh(le, r4, &l3); 1874 __ Ldrsh(gt, r4, &l3_not_taken); 1875 __ Cmp(r7, 1); 1876 __ Ldrb(ge, r5, &l4); 1877 __ Ldrb(lt, r5, &l4_not_taken); 1878 __ Ldrsb(eq, r6, &l5); 1879 __ Ldrsb(ne, r6, &l5_not_taken); 1880 __ Vldr(Condition(eq), s0, &l6); 1881 __ Vldr(Condition(ne), s0, &l6_not_taken); 1882 __ Vldr(Condition(eq), d1, &l7); 1883 __ Vldr(Condition(ne), d1, &l7_not_taken); 1884 1885 END(); 1886 1887 RUN(); 1888 1889 ASSERT_EQUAL_32(0x90abcdef, r0); 1890 ASSERT_EQUAL_32(0x12345678, r1); 1891 ASSERT_EQUAL_32(0x12345678, r2); 1892 ASSERT_EQUAL_32(1234, r3); 1893 ASSERT_EQUAL_32(-678, r4); 1894 ASSERT_EQUAL_32(42, r5); 1895 ASSERT_EQUAL_32(-12, r6); 1896 ASSERT_EQUAL_FP32(1.2345f, s0); 1897 ASSERT_EQUAL_FP64(1.3333, d1); 1898 1899 TEARDOWN(); 1900 } 1901 1902 1903 struct LdrLiteralRangeTest { 1904 void (MacroAssembler::*instruction)(Register, RawLiteral*); 1905 Register result_reg; 1906 int a32_range; 1907 int t32_range; 1908 uint32_t literal_value; 1909 uint32_t test_value; 1910 }; 1911 1912 1913 const LdrLiteralRangeTest kLdrLiteralRangeTestData[] = 1914 {{&MacroAssembler::Ldr, r1, 4095, 4095, 0x12345678, 0x12345678}, 1915 {&MacroAssembler::Ldrh, r2, 255, 4095, 0xabcdefff, 0x0000efff}, 1916 {&MacroAssembler::Ldrsh, r3, 255, 4095, 0x00008765, 0xffff8765}, 1917 {&MacroAssembler::Ldrb, r4, 4095, 4095, 0x12345678, 0x00000078}, 1918 {&MacroAssembler::Ldrsb, r5, 255, 4095, 0x00000087, 0xffffff87}}; 1919 1920 1921 void GenerateLdrLiteralTriggerPoolEmission(InstructionSet isa, 1922 bool unaligned_ldr) { 1923 SETUP(); 1924 1925 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 1926 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 1927 1928 START(); 1929 1930 if (unaligned_ldr) { 1931 // Generate a nop to break the 4-byte alignment. 1932 __ Nop(); 1933 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 1934 } 1935 1936 __ Ldr(r6, 0x12345678); 1937 ASSERT_LITERAL_POOL_SIZE(4); 1938 1939 // TODO: The MacroAssembler currently checks for more space than required 1940 // when emitting macro instructions, triggering emission of the pool before 1941 // absolutely required. For now we keep a buffer. Fix this test when the 1942 // MacroAssembler becomes precise again. 1943 int masm_check_margin = 10 * kMaxInstructionSizeInBytes; 1944 size_t expected_pool_size = 4; 1945 while ((masm.GetMarginBeforeLiteralEmission() - masm_check_margin) >= 1946 static_cast<int32_t>(kMaxInstructionSizeInBytes)) { 1947 __ Ldr(r7, 0x90abcdef); 1948 // Each ldr instruction will force a new literal value to be added 1949 // to the pool. Check that the literal pool grows accordingly. 1950 expected_pool_size += 4; 1951 ASSERT_LITERAL_POOL_SIZE(expected_pool_size); 1952 } 1953 1954 int space = masm.GetMarginBeforeLiteralEmission(); 1955 int end = masm.GetCursorOffset() + space; 1956 { 1957 // Generate nops precisely to fill the buffer. 1958 ExactAssemblyScope accurate_scope(&masm, space); // This should not 1959 // trigger emission of 1960 // the pool. 1961 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1962 while (masm.GetCursorOffset() < end) { 1963 __ nop(); 1964 } 1965 } 1966 1967 // This ldr will force the literal pool to be emitted before emitting 1968 // the load and will create a new pool for the new literal used by this ldr. 1969 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1970 Literal<uint32_t> literal(test.literal_value); 1971 (masm.*test.instruction)(test.result_reg, &literal); 1972 ASSERT_LITERAL_POOL_SIZE(4); 1973 1974 END(); 1975 1976 RUN(); 1977 1978 ASSERT_EQUAL_32(0x12345678, r6); 1979 ASSERT_EQUAL_32(0x90abcdef, r7); 1980 ASSERT_EQUAL_32(test.test_value, test.result_reg); 1981 } 1982 1983 TEARDOWN(); 1984 } 1985 1986 1987 TEST(ldr_literal_trigger_pool_emission) { 1988 GenerateLdrLiteralTriggerPoolEmission(isa, false); 1989 } 1990 1991 1992 TEST_T32(ldr_literal_trigger_pool_emission_unaligned) { 1993 GenerateLdrLiteralTriggerPoolEmission(isa, true); 1994 } 1995 1996 1997 void GenerateLdrLiteralRangeTest(InstructionSet isa, bool unaligned_ldr) { 1998 SETUP(); 1999 2000 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 2001 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 2002 2003 START(); 2004 2005 // Make sure the pool is empty. 2006 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2007 ASSERT_LITERAL_POOL_SIZE(0); 2008 2009 if (unaligned_ldr) { 2010 // Generate a nop to break the 4-byte alignment. 2011 __ Nop(); 2012 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 2013 } 2014 2015 Literal<uint32_t> literal(test.literal_value); 2016 (masm.*test.instruction)(test.result_reg, &literal); 2017 ASSERT_LITERAL_POOL_SIZE(4); 2018 2019 // Generate enough instruction so that we go out of range for the load 2020 // literal we just emitted. 2021 ptrdiff_t end = masm.GetBuffer()->GetCursorOffset() + 2022 ((masm.IsUsingA32()) ? test.a32_range : test.t32_range); 2023 while (masm.GetBuffer()->GetCursorOffset() < end) { 2024 __ Mov(r0, 0); 2025 } 2026 2027 // The literal pool should have been emitted now. 2028 VIXL_CHECK(literal.IsBound()); 2029 ASSERT_LITERAL_POOL_SIZE(0); 2030 2031 END(); 2032 2033 RUN(); 2034 2035 ASSERT_EQUAL_32(test.test_value, test.result_reg); 2036 } 2037 2038 TEARDOWN(); 2039 } 2040 2041 2042 TEST(ldr_literal_range) { GenerateLdrLiteralRangeTest(isa, false); } 2043 2044 2045 TEST_T32(ldr_literal_range_unaligned) { 2046 GenerateLdrLiteralRangeTest(isa, true); 2047 } 2048 2049 2050 TEST(string_literal) { 2051 SETUP(); 2052 2053 START(); 2054 // Make sure the pool is empty. 2055 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2056 ASSERT_LITERAL_POOL_SIZE(0); 2057 2058 StringLiteral hello_string("hello"); 2059 2060 __ Ldrb(r1, &hello_string); 2061 2062 __ Adr(r0, &hello_string); 2063 __ Ldrb(r2, MemOperand(r0)); 2064 END(); 2065 2066 RUN(); 2067 2068 ASSERT_EQUAL_32('h', r1); 2069 ASSERT_EQUAL_32('h', r2); 2070 2071 TEARDOWN(); 2072 } 2073 2074 2075 TEST(custom_literal_in_pool) { 2076 SETUP(); 2077 2078 START(); 2079 // Make sure the pool is empty. 2080 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2081 ASSERT_LITERAL_POOL_SIZE(0); 2082 2083 Literal<uint32_t> l0(static_cast<uint32_t>(0x12345678)); 2084 __ Ldr(r0, &l0); 2085 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2086 __ Ldr(r1, &l0); 2087 ASSERT_LITERAL_POOL_SIZE(0); 2088 2089 Literal<uint64_t> cafebeefdeadbaba(0xcafebeefdeadbaba); 2090 __ Ldrd(r8, r9, &cafebeefdeadbaba); 2091 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2092 __ Ldrd(r2, r3, &cafebeefdeadbaba); 2093 ASSERT_LITERAL_POOL_SIZE(0); 2094 2095 Literal<uint32_t> l1(0x09abcdef); 2096 __ Adr(r4, &l1); 2097 __ Ldr(r4, MemOperand(r4)); 2098 masm.EmitLiteralPool(); 2099 __ Adr(r5, &l1); 2100 __ Ldr(r5, MemOperand(r5)); 2101 ASSERT_LITERAL_POOL_SIZE(0); 2102 2103 END(); 2104 2105 RUN(); 2106 2107 // Check that the literals loaded correctly. 2108 ASSERT_EQUAL_32(0x12345678, r0); 2109 ASSERT_EQUAL_32(0x12345678, r1); 2110 ASSERT_EQUAL_32(0xdeadbaba, r2); 2111 ASSERT_EQUAL_32(0xcafebeef, r3); 2112 ASSERT_EQUAL_32(0xdeadbaba, r8); 2113 ASSERT_EQUAL_32(0xcafebeef, r9); 2114 ASSERT_EQUAL_32(0x09abcdef, r4); 2115 ASSERT_EQUAL_32(0x09abcdef, r5); 2116 } 2117 2118 2119 TEST(custom_literal_place) { 2120 SETUP(); 2121 2122 START(); 2123 // Make sure the pool is empty. 2124 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2125 ASSERT_LITERAL_POOL_SIZE(0); 2126 2127 Literal<uint64_t> l0(0xcafebeefdeadbaba, RawLiteral::kManuallyPlaced); 2128 Literal<int32_t> l1(0x12345678, RawLiteral::kManuallyPlaced); 2129 Literal<uint16_t> l2(4567, RawLiteral::kManuallyPlaced); 2130 Literal<int16_t> l3(-4567, RawLiteral::kManuallyPlaced); 2131 Literal<uint8_t> l4(123, RawLiteral::kManuallyPlaced); 2132 Literal<int8_t> l5(-123, RawLiteral::kManuallyPlaced); 2133 2134 __ Ldrd(r0, r1, &l0); 2135 __ Ldr(r2, &l1); 2136 __ Ldrh(r3, &l2); 2137 __ Ldrsh(r4, &l3); 2138 __ Ldrb(r5, &l4); 2139 __ Ldrsb(r6, &l5); 2140 2141 ASSERT_LITERAL_POOL_SIZE(0); 2142 2143 // Manually generate a literal pool. 2144 Label after_pool; 2145 __ B(&after_pool); 2146 __ Place(&l0); 2147 __ Place(&l1); 2148 __ Place(&l2); 2149 __ Place(&l3); 2150 __ Place(&l4); 2151 __ Place(&l5); 2152 __ Bind(&after_pool); 2153 2154 { 2155 UseScratchRegisterScope temps(&masm); 2156 Register temp = temps.Acquire(); 2157 VIXL_CHECK(temp.Is(r12)); 2158 2159 __ Ldrd(r8, r9, &l0); 2160 __ Ldr(r7, &l1); 2161 __ Ldrh(r10, &l2); 2162 __ Ldrsh(r11, &l3); 2163 __ Ldrb(temp, &l4); 2164 // We don't use any function call so we can use lr as an extra register. 2165 __ Ldrsb(lr, &l5); 2166 } 2167 2168 ASSERT_LITERAL_POOL_SIZE(0); 2169 2170 END(); 2171 2172 RUN(); 2173 2174 // Check that the literals loaded correctly. 2175 ASSERT_EQUAL_32(0xdeadbaba, r0); 2176 ASSERT_EQUAL_32(0xcafebeef, r1); 2177 ASSERT_EQUAL_32(0x12345678, r2); 2178 ASSERT_EQUAL_32(4567, r3); 2179 ASSERT_EQUAL_32(-4567, r4); 2180 ASSERT_EQUAL_32(123, r5); 2181 ASSERT_EQUAL_32(-123, r6); 2182 2183 ASSERT_EQUAL_32(0xdeadbaba, r8); 2184 ASSERT_EQUAL_32(0xcafebeef, r9); 2185 ASSERT_EQUAL_32(0x12345678, r7); 2186 ASSERT_EQUAL_32(4567, r10); 2187 ASSERT_EQUAL_32(-4567, r11); 2188 ASSERT_EQUAL_32(123, r12); 2189 ASSERT_EQUAL_32(-123, lr); 2190 2191 TEARDOWN(); 2192 } 2193 2194 2195 TEST(custom_literal_place_shared) { 2196 SETUP(); 2197 2198 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 2199 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 2200 2201 START(); 2202 2203 // Make sure the pool is empty. 2204 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2205 ASSERT_LITERAL_POOL_SIZE(0); 2206 2207 Literal<uint32_t> before(test.literal_value, RawLiteral::kManuallyPlaced); 2208 Literal<uint32_t> after(test.literal_value, RawLiteral::kManuallyPlaced); 2209 2210 VIXL_CHECK(!before.IsBound()); 2211 VIXL_CHECK(!after.IsBound()); 2212 2213 // Manually generate a pool. 2214 Label end_of_pool_before; 2215 __ B(&end_of_pool_before); 2216 __ Place(&before); 2217 __ Bind(&end_of_pool_before); 2218 2219 ASSERT_LITERAL_POOL_SIZE(0); 2220 VIXL_CHECK(before.IsBound()); 2221 VIXL_CHECK(!after.IsBound()); 2222 2223 // Load the entries several times to test that literals can be shared. 2224 for (int i = 0; i < 20; i++) { 2225 (masm.*test.instruction)(r0, &before); 2226 (masm.*test.instruction)(r1, &after); 2227 } 2228 2229 ASSERT_LITERAL_POOL_SIZE(0); 2230 VIXL_CHECK(before.IsBound()); 2231 VIXL_CHECK(!after.IsBound()); 2232 2233 // Manually generate a pool. 2234 Label end_of_pool_after; 2235 __ B(&end_of_pool_after); 2236 __ Place(&after); 2237 __ Bind(&end_of_pool_after); 2238 2239 ASSERT_LITERAL_POOL_SIZE(0); 2240 VIXL_CHECK(before.IsBound()); 2241 VIXL_CHECK(after.IsBound()); 2242 2243 END(); 2244 2245 RUN(); 2246 2247 ASSERT_EQUAL_32(test.test_value, r0); 2248 ASSERT_EQUAL_32(test.test_value, r1); 2249 } 2250 2251 TEARDOWN(); 2252 } 2253 2254 2255 TEST(custom_literal_place_range) { 2256 SETUP(); 2257 2258 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 2259 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 2260 const int nop_size = masm.IsUsingA32() ? kA32InstructionSizeInBytes 2261 : k16BitT32InstructionSizeInBytes; 2262 const int range = masm.IsUsingA32() ? test.a32_range : test.t32_range; 2263 // On T32 the PC will be 4-byte aligned to compute the range. The 2264 // MacroAssembler might also need to align the code buffer before emitting 2265 // the literal when placing it. We keep a margin to account for this. 2266 const int margin = masm.IsUsingT32() ? 4 : 0; 2267 2268 // Take PC offset into account and make sure the literal is in the range. 2269 const int padding_before = 2270 range - masm.GetArchitectureStatePCOffset() - sizeof(uint32_t) - margin; 2271 2272 // The margin computation below is correct because the ranges are not 2273 // 4-byte aligned. Otherwise this test would insert the exact number of 2274 // instructions to cover the range and the literal would end up being 2275 // placed outside the range. 2276 VIXL_ASSERT((range % 4) != 0); 2277 2278 // The range is extended by the PC offset but we need to consider the ldr 2279 // instruction itself and the branch over the pool. 2280 const int padding_after = range + masm.GetArchitectureStatePCOffset() - 2281 (2 * kMaxInstructionSizeInBytes) - margin; 2282 START(); 2283 2284 Literal<uint32_t> before(test.literal_value, RawLiteral::kManuallyPlaced); 2285 Literal<uint32_t> after(test.literal_value, RawLiteral::kManuallyPlaced); 2286 2287 Label test_start; 2288 __ B(&test_start); 2289 __ Place(&before); 2290 2291 { 2292 int space = AlignDown(padding_before, nop_size); 2293 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 2294 for (int32_t end = masm.GetCursorOffset() + space; 2295 masm.GetCursorOffset() < end;) { 2296 __ nop(); 2297 } 2298 } 2299 2300 __ Bind(&test_start); 2301 (masm.*test.instruction)(r0, &before); 2302 (masm.*test.instruction)(r1, &after); 2303 2304 { 2305 int space = AlignDown(padding_after, nop_size); 2306 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 2307 for (int32_t end = masm.GetCursorOffset() + space; 2308 masm.GetCursorOffset() < end;) { 2309 __ nop(); 2310 } 2311 } 2312 2313 Label after_pool; 2314 __ B(&after_pool); 2315 __ Place(&after); 2316 __ Bind(&after_pool); 2317 2318 END(); 2319 2320 RUN(); 2321 2322 ASSERT_EQUAL_32(test.test_value, r0); 2323 ASSERT_EQUAL_32(test.test_value, r1); 2324 } 2325 2326 TEARDOWN(); 2327 } 2328 2329 2330 TEST(emit_big_pool) { 2331 SETUP(); 2332 2333 START(); 2334 // Make sure the pool is empty. 2335 ASSERT_LITERAL_POOL_SIZE(0); 2336 2337 Label start; 2338 __ Bind(&start); 2339 for (int i = 1000; i > 0; --i) { 2340 __ Ldr(r0, i); 2341 } 2342 2343 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&start) == 4000); 2344 2345 ASSERT_LITERAL_POOL_SIZE(4000); 2346 END(); 2347 2348 RUN(); 2349 2350 // Check that the literals loaded correctly. 2351 ASSERT_EQUAL_32(1, r0); 2352 2353 TEARDOWN(); 2354 } 2355 2356 2357 TEST_T32(too_far_cbz) { 2358 SETUP(); 2359 2360 START(); 2361 Label start; 2362 Label end; 2363 Label exit; 2364 __ Mov(r0, 0); 2365 __ B(&start); 2366 __ Bind(&end); 2367 __ Mov(r0, 1); 2368 __ B(&exit); 2369 __ Bind(&start); 2370 // Cbz is only defined for forward jump. Check that it will work (substituted 2371 // by Cbnz/B). 2372 __ Cbz(r0, &end); 2373 __ Bind(&exit); 2374 END(); 2375 2376 RUN(); 2377 2378 ASSERT_EQUAL_32(1, r0); 2379 } 2380 2381 2382 TEST_T32(close_cbz) { 2383 SETUP(); 2384 2385 START(); 2386 Label first; 2387 Label second; 2388 __ Mov(r0, 0); 2389 __ Mov(r1, 0); 2390 __ Mov(r2, 0); 2391 __ Cbz(r0, &first); 2392 __ Bind(&first); 2393 __ Mov(r1, 1); 2394 __ Cbnz(r0, &second); 2395 __ Bind(&second); 2396 __ Mov(r2, 2); 2397 END(); 2398 2399 RUN(); 2400 2401 ASSERT_EQUAL_32(0, r0); 2402 ASSERT_EQUAL_32(1, r1); 2403 ASSERT_EQUAL_32(2, r2); 2404 } 2405 2406 2407 TEST_T32(close_cbz2) { 2408 SETUP(); 2409 2410 START(); 2411 Label first; 2412 Label second; 2413 __ Mov(r0, 0); 2414 __ Mov(r1, 0); 2415 __ Mov(r2, 0); 2416 __ Cmp(r0, 0); 2417 __ B(ne, &first); 2418 __ B(gt, &second); 2419 __ Cbz(r0, &first); 2420 __ Bind(&first); 2421 __ Mov(r1, 1); 2422 __ Cbnz(r0, &second); 2423 __ Bind(&second); 2424 __ Mov(r2, 2); 2425 END(); 2426 2427 RUN(); 2428 2429 ASSERT_EQUAL_32(0, r0); 2430 ASSERT_EQUAL_32(1, r1); 2431 ASSERT_EQUAL_32(2, r2); 2432 } 2433 2434 2435 TEST_T32(not_close_cbz) { 2436 SETUP(); 2437 2438 START(); 2439 Label first; 2440 Label second; 2441 __ Cbz(r0, &first); 2442 __ B(ne, &first); 2443 __ Bind(&first); 2444 __ Cbnz(r0, &second); 2445 __ B(gt, &second); 2446 __ Bind(&second); 2447 END(); 2448 2449 RUN(); 2450 } 2451 2452 2453 TEST_T32(veneers) { 2454 SETUP(); 2455 2456 START(); 2457 Label zero; 2458 Label exit; 2459 __ Mov(r0, 0); 2460 // Create one literal pool entry. 2461 __ Ldr(r1, 0x12345678); 2462 ASSERT_LITERAL_POOL_SIZE(4); 2463 __ Cbz(r0, &zero); 2464 __ Mov(r0, 1); 2465 __ B(&exit); 2466 for (int i = 32; i > 0; i--) { 2467 __ Mov(r1, 0); 2468 } 2469 // Assert that the literal pool has been generated with the veneers. 2470 ASSERT_LITERAL_POOL_SIZE(0); 2471 __ Bind(&zero); 2472 __ Mov(r0, 2); 2473 __ Bind(&exit); 2474 END(); 2475 2476 RUN(); 2477 2478 ASSERT_EQUAL_32(2, r0); 2479 ASSERT_EQUAL_32(0x12345678, r1); 2480 } 2481 2482 2483 // This test checks that veneers are sorted. If not, the test failed as the 2484 // veneer for "exit" is emitted before the veneer for "zero" and the "zero" 2485 // veneer is out of range for Cbz. 2486 TEST_T32(veneers_labels_sort) { 2487 SETUP(); 2488 2489 START(); 2490 Label start; 2491 Label zero; 2492 Label exit; 2493 __ Movs(r0, 0); 2494 __ B(ne, &exit); 2495 __ B(&start); 2496 for (int i = 1048400; i > 0; i -= 4) { 2497 __ Mov(r1, 0); 2498 } 2499 __ Bind(&start); 2500 __ Cbz(r0, &zero); 2501 __ Mov(r0, 1); 2502 __ B(&exit); 2503 for (int i = 32; i > 0; i--) { 2504 __ Mov(r1, 0); 2505 } 2506 __ Bind(&zero); 2507 __ Mov(r0, 2); 2508 __ Bind(&exit); 2509 END(); 2510 2511 RUN(); 2512 2513 ASSERT_EQUAL_32(2, r0); 2514 } 2515 2516 // Check that a label bound within the assembler is effectively removed from 2517 // the veneer pool. 2518 TEST_T32(veneer_bind) { 2519 SETUP(); 2520 Label target; 2521 __ Cbz(r0, &target); 2522 __ Nop(); 2523 2524 { 2525 // Bind the target label using the `Assembler`. 2526 ExactAssemblyScope scope(&masm, 2527 kMaxInstructionSizeInBytes, 2528 ExactAssemblyScope::kMaximumSize); 2529 __ bind(&target); 2530 __ nop(); 2531 } 2532 2533 VIXL_CHECK(target.IsBound()); 2534 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 2535 2536 END(); 2537 } 2538 2539 2540 // Check that the veneer pool is correctly emitted even if we do enough narrow 2541 // branches before a cbz so that the cbz needs its veneer emitted first in the 2542 // pool in order to work. 2543 TEST_T32(b_narrow_and_cbz_sort) { 2544 SETUP(); 2545 START(); 2546 2547 const int kLabelsCount = 40; 2548 const int kNops = 30; 2549 Label b_labels[kLabelsCount]; 2550 Label cbz_label; 2551 2552 __ Nop(); 2553 2554 __ Mov(r0, 0); 2555 __ Cmp(r0, 0); 2556 2557 for (int i = 0; i < kLabelsCount; ++i) { 2558 __ B(ne, &b_labels[i], kNear); 2559 } 2560 2561 { 2562 ExactAssemblyScope scope(&masm, 2563 k16BitT32InstructionSizeInBytes * kNops, 2564 ExactAssemblyScope::kExactSize); 2565 for (int i = 0; i < kNops; i++) { 2566 __ nop(); 2567 } 2568 } 2569 2570 // The pool should not be emitted here. 2571 __ Cbz(r0, &cbz_label); 2572 2573 // Force pool emission. If the labels are not sorted, the cbz will be out 2574 // of range. 2575 int32_t margin = masm.GetMarginBeforeVeneerEmission(); 2576 int32_t end = masm.GetCursorOffset() + margin; 2577 2578 { 2579 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize); 2580 while (masm.GetCursorOffset() < end) { 2581 __ nop(); 2582 } 2583 } 2584 2585 __ Mov(r0, 1); 2586 2587 for (int i = 0; i < kLabelsCount; ++i) { 2588 __ Bind(&b_labels[i]); 2589 } 2590 2591 __ Bind(&cbz_label); 2592 2593 END(); 2594 2595 RUN(); 2596 2597 ASSERT_EQUAL_32(0, r0); 2598 2599 TEARDOWN(); 2600 } 2601 2602 2603 TEST_T32(b_narrow_and_cbz_sort_2) { 2604 SETUP(); 2605 START(); 2606 2607 const int kLabelsCount = 40; 2608 const int kNops = 30; 2609 Label b_labels[kLabelsCount]; 2610 Label cbz_label; 2611 2612 __ Mov(r0, 0); 2613 __ Cmp(r0, 0); 2614 2615 for (int i = 0; i < kLabelsCount; ++i) { 2616 __ B(ne, &b_labels[i], kNear); 2617 } 2618 2619 { 2620 ExactAssemblyScope scope(&masm, 2621 k16BitT32InstructionSizeInBytes * kNops, 2622 ExactAssemblyScope::kExactSize); 2623 for (int i = 0; i < kNops; i++) { 2624 __ nop(); 2625 } 2626 } 2627 2628 // The pool should not be emitted here. 2629 __ Cbz(r0, &cbz_label); 2630 2631 // Force pool emission. If the labels are not sorted, the cbz will be out 2632 // of range. 2633 int32_t margin = masm.GetMarginBeforeVeneerEmission(); 2634 int32_t end = masm.GetCursorOffset() + margin; 2635 2636 while (masm.GetCursorOffset() < end) __ Nop(); 2637 2638 __ Mov(r0, 1); 2639 2640 for (int i = 0; i < kLabelsCount; ++i) { 2641 __ Bind(&b_labels[i]); 2642 } 2643 2644 __ Bind(&cbz_label); 2645 2646 END(); 2647 2648 RUN(); 2649 2650 ASSERT_EQUAL_32(0, r0); 2651 2652 TEARDOWN(); 2653 } 2654 2655 2656 TEST_T32(long_branch) { 2657 SETUP(); 2658 START(); 2659 2660 for (int label_count = 128; label_count < 2048; label_count *= 2) { 2661 Label* l = new Label[label_count]; 2662 2663 for (int i = 0; i < label_count; i++) { 2664 __ B(&l[i]); 2665 } 2666 2667 for (int i = 0; i < label_count; i++) { 2668 __ B(ne, &l[i]); 2669 } 2670 2671 for (int i = 0; i < 261625; i++) { 2672 __ Clz(r0, r0); 2673 } 2674 2675 for (int i = label_count - 1; i >= 0; i--) { 2676 __ Bind(&l[i]); 2677 __ Nop(); 2678 } 2679 2680 delete[] l; 2681 } 2682 2683 masm.FinalizeCode(); 2684 2685 END(); 2686 RUN(); 2687 TEARDOWN(); 2688 } 2689 2690 2691 TEST_T32(unaligned_branch_after_literal) { 2692 SETUP(); 2693 2694 START(); 2695 2696 // This test manually places a 32-bit literal after a 16-bit branch 2697 // which branches over the literal to an unaligned PC. 2698 Literal<int32_t> l0(0x01234567, RawLiteral::kManuallyPlaced); 2699 2700 __ Ldr(r0, &l0); 2701 ASSERT_LITERAL_POOL_SIZE(0); 2702 2703 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2704 ASSERT_LITERAL_POOL_SIZE(0); 2705 2706 // Manually generate a literal pool. 2707 { 2708 Label after_pool; 2709 ExactAssemblyScope scope(&masm, 2710 k16BitT32InstructionSizeInBytes + sizeof(int32_t), 2711 CodeBufferCheckScope::kMaximumSize); 2712 __ b(Narrow, &after_pool); 2713 __ place(&l0); 2714 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 2715 __ bind(&after_pool); 2716 } 2717 2718 ASSERT_LITERAL_POOL_SIZE(0); 2719 2720 END(); 2721 2722 RUN(); 2723 2724 // Check that the literal was loaded correctly. 2725 ASSERT_EQUAL_32(0x01234567, r0); 2726 2727 TEARDOWN(); 2728 } 2729 2730 2731 // This test check that we can update a Literal after usage. 2732 TEST(literal_update) { 2733 SETUP(); 2734 2735 START(); 2736 Label exit; 2737 Literal<uint32_t>* a32 = 2738 new Literal<uint32_t>(0xabcdef01, RawLiteral::kDeletedOnPoolDestruction); 2739 Literal<uint64_t>* a64 = 2740 new Literal<uint64_t>(UINT64_C(0xabcdef01abcdef01), 2741 RawLiteral::kDeletedOnPoolDestruction); 2742 __ Ldr(r0, a32); 2743 __ Ldrd(r2, r3, a64); 2744 __ EmitLiteralPool(); 2745 Literal<uint32_t>* b32 = 2746 new Literal<uint32_t>(0x10fedcba, RawLiteral::kDeletedOnPoolDestruction); 2747 Literal<uint64_t>* b64 = 2748 new Literal<uint64_t>(UINT64_C(0x10fedcba10fedcba), 2749 RawLiteral::kDeletedOnPoolDestruction); 2750 __ Ldr(r1, b32); 2751 __ Ldrd(r4, r5, b64); 2752 // Update literals' values. "a32" and "a64" are already emitted. "b32" and 2753 // "b64" will only be emitted when "END()" will be called. 2754 a32->UpdateValue(0x12345678, masm.GetBuffer()); 2755 a64->UpdateValue(UINT64_C(0x13579bdf02468ace), masm.GetBuffer()); 2756 b32->UpdateValue(0x87654321, masm.GetBuffer()); 2757 b64->UpdateValue(UINT64_C(0x1032547698badcfe), masm.GetBuffer()); 2758 END(); 2759 2760 RUN(); 2761 2762 ASSERT_EQUAL_32(0x12345678, r0); 2763 ASSERT_EQUAL_32(0x87654321, r1); 2764 ASSERT_EQUAL_32(0x02468ace, r2); 2765 ASSERT_EQUAL_32(0x13579bdf, r3); 2766 ASSERT_EQUAL_32(0x98badcfe, r4); 2767 ASSERT_EQUAL_32(0x10325476, r5); 2768 } 2769 2770 2771 TEST(claim_peek_poke) { 2772 SETUP(); 2773 2774 START(); 2775 2776 Label start; 2777 __ Bind(&start); 2778 __ Claim(0); 2779 __ Drop(0); 2780 VIXL_CHECK((masm.GetCursorOffset() - start.GetLocation()) == 0); 2781 2782 __ Claim(32); 2783 __ Ldr(r0, 0xcafe0000); 2784 __ Ldr(r1, 0xcafe0001); 2785 __ Ldr(r2, 0xcafe0002); 2786 __ Poke(r0, 0); 2787 __ Poke(r1, 4); 2788 __ Poke(r2, 8); 2789 __ Peek(r2, 0); 2790 __ Peek(r0, 4); 2791 __ Peek(r1, 8); 2792 __ Drop(32); 2793 2794 END(); 2795 2796 RUN(); 2797 2798 ASSERT_EQUAL_32(0xcafe0001, r0); 2799 ASSERT_EQUAL_32(0xcafe0002, r1); 2800 ASSERT_EQUAL_32(0xcafe0000, r2); 2801 2802 TEARDOWN(); 2803 } 2804 2805 2806 TEST(msr_i) { 2807 SETUP(); 2808 2809 START(); 2810 __ Mov(r0, 0xdead); 2811 __ Mov(r1, 0xdead); 2812 __ Mov(r2, 0xdead); 2813 __ Mov(r3, 0xb); 2814 __ Msr(APSR_nzcvqg, 0); 2815 __ Mrs(r0, APSR); 2816 __ Msr(APSR_nzcvqg, 0xffffffff); 2817 __ Mrs(r1, APSR); 2818 // Only modify nzcvq => keep previous g. 2819 __ Lsl(r4, r3, 28); 2820 __ Msr(APSR_nzcvq, r4); 2821 __ Mrs(r2, APSR); 2822 END(); 2823 2824 RUN(); 2825 2826 ASSERT_EQUAL_32(0x10, r0); 2827 ASSERT_EQUAL_32(0xf80f0010, r1); 2828 ASSERT_EQUAL_32(0xb00f0010, r2); 2829 2830 TEARDOWN(); 2831 } 2832 2833 2834 TEST(vmrs_vmsr) { 2835 SETUP(); 2836 2837 START(); 2838 // Move some value to FPSCR and get them back to test vmsr/vmrs instructions. 2839 __ Mov(r0, 0x2a000000); 2840 __ Vmsr(FPSCR, r0); 2841 __ Vmrs(RegisterOrAPSR_nzcv(r1.GetCode()), FPSCR); 2842 2843 __ Mov(r0, 0x5a000000); 2844 __ Vmsr(FPSCR, r0); 2845 __ Vmrs(RegisterOrAPSR_nzcv(r2.GetCode()), FPSCR); 2846 2847 // Move to APSR_nzcv. 2848 __ Vmrs(RegisterOrAPSR_nzcv(pc.GetCode()), FPSCR); 2849 __ Mrs(r3, APSR); 2850 __ And(r3, r3, 0xf0000000); 2851 2852 END(); 2853 2854 RUN(); 2855 2856 ASSERT_EQUAL_32(0x2a000000, r1); 2857 ASSERT_EQUAL_32(0x5a000000, r2); 2858 ASSERT_EQUAL_32(0x50000000, r3); 2859 2860 TEARDOWN(); 2861 } 2862 2863 2864 TEST(printf) { 2865 SETUP(); 2866 2867 START(); 2868 __ Mov(r0, 0xb00e0000); 2869 __ Msr(APSR_nzcvqg, r0); 2870 __ Mov(r0, sp); 2871 __ Printf("sp=%x\n", r0); 2872 // __ Printf("Hello world!\n"); 2873 __ Mov(r0, 0x1234); 2874 __ Mov(r1, 0x5678); 2875 StringLiteral literal("extra string"); 2876 __ Adr(r2, &literal); 2877 __ Mov(r3, 5); 2878 __ Mov(r4, 0xdead4444); 2879 __ Mov(r5, 0xdead5555); 2880 __ Mov(r6, 0xdead6666); 2881 __ Mov(r7, 0xdead7777); 2882 __ Mov(r8, 0xdead8888); 2883 __ Mov(r9, 0xdead9999); 2884 __ Mov(r10, 0xdeadaaaa); 2885 __ Mov(r11, 0xdeadbbbb); 2886 __ Vldr(d0, 1.2345); 2887 __ Vldr(d1, 2.9876); 2888 __ Vldr(s4, 1.3333); 2889 __ Vldr(s5, 3.21); 2890 __ Vldr(d3, 3.333); 2891 __ Vldr(d4, 4.444); 2892 __ Vldr(d5, 5.555); 2893 __ Vldr(d6, 6.666); 2894 __ Vldr(d7, 7.777); 2895 __ Vldr(d8, 8.888); 2896 __ Vldr(d9, 9.999); 2897 __ Vldr(d10, 10.000); 2898 __ Vldr(d11, 11.111); 2899 __ Vldr(d12, 12.222); 2900 __ Vldr(d13, 13.333); 2901 __ Vldr(d14, 14.444); 2902 __ Vldr(d15, 15.555); 2903 __ Vldr(d16, 16.666); 2904 __ Vldr(d17, 17.777); 2905 __ Vldr(d18, 18.888); 2906 __ Vldr(d19, 19.999); 2907 __ Vldr(d20, 20.000); 2908 __ Vldr(d21, 21.111); 2909 __ Vldr(d22, 22.222); 2910 __ Vldr(d23, 23.333); 2911 __ Vldr(d24, 24.444); 2912 __ Vldr(d25, 25.555); 2913 __ Vldr(d26, 26.666); 2914 __ Vldr(d27, 27.777); 2915 __ Vldr(d28, 28.888); 2916 __ Vldr(d29, 29.999); 2917 __ Vldr(d30, 30.000); 2918 __ Vldr(d31, 31.111); 2919 { 2920 UseScratchRegisterScope temps(&masm); 2921 // For effective use as an inspection tool, Printf must work without any 2922 // scratch registers. 2923 VIXL_CHECK(r12.Is(temps.Acquire())); 2924 __ Mov(r12, 0xdeadcccc); 2925 VIXL_CHECK(masm.GetScratchRegisterList()->IsEmpty()); 2926 2927 __ Printf("%% r0=%x r1=%x str=<%.*s>\n", r0, r1, r3, r2); 2928 __ Printf("r0=%d r1=%d str=<%s>\n", r0, r1, r2); 2929 __ Printf("d0=%g\n", d0); 2930 __ Printf("s4=%g\n", s4); 2931 __ Printf("d0=%g d1=%g s4=%g s5=%g\n", d0, d1, s4, s5); 2932 __ Printf("d0=%g r0=%x s4=%g r1=%x\n", d0, r0, s4, r1); 2933 __ Printf("r0=%x d0=%g r1=%x s4=%g\n", r0, d0, r1, s4); 2934 __ Mov(r0, sp); 2935 __ Printf("sp=%x\n", r0); 2936 __ Mrs(r0, APSR); 2937 // Only keep R/W fields. 2938 __ Mov(r2, 0xf80f0200); 2939 __ And(r0, r0, r2); 2940 } 2941 END(); 2942 2943 RUN(); 2944 2945 ASSERT_EQUAL_32(0xb00e0000, r0); 2946 ASSERT_EQUAL_32(0x5678, r1); 2947 ASSERT_EQUAL_32(5, r3); 2948 ASSERT_EQUAL_32(0xdead4444, r4); 2949 ASSERT_EQUAL_32(0xdead5555, r5); 2950 ASSERT_EQUAL_32(0xdead6666, r6); 2951 ASSERT_EQUAL_32(0xdead7777, r7); 2952 ASSERT_EQUAL_32(0xdead8888, r8); 2953 ASSERT_EQUAL_32(0xdead9999, r9); 2954 ASSERT_EQUAL_32(0xdeadaaaa, r10); 2955 ASSERT_EQUAL_32(0xdeadbbbb, r11); 2956 ASSERT_EQUAL_32(0xdeadcccc, r12); 2957 ASSERT_EQUAL_FP64(1.2345, d0); 2958 ASSERT_EQUAL_FP64(2.9876, d1); 2959 ASSERT_EQUAL_FP32(1.3333, s4); 2960 ASSERT_EQUAL_FP32(3.21, s5); 2961 ASSERT_EQUAL_FP64(4.444, d4); 2962 ASSERT_EQUAL_FP64(5.555, d5); 2963 ASSERT_EQUAL_FP64(6.666, d6); 2964 ASSERT_EQUAL_FP64(7.777, d7); 2965 ASSERT_EQUAL_FP64(8.888, d8); 2966 ASSERT_EQUAL_FP64(9.999, d9); 2967 ASSERT_EQUAL_FP64(10.000, d10); 2968 ASSERT_EQUAL_FP64(11.111, d11); 2969 ASSERT_EQUAL_FP64(12.222, d12); 2970 ASSERT_EQUAL_FP64(13.333, d13); 2971 ASSERT_EQUAL_FP64(14.444, d14); 2972 ASSERT_EQUAL_FP64(15.555, d15); 2973 ASSERT_EQUAL_FP64(16.666, d16); 2974 ASSERT_EQUAL_FP64(17.777, d17); 2975 ASSERT_EQUAL_FP64(18.888, d18); 2976 ASSERT_EQUAL_FP64(19.999, d19); 2977 ASSERT_EQUAL_FP64(20.000, d20); 2978 ASSERT_EQUAL_FP64(21.111, d21); 2979 ASSERT_EQUAL_FP64(22.222, d22); 2980 ASSERT_EQUAL_FP64(23.333, d23); 2981 ASSERT_EQUAL_FP64(24.444, d24); 2982 ASSERT_EQUAL_FP64(25.555, d25); 2983 ASSERT_EQUAL_FP64(26.666, d26); 2984 ASSERT_EQUAL_FP64(27.777, d27); 2985 ASSERT_EQUAL_FP64(28.888, d28); 2986 ASSERT_EQUAL_FP64(29.999, d29); 2987 ASSERT_EQUAL_FP64(30.000, d30); 2988 ASSERT_EQUAL_FP64(31.111, d31); 2989 2990 TEARDOWN(); 2991 } 2992 2993 TEST(printf2) { 2994 SETUP(); 2995 2996 START(); 2997 __ Mov(r0, 0x1234); 2998 __ Mov(r1, 0x5678); 2999 __ Vldr(d0, 1.2345); 3000 __ Vldr(s2, 2.9876); 3001 __ Printf("d0=%g d1=%g r0=%x r1=%x\n", d0, s2, r0, r1); 3002 END(); 3003 3004 RUN(); 3005 3006 TEARDOWN(); 3007 } 3008 3009 3010 template <typename T> 3011 void CheckInstructionSetA32(const T& assm) { 3012 VIXL_CHECK(assm.IsUsingA32()); 3013 VIXL_CHECK(!assm.IsUsingT32()); 3014 VIXL_CHECK(assm.GetInstructionSetInUse() == A32); 3015 } 3016 3017 3018 template <typename T> 3019 void CheckInstructionSetT32(const T& assm) { 3020 VIXL_CHECK(assm.IsUsingT32()); 3021 VIXL_CHECK(!assm.IsUsingA32()); 3022 VIXL_CHECK(assm.GetInstructionSetInUse() == T32); 3023 } 3024 3025 3026 TEST_NOASM(set_isa_constructors) { 3027 byte buffer[1024]; 3028 3029 #ifndef VIXL_INCLUDE_TARGET_T32_ONLY 3030 // A32 by default. 3031 CheckInstructionSetA32(Assembler()); 3032 CheckInstructionSetA32(Assembler(1024)); 3033 CheckInstructionSetA32(Assembler(buffer, sizeof(buffer))); 3034 3035 CheckInstructionSetA32(MacroAssembler()); 3036 CheckInstructionSetA32(MacroAssembler(1024)); 3037 CheckInstructionSetA32(MacroAssembler(buffer, sizeof(buffer))); 3038 #else 3039 // T32 by default. 3040 CheckInstructionSetT32(Assembler()); 3041 CheckInstructionSetT32(Assembler(1024)); 3042 CheckInstructionSetT32(Assembler(buffer, sizeof(buffer))); 3043 3044 CheckInstructionSetT32(MacroAssembler()); 3045 CheckInstructionSetT32(MacroAssembler(1024)); 3046 CheckInstructionSetT32(MacroAssembler(buffer, sizeof(buffer))); 3047 #endif 3048 3049 #ifdef VIXL_INCLUDE_TARGET_A32 3050 // Explicit A32. 3051 CheckInstructionSetA32(Assembler(A32)); 3052 CheckInstructionSetA32(Assembler(1024, A32)); 3053 CheckInstructionSetA32(Assembler(buffer, sizeof(buffer), A32)); 3054 3055 CheckInstructionSetA32(MacroAssembler(A32)); 3056 CheckInstructionSetA32(MacroAssembler(1024, A32)); 3057 CheckInstructionSetA32(MacroAssembler(buffer, sizeof(buffer), A32)); 3058 #endif 3059 3060 #ifdef VIXL_INCLUDE_TARGET_T32 3061 // Explicit T32. 3062 CheckInstructionSetT32(Assembler(T32)); 3063 CheckInstructionSetT32(Assembler(1024, T32)); 3064 CheckInstructionSetT32(Assembler(buffer, sizeof(buffer), T32)); 3065 3066 CheckInstructionSetT32(MacroAssembler(T32)); 3067 CheckInstructionSetT32(MacroAssembler(1024, T32)); 3068 CheckInstructionSetT32(MacroAssembler(buffer, sizeof(buffer), T32)); 3069 #endif 3070 } 3071 3072 3073 TEST_NOASM(set_isa_empty) { 3074 // It is possible to change the instruction set if no instructions have yet 3075 // been generated. This test only makes sense when both A32 and T32 are 3076 // supported. 3077 #ifdef VIXL_INCLUDE_TARGET_AARCH32 3078 Assembler assm; 3079 CheckInstructionSetA32(assm); 3080 assm.UseT32(); 3081 CheckInstructionSetT32(assm); 3082 assm.UseA32(); 3083 CheckInstructionSetA32(assm); 3084 assm.UseInstructionSet(T32); 3085 CheckInstructionSetT32(assm); 3086 assm.UseInstructionSet(A32); 3087 CheckInstructionSetA32(assm); 3088 3089 MacroAssembler masm; 3090 CheckInstructionSetA32(masm); 3091 masm.UseT32(); 3092 CheckInstructionSetT32(masm); 3093 masm.UseA32(); 3094 CheckInstructionSetA32(masm); 3095 masm.UseInstructionSet(T32); 3096 CheckInstructionSetT32(masm); 3097 masm.UseInstructionSet(A32); 3098 CheckInstructionSetA32(masm); 3099 #endif 3100 } 3101 3102 3103 TEST_NOASM(set_isa_noop) { 3104 // It is possible to call a no-op UseA32/T32 or UseInstructionSet even if 3105 // one or more instructions have been generated. 3106 #ifdef VIXL_INCLUDE_TARGET_A32 3107 { 3108 Assembler assm(A32); 3109 CheckInstructionSetA32(assm); 3110 CodeBufferCheckScope scope(&assm, kMaxInstructionSizeInBytes); 3111 assm.bx(lr); 3112 VIXL_ASSERT(assm.GetCursorOffset() > 0); 3113 CheckInstructionSetA32(assm); 3114 assm.UseA32(); 3115 CheckInstructionSetA32(assm); 3116 assm.UseInstructionSet(A32); 3117 CheckInstructionSetA32(assm); 3118 assm.FinalizeCode(); 3119 } 3120 { 3121 MacroAssembler masm(A32); 3122 CheckInstructionSetA32(masm); 3123 masm.Bx(lr); 3124 VIXL_ASSERT(masm.GetCursorOffset() > 0); 3125 CheckInstructionSetA32(masm); 3126 masm.UseA32(); 3127 CheckInstructionSetA32(masm); 3128 masm.UseInstructionSet(A32); 3129 CheckInstructionSetA32(masm); 3130 masm.FinalizeCode(); 3131 } 3132 #endif 3133 3134 #ifdef VIXL_INCLUDE_TARGET_T32 3135 { 3136 Assembler assm(T32); 3137 CheckInstructionSetT32(assm); 3138 CodeBufferCheckScope scope(&assm, kMaxInstructionSizeInBytes); 3139 assm.bx(lr); 3140 VIXL_ASSERT(assm.GetCursorOffset() > 0); 3141 CheckInstructionSetT32(assm); 3142 assm.UseT32(); 3143 CheckInstructionSetT32(assm); 3144 assm.UseInstructionSet(T32); 3145 CheckInstructionSetT32(assm); 3146 assm.FinalizeCode(); 3147 } 3148 { 3149 MacroAssembler masm(T32); 3150 CheckInstructionSetT32(masm); 3151 masm.Bx(lr); 3152 VIXL_ASSERT(masm.GetCursorOffset() > 0); 3153 CheckInstructionSetT32(masm); 3154 masm.UseT32(); 3155 CheckInstructionSetT32(masm); 3156 masm.UseInstructionSet(T32); 3157 CheckInstructionSetT32(masm); 3158 masm.FinalizeCode(); 3159 } 3160 #endif 3161 } 3162 3163 3164 TEST(logical_arithmetic_identities) { 3165 SETUP(); 3166 3167 START(); 3168 3169 Label blob_1; 3170 __ Bind(&blob_1); 3171 __ Add(r0, r0, 0); 3172 __ And(r0, r0, 0xffffffff); 3173 __ Bic(r0, r0, 0); 3174 __ Eor(r0, r0, 0); 3175 __ Orn(r0, r0, 0xffffffff); 3176 __ Orr(r0, r0, 0); 3177 __ Sub(r0, r0, 0); 3178 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_1) == 0); 3179 3180 Label blob_2; 3181 __ Bind(&blob_2); 3182 __ Adds(r0, r0, 0); 3183 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_2) != 0); 3184 3185 Label blob_3; 3186 __ Bind(&blob_3); 3187 __ Ands(r0, r0, 0); 3188 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_3) != 0); 3189 3190 Label blob_4; 3191 __ Bind(&blob_4); 3192 __ Bics(r0, r0, 0); 3193 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_4) != 0); 3194 3195 Label blob_5; 3196 __ Bind(&blob_5); 3197 __ Eors(r0, r0, 0); 3198 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_5) != 0); 3199 3200 Label blob_6; 3201 __ Bind(&blob_6); 3202 __ Orns(r0, r0, 0); 3203 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_6) != 0); 3204 3205 Label blob_7; 3206 __ Bind(&blob_7); 3207 __ Orrs(r0, r0, 0); 3208 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_7) != 0); 3209 3210 Label blob_8; 3211 __ Bind(&blob_8); 3212 __ Subs(r0, r0, 0); 3213 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_8) != 0); 3214 3215 __ Mov(r0, 0xbad); 3216 __ And(r1, r0, 0); 3217 __ Bic(r2, r0, 0xffffffff); 3218 __ Eor(r3, r0, 0xffffffff); 3219 __ Orn(r4, r0, 0); 3220 __ Orr(r5, r0, 0xffffffff); 3221 3222 END(); 3223 3224 RUN(); 3225 3226 ASSERT_EQUAL_32(0xbad, r0); 3227 ASSERT_EQUAL_32(0, r1); 3228 ASSERT_EQUAL_32(0, r2); 3229 ASSERT_EQUAL_32(~0xbad, r3); 3230 ASSERT_EQUAL_32(0xffffffff, r4); 3231 ASSERT_EQUAL_32(0xffffffff, r5); 3232 3233 TEARDOWN(); 3234 } 3235 3236 3237 TEST(scratch_register_checks) { 3238 // It is unsafe for users to use registers that the MacroAssembler is also 3239 // using as scratch registers. This test checks the MacroAssembler's checking 3240 // mechanism itself. 3241 SETUP(); 3242 START(); 3243 { 3244 UseScratchRegisterScope temps(&masm); 3245 // 'ip' is a scratch register by default. 3246 VIXL_CHECK(masm.GetScratchRegisterList()->GetList() == 3247 (1u << ip.GetCode())); 3248 VIXL_CHECK(temps.IsAvailable(ip)); 3249 3250 // Integer registers have no complicated aliasing so 3251 // masm.AliasesAvailableScratchRegister(reg) == temps.IsAvailable(reg). 3252 for (unsigned i = 0; i < kNumberOfRegisters; i++) { 3253 Register reg(i); 3254 VIXL_CHECK(masm.AliasesAvailableScratchRegister(reg) == 3255 temps.IsAvailable(reg)); 3256 } 3257 } 3258 END(); 3259 TEARDOWN(); 3260 } 3261 3262 3263 TEST(scratch_register_checks_v) { 3264 // It is unsafe for users to use registers that the MacroAssembler is also 3265 // using as scratch registers. This test checks the MacroAssembler's checking 3266 // mechanism itself. 3267 SETUP(); 3268 { 3269 UseScratchRegisterScope temps(&masm); 3270 // There is no default floating-point scratch register. Add temps of various 3271 // sizes to check handling of aliased registers. 3272 VIXL_CHECK(masm.GetScratchVRegisterList()->GetList() == 0); 3273 temps.Include(q15); 3274 temps.Include(d15); 3275 temps.Include(s15); 3276 temps.Include(d4); 3277 temps.Include(d5); 3278 temps.Include(s24); 3279 temps.Include(s25); 3280 temps.Include(s26); 3281 temps.Include(s27); 3282 temps.Include(q0); 3283 // See VRegisterList for details of the list encoding. 3284 VIXL_CHECK(masm.GetScratchVRegisterList()->GetList() == 3285 UINT64_C(0xf0000000cf008f0f)); 3286 // | || || | 3287 // q15 d15| || q0 3288 // s24-s27 |d4-d5 3289 // s15 3290 3291 // Simple checks: Included registers are available. 3292 VIXL_CHECK(temps.IsAvailable(q15)); 3293 VIXL_CHECK(temps.IsAvailable(d15)); 3294 VIXL_CHECK(temps.IsAvailable(s15)); 3295 VIXL_CHECK(temps.IsAvailable(d4)); 3296 VIXL_CHECK(temps.IsAvailable(d5)); 3297 VIXL_CHECK(temps.IsAvailable(s24)); 3298 VIXL_CHECK(temps.IsAvailable(s25)); 3299 VIXL_CHECK(temps.IsAvailable(s26)); 3300 VIXL_CHECK(temps.IsAvailable(s27)); 3301 VIXL_CHECK(temps.IsAvailable(q0)); 3302 3303 // Each available S register should mark the corresponding D and Q registers 3304 // as aliasing an available scratch register. 3305 for (unsigned s = 0; s < kNumberOfSRegisters; s++) { 3306 if (temps.IsAvailable(SRegister(s))) { 3307 VIXL_CHECK(masm.AliasesAvailableScratchRegister(SRegister(s))); 3308 VIXL_CHECK(masm.AliasesAvailableScratchRegister(DRegister(s / 2))); 3309 VIXL_CHECK(masm.AliasesAvailableScratchRegister(QRegister(s / 4))); 3310 } else { 3311 // AliasesAvailableScratchRegiters == IsAvailable for S registers. 3312 VIXL_CHECK(!masm.AliasesAvailableScratchRegister(SRegister(s))); 3313 } 3314 } 3315 3316 // Similar checks for high D registers. 3317 unsigned first_high_d_register = kNumberOfSRegisters / 2; 3318 for (unsigned d = first_high_d_register; d < kMaxNumberOfDRegisters; d++) { 3319 if (temps.IsAvailable(DRegister(d))) { 3320 VIXL_CHECK(masm.AliasesAvailableScratchRegister(DRegister(d))); 3321 VIXL_CHECK(masm.AliasesAvailableScratchRegister(QRegister(d / 2))); 3322 } else { 3323 // AliasesAvailableScratchRegiters == IsAvailable for high D registers. 3324 VIXL_CHECK(!masm.AliasesAvailableScratchRegister(DRegister(d))); 3325 } 3326 } 3327 } 3328 TEARDOWN(); 3329 } 3330 3331 3332 TEST(nop) { 3333 SETUP(); 3334 3335 Label start; 3336 __ Bind(&start); 3337 __ Nop(); 3338 size_t nop_size = (isa == T32) ? k16BitT32InstructionSizeInBytes 3339 : kA32InstructionSizeInBytes; 3340 // `MacroAssembler::Nop` must generate at least one nop. 3341 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= nop_size); 3342 3343 masm.FinalizeCode(); 3344 3345 TEARDOWN(); 3346 } 3347 3348 3349 // Check that `GetMarginBeforeLiteralEmission()` is precise. 3350 TEST(literal_pool_margin) { 3351 SETUP(); 3352 3353 START(); 3354 3355 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3356 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3357 3358 // Create a single literal. 3359 __ Ldrd(r0, r1, 0x1234567890abcdef); 3360 3361 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 3362 3363 // Generate code to fill all the margin we have before generating the literal 3364 // pool. 3365 int32_t margin = masm.GetMarginBeforeLiteralEmission(); 3366 int32_t end = masm.GetCursorOffset() + margin; 3367 { 3368 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize); 3369 // Opening the scope should not have triggered the emission of the literal 3370 // pool. 3371 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 3372 while (masm.GetCursorOffset() < end) { 3373 __ nop(); 3374 } 3375 VIXL_CHECK(masm.GetCursorOffset() == end); 3376 } 3377 3378 // There should be no margin left to emit the literal pool. 3379 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 3380 VIXL_CHECK(masm.GetMarginBeforeLiteralEmission() == 0); 3381 3382 // So emitting a single instruction should force emission of the pool. 3383 __ Nop(); 3384 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3385 END(); 3386 3387 RUN(); 3388 3389 // Check that the literals loaded correctly. 3390 ASSERT_EQUAL_32(0x90abcdef, r0); 3391 ASSERT_EQUAL_32(0x12345678, r1); 3392 3393 TEARDOWN(); 3394 } 3395 3396 3397 // Check that `GetMarginBeforeVeneerEmission()` is precise. 3398 TEST(veneer_pool_margin) { 3399 SETUP(); 3400 3401 START(); 3402 3403 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3404 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3405 3406 // Create a single veneer. 3407 Label target; 3408 __ B(eq, &target); 3409 3410 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3411 3412 // Generate code to fill all the margin we have before generating the veneer 3413 // pool. 3414 int32_t margin = masm.GetMarginBeforeVeneerEmission(); 3415 int32_t end = masm.GetCursorOffset() + margin; 3416 { 3417 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize); 3418 // Opening the scope should not have triggered the emission of the veneer 3419 // pool. 3420 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3421 while (masm.GetCursorOffset() < end) { 3422 __ nop(); 3423 } 3424 VIXL_CHECK(masm.GetCursorOffset() == end); 3425 } 3426 // There should be no margin left to emit the veneer pool. 3427 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() == 0); 3428 3429 // So emitting a single instruction should force emission of the pool. 3430 // We cannot simply check that the veneer pool is empty, because the veneer 3431 // emitted for the CBZ instruction above is itself tracked by the veneer 3432 // mechanisms. Instead, check that some 'unexpected' code is generated. 3433 Label check; 3434 __ Bind(&check); 3435 { 3436 ExactAssemblyScope scope(&masm, 2, ExactAssemblyScope::kMaximumSize); 3437 // Do not actually generate any code. 3438 } 3439 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) > 0); 3440 __ Bind(&target); 3441 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3442 3443 END(); 3444 3445 RUN(); 3446 3447 TEARDOWN(); 3448 } 3449 3450 3451 TEST_T32(near_branch_fuzz) { 3452 SETUP(); 3453 START(); 3454 3455 uint16_t seed[3] = {1, 2, 3}; 3456 seed48(seed); 3457 3458 const int label_count = 31; 3459 bool allbound; 3460 Label* l; 3461 3462 // Use multiple iterations, as each produces a different predictably random 3463 // sequence. 3464 const int iterations = 64; 3465 3466 int loop_count = 0; 3467 __ Mov(r1, 0); 3468 3469 // Initialise the status flags to Z set. 3470 __ Cmp(r1, r1); 3471 3472 // Gradually increasing the number of cases effectively increases the 3473 // probability of nops being emitted in the sequence. The branch-to-bind 3474 // ratio in the sequence is fixed at 4:1 by the ratio of cases. 3475 for (int case_count = 6; case_count < 37; case_count++) { 3476 for (int iter = 0; iter < iterations; iter++) { 3477 // Reset local state. 3478 allbound = false; 3479 l = new Label[label_count]; 3480 3481 // Set r0 != 0 to force no branches to be taken. Also acts as a marker 3482 // between each iteration in the disassembly. 3483 __ Mov(r0, 1); 3484 3485 for (;;) { 3486 uint32_t inst_case = static_cast<uint32_t>(mrand48()) % case_count; 3487 uint32_t label_index = static_cast<uint32_t>(mrand48()) % label_count; 3488 3489 switch (inst_case) { 3490 case 0: // Bind. 3491 if (!l[label_index].IsBound()) { 3492 __ Bind(&l[label_index]); 3493 3494 // We should hit each label exactly once (because the branches are 3495 // never taken). Keep a counter to verify this. 3496 loop_count++; 3497 __ Add(r1, r1, 1); 3498 } 3499 break; 3500 case 1: // Compare and branch if zero (untaken as r0 == 1). 3501 __ Cbz(r0, &l[label_index]); 3502 break; 3503 case 2: { // Compare and branch if not zero. 3504 Label past_branch; 3505 __ B(eq, &past_branch, kNear); 3506 __ Cbnz(r0, &l[label_index]); 3507 __ Bind(&past_branch); 3508 break; 3509 } 3510 case 3: { // Unconditional branch preferred near. 3511 Label past_branch; 3512 __ B(eq, &past_branch, kNear); 3513 __ B(&l[label_index], kNear); 3514 __ Bind(&past_branch); 3515 break; 3516 } 3517 case 4: // Conditional branch (untaken as Z set) preferred near. 3518 __ B(ne, &l[label_index], kNear); 3519 break; 3520 default: // Nop. 3521 __ Nop(); 3522 break; 3523 } 3524 3525 // If all labels have been bound, exit the inner loop and finalise the 3526 // code. 3527 allbound = true; 3528 for (int i = 0; i < label_count; i++) { 3529 allbound = allbound && l[i].IsBound(); 3530 } 3531 if (allbound) break; 3532 } 3533 3534 // Ensure that the veneer pools are emitted, to keep each branch/bind test 3535 // independent. 3536 masm.FinalizeCode(); 3537 delete[] l; 3538 } 3539 } 3540 3541 END(); 3542 RUN(); 3543 3544 ASSERT_EQUAL_32(loop_count, r1); 3545 3546 TEARDOWN(); 3547 } 3548 3549 3550 #ifdef VIXL_INCLUDE_TARGET_T32 3551 TEST_NOASM(code_buffer_precise_growth) { 3552 static const int kBaseBufferSize = 16; 3553 MacroAssembler masm(kBaseBufferSize, T32); 3554 3555 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3556 3557 { 3558 // Fill the buffer with nops. 3559 ExactAssemblyScope scope(&masm, 3560 kBaseBufferSize, 3561 ExactAssemblyScope::kExactSize); 3562 for (int i = 0; i < kBaseBufferSize; i += k16BitT32InstructionSizeInBytes) { 3563 __ nop(); 3564 } 3565 } 3566 3567 // The buffer should not have grown yet. 3568 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3569 3570 // Generating a single instruction should force the buffer to grow. 3571 __ Nop(); 3572 3573 VIXL_CHECK(masm.GetBuffer()->GetCapacity() > kBaseBufferSize); 3574 3575 masm.FinalizeCode(); 3576 } 3577 #endif 3578 3579 3580 #ifdef VIXL_INCLUDE_TARGET_T32 3581 TEST_NOASM(out_of_space_immediately_before_PerformEnsureEmit) { 3582 static const int kBaseBufferSize = 64; 3583 MacroAssembler masm(kBaseBufferSize, T32); 3584 3585 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3586 3587 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3588 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3589 3590 // Create a veneer. 3591 Label target; 3592 __ Cbz(r0, &target); 3593 3594 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3595 3596 VIXL_CHECK(IsUint32(masm.GetBuffer()->GetRemainingBytes())); 3597 uint32_t space = static_cast<uint32_t>(masm.GetBuffer()->GetRemainingBytes()); 3598 { 3599 // Fill the buffer with nops. 3600 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 3601 for (uint32_t i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { 3602 __ nop(); 3603 } 3604 } 3605 3606 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3607 3608 // The buffer should not have grown yet, and there should be no space left. 3609 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3610 VIXL_CHECK(masm.GetBuffer()->GetRemainingBytes() == 0); 3611 3612 // Force emission of the veneer, at a point where there is no space available 3613 // in the buffer. 3614 int32_t past_cbz_range = masm.GetMarginBeforeVeneerEmission() + 1; 3615 masm.EnsureEmitFor(past_cbz_range); 3616 3617 __ Bind(&target); 3618 3619 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3620 3621 masm.FinalizeCode(); 3622 } 3623 #endif 3624 3625 3626 TEST_T32(distant_literal_references) { 3627 SETUP(); 3628 START(); 3629 3630 Literal<uint64_t>* literal = 3631 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3632 RawLiteral::kPlacedWhenUsed, 3633 RawLiteral::kDeletedOnPoolDestruction); 3634 // Refer to the literal so that it is emitted early. 3635 __ Ldr(r0, literal); 3636 3637 // Add enough nops to exceed the range of all loads. 3638 int space = 5000; 3639 { 3640 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize); 3641 VIXL_ASSERT(masm.IsUsingT32()); 3642 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { 3643 __ nop(); 3644 } 3645 } 3646 3647 #define ENSURE_ALIGNED() \ 3648 do { \ 3649 if (!IsMultiple<k32BitT32InstructionSizeInBytes>( \ 3650 masm.GetCursorOffset())) { \ 3651 ExactAssemblyScope scope(&masm, \ 3652 k16BitT32InstructionSizeInBytes, \ 3653 ExactAssemblyScope::kExactSize); \ 3654 __ nop(); \ 3655 } \ 3656 VIXL_ASSERT( \ 3657 IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \ 3658 } while (0) 3659 3660 // The literal has already been emitted, and is out of range of all of these 3661 // instructions. The delegates must generate fix-up code. 3662 ENSURE_ALIGNED(); 3663 __ Ldr(r1, literal); 3664 ENSURE_ALIGNED(); 3665 __ Ldrb(r2, literal); 3666 ENSURE_ALIGNED(); 3667 __ Ldrsb(r3, literal); 3668 ENSURE_ALIGNED(); 3669 __ Ldrh(r4, literal); 3670 ENSURE_ALIGNED(); 3671 __ Ldrsh(r5, literal); 3672 ENSURE_ALIGNED(); 3673 __ Ldrd(r6, r7, literal); 3674 ENSURE_ALIGNED(); 3675 __ Vldr(d0, literal); 3676 ENSURE_ALIGNED(); 3677 __ Vldr(s3, literal); 3678 3679 #undef ENSURE_ALIGNED 3680 3681 END(); 3682 RUN(); 3683 3684 // Check that the literals loaded correctly. 3685 ASSERT_EQUAL_32(0x89abcdef, r0); 3686 ASSERT_EQUAL_32(0x89abcdef, r1); 3687 ASSERT_EQUAL_32(0xef, r2); 3688 ASSERT_EQUAL_32(0xffffffef, r3); 3689 ASSERT_EQUAL_32(0xcdef, r4); 3690 ASSERT_EQUAL_32(0xffffcdef, r5); 3691 ASSERT_EQUAL_32(0x89abcdef, r6); 3692 ASSERT_EQUAL_32(0x01234567, r7); 3693 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 3694 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 3695 3696 TEARDOWN(); 3697 } 3698 3699 3700 TEST_T32(distant_literal_references_unaligned_pc) { 3701 SETUP(); 3702 START(); 3703 3704 Literal<uint64_t>* literal = 3705 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3706 RawLiteral::kPlacedWhenUsed, 3707 RawLiteral::kDeletedOnPoolDestruction); 3708 // Refer to the literal so that it is emitted early. 3709 __ Ldr(r0, literal); 3710 3711 // Add enough nops to exceed the range of all loads, leaving the PC aligned 3712 // to only a two-byte boundary. 3713 int space = 5002; 3714 { 3715 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize); 3716 VIXL_ASSERT(masm.IsUsingT32()); 3717 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { 3718 __ nop(); 3719 } 3720 } 3721 3722 #define ENSURE_NOT_ALIGNED() \ 3723 do { \ 3724 if (IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())) { \ 3725 ExactAssemblyScope scope(&masm, \ 3726 k16BitT32InstructionSizeInBytes, \ 3727 ExactAssemblyScope::kExactSize); \ 3728 __ nop(); \ 3729 } \ 3730 VIXL_ASSERT( \ 3731 !IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \ 3732 } while (0) 3733 3734 // The literal has already been emitted, and is out of range of all of these 3735 // instructions. The delegates must generate fix-up code. 3736 ENSURE_NOT_ALIGNED(); 3737 __ Ldr(r1, literal); 3738 ENSURE_NOT_ALIGNED(); 3739 __ Ldrb(r2, literal); 3740 ENSURE_NOT_ALIGNED(); 3741 __ Ldrsb(r3, literal); 3742 ENSURE_NOT_ALIGNED(); 3743 __ Ldrh(r4, literal); 3744 ENSURE_NOT_ALIGNED(); 3745 __ Ldrsh(r5, literal); 3746 ENSURE_NOT_ALIGNED(); 3747 __ Ldrd(r6, r7, literal); 3748 { 3749 // TODO: We currently require an extra scratch register for these cases 3750 // because MemOperandComputationHelper isn't able to fit add_sub_offset into 3751 // a single 'sub' instruction, so 'pc' gets preserved first. The same 3752 // problem technically exists for the other loads, but vldr is particularly 3753 // badly affected because vldr cannot set the low bits in its offset mask, 3754 // so the add/sub operand is likely to be difficult to encode. 3755 // 3756 // At the moment, we get this: 3757 // mov r8, pc 3758 // mov ip, #5118 3759 // sub r8, pc 3760 // vldr d0, [r8, #48] 3761 // 3762 // We should be able to generate something like this: 3763 // sub ip, pc, #0x1300 // 5118 & 0xff00 3764 // sub ip, #0xfe // 5118 & 0x00ff 3765 // vldr d0, [ip, #48] 3766 UseScratchRegisterScope temps(&masm); 3767 temps.Include(r8); 3768 ENSURE_NOT_ALIGNED(); 3769 __ Vldr(d0, literal); 3770 ENSURE_NOT_ALIGNED(); 3771 __ Vldr(s3, literal); 3772 } 3773 3774 #undef ENSURE_NOT_ALIGNED 3775 3776 END(); 3777 RUN(); 3778 3779 // Check that the literals loaded correctly. 3780 ASSERT_EQUAL_32(0x89abcdef, r0); 3781 ASSERT_EQUAL_32(0x89abcdef, r1); 3782 ASSERT_EQUAL_32(0xef, r2); 3783 ASSERT_EQUAL_32(0xffffffef, r3); 3784 ASSERT_EQUAL_32(0xcdef, r4); 3785 ASSERT_EQUAL_32(0xffffcdef, r5); 3786 ASSERT_EQUAL_32(0x89abcdef, r6); 3787 ASSERT_EQUAL_32(0x01234567, r7); 3788 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 3789 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 3790 3791 TEARDOWN(); 3792 } 3793 3794 3795 TEST_T32(distant_literal_references_short_range) { 3796 SETUP(); 3797 START(); 3798 3799 Literal<uint64_t>* literal = 3800 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3801 RawLiteral::kPlacedWhenUsed, 3802 RawLiteral::kDeletedOnPoolDestruction); 3803 // Refer to the literal so that it is emitted early. 3804 __ Vldr(s4, literal); 3805 3806 // Add enough nops to exceed the range of the loads, but not the adr that will 3807 // be generated to read the PC. 3808 int space = 4000; 3809 { 3810 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize); 3811 VIXL_ASSERT(masm.IsUsingT32()); 3812 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { 3813 __ nop(); 3814 } 3815 } 3816 3817 #define ENSURE_ALIGNED() \ 3818 do { \ 3819 if (!IsMultiple<k32BitT32InstructionSizeInBytes>( \ 3820 masm.GetCursorOffset())) { \ 3821 ExactAssemblyScope scope(&masm, \ 3822 k16BitT32InstructionSizeInBytes, \ 3823 ExactAssemblyScope::kExactSize); \ 3824 __ nop(); \ 3825 } \ 3826 VIXL_ASSERT( \ 3827 IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \ 3828 } while (0) 3829 3830 // The literal has already been emitted, and is out of range of all of these 3831 // instructions. The delegates must generate fix-up code. 3832 ENSURE_ALIGNED(); 3833 __ Ldr(r1, literal); 3834 ENSURE_ALIGNED(); 3835 __ Ldrb(r2, literal); 3836 ENSURE_ALIGNED(); 3837 __ Ldrsb(r3, literal); 3838 ENSURE_ALIGNED(); 3839 __ Ldrh(r4, literal); 3840 ENSURE_ALIGNED(); 3841 __ Ldrsh(r5, literal); 3842 ENSURE_ALIGNED(); 3843 __ Ldrd(r6, r7, literal); 3844 ENSURE_ALIGNED(); 3845 __ Vldr(d0, literal); 3846 ENSURE_ALIGNED(); 3847 __ Vldr(s3, literal); 3848 3849 #undef ENSURE_ALIGNED 3850 3851 END(); 3852 RUN(); 3853 3854 // Check that the literals loaded correctly. 3855 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s4); 3856 ASSERT_EQUAL_32(0x89abcdef, r1); 3857 ASSERT_EQUAL_32(0xef, r2); 3858 ASSERT_EQUAL_32(0xffffffef, r3); 3859 ASSERT_EQUAL_32(0xcdef, r4); 3860 ASSERT_EQUAL_32(0xffffcdef, r5); 3861 ASSERT_EQUAL_32(0x89abcdef, r6); 3862 ASSERT_EQUAL_32(0x01234567, r7); 3863 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 3864 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 3865 3866 TEARDOWN(); 3867 } 3868 3869 3870 TEST_T32(distant_literal_references_short_range_unaligned_pc) { 3871 SETUP(); 3872 START(); 3873 3874 Literal<uint64_t>* literal = 3875 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3876 RawLiteral::kPlacedWhenUsed, 3877 RawLiteral::kDeletedOnPoolDestruction); 3878 // Refer to the literal so that it is emitted early. 3879 __ Vldr(s4, literal); 3880 3881 // Add enough nops to exceed the range of the loads, but not the adr that will 3882 // be generated to read the PC. 3883 int space = 4000; 3884 { 3885 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize); 3886 VIXL_ASSERT(masm.IsUsingT32()); 3887 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { 3888 __ nop(); 3889 } 3890 } 3891 3892 #define ENSURE_NOT_ALIGNED() \ 3893 do { \ 3894 if (IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())) { \ 3895 ExactAssemblyScope scope(&masm, \ 3896 k16BitT32InstructionSizeInBytes, \ 3897 ExactAssemblyScope::kExactSize); \ 3898 __ nop(); \ 3899 } \ 3900 VIXL_ASSERT( \ 3901 !IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \ 3902 } while (0) 3903 3904 // The literal has already been emitted, and is out of range of all of these 3905 // instructions. The delegates must generate fix-up code. 3906 ENSURE_NOT_ALIGNED(); 3907 __ Ldr(r1, literal); 3908 ENSURE_NOT_ALIGNED(); 3909 __ Ldrb(r2, literal); 3910 ENSURE_NOT_ALIGNED(); 3911 __ Ldrsb(r3, literal); 3912 ENSURE_NOT_ALIGNED(); 3913 __ Ldrh(r4, literal); 3914 ENSURE_NOT_ALIGNED(); 3915 __ Ldrsh(r5, literal); 3916 ENSURE_NOT_ALIGNED(); 3917 __ Ldrd(r6, r7, literal); 3918 ENSURE_NOT_ALIGNED(); 3919 __ Vldr(d0, literal); 3920 ENSURE_NOT_ALIGNED(); 3921 __ Vldr(s3, literal); 3922 3923 #undef ENSURE_NOT_ALIGNED 3924 3925 END(); 3926 RUN(); 3927 3928 // Check that the literals loaded correctly. 3929 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s4); 3930 ASSERT_EQUAL_32(0x89abcdef, r1); 3931 ASSERT_EQUAL_32(0xef, r2); 3932 ASSERT_EQUAL_32(0xffffffef, r3); 3933 ASSERT_EQUAL_32(0xcdef, r4); 3934 ASSERT_EQUAL_32(0xffffcdef, r5); 3935 ASSERT_EQUAL_32(0x89abcdef, r6); 3936 ASSERT_EQUAL_32(0x01234567, r7); 3937 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 3938 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 3939 3940 TEARDOWN(); 3941 } 3942 3943 3944 TEST_T32(distant_literal_references_long_range) { 3945 SETUP(); 3946 START(); 3947 3948 Literal<uint64_t>* literal = 3949 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3950 RawLiteral::kPlacedWhenUsed, 3951 RawLiteral::kDeletedOnPoolDestruction); 3952 // Refer to the literal so that it is emitted early. 3953 __ Ldr(r0, literal); 3954 3955 #define PAD_WITH_NOPS(space) \ 3956 do { \ 3957 { \ 3958 ExactAssemblyScope scope(&masm, \ 3959 space, \ 3960 CodeBufferCheckScope::kExactSize); \ 3961 VIXL_ASSERT(masm.IsUsingT32()); \ 3962 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { \ 3963 __ nop(); \ 3964 } \ 3965 } \ 3966 } while (0) 3967 3968 // Add enough nops to exceed the range of all loads. 3969 PAD_WITH_NOPS(5000); 3970 3971 // The literal has already been emitted, and is out of range of all of these 3972 // instructions. The delegates must generate fix-up code. 3973 __ Ldr(r1, literal); 3974 __ Ldrb(r2, literal); 3975 __ Ldrsb(r3, literal); 3976 __ Ldrh(r4, literal); 3977 __ Ldrsh(r5, literal); 3978 __ Ldrd(r6, r7, literal); 3979 __ Vldr(d0, literal); 3980 __ Vldr(s3, literal); 3981 3982 // Add enough nops to exceed the range of the adr+sub sequence. 3983 PAD_WITH_NOPS(0x421000); 3984 3985 __ Ldr(r1, literal); 3986 __ Ldrb(r2, literal); 3987 __ Ldrsb(r3, literal); 3988 __ Ldrh(r4, literal); 3989 __ Ldrsh(r5, literal); 3990 __ Ldrd(r6, r7, literal); 3991 { 3992 // TODO: We currently require an extra scratch register for these cases. We 3993 // should be able to optimise the code generation to avoid this requirement 3994 // (and in many cases avoid a 32-bit instruction). 3995 UseScratchRegisterScope temps(&masm); 3996 temps.Include(r8); 3997 __ Vldr(d0, literal); 3998 __ Vldr(s3, literal); 3999 } 4000 4001 #undef PAD_WITH_NOPS 4002 4003 END(); 4004 RUN(); 4005 4006 // Check that the literals loaded correctly. 4007 ASSERT_EQUAL_32(0x89abcdef, r0); 4008 ASSERT_EQUAL_32(0x89abcdef, r1); 4009 ASSERT_EQUAL_32(0xef, r2); 4010 ASSERT_EQUAL_32(0xffffffef, r3); 4011 ASSERT_EQUAL_32(0xcdef, r4); 4012 ASSERT_EQUAL_32(0xffffcdef, r5); 4013 ASSERT_EQUAL_32(0x89abcdef, r6); 4014 ASSERT_EQUAL_32(0x01234567, r7); 4015 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 4016 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 4017 4018 TEARDOWN(); 4019 } 4020 4021 4022 TEST(barriers) { 4023 // Generate all supported barriers, this is just a smoke test 4024 SETUP(); 4025 4026 START(); 4027 4028 // DMB 4029 __ Dmb(SY); 4030 __ Dmb(ST); 4031 __ Dmb(ISH); 4032 __ Dmb(ISHST); 4033 __ Dmb(NSH); 4034 __ Dmb(NSHST); 4035 __ Dmb(OSH); 4036 __ Dmb(OSHST); 4037 4038 // DSB 4039 __ Dsb(SY); 4040 __ Dsb(ST); 4041 __ Dsb(ISH); 4042 __ Dsb(ISHST); 4043 __ Dsb(NSH); 4044 __ Dsb(NSHST); 4045 __ Dsb(OSH); 4046 __ Dsb(OSHST); 4047 4048 // ISB 4049 __ Isb(SY); 4050 4051 END(); 4052 4053 TEARDOWN(); 4054 } 4055 4056 4057 TEST(preloads) { 4058 // Smoke test for various pld/pli forms. 4059 SETUP(); 4060 4061 START(); 4062 4063 // PLD immediate 4064 __ Pld(MemOperand(sp, 0)); 4065 __ Pld(MemOperand(r0, 0)); 4066 __ Pld(MemOperand(r1, 123)); 4067 __ Pld(MemOperand(r2, 1234)); 4068 __ Pld(MemOperand(r3, 4095)); 4069 __ Pld(MemOperand(r4, -123)); 4070 __ Pld(MemOperand(r5, -255)); 4071 4072 if (masm.IsUsingA32()) { 4073 __ Pld(MemOperand(r6, -1234)); 4074 __ Pld(MemOperand(r7, -4095)); 4075 } 4076 4077 4078 // PLDW immediate 4079 __ Pldw(MemOperand(sp, 0)); 4080 __ Pldw(MemOperand(r0, 0)); 4081 __ Pldw(MemOperand(r1, 123)); 4082 __ Pldw(MemOperand(r2, 1234)); 4083 __ Pldw(MemOperand(r3, 4095)); 4084 __ Pldw(MemOperand(r4, -123)); 4085 __ Pldw(MemOperand(r5, -255)); 4086 4087 if (masm.IsUsingA32()) { 4088 __ Pldw(MemOperand(r6, -1234)); 4089 __ Pldw(MemOperand(r7, -4095)); 4090 } 4091 4092 // PLD register 4093 __ Pld(MemOperand(r0, r1)); 4094 __ Pld(MemOperand(r0, r1, LSL, 1)); 4095 __ Pld(MemOperand(r0, r1, LSL, 2)); 4096 __ Pld(MemOperand(r0, r1, LSL, 3)); 4097 4098 if (masm.IsUsingA32()) { 4099 __ Pld(MemOperand(r0, r1, LSL, 4)); 4100 __ Pld(MemOperand(r0, r1, LSL, 20)); 4101 } 4102 4103 // PLDW register 4104 __ Pldw(MemOperand(r0, r1)); 4105 __ Pldw(MemOperand(r0, r1, LSL, 1)); 4106 __ Pldw(MemOperand(r0, r1, LSL, 2)); 4107 __ Pldw(MemOperand(r0, r1, LSL, 3)); 4108 4109 if (masm.IsUsingA32()) { 4110 __ Pldw(MemOperand(r0, r1, LSL, 4)); 4111 __ Pldw(MemOperand(r0, r1, LSL, 20)); 4112 } 4113 4114 // PLD literal 4115 Label pld_label; 4116 __ Pld(&pld_label); 4117 __ Bind(&pld_label); 4118 4119 // PLI immediate 4120 __ Pli(MemOperand(sp, 0)); 4121 __ Pli(MemOperand(r0, 0)); 4122 __ Pli(MemOperand(r1, 123)); 4123 __ Pli(MemOperand(r2, 1234)); 4124 __ Pli(MemOperand(r3, 4095)); 4125 __ Pli(MemOperand(r4, -123)); 4126 __ Pli(MemOperand(r5, -255)); 4127 4128 if (masm.IsUsingA32()) { 4129 __ Pli(MemOperand(r6, -1234)); 4130 __ Pli(MemOperand(r7, -4095)); 4131 } 4132 4133 // PLI register 4134 __ Pli(MemOperand(r0, r1)); 4135 __ Pli(MemOperand(r0, r1, LSL, 1)); 4136 __ Pli(MemOperand(r0, r1, LSL, 2)); 4137 __ Pli(MemOperand(r0, r1, LSL, 3)); 4138 4139 if (masm.IsUsingA32()) { 4140 __ Pli(MemOperand(r0, r1, LSL, 4)); 4141 __ Pli(MemOperand(r0, r1, LSL, 20)); 4142 } 4143 4144 // PLI literal 4145 Label pli_label; 4146 __ Pli(&pli_label); 4147 __ Bind(&pli_label); 4148 4149 END(); 4150 4151 TEARDOWN(); 4152 } 4153 4154 4155 TEST_T32(veneer_mirrored_branches) { 4156 SETUP(); 4157 4158 START(); 4159 4160 const int kMaxBranchCount = 256; 4161 4162 for (int branch_count = 1; branch_count < kMaxBranchCount; branch_count++) { 4163 Label* targets = new Label[branch_count]; 4164 4165 for (int i = 0; i < branch_count; i++) { 4166 __ Cbz(r0, &targets[i]); 4167 } 4168 4169 for (int i = 0; i < branch_count; i++) { 4170 __ Bind(&targets[branch_count - i - 1]); 4171 __ Orr(r0, r0, r0); 4172 } 4173 4174 delete[] targets; 4175 } 4176 4177 END(); 4178 4179 TEARDOWN(); 4180 } 4181 4182 4183 TEST_T32(branch_fuzz_example) { 4184 SETUP(); 4185 4186 START(); 4187 4188 Label l[64]; 4189 __ And(r0, r0, r0); 4190 __ Cbz(r0, &l[30]); 4191 __ And(r0, r0, r0); 4192 __ Cbz(r0, &l[22]); 4193 __ And(r0, r0, r0); 4194 __ Cbz(r0, &l[1]); 4195 __ Cbz(r0, &l[15]); 4196 __ Cbz(r0, &l[9]); 4197 __ Cbz(r0, &l[6]); 4198 __ Bind(&l[26]); 4199 __ Cbz(r0, &l[29]); 4200 __ And(r0, r0, r0); 4201 __ And(r0, r0, r0); 4202 __ Cbz(r0, &l[22]); 4203 __ Bind(&l[12]); 4204 __ Bind(&l[22]); 4205 __ Cbz(r0, &l[10]); 4206 __ And(r0, r0, r0); 4207 __ Cbz(r0, &l[30]); 4208 __ Cbz(r0, &l[17]); 4209 __ Cbz(r0, &l[27]); 4210 __ Cbz(r0, &l[11]); 4211 __ Bind(&l[7]); 4212 __ Cbz(r0, &l[18]); 4213 __ Bind(&l[14]); 4214 __ Cbz(r0, &l[1]); 4215 __ Bind(&l[18]); 4216 __ Cbz(r0, &l[11]); 4217 __ Cbz(r0, &l[6]); 4218 __ Bind(&l[21]); 4219 __ Cbz(r0, &l[28]); 4220 __ And(r0, r0, r0); 4221 __ Cbz(r0, &l[28]); 4222 __ Cbz(r0, &l[22]); 4223 __ Bind(&l[23]); 4224 __ Cbz(r0, &l[21]); 4225 __ Cbz(r0, &l[28]); 4226 __ Cbz(r0, &l[9]); 4227 __ Bind(&l[9]); 4228 __ Cbz(r0, &l[4]); 4229 __ And(r0, r0, r0); 4230 __ Cbz(r0, &l[10]); 4231 __ And(r0, r0, r0); 4232 __ Bind(&l[8]); 4233 __ And(r0, r0, r0); 4234 __ Cbz(r0, &l[10]); 4235 __ And(r0, r0, r0); 4236 __ Cbz(r0, &l[17]); 4237 __ Bind(&l[10]); 4238 __ Cbz(r0, &l[8]); 4239 __ Cbz(r0, &l[25]); 4240 __ Cbz(r0, &l[4]); 4241 __ Bind(&l[28]); 4242 __ And(r0, r0, r0); 4243 __ Cbz(r0, &l[16]); 4244 __ Bind(&l[19]); 4245 __ Cbz(r0, &l[14]); 4246 __ Cbz(r0, &l[28]); 4247 __ Cbz(r0, &l[26]); 4248 __ Cbz(r0, &l[21]); 4249 __ And(r0, r0, r0); 4250 __ Bind(&l[24]); 4251 __ And(r0, r0, r0); 4252 __ Cbz(r0, &l[24]); 4253 __ Cbz(r0, &l[24]); 4254 __ Cbz(r0, &l[19]); 4255 __ Cbz(r0, &l[26]); 4256 __ Cbz(r0, &l[4]); 4257 __ And(r0, r0, r0); 4258 __ Cbz(r0, &l[27]); 4259 __ Cbz(r0, &l[14]); 4260 __ Cbz(r0, &l[5]); 4261 __ Cbz(r0, &l[18]); 4262 __ Cbz(r0, &l[5]); 4263 __ Cbz(r0, &l[6]); 4264 __ Cbz(r0, &l[28]); 4265 __ Cbz(r0, &l[15]); 4266 __ Cbz(r0, &l[0]); 4267 __ Cbz(r0, &l[10]); 4268 __ Cbz(r0, &l[16]); 4269 __ Cbz(r0, &l[30]); 4270 __ Cbz(r0, &l[8]); 4271 __ Cbz(r0, &l[16]); 4272 __ Cbz(r0, &l[22]); 4273 __ Cbz(r0, &l[27]); 4274 __ Cbz(r0, &l[12]); 4275 __ Cbz(r0, &l[0]); 4276 __ Cbz(r0, &l[23]); 4277 __ Cbz(r0, &l[27]); 4278 __ Cbz(r0, &l[16]); 4279 __ Cbz(r0, &l[24]); 4280 __ Cbz(r0, &l[17]); 4281 __ Cbz(r0, &l[4]); 4282 __ Cbz(r0, &l[11]); 4283 __ Cbz(r0, &l[6]); 4284 __ Cbz(r0, &l[23]); 4285 __ Bind(&l[16]); 4286 __ Cbz(r0, &l[10]); 4287 __ Cbz(r0, &l[17]); 4288 __ Cbz(r0, &l[12]); 4289 __ And(r0, r0, r0); 4290 __ Cbz(r0, &l[11]); 4291 __ Cbz(r0, &l[17]); 4292 __ Cbz(r0, &l[1]); 4293 __ Cbz(r0, &l[3]); 4294 __ Cbz(r0, &l[18]); 4295 __ Bind(&l[4]); 4296 __ Cbz(r0, &l[31]); 4297 __ Cbz(r0, &l[25]); 4298 __ Cbz(r0, &l[22]); 4299 __ And(r0, r0, r0); 4300 __ Cbz(r0, &l[19]); 4301 __ Cbz(r0, &l[16]); 4302 __ Cbz(r0, &l[21]); 4303 __ Cbz(r0, &l[27]); 4304 __ Bind(&l[1]); 4305 __ Cbz(r0, &l[9]); 4306 __ Cbz(r0, &l[13]); 4307 __ Cbz(r0, &l[10]); 4308 __ Cbz(r0, &l[6]); 4309 __ Cbz(r0, &l[30]); 4310 __ Cbz(r0, &l[28]); 4311 __ Cbz(r0, &l[7]); 4312 __ Cbz(r0, &l[17]); 4313 __ Bind(&l[0]); 4314 __ Cbz(r0, &l[13]); 4315 __ Cbz(r0, &l[11]); 4316 __ Cbz(r0, &l[19]); 4317 __ Cbz(r0, &l[22]); 4318 __ Cbz(r0, &l[9]); 4319 __ And(r0, r0, r0); 4320 __ Cbz(r0, &l[15]); 4321 __ Cbz(r0, &l[31]); 4322 __ Cbz(r0, &l[2]); 4323 __ And(r0, r0, r0); 4324 __ Cbz(r0, &l[6]); 4325 __ Bind(&l[27]); 4326 __ Bind(&l[13]); 4327 __ Cbz(r0, &l[23]); 4328 __ Cbz(r0, &l[7]); 4329 __ Bind(&l[2]); 4330 __ And(r0, r0, r0); 4331 __ Cbz(r0, &l[1]); 4332 __ Bind(&l[15]); 4333 __ Cbz(r0, &l[13]); 4334 __ Cbz(r0, &l[17]); 4335 __ Cbz(r0, &l[8]); 4336 __ Cbz(r0, &l[30]); 4337 __ Cbz(r0, &l[8]); 4338 __ Cbz(r0, &l[27]); 4339 __ Cbz(r0, &l[2]); 4340 __ Cbz(r0, &l[31]); 4341 __ Cbz(r0, &l[4]); 4342 __ Cbz(r0, &l[11]); 4343 __ Bind(&l[29]); 4344 __ Cbz(r0, &l[7]); 4345 __ Cbz(r0, &l[5]); 4346 __ Cbz(r0, &l[11]); 4347 __ Cbz(r0, &l[24]); 4348 __ Cbz(r0, &l[9]); 4349 __ Cbz(r0, &l[3]); 4350 __ Cbz(r0, &l[3]); 4351 __ Cbz(r0, &l[22]); 4352 __ Cbz(r0, &l[19]); 4353 __ Cbz(r0, &l[4]); 4354 __ Bind(&l[6]); 4355 __ And(r0, r0, r0); 4356 __ And(r0, r0, r0); 4357 __ Cbz(r0, &l[9]); 4358 __ Cbz(r0, &l[3]); 4359 __ Cbz(r0, &l[23]); 4360 __ Cbz(r0, &l[12]); 4361 __ Cbz(r0, &l[1]); 4362 __ Cbz(r0, &l[22]); 4363 __ Cbz(r0, &l[24]); 4364 __ And(r0, r0, r0); 4365 __ Cbz(r0, &l[16]); 4366 __ Cbz(r0, &l[19]); 4367 __ Cbz(r0, &l[20]); 4368 __ Cbz(r0, &l[1]); 4369 __ Cbz(r0, &l[4]); 4370 __ Cbz(r0, &l[1]); 4371 __ Cbz(r0, &l[25]); 4372 __ Cbz(r0, &l[21]); 4373 __ Cbz(r0, &l[20]); 4374 __ Cbz(r0, &l[29]); 4375 __ And(r0, r0, r0); 4376 __ Cbz(r0, &l[10]); 4377 __ Cbz(r0, &l[5]); 4378 __ And(r0, r0, r0); 4379 __ Cbz(r0, &l[25]); 4380 __ Cbz(r0, &l[26]); 4381 __ Cbz(r0, &l[28]); 4382 __ Cbz(r0, &l[19]); 4383 __ And(r0, r0, r0); 4384 __ Bind(&l[17]); 4385 __ And(r0, r0, r0); 4386 __ And(r0, r0, r0); 4387 __ And(r0, r0, r0); 4388 __ And(r0, r0, r0); 4389 __ Cbz(r0, &l[6]); 4390 __ And(r0, r0, r0); 4391 __ Cbz(r0, &l[5]); 4392 __ Cbz(r0, &l[26]); 4393 __ Cbz(r0, &l[28]); 4394 __ Cbz(r0, &l[24]); 4395 __ Bind(&l[20]); 4396 __ And(r0, r0, r0); 4397 __ Cbz(r0, &l[10]); 4398 __ Cbz(r0, &l[19]); 4399 __ Cbz(r0, &l[6]); 4400 __ And(r0, r0, r0); 4401 __ Cbz(r0, &l[13]); 4402 __ Cbz(r0, &l[15]); 4403 __ Cbz(r0, &l[22]); 4404 __ Cbz(r0, &l[8]); 4405 __ Cbz(r0, &l[6]); 4406 __ Cbz(r0, &l[23]); 4407 __ Cbz(r0, &l[6]); 4408 __ And(r0, r0, r0); 4409 __ Cbz(r0, &l[13]); 4410 __ Bind(&l[31]); 4411 __ Cbz(r0, &l[14]); 4412 __ Cbz(r0, &l[5]); 4413 __ Cbz(r0, &l[1]); 4414 __ Cbz(r0, &l[17]); 4415 __ Cbz(r0, &l[27]); 4416 __ Cbz(r0, &l[10]); 4417 __ Cbz(r0, &l[30]); 4418 __ Cbz(r0, &l[14]); 4419 __ Cbz(r0, &l[24]); 4420 __ Cbz(r0, &l[26]); 4421 __ And(r0, r0, r0); 4422 __ Cbz(r0, &l[2]); 4423 __ Cbz(r0, &l[21]); 4424 __ Cbz(r0, &l[5]); 4425 __ Cbz(r0, &l[24]); 4426 __ And(r0, r0, r0); 4427 __ Cbz(r0, &l[24]); 4428 __ Cbz(r0, &l[17]); 4429 __ And(r0, r0, r0); 4430 __ And(r0, r0, r0); 4431 __ Cbz(r0, &l[24]); 4432 __ And(r0, r0, r0); 4433 __ Cbz(r0, &l[17]); 4434 __ Cbz(r0, &l[12]); 4435 __ And(r0, r0, r0); 4436 __ Cbz(r0, &l[9]); 4437 __ Cbz(r0, &l[9]); 4438 __ Cbz(r0, &l[31]); 4439 __ Cbz(r0, &l[25]); 4440 __ And(r0, r0, r0); 4441 __ And(r0, r0, r0); 4442 __ Cbz(r0, &l[13]); 4443 __ Cbz(r0, &l[14]); 4444 __ Cbz(r0, &l[5]); 4445 __ Cbz(r0, &l[5]); 4446 __ Cbz(r0, &l[12]); 4447 __ Cbz(r0, &l[3]); 4448 __ Cbz(r0, &l[25]); 4449 __ Bind(&l[11]); 4450 __ Cbz(r0, &l[15]); 4451 __ Cbz(r0, &l[20]); 4452 __ Cbz(r0, &l[22]); 4453 __ Cbz(r0, &l[19]); 4454 __ And(r0, r0, r0); 4455 __ Cbz(r0, &l[19]); 4456 __ And(r0, r0, r0); 4457 __ Cbz(r0, &l[21]); 4458 __ Cbz(r0, &l[0]); 4459 __ And(r0, r0, r0); 4460 __ Cbz(r0, &l[16]); 4461 __ Cbz(r0, &l[28]); 4462 __ Cbz(r0, &l[18]); 4463 __ Cbz(r0, &l[3]); 4464 __ And(r0, r0, r0); 4465 __ Cbz(r0, &l[15]); 4466 __ Cbz(r0, &l[8]); 4467 __ Cbz(r0, &l[25]); 4468 __ Cbz(r0, &l[1]); 4469 __ Cbz(r0, &l[21]); 4470 __ Cbz(r0, &l[1]); 4471 __ Cbz(r0, &l[29]); 4472 __ Cbz(r0, &l[15]); 4473 __ And(r0, r0, r0); 4474 __ Cbz(r0, &l[24]); 4475 __ Cbz(r0, &l[3]); 4476 __ Cbz(r0, &l[9]); 4477 __ Cbz(r0, &l[9]); 4478 __ Cbz(r0, &l[24]); 4479 __ And(r0, r0, r0); 4480 __ Cbz(r0, &l[19]); 4481 __ And(r0, r0, r0); 4482 __ Cbz(r0, &l[30]); 4483 __ Bind(&l[25]); 4484 __ Bind(&l[3]); 4485 __ Bind(&l[30]); 4486 __ Bind(&l[5]); 4487 4488 END(); 4489 4490 TEARDOWN(); 4491 } 4492 4493 4494 // Generate a "B" and a "Cbz" which have the same checkpoint. Without proper 4495 // management (i.e. if the veneers were only generated at the shared 4496 // checkpoint), one one of the branches would be out of range. 4497 TEST_T32(veneer_simultaneous) { 4498 SETUP(); 4499 4500 START(); 4501 4502 // `2046` max range - the size of the B.EQ itself. 4503 static const int kMaxBCondRange = 1048574; 4504 4505 Label target_1; 4506 Label target_2; 4507 4508 __ B(eq, &target_1); 4509 4510 int target_1_size_1 = 4511 kMaxBCondRange - kCbzCbnzRange - k32BitT32InstructionSizeInBytes; 4512 int end_1 = masm.GetCursorOffset() + target_1_size_1; 4513 while (masm.GetCursorOffset() < end_1) { 4514 __ Nop(); 4515 } 4516 4517 __ Cbz(r0, &target_2); 4518 4519 int target_1_size_2 = kCbzCbnzRange - k16BitT32InstructionSizeInBytes; 4520 int end_2 = masm.GetCursorOffset() + target_1_size_2; 4521 while (masm.GetCursorOffset() < end_2) { 4522 __ Nop(); 4523 } 4524 4525 __ Nop(); 4526 4527 __ Bind(&target_1); 4528 __ Bind(&target_2); 4529 4530 END(); 4531 4532 TEARDOWN(); 4533 } 4534 4535 4536 // Generate a "B" and a "Cbz" which have the same checkpoint and the same label. 4537 TEST_T32(veneer_simultaneous_one_label) { 4538 SETUP(); 4539 4540 START(); 4541 4542 // `2046` max range - the size of the B.EQ itself. 4543 static const int kMaxBCondRange = 1048574; 4544 4545 Label target; 4546 4547 __ B(eq, &target); 4548 4549 int target_1_size_1 = 4550 kMaxBCondRange - kCbzCbnzRange - k32BitT32InstructionSizeInBytes; 4551 int end_1 = masm.GetCursorOffset() + target_1_size_1; 4552 while (masm.GetCursorOffset() < end_1) { 4553 __ Nop(); 4554 } 4555 4556 __ Cbz(r0, &target); 4557 4558 int target_1_size_2 = kCbzCbnzRange - k16BitT32InstructionSizeInBytes; 4559 int end_2 = masm.GetCursorOffset() + target_1_size_2; 4560 while (masm.GetCursorOffset() < end_2) { 4561 __ Nop(); 4562 } 4563 4564 __ Nop(); 4565 4566 __ Bind(&target); 4567 4568 END(); 4569 4570 TEARDOWN(); 4571 } 4572 4573 4574 // The literal pool will be emitted early because we keep a margin to always be 4575 // able to generate the veneers before the literal. 4576 TEST_T32(veneer_and_literal) { 4577 SETUP(); 4578 4579 START(); 4580 4581 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 4582 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 4583 4584 const uint32_t ldrd_range = 1020; 4585 const uint32_t cbz_range = 126; 4586 const uint32_t kLabelsCount = 20; 4587 Label labels[kLabelsCount]; 4588 4589 // Create one literal pool entry. 4590 __ Ldrd(r0, r1, 0x1234567890abcdef); 4591 4592 // Generate some nops. 4593 uint32_t i = 0; 4594 for (; i < ldrd_range - cbz_range - 40; 4595 i += k16BitT32InstructionSizeInBytes) { 4596 __ Nop(); 4597 } 4598 4599 // At this point, it remains cbz_range + 40 => 166 bytes before ldrd becomes 4600 // out of range. 4601 // We generate kLabelsCount * 4 => 80 bytes. We shouldn't generate the 4602 // literal pool. 4603 for (uint32_t j = 0; j < kLabelsCount; j++) { 4604 __ Cbz(r0, &labels[j]); 4605 __ Nop(); 4606 i += 2 * k16BitT32InstructionSizeInBytes; 4607 } 4608 4609 // However as we have pending veneer, the range is shrinken and the literal 4610 // pool is generated. 4611 VIXL_ASSERT(masm.LiteralPoolIsEmpty()); 4612 // However, we didn't generate the veneer pool. 4613 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() < 4614 static_cast<int32_t>(cbz_range)); 4615 4616 // We generate a few more instructions. 4617 for (; i < ldrd_range - 4 * kA32InstructionSizeInBytes; 4618 i += k16BitT32InstructionSizeInBytes) { 4619 __ Nop(); 4620 } 4621 4622 // And a veneer pool has been generated. 4623 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() > 4624 static_cast<int32_t>(cbz_range)); 4625 4626 // Bind all the used labels. 4627 for (uint32_t j = 0; j < kLabelsCount; j++) { 4628 __ Bind(&labels[j]); 4629 __ Nop(); 4630 } 4631 4632 // Now that all the labels have been bound, we have no more veneer. 4633 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 4634 4635 END(); 4636 4637 RUN(); 4638 4639 // Check that the literals loaded correctly. 4640 ASSERT_EQUAL_32(0x90abcdef, r0); 4641 ASSERT_EQUAL_32(0x12345678, r1); 4642 4643 TEARDOWN(); 4644 } 4645 4646 4647 // The literal pool will be emitted early and, as the emission of the literal 4648 // pool would have put veneer out of range, the veneers are emitted first. 4649 TEST_T32(veneer_and_literal2) { 4650 SETUP(); 4651 4652 START(); 4653 4654 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 4655 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 4656 4657 const uint32_t ldrd_range = 1020; 4658 const uint32_t cbz_range = 126; 4659 const uint32_t kLabelsCount = 20; 4660 const int32_t kTypicalMacroInstructionMaxSize = 4661 8 * kMaxInstructionSizeInBytes; 4662 Label labels[kLabelsCount]; 4663 4664 // Create one literal pool entry. 4665 __ Ldrd(r0, r1, 0x1234567890abcdef); 4666 4667 for (uint32_t i = 0; i < ldrd_range - cbz_range - 4 * kLabelsCount; 4668 i += k16BitT32InstructionSizeInBytes) { 4669 __ Nop(); 4670 } 4671 4672 // Add entries to the veneer pool. 4673 for (uint32_t i = 0; i < kLabelsCount; i++) { 4674 __ Cbz(r0, &labels[i]); 4675 __ Nop(); 4676 } 4677 4678 // Generate nops up to the literal pool limit. 4679 while (masm.GetMarginBeforeLiteralEmission() >= 4680 kTypicalMacroInstructionMaxSize) { 4681 __ Nop(); 4682 } 4683 4684 // At this point, no literals and no veneers have been generated. 4685 VIXL_ASSERT(!masm.LiteralPoolIsEmpty()); 4686 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() < 4687 static_cast<int32_t>(cbz_range)); 4688 // The literal pool needs to be generated. 4689 VIXL_ASSERT(masm.GetMarginBeforeLiteralEmission() < 4690 kTypicalMacroInstructionMaxSize); 4691 // But not the veneer pool. 4692 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() >= 4693 kTypicalMacroInstructionMaxSize); 4694 // However, as the literal emission would put veneers out of range. 4695 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() < 4696 kTypicalMacroInstructionMaxSize + 4697 static_cast<int32_t>(masm.GetLiteralPoolSize())); 4698 4699 // This extra Nop will generate the literal pool and before that the veneer 4700 // pool. 4701 __ Nop(); 4702 // Now the literal pool has been generated. 4703 VIXL_ASSERT(masm.LiteralPoolIsEmpty()); 4704 // And also the veneer pool. 4705 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() > 1000); 4706 4707 // Bind all the used labels. 4708 for (uint32_t j = 0; j < kLabelsCount; j++) { 4709 __ Bind(&labels[j]); 4710 __ Nop(); 4711 } 4712 4713 // Now that all the labels have been bound, we have no more veneer. 4714 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 4715 4716 END(); 4717 4718 RUN(); 4719 4720 // Check that the literals loaded correctly. 4721 ASSERT_EQUAL_32(0x90abcdef, r0); 4722 ASSERT_EQUAL_32(0x12345678, r1); 4723 4724 TEARDOWN(); 4725 } 4726 4727 4728 // Use a literal when we already have a veneer pool potential size greater than 4729 // the literal range => generate the literal immediately (not optimum but it 4730 // works). 4731 TEST_T32(veneer_and_literal3) { 4732 SETUP(); 4733 4734 START(); 4735 4736 static const int kLabelsCount = 1000; 4737 4738 Label labels[kLabelsCount]; 4739 4740 // Set the Z flag so that the following branches are not taken. 4741 __ Movs(r0, 0); 4742 4743 for (int i = 0; i < kLabelsCount; i++) { 4744 __ B(ne, &labels[i]); 4745 } 4746 4747 // Create one literal pool entry. 4748 __ Ldrd(r0, r1, 0x1234567890abcdef); 4749 4750 for (int i = 0; i < 10; i++) { 4751 __ Nop(); 4752 } 4753 4754 for (int i = 0; i < kLabelsCount; i++) { 4755 __ Bind(&labels[i]); 4756 } 4757 4758 END(); 4759 4760 RUN(); 4761 4762 // Check that the literals loaded correctly. 4763 ASSERT_EQUAL_32(0x90abcdef, r0); 4764 ASSERT_EQUAL_32(0x12345678, r1); 4765 4766 TEARDOWN(); 4767 } 4768 4769 4770 // Literal has to be generated sooner than veneers. However, as the literal 4771 // pool generation would make the veneers out of range, generate the veneers 4772 // first. 4773 TEST_T32(veneer_and_literal4) { 4774 SETUP(); 4775 4776 START(); 4777 4778 Label end; 4779 4780 // Set the Z flag so that the following branch is not taken. 4781 __ Movs(r0, 0); 4782 __ B(ne, &end); 4783 4784 uint32_t value = 0x1234567; 4785 Literal<uint32_t>* literal = 4786 new Literal<uint32_t>(value, 4787 RawLiteral::kPlacedWhenUsed, 4788 RawLiteral::kDeletedOnPoolDestruction); 4789 4790 __ Ldr(r11, literal); 4791 4792 // The range for ldr is 4095, the range for cbz is 127. Generate nops 4793 // to have the ldr becomming out of range just before the cbz. 4794 const int NUM_NOPS = 2044; 4795 const int NUM_RANGE = 58; 4796 4797 const int NUM1 = NUM_NOPS - NUM_RANGE; 4798 const int NUM2 = NUM_RANGE; 4799 4800 { 4801 ExactAssemblyScope aas(&masm, 2 * NUM1, CodeBufferCheckScope::kMaximumSize); 4802 for (int i = 0; i < NUM1; i++) { 4803 __ nop(); 4804 } 4805 } 4806 4807 __ Cbz(r1, &end); 4808 4809 { 4810 ExactAssemblyScope aas(&masm, 2 * NUM2, CodeBufferCheckScope::kMaximumSize); 4811 for (int i = 0; i < NUM2; i++) { 4812 __ nop(); 4813 } 4814 } 4815 4816 { 4817 ExactAssemblyScope aas(&masm, 4, CodeBufferCheckScope::kMaximumSize); 4818 __ add(r1, r1, 3); 4819 } 4820 __ Bind(&end); 4821 4822 END(); 4823 4824 RUN(); 4825 4826 // Check that the literals loaded correctly. 4827 ASSERT_EQUAL_32(0x1234567, r11); 4828 4829 TEARDOWN(); 4830 } 4831 4832 4833 // Literal has to be generated sooner than veneers. However, as the literal 4834 // pool generation would make the veneers out of range, generate the veneers 4835 // first. 4836 TEST_T32(veneer_and_literal5) { 4837 SETUP(); 4838 4839 START(); 4840 4841 static const int kTestCount = 100; 4842 Label labels[kTestCount]; 4843 4844 int first_test = 2000; 4845 // Test on both sizes of the Adr range which is 4095. 4846 for (int test = 0; test < kTestCount; test++) { 4847 const int string_size = 1000; // A lot more than the cbz range. 4848 std::string test_string(string_size, 'x'); 4849 StringLiteral big_literal(test_string.c_str()); 4850 4851 __ Adr(r11, &big_literal); 4852 4853 { 4854 int num_nops = first_test + test; 4855 ExactAssemblyScope aas(&masm, 4856 2 * num_nops, 4857 CodeBufferCheckScope::kMaximumSize); 4858 for (int i = 0; i < num_nops; i++) { 4859 __ nop(); 4860 } 4861 } 4862 4863 __ Cbz(r1, &labels[test]); 4864 4865 { 4866 ExactAssemblyScope aas(&masm, 4, CodeBufferCheckScope::kMaximumSize); 4867 __ add(r1, r1, 3); 4868 } 4869 __ Bind(&labels[test]); 4870 // Emit the literal pool if it has not beeen emitted (it's the case for 4871 // the lower values of test). 4872 __ EmitLiteralPool(MacroAssembler::kBranchRequired); 4873 } 4874 4875 END(); 4876 4877 TEARDOWN(); 4878 } 4879 4880 4881 // Check that veneer and literals are well generated when they are out of 4882 // range at the same time. 4883 TEST_T32(veneer_and_literal6) { 4884 SETUP(); 4885 4886 START(); 4887 4888 Label t1, t2, t3, t4, t5; 4889 static const int kLdrdRange = 1020; 4890 static const int kSizeForCbz = k16BitT32InstructionSizeInBytes; 4891 4892 __ Ldrd(r0, r1, 0x1111111111111111); 4893 __ Ldrd(r2, r3, 0x2222222222222222); 4894 __ Ldrd(r4, r5, 0x3333333333333333); 4895 __ Ldrd(r6, r7, 0x4444444444444444); 4896 __ Ldrd(r8, r9, 0x5555555555555555); 4897 __ Ldrd(r10, r11, 0x6666666666666666); 4898 __ Ldrd(r10, r11, 0x1234567890abcdef); 4899 4900 // Ldrd has a bigger range that cbz. Generate some nops before the cbzs in 4901 // order to reach the maximum range of ldrd and cbz at the same time. 4902 { 4903 int nop_size = kLdrdRange - kCbzCbnzRange - 5 * kSizeForCbz; 4904 ExactAssemblyScope scope(&masm, nop_size, CodeBufferCheckScope::kExactSize); 4905 for (int i = 0; i < nop_size; i += k16BitT32InstructionSizeInBytes) { 4906 __ nop(); 4907 } 4908 } 4909 4910 __ Cbz(r2, &t1); 4911 __ Cbz(r2, &t2); 4912 __ Cbz(r2, &t3); 4913 __ Cbz(r2, &t4); 4914 __ Cbz(r2, &t5); 4915 4916 // At this point, the ldrds are not out of range. It remains a kCbzCbnzRange 4917 // margin (minus the size of the veneers). 4918 4919 // At this point, the literal and the veneer pools are not emitted. 4920 VIXL_CHECK(masm.GetLiteralPoolSize() > 0); 4921 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() < kCbzCbnzRange); 4922 4923 // This scope will generate both veneers (they are both out of range). 4924 { 4925 int nop_size = kCbzCbnzRange; 4926 ExactAssemblyScope scope(&masm, nop_size, CodeBufferCheckScope::kExactSize); 4927 for (int i = 0; i < nop_size; i += k16BitT32InstructionSizeInBytes) { 4928 __ nop(); 4929 } 4930 } 4931 4932 // Check that both veneers have been emitted. 4933 VIXL_CHECK(masm.GetLiteralPoolSize() == 0); 4934 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() > kCbzCbnzRange); 4935 4936 __ Bind(&t1); 4937 __ Bind(&t2); 4938 __ Bind(&t3); 4939 __ Bind(&t4); 4940 __ Bind(&t5); 4941 4942 END(); 4943 4944 RUN(); 4945 4946 // Check that the literals loaded correctly. 4947 ASSERT_EQUAL_32(0x11111111, r0); 4948 ASSERT_EQUAL_32(0x11111111, r1); 4949 ASSERT_EQUAL_32(0x22222222, r2); 4950 ASSERT_EQUAL_32(0x22222222, r3); 4951 ASSERT_EQUAL_32(0x33333333, r4); 4952 ASSERT_EQUAL_32(0x33333333, r5); 4953 ASSERT_EQUAL_32(0x44444444, r6); 4954 ASSERT_EQUAL_32(0x44444444, r7); 4955 ASSERT_EQUAL_32(0x55555555, r8); 4956 ASSERT_EQUAL_32(0x55555555, r9); 4957 ASSERT_EQUAL_32(0x90abcdef, r10); 4958 ASSERT_EQUAL_32(0x12345678, r11); 4959 4960 TEARDOWN(); 4961 } 4962 4963 4964 // Check that a label which is just bound during the MacroEmissionCheckScope 4965 // can be used. 4966 TEST(ldr_label_bound_during_scope) { 4967 SETUP(); 4968 START(); 4969 4970 const int32_t kTypicalMacroInstructionMaxSize = 4971 8 * kMaxInstructionSizeInBytes; 4972 4973 Literal<uint64_t>* literal = 4974 new Literal<uint64_t>(UINT64_C(0x1234567890abcdef), 4975 RawLiteral::kPlacedWhenUsed, 4976 RawLiteral::kDeletedOnPoolDestruction); 4977 __ Ldrd(r0, r1, literal); 4978 4979 while (masm.GetMarginBeforeLiteralEmission() >= 4980 kTypicalMacroInstructionMaxSize) { 4981 __ Nop(); 4982 } 4983 4984 VIXL_ASSERT(!masm.LiteralPoolIsEmpty()); 4985 4986 // This Ldrd will first generate the pool and then use literal which has just 4987 // been bound. 4988 __ Ldrd(r2, r3, literal); 4989 4990 VIXL_ASSERT(masm.LiteralPoolIsEmpty()); 4991 4992 END(); 4993 4994 RUN(); 4995 4996 // Check that the literals loaded correctly. 4997 ASSERT_EQUAL_32(0x90abcdef, r0); 4998 ASSERT_EQUAL_32(0x12345678, r1); 4999 ASSERT_EQUAL_32(0x90abcdef, r2); 5000 ASSERT_EQUAL_32(0x12345678, r3); 5001 5002 TEARDOWN(); 5003 } 5004 5005 5006 TEST_T32(test_it_scope_and_literal_pool) { 5007 // This test stresses the EnsureEmitFor check inside ITScope to make sure the 5008 // number of bytes it tries to ensure we can emit is in sync with the 5009 // MacroEmissionCheckScope that is usually around it. 5010 SETUP(); 5011 5012 START(); 5013 5014 // Make sure the pool is empty. 5015 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 5016 ASSERT_LITERAL_POOL_SIZE(0); 5017 5018 Literal<uint64_t> l0(0xcafebeefdeadbaba); 5019 __ Ldrd(r0, r1, &l0); 5020 // Leave exactly as many bytes between cursor and pool emission checkpoint as 5021 // the typical macro instruction needs (and MacroEmissionCheckScope allows 5022 // for). 5023 const int32_t kTypicalMacroInstructionMaxSize = 5024 8 * kMaxInstructionSizeInBytes; 5025 int32_t margin = 5026 masm.GetMarginBeforeLiteralEmission() - kTypicalMacroInstructionMaxSize; 5027 int32_t end = masm.GetCursorOffset() + margin; 5028 5029 { 5030 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize); 5031 while (masm.GetCursorOffset() < end) { 5032 __ nop(); 5033 } 5034 } 5035 VIXL_CHECK(masm.GetMarginBeforeLiteralEmission() == 5036 kTypicalMacroInstructionMaxSize); 5037 5038 // We cannot use an IT block for this instruction, hence ITScope will 5039 // generate a branch over it. 5040 __ Add(ne, r8, r9, 256); 5041 5042 END(); 5043 5044 RUN(); 5045 5046 // Check that the literals loaded correctly. 5047 ASSERT_EQUAL_32(0xdeadbaba, r0); 5048 ASSERT_EQUAL_32(0xcafebeef, r1); 5049 5050 TEARDOWN(); 5051 } 5052 5053 5054 // TODO: Remove this limitation by having a sandboxing mechanism. 5055 #if defined(VIXL_HOST_POINTER_32) 5056 TEST(ldm_stm_no_writeback) { 5057 SETUP(); 5058 5059 START(); 5060 5061 const uint32_t src[4] = {0x12345678, 0x09abcdef, 0xc001c0de, 0xdeadbeef}; 5062 uint32_t dst1[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; 5063 uint32_t dst2[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; 5064 5065 __ Mov(r0, reinterpret_cast<uintptr_t>(src)); 5066 __ Ldm(r0, NO_WRITE_BACK, RegisterList(r1, r2, r3, r4)); 5067 ; 5068 __ Ldm(r0, NO_WRITE_BACK, RegisterList(r5, r6, r9, r11)); 5069 5070 __ Mov(r0, reinterpret_cast<uintptr_t>(dst1)); 5071 __ Stm(r0, NO_WRITE_BACK, RegisterList(r1, r2, r3, r4)); 5072 ; 5073 5074 __ Mov(r0, reinterpret_cast<uintptr_t>(dst2)); 5075 __ Stm(r0, NO_WRITE_BACK, RegisterList(r5, r6, r9, r11)); 5076 5077 END(); 5078 5079 RUN(); 5080 5081 ASSERT_EQUAL_32(0x12345678, r1); 5082 ASSERT_EQUAL_32(0x09abcdef, r2); 5083 ASSERT_EQUAL_32(0xc001c0de, r3); 5084 ASSERT_EQUAL_32(0xdeadbeef, r4); 5085 5086 ASSERT_EQUAL_32(0x12345678, r5); 5087 ASSERT_EQUAL_32(0x09abcdef, r6); 5088 ASSERT_EQUAL_32(0xc001c0de, r9); 5089 ASSERT_EQUAL_32(0xdeadbeef, r11); 5090 5091 ASSERT_EQUAL_32(0x12345678, dst1[0]); 5092 ASSERT_EQUAL_32(0x09abcdef, dst1[1]); 5093 ASSERT_EQUAL_32(0xc001c0de, dst1[2]); 5094 ASSERT_EQUAL_32(0xdeadbeef, dst1[3]); 5095 5096 ASSERT_EQUAL_32(0x12345678, dst2[0]); 5097 ASSERT_EQUAL_32(0x09abcdef, dst2[1]); 5098 ASSERT_EQUAL_32(0xc001c0de, dst2[2]); 5099 ASSERT_EQUAL_32(0xdeadbeef, dst2[3]); 5100 5101 TEARDOWN(); 5102 } 5103 5104 5105 TEST(ldm_stm_writeback) { 5106 SETUP(); 5107 5108 START(); 5109 5110 const uint32_t src[4] = {0x12345678, 0x09abcdef, 0xc001c0de, 0xdeadbeef}; 5111 uint32_t dst[8] = {0x00000000, 5112 0x00000000, 5113 0x00000000, 5114 0x00000000, 5115 0x00000000, 5116 0x00000000, 5117 0x00000000, 5118 0x00000000}; 5119 5120 __ Mov(r0, reinterpret_cast<uintptr_t>(src)); 5121 __ Ldm(r0, WRITE_BACK, RegisterList(r2, r3)); 5122 ; 5123 __ Ldm(r0, WRITE_BACK, RegisterList(r4, r5)); 5124 ; 5125 5126 __ Mov(r1, reinterpret_cast<uintptr_t>(dst)); 5127 __ Stm(r1, WRITE_BACK, RegisterList(r2, r3, r4, r5)); 5128 __ Stm(r1, WRITE_BACK, RegisterList(r2, r3, r4, r5)); 5129 5130 END(); 5131 5132 RUN(); 5133 5134 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src + 4), r0); 5135 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst + 8), r1); 5136 5137 ASSERT_EQUAL_32(0x12345678, r2); 5138 ASSERT_EQUAL_32(0x09abcdef, r3); 5139 ASSERT_EQUAL_32(0xc001c0de, r4); 5140 ASSERT_EQUAL_32(0xdeadbeef, r5); 5141 5142 ASSERT_EQUAL_32(0x12345678, dst[0]); 5143 ASSERT_EQUAL_32(0x09abcdef, dst[1]); 5144 ASSERT_EQUAL_32(0xc001c0de, dst[2]); 5145 ASSERT_EQUAL_32(0xdeadbeef, dst[3]); 5146 ASSERT_EQUAL_32(0x12345678, dst[4]); 5147 ASSERT_EQUAL_32(0x09abcdef, dst[5]); 5148 ASSERT_EQUAL_32(0xc001c0de, dst[6]); 5149 ASSERT_EQUAL_32(0xdeadbeef, dst[7]); 5150 5151 TEARDOWN(); 5152 } 5153 5154 5155 TEST_A32(ldm_stm_da_ib) { 5156 SETUP(); 5157 5158 START(); 5159 5160 const uint32_t src1[4] = {0x33333333, 0x44444444, 0x11111111, 0x22222222}; 5161 const uint32_t src2[4] = {0x11111111, 0x22222222, 0x33333333, 0x44444444}; 5162 5163 uint32_t dst1[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; 5164 uint32_t dst2[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; 5165 5166 __ Mov(r11, reinterpret_cast<uintptr_t>(src1 + 3)); 5167 __ Ldmda(r11, WRITE_BACK, RegisterList(r0, r1)); 5168 __ Ldmda(r11, NO_WRITE_BACK, RegisterList(r2, r3)); 5169 5170 __ Mov(r10, reinterpret_cast<uintptr_t>(src2 - 1)); 5171 __ Ldmib(r10, WRITE_BACK, RegisterList(r4, r5)); 5172 __ Ldmib(r10, NO_WRITE_BACK, RegisterList(r6, r7)); 5173 5174 __ Mov(r9, reinterpret_cast<uintptr_t>(dst1 + 3)); 5175 __ Stmda(r9, WRITE_BACK, RegisterList(r0, r1)); 5176 __ Stmda(r9, NO_WRITE_BACK, RegisterList(r2, r3)); 5177 5178 __ Mov(r8, reinterpret_cast<uintptr_t>(dst2 - 1)); 5179 __ Stmib(r8, WRITE_BACK, RegisterList(r4, r5)); 5180 __ Stmib(r8, NO_WRITE_BACK, RegisterList(r6, r7)); 5181 5182 5183 END(); 5184 5185 RUN(); 5186 5187 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src1 + 1), r11); 5188 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src2 + 1), r10); 5189 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst1 + 1), r9); 5190 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst2 + 1), r8); 5191 5192 ASSERT_EQUAL_32(0x11111111, r0); 5193 ASSERT_EQUAL_32(0x22222222, r1); 5194 ASSERT_EQUAL_32(0x33333333, r2); 5195 ASSERT_EQUAL_32(0x44444444, r3); 5196 5197 ASSERT_EQUAL_32(0x11111111, r4); 5198 ASSERT_EQUAL_32(0x22222222, r5); 5199 ASSERT_EQUAL_32(0x33333333, r6); 5200 ASSERT_EQUAL_32(0x44444444, r7); 5201 5202 ASSERT_EQUAL_32(0x33333333, dst1[0]); 5203 ASSERT_EQUAL_32(0x44444444, dst1[1]); 5204 ASSERT_EQUAL_32(0x11111111, dst1[2]); 5205 ASSERT_EQUAL_32(0x22222222, dst1[3]); 5206 5207 ASSERT_EQUAL_32(0x11111111, dst2[0]); 5208 ASSERT_EQUAL_32(0x22222222, dst2[1]); 5209 ASSERT_EQUAL_32(0x33333333, dst2[2]); 5210 ASSERT_EQUAL_32(0x44444444, dst2[3]); 5211 5212 TEARDOWN(); 5213 } 5214 5215 5216 TEST(ldmdb_stmdb) { 5217 SETUP(); 5218 5219 START(); 5220 5221 const uint32_t src[6] = 5222 {0x55555555, 0x66666666, 0x33333333, 0x44444444, 0x11111111, 0x22222222}; 5223 5224 uint32_t dst[6] = 5225 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}; 5226 5227 __ Mov(r11, reinterpret_cast<uintptr_t>(src + 6)); 5228 __ Ldmdb(r11, WRITE_BACK, RegisterList(r1, r2)); 5229 __ Ldmdb(r11, WRITE_BACK, RegisterList(r3, r4)); 5230 __ Ldmdb(r11, NO_WRITE_BACK, RegisterList(r5, r6)); 5231 5232 __ Mov(r10, reinterpret_cast<uintptr_t>(dst + 6)); 5233 __ Stmdb(r10, WRITE_BACK, RegisterList(r5, r6)); 5234 __ Stmdb(r10, WRITE_BACK, RegisterList(r3, r4)); 5235 __ Stmdb(r10, NO_WRITE_BACK, RegisterList(r1, r2)); 5236 5237 END(); 5238 5239 RUN(); 5240 5241 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src + 2), r11); 5242 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst + 2), r10); 5243 5244 ASSERT_EQUAL_32(0x11111111, r1); 5245 ASSERT_EQUAL_32(0x22222222, r2); 5246 ASSERT_EQUAL_32(0x33333333, r3); 5247 ASSERT_EQUAL_32(0x44444444, r4); 5248 ASSERT_EQUAL_32(0x55555555, r5); 5249 ASSERT_EQUAL_32(0x66666666, r6); 5250 5251 ASSERT_EQUAL_32(0x11111111, dst[0]); 5252 ASSERT_EQUAL_32(0x22222222, dst[1]); 5253 ASSERT_EQUAL_32(0x33333333, dst[2]); 5254 ASSERT_EQUAL_32(0x44444444, dst[3]); 5255 ASSERT_EQUAL_32(0x55555555, dst[4]); 5256 ASSERT_EQUAL_32(0x66666666, dst[5]); 5257 5258 TEARDOWN(); 5259 } 5260 #endif 5261 5262 5263 TEST(blx) { 5264 SETUP(); 5265 5266 START(); 5267 5268 // TODO(all): Ideally this test should jump back and forth between ARM and 5269 // Thumb mode and should also cover BLX immediate. Update this test if we 5270 // allow VIXL assembler to change ISA anywhere in the code buffer. 5271 5272 Label test_start; 5273 Label func1; 5274 Label func2; 5275 5276 __ B(&test_start); 5277 5278 __ Bind(&func1); 5279 __ Mov(r0, 0x11111111); 5280 __ Push(lr); 5281 { 5282 size_t size_of_generated_code; 5283 if (masm.IsUsingA32()) { 5284 size_of_generated_code = 7 * kA32InstructionSizeInBytes; 5285 } else { 5286 size_of_generated_code = 5 * k32BitT32InstructionSizeInBytes + 5287 3 * k16BitT32InstructionSizeInBytes; 5288 } 5289 ExactAssemblyScope scope(&masm, 5290 size_of_generated_code, 5291 ExactAssemblyScope::kExactSize); 5292 __ adr(r11, &func2); 5293 if (masm.IsUsingT32()) { 5294 // The jump target needs to have its least significant bit set to indicate 5295 // that we are jumping into thumb mode. 5296 __ orr(r11, r11, 1); 5297 } 5298 __ blx(r11); 5299 __ pop(lr); 5300 __ bx(lr); 5301 5302 __ bind(&func2); 5303 __ movw(r1, 0x2222); 5304 __ movt(r1, 0x2222); 5305 __ bx(lr); 5306 } 5307 5308 __ Bind(&test_start); 5309 __ Mov(r0, 0xdeadc0de); 5310 __ Mov(r1, 0xdeadc0de); 5311 __ Bl(&func1); 5312 5313 END(); 5314 5315 RUN(); 5316 5317 // Really basic test to check that we reached the different parts of the test. 5318 ASSERT_EQUAL_32(0x11111111, r0); 5319 ASSERT_EQUAL_32(0x22222222, r1); 5320 5321 TEARDOWN(); 5322 } 5323 5324 5325 // Check that B with a near hint use a narrow branch when it can. 5326 TEST_T32(b_near_hint) { 5327 SETUP(); 5328 START(); 5329 5330 Label start; 5331 Label end; 5332 5333 __ Bind(&start); 5334 __ Nop(); 5335 5336 { 5337 // Generate a branch which should be narrow. 5338 EmissionCheckScope scope(&masm, 5339 k16BitT32InstructionSizeInBytes, 5340 EmissionCheckScope::kExactSize); 5341 __ B(&start, kNear); 5342 } 5343 { 5344 ExactAssemblyScope scope(&masm, 5345 kBNarrowRange, 5346 ExactAssemblyScope::kExactSize); 5347 for (int32_t i = 0; i < kBNarrowRange; 5348 i += k16BitT32InstructionSizeInBytes) { 5349 __ nop(); 5350 } 5351 } 5352 { 5353 // Generate a branch which should be wide. 5354 EmissionCheckScope scope(&masm, 5355 k32BitT32InstructionSizeInBytes, 5356 EmissionCheckScope::kExactSize); 5357 __ B(&start, kNear); 5358 } 5359 { 5360 // Generate a forward branch which should be narrow. 5361 EmissionCheckScope scope(&masm, 5362 k16BitT32InstructionSizeInBytes, 5363 EmissionCheckScope::kExactSize); 5364 __ B(&end, kNear); 5365 } 5366 5367 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() < kBNarrowRange); 5368 5369 { 5370 ExactAssemblyScope scope(&masm, 5371 kBNarrowRange, 5372 ExactAssemblyScope::kExactSize); 5373 for (int32_t i = 0; i < kBNarrowRange; 5374 i += k16BitT32InstructionSizeInBytes) { 5375 __ nop(); 5376 } 5377 } 5378 5379 // A veneer should have been generated. 5380 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() > kBNarrowRange); 5381 5382 __ Bind(&end); 5383 5384 END(); 5385 5386 DISASSEMBLE(); 5387 5388 TEARDOWN(); 5389 } 5390 5391 5392 // Check that B with a far hint use a narrow branch only for a near backward 5393 // branch. 5394 TEST_T32(b_far_hint) { 5395 SETUP(); 5396 START(); 5397 5398 Label start; 5399 Label end; 5400 5401 __ Bind(&start); 5402 __ Nop(); 5403 5404 { 5405 // Generate a branch which should be narrow. 5406 EmissionCheckScope scope(&masm, 5407 k16BitT32InstructionSizeInBytes, 5408 EmissionCheckScope::kExactSize); 5409 __ B(&start, kFar); 5410 } 5411 { 5412 ExactAssemblyScope scope(&masm, 5413 kBNarrowRange, 5414 ExactAssemblyScope::kExactSize); 5415 for (int32_t i = 0; i < kBNarrowRange; 5416 i += k16BitT32InstructionSizeInBytes) { 5417 __ nop(); 5418 } 5419 } 5420 { 5421 // Generate a branch which should be wide. 5422 EmissionCheckScope scope(&masm, 5423 k32BitT32InstructionSizeInBytes, 5424 EmissionCheckScope::kExactSize); 5425 __ B(&start, kFar); 5426 } 5427 { 5428 // Generate a forward branch which should be wide. 5429 EmissionCheckScope scope(&masm, 5430 k32BitT32InstructionSizeInBytes, 5431 EmissionCheckScope::kExactSize); 5432 __ B(&end, kFar); 5433 } 5434 5435 __ Bind(&end); 5436 5437 END(); 5438 5439 DISASSEMBLE(); 5440 5441 TEARDOWN(); 5442 } 5443 5444 5445 // Check that conditional B with a near hint use a narrow branch when it can. 5446 TEST_T32(b_conditional_near_hint) { 5447 SETUP(); 5448 START(); 5449 5450 Label start; 5451 Label end; 5452 5453 __ Bind(&start); 5454 __ Nop(); 5455 { 5456 // Generate a branch which should be narrow. 5457 EmissionCheckScope scope(&masm, 5458 k16BitT32InstructionSizeInBytes, 5459 EmissionCheckScope::kExactSize); 5460 __ B(eq, &start, kNear); 5461 } 5462 { 5463 ExactAssemblyScope scope(&masm, 5464 kBConditionalNarrowRange, 5465 ExactAssemblyScope::kExactSize); 5466 for (int32_t i = 0; i < kBConditionalNarrowRange; 5467 i += k16BitT32InstructionSizeInBytes) { 5468 __ nop(); 5469 } 5470 } 5471 { 5472 // Generate a branch which should be wide. 5473 EmissionCheckScope scope(&masm, 5474 k32BitT32InstructionSizeInBytes, 5475 EmissionCheckScope::kExactSize); 5476 __ B(eq, &start, kNear); 5477 } 5478 { 5479 // Generate a forward branch which should be narrow. 5480 EmissionCheckScope scope(&masm, 5481 k16BitT32InstructionSizeInBytes, 5482 EmissionCheckScope::kExactSize); 5483 __ B(eq, &end, kNear); 5484 } 5485 5486 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() < kBConditionalNarrowRange); 5487 5488 { 5489 ExactAssemblyScope scope(&masm, 5490 kBConditionalNarrowRange, 5491 ExactAssemblyScope::kExactSize); 5492 for (int32_t i = 0; i < kBConditionalNarrowRange; 5493 i += k16BitT32InstructionSizeInBytes) { 5494 __ nop(); 5495 } 5496 } 5497 5498 // A veneer should have been generated. 5499 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() > kBConditionalNarrowRange); 5500 5501 __ Bind(&end); 5502 5503 END(); 5504 5505 DISASSEMBLE(); 5506 5507 TEARDOWN(); 5508 } 5509 5510 5511 // Check that conditional B with a far hint use a narrow branch only for a 5512 // near backward branch. 5513 TEST_T32(b_conditional_far_hint) { 5514 SETUP(); 5515 START(); 5516 5517 Label start; 5518 Label end; 5519 5520 __ Bind(&start); 5521 __ Nop(); 5522 5523 { 5524 // Generate a branch which should be narrow. 5525 EmissionCheckScope scope(&masm, 5526 k16BitT32InstructionSizeInBytes, 5527 EmissionCheckScope::kExactSize); 5528 __ B(eq, &start, kFar); 5529 } 5530 { 5531 ExactAssemblyScope scope(&masm, 5532 kBConditionalNarrowRange, 5533 ExactAssemblyScope::kExactSize); 5534 for (int32_t i = 0; i < kBConditionalNarrowRange; 5535 i += k16BitT32InstructionSizeInBytes) { 5536 __ nop(); 5537 } 5538 } 5539 { 5540 // Generate a branch which should be wide. 5541 EmissionCheckScope scope(&masm, 5542 k32BitT32InstructionSizeInBytes, 5543 EmissionCheckScope::kExactSize); 5544 __ B(eq, &start, kFar); 5545 } 5546 { 5547 // Generate a forward branch which should be wide. 5548 EmissionCheckScope scope(&masm, 5549 k32BitT32InstructionSizeInBytes, 5550 EmissionCheckScope::kExactSize); 5551 __ B(eq, &end, kFar); 5552 } 5553 5554 __ Bind(&end); 5555 5556 END(); 5557 5558 DISASSEMBLE(); 5559 5560 TEARDOWN(); 5561 } 5562 5563 5564 // Check that the veneer pool is correctly emitted even if we do a lot of narrow 5565 // branches. 5566 TEST_T32(b_narrow_many) { 5567 SETUP(); 5568 START(); 5569 5570 static const int kLabelsCount = kBNarrowRange / 2; 5571 5572 Label labels[kLabelsCount]; 5573 5574 __ Mov(r0, 0); 5575 5576 for (int i = 0; i < kLabelsCount; i++) { 5577 __ B(&labels[i], kNear); 5578 } 5579 5580 __ Mov(r0, 1); 5581 for (int i = 0; i < kLabelsCount; i++) { 5582 __ Bind(&labels[i]); 5583 } 5584 __ Nop(); 5585 5586 END(); 5587 5588 RUN(); 5589 5590 ASSERT_EQUAL_32(0, r0); 5591 5592 TEARDOWN(); 5593 } 5594 5595 5596 // Check that the veneer pool is correctly emitted even if we do a lot of narrow 5597 // branches and cbz. 5598 TEST_T32(b_narrow_and_cbz) { 5599 SETUP(); 5600 START(); 5601 5602 static const int kLabelsCount = kBNarrowRange / 4; 5603 5604 Label b_labels[kLabelsCount]; 5605 Label cbz_labels[kLabelsCount]; 5606 5607 __ Mov(r0, 0); 5608 5609 for (int i = 0; i < kLabelsCount; i++) { 5610 __ B(&b_labels[i], kNear); 5611 __ Cbz(r0, &cbz_labels[i]); 5612 } 5613 5614 __ Mov(r0, 1); 5615 for (int i = 0; i < kLabelsCount; i++) { 5616 __ Bind(&b_labels[i]); 5617 } 5618 5619 __ Mov(r0, 2); 5620 for (int i = 0; i < kLabelsCount; i++) { 5621 __ Bind(&cbz_labels[i]); 5622 } 5623 5624 __ Nop(); 5625 5626 END(); 5627 5628 RUN(); 5629 5630 ASSERT_EQUAL_32(2, r0); 5631 5632 TEARDOWN(); 5633 } 5634 5635 5636 #define CHECK_SIZE_MATCH(ASM1, ASM2) \ 5637 { \ 5638 MacroAssembler masm1(BUF_SIZE); \ 5639 masm1.UseInstructionSet(isa); \ 5640 VIXL_ASSERT(masm1.GetCursorOffset() == 0); \ 5641 masm1.ASM1; \ 5642 masm1.FinalizeCode(); \ 5643 int size1 = masm1.GetCursorOffset(); \ 5644 \ 5645 MacroAssembler masm2(BUF_SIZE); \ 5646 masm2.UseInstructionSet(isa); \ 5647 VIXL_ASSERT(masm2.GetCursorOffset() == 0); \ 5648 masm2.ASM2; \ 5649 masm2.FinalizeCode(); \ 5650 int size2 = masm2.GetCursorOffset(); \ 5651 \ 5652 bool disassemble = Test::disassemble(); \ 5653 if (size1 != size2) { \ 5654 printf("Sizes did not match:\n"); \ 5655 disassemble = true; \ 5656 } \ 5657 if (disassemble) { \ 5658 PrintDisassembler dis(std::cout, 0); \ 5659 printf("// " #ASM1 "\n"); \ 5660 if (masm1.IsUsingT32()) { \ 5661 dis.DisassembleT32Buffer(masm1.GetBuffer() \ 5662 ->GetStartAddress<uint16_t*>(), \ 5663 size1); \ 5664 } else { \ 5665 dis.DisassembleA32Buffer(masm1.GetBuffer() \ 5666 ->GetStartAddress<uint32_t*>(), \ 5667 size1); \ 5668 } \ 5669 printf("\n"); \ 5670 \ 5671 dis.SetCodeAddress(0); \ 5672 printf("// " #ASM2 "\n"); \ 5673 if (masm2.IsUsingT32()) { \ 5674 dis.DisassembleT32Buffer(masm2.GetBuffer() \ 5675 ->GetStartAddress<uint16_t*>(), \ 5676 size2); \ 5677 } else { \ 5678 dis.DisassembleA32Buffer(masm2.GetBuffer() \ 5679 ->GetStartAddress<uint32_t*>(), \ 5680 size2); \ 5681 } \ 5682 printf("\n"); \ 5683 } \ 5684 VIXL_CHECK(size1 == size2); \ 5685 } 5686 5687 5688 TEST_T32(macro_assembler_commute) { 5689 // Test that the MacroAssembler will commute operands if it means it can use a 5690 // 16-bit instruction with the same effect. 5691 5692 // TODO: The commented-out tests should pass, but don't. When they are fixed, 5693 // we should update this test. 5694 5695 // CHECK_SIZE_MATCH(Adc(DontCare, r7, r6, r7), 5696 // Adc(DontCare, r7, r7, r6)); 5697 5698 // CHECK_SIZE_MATCH(Adc(DontCare, eq, r7, r6, r7), 5699 // Adc(DontCare, eq, r7, r7, r6)); 5700 5701 CHECK_SIZE_MATCH(Add(DontCare, r1, r2, r7), Add(DontCare, r1, r7, r2)); 5702 5703 CHECK_SIZE_MATCH(Add(DontCare, lt, r1, r2, r7), 5704 Add(DontCare, lt, r1, r7, r2)); 5705 5706 // CHECK_SIZE_MATCH(Add(DontCare, r4, r4, r10), 5707 // Add(DontCare, r4, r10, r4)); 5708 5709 // CHECK_SIZE_MATCH(Add(DontCare, eq, r4, r4, r10), 5710 // Add(DontCare, eq, r4, r10, r4)); 5711 5712 // CHECK_SIZE_MATCH(Add(DontCare, r7, sp, r7), 5713 // Add(DontCare, r7, r7, sp)); 5714 5715 // CHECK_SIZE_MATCH(Add(DontCare, eq, r7, sp, r7), 5716 // Add(DontCare, eq, r7, r7, sp)); 5717 5718 // CHECK_SIZE_MATCH(Add(DontCare, sp, sp, r10), 5719 // Add(DontCare, sp, r10, sp)); 5720 5721 // CHECK_SIZE_MATCH(Add(DontCare, eq, sp, sp, r10), 5722 // Add(DontCare, eq, sp, r10, sp)); 5723 5724 // CHECK_SIZE_MATCH(And(DontCare, r7, r7, r6), 5725 // And(DontCare, r7, r6, r7)); 5726 5727 // CHECK_SIZE_MATCH(And(DontCare, eq, r7, r7, r6), 5728 // And(DontCare, eq, r7, r6, r7)); 5729 5730 // CHECK_SIZE_MATCH(Eor(DontCare, r7, r7, r6), 5731 // Eor(DontCare, r7, r6, r7)); 5732 5733 // CHECK_SIZE_MATCH(Eor(DontCare, eq, r7, r7, r6), 5734 // Eor(DontCare, eq, r7, r6, r7)); 5735 5736 // CHECK_SIZE_MATCH(Mul(DontCare, r0, r1, r0), 5737 // Mul(DontCare, r0, r0, r1)); 5738 5739 // CHECK_SIZE_MATCH(Mul(DontCare, eq, r0, r1, r0), 5740 // Mul(DontCare, eq, r0, r0, r1)); 5741 5742 // CHECK_SIZE_MATCH(Orr(DontCare, r7, r7, r6), 5743 // Orr(DontCare, r7, r6, r7)); 5744 5745 // CHECK_SIZE_MATCH(Orr(DontCare, eq, r7, r7, r6), 5746 // Orr(DontCare, eq, r7, r6, r7)); 5747 5748 5749 CHECK_SIZE_MATCH(Adc(r7, r6, r7), Adc(r7, r7, r6)); 5750 5751 // CHECK_SIZE_MATCH(Adc(eq, r7, r6, r7), 5752 // Adc(eq, r7, r7, r6)); 5753 5754 CHECK_SIZE_MATCH(Add(r1, r2, r7), Add(r1, r7, r2)); 5755 5756 CHECK_SIZE_MATCH(Add(lt, r1, r2, r7), Add(lt, r1, r7, r2)); 5757 5758 // CHECK_SIZE_MATCH(Add(r4, r4, r10), 5759 // Add(r4, r10, r4)); 5760 5761 // CHECK_SIZE_MATCH(Add(eq, r4, r4, r10), 5762 // Add(eq, r4, r10, r4)); 5763 5764 // CHECK_SIZE_MATCH(Add(r7, sp, r7), 5765 // Add(r7, r7, sp)); 5766 5767 // CHECK_SIZE_MATCH(Add(eq, r7, sp, r7), 5768 // Add(eq, r7, r7, sp)); 5769 5770 // CHECK_SIZE_MATCH(Add(sp, sp, r10), 5771 // Add(sp, r10, sp)); 5772 5773 // CHECK_SIZE_MATCH(Add(eq, sp, sp, r10), 5774 // Add(eq, sp, r10, sp)); 5775 5776 CHECK_SIZE_MATCH(And(r7, r7, r6), And(r7, r6, r7)); 5777 5778 // CHECK_SIZE_MATCH(And(eq, r7, r7, r6), 5779 // And(eq, r7, r6, r7)); 5780 5781 CHECK_SIZE_MATCH(Eor(r7, r7, r6), Eor(r7, r6, r7)); 5782 5783 // CHECK_SIZE_MATCH(Eor(eq, r7, r7, r6), 5784 // Eor(eq, r7, r6, r7)); 5785 5786 CHECK_SIZE_MATCH(Mul(r0, r1, r0), Mul(r0, r0, r1)); 5787 5788 // CHECK_SIZE_MATCH(Mul(eq, r0, r1, r0), 5789 // Mul(eq, r0, r0, r1)); 5790 5791 CHECK_SIZE_MATCH(Orr(r7, r7, r6), Orr(r7, r6, r7)); 5792 5793 // CHECK_SIZE_MATCH(Orr(eq, r7, r7, r6), 5794 // Orr(eq, r7, r6, r7)); 5795 5796 5797 // CHECK_SIZE_MATCH(Adcs(r7, r6, r7), 5798 // Adcs(r7, r7, r6)); 5799 5800 // CHECK_SIZE_MATCH(Adcs(eq, r7, r6, r7), 5801 // Adcs(eq, r7, r7, r6)); 5802 5803 CHECK_SIZE_MATCH(Adds(r1, r2, r7), Adds(r1, r7, r2)); 5804 5805 CHECK_SIZE_MATCH(Adds(lt, r1, r2, r7), Adds(lt, r1, r7, r2)); 5806 5807 CHECK_SIZE_MATCH(Adds(r4, r4, r10), Adds(r4, r10, r4)); 5808 5809 CHECK_SIZE_MATCH(Adds(eq, r4, r4, r10), Adds(eq, r4, r10, r4)); 5810 5811 CHECK_SIZE_MATCH(Adds(r7, sp, r7), Adds(r7, r7, sp)); 5812 5813 CHECK_SIZE_MATCH(Adds(eq, r7, sp, r7), Adds(eq, r7, r7, sp)); 5814 5815 CHECK_SIZE_MATCH(Adds(sp, sp, r10), Adds(sp, r10, sp)); 5816 5817 CHECK_SIZE_MATCH(Adds(eq, sp, sp, r10), Adds(eq, sp, r10, sp)); 5818 5819 // CHECK_SIZE_MATCH(Ands(r7, r7, r6), 5820 // Ands(r7, r6, r7)); 5821 5822 // CHECK_SIZE_MATCH(Ands(eq, r7, r7, r6), 5823 // Ands(eq, r7, r6, r7)); 5824 5825 // CHECK_SIZE_MATCH(Eors(r7, r7, r6), 5826 // Eors(r7, r6, r7)); 5827 5828 // CHECK_SIZE_MATCH(Eors(eq, r7, r7, r6), 5829 // Eors(eq, r7, r6, r7)); 5830 5831 // CHECK_SIZE_MATCH(Muls(r0, r1, r0), 5832 // Muls(r0, r0, r1)); 5833 5834 // CHECK_SIZE_MATCH(Muls(eq, r0, r1, r0), 5835 // Muls(eq, r0, r0, r1)); 5836 5837 // CHECK_SIZE_MATCH(Orrs(r7, r7, r6), 5838 // Orrs(r7, r6, r7)); 5839 5840 // CHECK_SIZE_MATCH(Orrs(eq, r7, r7, r6), 5841 // Orrs(eq, r7, r6, r7)); 5842 } 5843 5844 5845 } // namespace aarch32 5846 } // namespace vixl 5847