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