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