test-assembler-aarch32.cc revision e44090587ff7104b4ad3f786e64940c82838387c
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// Tests declared with this macro will be run twice: once targeting A32 and 44// once targeting T32. 45#define TEST(Name) \ 46void Test##Name##Impl(InstructionSet isa); \ 47void Test##Name() { \ 48 Test##Name##Impl(A32); \ 49 printf(" > A32 done\n"); \ 50 Test##Name##Impl(T32); \ 51 printf(" > T32 done\n"); \ 52} \ 53Test test_##Name(STRINGIFY(AARCH32_ASM_##Name), &Test##Name); \ 54void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 55 56// Test declared with this macro will only target A32. 57#define TEST_A32(Name) \ 58void Test##Name##Impl(InstructionSet isa); \ 59void Test##Name() { \ 60 Test##Name##Impl(A32); \ 61} \ 62Test test_##Name(STRINGIFY(AARCH32_A32_##Name), &Test##Name); \ 63void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 64 65// Tests declared with this macro will only target T32. 66#define TEST_T32(Name) \ 67void Test##Name##Impl(InstructionSet isa); \ 68void Test##Name() { \ 69 Test##Name##Impl(T32); \ 70} \ 71Test test_##Name(STRINGIFY(AARCH32_T32_##Name), &Test##Name); \ 72void Test##Name##Impl(InstructionSet isa __attribute__((unused))) 73 74// Tests declared with this macro are not expected to use any provided test 75// helpers such as SETUP, RUN, etc. 76#define TEST_NOASM(Name) \ 77void Test##Name(); \ 78Test test_##Name(STRINGIFY(AARCH32_##Name), &Test##Name); \ 79void Test##Name() 80 81#define __ masm. 82#define BUF_SIZE (4096) 83 84#define ASSERT_LITERAL_POOL_SIZE(size) \ 85 do { VIXL_CHECK(__ GetLiteralPoolSize() == size); } while (false) 86 87#ifdef VIXL_INCLUDE_SIMULATOR_AARCH32 88// No simulator yet. 89 90#define SETUP() \ 91 MacroAssembler masm(BUF_SIZE, isa); \ 92 93#define START() \ 94 masm.GetBuffer()->Reset(); 95 96#define END() \ 97 __ Hlt(0); \ 98 __ FinalizeCode(); 99 100#define RUN() \ 101 DISASSEMBLE(); 102 103#define TEARDOWN() 104 105#else // ifdef VIXL_INCLUDE_SIMULATOR_AARCH32. 106 107#define SETUP() \ 108 RegisterDump core; \ 109 MacroAssembler masm(BUF_SIZE, isa); \ 110 UseScratchRegisterScope harness_scratch(&masm); \ 111 harness_scratch.ExcludeAll(); 112 113#define START() \ 114 masm.GetBuffer()->Reset(); \ 115 __ Push(r4); \ 116 __ Push(r5); \ 117 __ Push(r6); \ 118 __ Push(r7); \ 119 __ Push(r8); \ 120 __ Push(r9); \ 121 __ Push(r10); \ 122 __ Push(r11); \ 123 __ Push(ip); \ 124 __ Push(lr); \ 125 __ Mov(r0, 0); \ 126 __ Msr(APSR_nzcvq, r0); \ 127 harness_scratch.Include(ip); 128 129#define END() \ 130 harness_scratch.Exclude(ip); \ 131 core.Dump(&masm); \ 132 __ Pop(lr); \ 133 __ Pop(ip); \ 134 __ Pop(r11); \ 135 __ Pop(r10); \ 136 __ Pop(r9); \ 137 __ Pop(r8); \ 138 __ Pop(r7); \ 139 __ Pop(r6); \ 140 __ Pop(r5); \ 141 __ Pop(r4); \ 142 __ Bx(lr); \ 143 __ FinalizeCode(); 144 145// Execute the generated code from the MacroAssembler's automatic code buffer. 146// Note the offset for ExecuteMemory since the PCS requires that 147// the address be odd in the case of branching to T32 code. 148#define RUN() \ 149 DISASSEMBLE(); \ 150 { \ 151 int pcs_offset = masm.IsUsingT32() ? 1 : 0; \ 152 masm.GetBuffer()->SetExecutable(); \ 153 ExecuteMemory(masm.GetBuffer()->GetStartAddress<byte*>(), \ 154 masm.GetSizeOfCodeGenerated(), \ 155 pcs_offset); \ 156 masm.GetBuffer()->SetWritable(); \ 157 } 158 159#define TEARDOWN() \ 160 harness_scratch.Close(); 161 162#endif // ifdef VIXL_INCLUDE_SIMULATOR_AARCH32 163 164#ifdef VIXL_INCLUDE_SIMULATOR_AARCH32 165// No simulator yet. We can't test the results. 166 167#define ASSERT_EQUAL_32(expected, result) 168 169#define ASSERT_EQUAL_64(expected, result) 170 171#define ASSERT_EQUAL_128(expected_h, expected_l, result) 172 173#define ASSERT_EQUAL_FP32(expected, result) 174 175#define ASSERT_EQUAL_FP64(expected, result) 176 177#define ASSERT_EQUAL_NZCV(expected) 178 179#else 180 181#define ASSERT_EQUAL_32(expected, result) \ 182 VIXL_CHECK(Equal32(expected, &core, result)) 183 184#define ASSERT_EQUAL_64(expected, result) \ 185 VIXL_CHECK(Equal64(expected, &core, result)) 186 187#define ASSERT_EQUAL_128(expected_h, expected_l, result) \ 188 VIXL_CHECK(Equal128(expected_h, expected_l, &core, result)) 189 190#define ASSERT_EQUAL_FP32(expected, result) \ 191 VIXL_CHECK(EqualFP32(expected, &core, result)) 192 193#define ASSERT_EQUAL_FP64(expected, result) \ 194 VIXL_CHECK(EqualFP64(expected, &core, result)) 195 196#define ASSERT_EQUAL_NZCV(expected) \ 197 VIXL_CHECK(EqualNzcv(expected, core.flags_nzcv())) 198 199#endif 200 201#define DISASSEMBLE() \ 202 if (Test::disassemble()) { \ 203 PrintDisassembler dis(std::cout, 0); \ 204 if (masm.IsUsingT32()) { \ 205 dis.DisassembleT32Buffer(masm.GetBuffer()->GetStartAddress<uint16_t*>(), \ 206 masm.GetCursorOffset()); \ 207 } else { \ 208 dis.DisassembleA32Buffer(masm.GetBuffer()->GetStartAddress<uint32_t*>(), \ 209 masm.GetCursorOffset()); \ 210 } \ 211 } 212 213// TODO: Add SBC to the ADC tests. 214 215 216TEST(adc_shift) { 217 SETUP(); 218 219 START(); 220 // Initialize registers. 221 __ Mov(r0, 0); 222 __ Mov(r1, 1); 223 __ Mov(r2, 0x01234567); 224 __ Mov(r3, 0xfedcba98); 225 226 // Clear the C flag. 227 __ Adds(r0, r0, 0); 228 229 __ Adc(r4, r2, r3); 230 __ Adc(r5, r0, Operand(r1, LSL, 30)); 231 __ Adc(r6, r0, Operand(r2, LSR, 16)); 232 __ Adc(r7, r2, Operand(r3, ASR, 4)); 233 __ Adc(r8, r2, Operand(r3, ROR, 8)); 234 __ Adc(r9, r2, Operand(r3, RRX)); 235 END(); 236 237 RUN(); 238 239 ASSERT_EQUAL_32(0xffffffff, r4); 240 ASSERT_EQUAL_32(INT32_C(1) << 30, r5); 241 ASSERT_EQUAL_32(0x00000123, r6); 242 ASSERT_EQUAL_32(0x01111110, r7); 243 ASSERT_EQUAL_32(0x9a222221, r8); 244 ASSERT_EQUAL_32(0x8091a2b3, r9); 245 246 START(); 247 // Initialize registers. 248 __ Mov(r0, 0); 249 __ Mov(r1, 1); 250 __ Mov(r2, 0x01234567); 251 __ Mov(r3, 0xfedcba98); 252 __ Mov(r4, 0xffffffff); 253 254 // Set the C flag. 255 __ Adds(r0, r4, r1); 256 257 __ Adc(r5, r2, r3); 258 __ Adc(r6, r0, Operand(r1, LSL, 30)); 259 __ Adc(r7, r0, Operand(r2, LSR, 16)); 260 __ Adc(r8, r2, Operand(r3, ASR, 4)); 261 __ Adc(r9, r2, Operand(r3, ROR, 8)); 262 __ Adc(r10, r2, Operand(r3, RRX)); 263 END(); 264 265 RUN(); 266 267 ASSERT_EQUAL_32(0xffffffff + 1, r5); 268 ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, r6); 269 ASSERT_EQUAL_32(0x00000123 + 1, r7); 270 ASSERT_EQUAL_32(0x01111110 + 1, r8); 271 ASSERT_EQUAL_32(0x9a222221 + 1, r9); 272 ASSERT_EQUAL_32(0x0091a2b3 + 1, r10); 273 274 // Check that adc correctly sets the condition flags. 275 START(); 276 __ Mov(r0, 0); 277 __ Mov(r1, 0xffffffff); 278 __ Mov(r2, 1); 279 280 // Clear the C flag. 281 __ Adds(r0, r0, 0); 282 __ Adcs(r3, r2, r1); 283 END(); 284 285 RUN(); 286 287 ASSERT_EQUAL_NZCV(ZCFlag); 288 ASSERT_EQUAL_32(0, r3); 289 290 START(); 291 __ Mov(r0, 0); 292 __ Mov(r1, 0x80000000); 293 __ Mov(r2, 1); 294 295 // Clear the C flag. 296 __ Adds(r0, r0, 0); 297 __ Adcs(r3, r2, Operand(r1, ASR, 31)); 298 END(); 299 300 RUN(); 301 302 ASSERT_EQUAL_NZCV(ZCFlag); 303 ASSERT_EQUAL_32(0, r3); 304 305 START(); 306 __ Mov(r0, 0); 307 __ Mov(r1, 0x80000000); 308 __ Mov(r2, 0xffffffff); 309 310 // Clear the C flag. 311 __ Adds(r0, r0, 0); 312 __ Adcs(r3, r2, Operand(r1, LSR, 31)); 313 END(); 314 315 RUN(); 316 317 ASSERT_EQUAL_NZCV(ZCFlag); 318 ASSERT_EQUAL_32(0, r3); 319 320 START(); 321 __ Mov(r0, 0); 322 __ Mov(r1, 0x07ffffff); 323 __ Mov(r2, 0x10); 324 325 // Clear the C flag. 326 __ Adds(r0, r0, 0); 327 __ Adcs(r3, r2, Operand(r1, LSL, 4)); 328 END(); 329 330 RUN(); 331 332 ASSERT_EQUAL_NZCV(NVFlag); 333 ASSERT_EQUAL_32(0x080000000, r3); 334 335 START(); 336 __ Mov(r0, 0); 337 __ Mov(r1, 0xffffff00); 338 __ Mov(r2, 0xff000001); 339 340 // Clear the C flag. 341 __ Adds(r0, r0, 0); 342 __ Adcs(r3, r2, Operand(r1, ROR, 8)); 343 END(); 344 345 RUN(); 346 347 ASSERT_EQUAL_NZCV(ZCFlag); 348 ASSERT_EQUAL_32(0, r3); 349 350 START(); 351 __ Mov(r0, 0); 352 __ Mov(r1, 0xffffffff); 353 __ Mov(r2, 0x1); 354 355 // Clear the C flag, forcing RRX to insert 0 in r1's most significant bit. 356 __ Adds(r0, r0, 0); 357 __ Adcs(r3, r2, Operand(r1, RRX)); 358 END(); 359 360 RUN(); 361 362 ASSERT_EQUAL_NZCV(NVFlag); 363 ASSERT_EQUAL_32(0x80000000, r3); 364 365 START(); 366 __ Mov(r0, 0); 367 __ Mov(r1, 0xffffffff); 368 __ Mov(r2, 0x1); 369 370 // Set the C flag, forcing RRX to insert 1 in r1's most significant bit. 371 __ Adds(r0, r1, r2); 372 __ Adcs(r3, r2, Operand(r1, RRX)); 373 END(); 374 375 RUN(); 376 377 ASSERT_EQUAL_NZCV(CFlag); 378 ASSERT_EQUAL_32(1, r3); 379 380 TEARDOWN(); 381} 382 383 384TEST(adc_wide_imm) { 385 SETUP(); 386 387 START(); 388 __ Mov(r0, 0); 389 390 // Clear the C flag. 391 __ Adds(r0, r0, 0); 392 393 __ Adc(r1, r0, 0x12345678); 394 __ Adc(r2, r0, 0xffffffff); 395 396 // Set the C flag. 397 __ Cmp(r0, r0); 398 399 __ Adc(r3, r0, 0x12345678); 400 __ Adc(r4, r0, 0xffffffff); 401 END(); 402 403 RUN(); 404 405 ASSERT_EQUAL_32(0x12345678, r1); 406 ASSERT_EQUAL_32(0xffffffff, r2); 407 ASSERT_EQUAL_32(0x12345678 + 1, r3); 408 ASSERT_EQUAL_32(0, r4); 409 410 TEARDOWN(); 411} 412 413 414// TODO: Add SUB tests to the ADD tests. 415 416 417TEST(add_imm) { 418 SETUP(); 419 420 START(); 421 __ Mov(r0, 0); 422 __ Mov(r1, 0x1111); 423 __ Mov(r2, 0xffffffff); 424 __ Mov(r3, 0x80000000); 425 426 __ Add(r4, r0, 0x12); 427 __ Add(r5, r1, 0x120000); 428 __ Add(r6, r0, 0xab << 12); 429 __ Add(r7, r2, 1); 430 431 END(); 432 433 RUN(); 434 435 ASSERT_EQUAL_32(0x12, r4); 436 ASSERT_EQUAL_32(0x121111, r5); 437 ASSERT_EQUAL_32(0xab000, r6); 438 ASSERT_EQUAL_32(0x0, r7); 439 440 TEARDOWN(); 441} 442 443 444TEST(add_wide_imm) { 445 SETUP(); 446 447 START(); 448 __ Mov(r0, 0); 449 __ Mov(r1, 1); 450 451 __ Add(r2, r0, 0x12345678); 452 __ Add(r3, r1, 0xffff); 453 END(); 454 455 RUN(); 456 457 ASSERT_EQUAL_32(0x12345678, r2); 458 ASSERT_EQUAL_32(0x00010000, r3); 459 460 TEARDOWN(); 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 TEARDOWN(); 500} 501 502 503TEST(and_) { 504 SETUP(); 505 506 START(); 507 __ Mov(r0, 0x0000fff0); 508 __ Mov(r1, 0xf00000ff); 509 __ Mov(r2, 0xffffffff); 510 511 __ And(r3, r0, r1); 512 __ And(r4, r0, Operand(r1, LSL, 4)); 513 __ And(r5, r0, Operand(r1, LSR, 1)); 514 __ And(r6, r0, Operand(r1, ASR, 20)); 515 __ And(r7, r0, Operand(r1, ROR, 28)); 516 __ And(r8, r0, 0xff); 517 518 // Set the C flag. 519 __ Adds(r9, r2, 1); 520 __ And(r9, r1, Operand(r1, RRX)); 521 522 // Clear the C flag. 523 __ Adds(r10, r0, 0); 524 __ And(r10, r1, Operand(r1, RRX)); 525 END(); 526 527 RUN(); 528 529 ASSERT_EQUAL_32(0x000000f0, r3); 530 ASSERT_EQUAL_32(0x00000ff0, r4); 531 ASSERT_EQUAL_32(0x00000070, r5); 532 ASSERT_EQUAL_32(0x0000ff00, r6); 533 ASSERT_EQUAL_32(0x00000ff0, r7); 534 ASSERT_EQUAL_32(0x000000f0, r8); 535 ASSERT_EQUAL_32(0xf000007f, r9); 536 ASSERT_EQUAL_32(0x7000007f, r10); 537 538 TEARDOWN(); 539} 540 541 542TEST(ands) { 543 SETUP(); 544 545 START(); 546 __ Mov(r0, 0); 547 __ Mov(r1, 0xf00000ff); 548 549 __ Ands(r0, r1, r1); 550 END(); 551 552 RUN(); 553 554 ASSERT_EQUAL_NZCV(NFlag); 555 ASSERT_EQUAL_32(0xf00000ff, r0); 556 557 START(); 558 __ Mov(r0, 0x00fff000); 559 __ Mov(r1, 0xf00000ff); 560 561 __ Ands(r0, r0, Operand(r1, LSL, 4)); 562 END(); 563 564 RUN(); 565 566 ASSERT_EQUAL_NZCV(ZCFlag); 567 ASSERT_EQUAL_32(0x00000000, r0); 568 569 START(); 570 __ Mov(r0, 0x0000fff0); 571 __ Mov(r1, 0xf00000ff); 572 573 __ Ands(r0, r0, Operand(r1, LSR, 4)); 574 END(); 575 576 RUN(); 577 578 ASSERT_EQUAL_NZCV(ZCFlag); 579 ASSERT_EQUAL_32(0x00000000, r0); 580 581 START(); 582 __ Mov(r0, 0xf000fff0); 583 __ Mov(r1, 0xf00000ff); 584 585 __ Ands(r0, r0, Operand(r1, ASR, 4)); 586 END(); 587 588 RUN(); 589 590 ASSERT_EQUAL_NZCV(NCFlag); 591 ASSERT_EQUAL_32(0xf0000000, r0); 592 593 START(); 594 __ Mov(r0, 0x80000000); 595 __ Mov(r1, 0x00000001); 596 597 __ Ands(r0, r0, Operand(r1, ROR, 1)); 598 END(); 599 600 RUN(); 601 602 ASSERT_EQUAL_NZCV(NCFlag); 603 ASSERT_EQUAL_32(0x80000000, r0); 604 605 START(); 606 __ Mov(r0, 0x80000000); 607 __ Mov(r1, 0x80000001); 608 609 // Clear the C flag, forcing RRX to insert 0 in r1's most significant bit. 610 __ Adds(r2, r0, 0); 611 __ Ands(r2, r0, Operand(r1, RRX)); 612 END(); 613 614 RUN(); 615 616 ASSERT_EQUAL_NZCV(ZCFlag); 617 ASSERT_EQUAL_32(0, r2); 618 619 START(); 620 __ Mov(r0, 0x80000000); 621 __ Mov(r1, 0x80000001); 622 __ Mov(r2, 0xffffffff); 623 624 // Set the C flag, forcing RRX to insert 1 in r1's most significant bit. 625 __ Adds(r2, r2, 1); 626 __ Ands(r2, r0, Operand(r1, RRX)); 627 END(); 628 629 RUN(); 630 631 ASSERT_EQUAL_NZCV(NCFlag); 632 ASSERT_EQUAL_32(0x80000000, r2); 633 634 START(); 635 __ Mov(r0, 0xfff0); 636 637 __ Ands(r0, r0, 0xf); 638 END(); 639 640 RUN(); 641 642 ASSERT_EQUAL_NZCV(ZFlag); 643 ASSERT_EQUAL_32(0x00000000, r0); 644 645 START(); 646 __ Mov(r0, 0xff000000); 647 648 __ Ands(r0, r0, 0x80000000); 649 END(); 650 651 RUN(); 652 653 ASSERT_EQUAL_NZCV(NCFlag); 654 ASSERT_EQUAL_32(0x80000000, r0); 655 656 TEARDOWN(); 657} 658 659 660// TODO: fix this test in T32. 661TEST_A32(adr) { 662 SETUP(); 663 664 Label label_1, label_2, label_3, label_4; 665 666 START(); 667 __ Mov(r0, 0x0); 668 __ Adr(r1, &label_3); // Set to zero to indicate success. 669 670 __ Adr(r2, &label_1); // Multiple forward references to the same label. 671 __ Adr(r3, &label_1); 672 __ Adr(r4, &label_1); 673 674 __ Bind(&label_2); 675 __ Eor(r5, r2, r3); // Ensure that r2,r3 and r4 are identical. 676 __ Eor(r6, r2, r4); 677 __ Mov(r0, r5); 678 __ Mov(r0, r6); 679 __ Bx(r2); // label_1, label_3 680 681 __ Bind(&label_3); 682 __ Adr(r2, &label_3); // Self-reference (offset 0). 683 __ Eor(r1, r1, r2); 684 __ Adr(r2, &label_4); // Simple forward reference. 685 __ Bx(r2); // label_4 686 687 __ Bind(&label_1); 688 __ Adr(r2, &label_3); // Multiple reverse references to the same label. 689 __ Adr(r3, &label_3); 690 __ Adr(r4, &label_3); 691 __ Adr(r5, &label_2); // Simple reverse reference. 692 __ Bx(r5); // label_2 693 694 __ Bind(&label_4); 695 END(); 696 697 RUN(); 698 699 ASSERT_EQUAL_32(0x0, r0); 700 ASSERT_EQUAL_32(0x0, r1); 701 702 TEARDOWN(); 703} 704 705 706TEST(shift_imm) { 707 SETUP(); 708 709 START(); 710 __ Mov(r0, 0); 711 __ Mov(r1, 0xfedcba98); 712 __ Mov(r2, 0xffffffff); 713 714 __ Lsl(r3, r1, 4); 715 __ Lsr(r4, r1, 8); 716 __ Asr(r5, r1, 16); 717 __ Ror(r6, r1, 20); 718 END(); 719 720 RUN(); 721 722 ASSERT_EQUAL_32(0xedcba980, r3); 723 ASSERT_EQUAL_32(0x00fedcba, r4); 724 ASSERT_EQUAL_32(0xfffffedc, r5); 725 ASSERT_EQUAL_32(0xcba98fed, r6); 726 727 TEARDOWN(); 728} 729 730 731TEST(shift_reg) { 732 SETUP(); 733 734 START(); 735 __ Mov(r0, 0); 736 __ Mov(r1, 0xfedcba98); 737 __ Mov(r2, 0xffffffff); 738 739 __ Add(r9, r0, 4); 740 __ Lsl(r3, r1, r9); 741 742 __ Add(r9, r0, 8); 743 __ Lsr(r4, r1, r9); 744 745 __ Add(r9, r0, 16); 746 __ Asr(r5, r1, r9); 747 748 __ Add(r9, r0, 20); 749 __ Ror(r6, r1, r9); 750 751 // Set the C flag. 752 __ Adds(r7, r2, 1); 753 __ Rrx(r7, r1); 754 755 // Clear the C flag. 756 __ Adds(r8, r0, 0); 757 __ Rrx(r8, r1); 758 END(); 759 760 RUN(); 761 762 ASSERT_EQUAL_32(0xedcba980, r3); 763 ASSERT_EQUAL_32(0x00fedcba, r4); 764 ASSERT_EQUAL_32(0xfffffedc, r5); 765 ASSERT_EQUAL_32(0xcba98fed, r6); 766 ASSERT_EQUAL_32(0xff6e5d4c, r7); 767 ASSERT_EQUAL_32(0x7f6e5d4c, r8); 768 769 TEARDOWN(); 770} 771 772 773TEST(branch_cond) { 774 SETUP(); 775 776 Label done, wrong; 777 778 START(); 779 __ Mov(r0, 0x0); 780 __ Mov(r1, 0x1); 781 __ Mov(r2, 0x80000000); 782 // TODO: Use r0 instead of r3 when r0 becomes available. 783 __ Mov(r3, 0x1); 784 785 // For each 'cmp' instruction below, condition codes other than the ones 786 // following it would branch. 787 788 __ Cmp(r1, 0); 789 __ B(eq, &wrong); 790 __ B(lo, &wrong); 791 __ B(mi, &wrong); 792 __ B(vs, &wrong); 793 __ B(ls, &wrong); 794 __ B(lt, &wrong); 795 __ B(le, &wrong); 796 Label ok_1; 797 __ B(ne, &ok_1); 798 // TODO: Use __ Mov(r0, 0x0) instead. 799 __ Add(r3, r0, 0x0); 800 __ Bind(&ok_1); 801 802 __ Cmp(r1, 1); 803 __ B(ne, &wrong); 804 __ B(lo, &wrong); 805 __ B(mi, &wrong); 806 __ B(vs, &wrong); 807 __ B(hi, &wrong); 808 __ B(lt, &wrong); 809 __ B(gt, &wrong); 810 Label ok_2; 811 __ B(pl, &ok_2); 812 // TODO: Use __ Mov(r0, 0x0) instead. 813 __ Add(r3, r0, 0x0); 814 __ Bind(&ok_2); 815 816 __ Cmp(r1, 2); 817 __ B(eq, &wrong); 818 __ B(hs, &wrong); 819 __ B(pl, &wrong); 820 __ B(vs, &wrong); 821 __ B(hi, &wrong); 822 __ B(ge, &wrong); 823 __ B(gt, &wrong); 824 Label ok_3; 825 __ B(vc, &ok_3); 826 // TODO: Use __ Mov(r0, 0x0) instead. 827 __ Add(r3, r0, 0x0); 828 __ Bind(&ok_3); 829 830 __ Cmp(r2, 1); 831 __ B(eq, &wrong); 832 __ B(lo, &wrong); 833 __ B(mi, &wrong); 834 __ B(vc, &wrong); 835 __ B(ls, &wrong); 836 __ B(ge, &wrong); 837 __ B(gt, &wrong); 838 Label ok_4; 839 __ B(le, &ok_4); 840 // TODO: Use __ Mov(r0, 0x0) instead. 841 __ Add(r3, r0, 0x0); 842 __ Bind(&ok_4); 843 844 Label ok_5; 845 __ B(&ok_5); 846 // TODO: Use __ Mov(r0, 0x0) instead. 847 __ Add(r3, r0, 0x0); 848 __ Bind(&ok_5); 849 850 __ B(&done); 851 852 __ Bind(&wrong); 853 // TODO: Use __ Mov(r0, 0x0) instead. 854 __ Add(r3, r0, 0x0); 855 856 __ Bind(&done); 857 END(); 858 859 RUN(); 860 861 // TODO: Use r0. 862 ASSERT_EQUAL_32(0x1, r3); 863 864 TEARDOWN(); 865} 866 867 868TEST(bfc_bfi) { 869 SETUP(); 870 871 START(); 872 __ Mov(r0, 0xffffffff); 873 __ Mov(r1, 0x01234567); 874 __ Mov(r2, 0x0); 875 876 __ Bfc(r0, 0, 3); 877 __ Bfc(r0, 16, 5); 878 879 __ Bfi(r2, r1, 0, 8); 880 __ Bfi(r2, r1, 16, 16); 881 END(); 882 883 RUN(); 884 885 ASSERT_EQUAL_32(0xffe0fff8, r0); 886 ASSERT_EQUAL_32(0x45670067, r2); 887 888 TEARDOWN(); 889} 890 891 892TEST(bic) { 893 SETUP(); 894 895 START(); 896 __ Mov(r0, 0xfff0); 897 __ Mov(r1, 0xf00000ff); 898 __ Mov(r2, 0xffffffff); 899 900 __ Bic(r3, r0, r1); 901 __ Bic(r4, r0, Operand(r1, LSL, 4)); 902 __ Bic(r5, r0, Operand(r1, LSR, 1)); 903 __ Bic(r6, r0, Operand(r1, ASR, 20)); 904 __ Bic(r7, r0, Operand(r1, ROR, 28)); 905 __ Bic(r8, r0, 0x1f); 906 907 // Set the C flag. 908 __ Adds(r9, r2, 1); 909 __ Bic(r9, r1, Operand(r1, RRX)); 910 911 // Clear the C flag. 912 __ Adds(r10, r0, 0); 913 __ Bic(r10, r1, Operand(r1, RRX)); 914 END(); 915 916 RUN(); 917 918 ASSERT_EQUAL_32(0x0000ff00, r3); 919 ASSERT_EQUAL_32(0x0000f000, r4); 920 ASSERT_EQUAL_32(0x0000ff80, r5); 921 ASSERT_EQUAL_32(0x000000f0, r6); 922 ASSERT_EQUAL_32(0x0000f000, r7); 923 ASSERT_EQUAL_32(0x0000ffe0, r8); 924 ASSERT_EQUAL_32(0x00000080, r9); 925 ASSERT_EQUAL_32(0x80000080, r10); 926 927 TEARDOWN(); 928} 929 930 931TEST(bics) { 932 SETUP(); 933 934 START(); 935 __ Mov(r0, 0); 936 __ Mov(r1, 0xf00000ff); 937 938 __ Bics(r0, r1, r1); 939 END(); 940 941 RUN(); 942 943 ASSERT_EQUAL_NZCV(ZFlag); 944 ASSERT_EQUAL_32(0, r0); 945 946 START(); 947 __ Mov(r0, 0x00fff000); 948 __ Mov(r1, 0x0fffff00); 949 950 __ Bics(r0, r0, Operand(r1, LSL, 4)); 951 END(); 952 953 RUN(); 954 955 ASSERT_EQUAL_NZCV(ZFlag); 956 ASSERT_EQUAL_32(0x00000000, r0); 957 958 START(); 959 __ Mov(r0, 0x0000fff0); 960 __ Mov(r1, 0x0fffff00); 961 962 __ Bics(r0, r0, Operand(r1, LSR, 4)); 963 END(); 964 965 RUN(); 966 967 ASSERT_EQUAL_NZCV(ZFlag); 968 ASSERT_EQUAL_32(0x00000000, r0); 969 970 START(); 971 __ Mov(r0, 0xf000fff0); 972 __ Mov(r1, 0x0fffff00); 973 974 __ Bics(r0, r0, Operand(r1, ASR, 4)); 975 END(); 976 977 RUN(); 978 979 ASSERT_EQUAL_NZCV(NFlag); 980 ASSERT_EQUAL_32(0xf0000000, r0); 981 982 START(); 983 __ Mov(r0, 0x80000000); 984 __ Mov(r1, 0xfffffffe); 985 986 __ Bics(r0, r0, Operand(r1, ROR, 1)); 987 END(); 988 989 RUN(); 990 991 ASSERT_EQUAL_NZCV(NFlag); 992 ASSERT_EQUAL_32(0x80000000, r0); 993 994 START(); 995 __ Mov(r0, 0x80000000); 996 __ Mov(r1, 0x80000001); 997 998 // Clear the C flag, forcing RRX to insert 0 in r1's most significant bit. 999 __ Adds(r2, r0, 0); 1000 __ Bics(r2, r0, Operand(r1, RRX)); 1001 END(); 1002 1003 RUN(); 1004 1005 ASSERT_EQUAL_NZCV(NCFlag); 1006 ASSERT_EQUAL_32(0x80000000, r2); 1007 1008 START(); 1009 __ Mov(r0, 0x80000000); 1010 __ Mov(r1, 0x80000001); 1011 __ Mov(r2, 0xffffffff); 1012 1013 // Set the C flag, forcing RRX to insert 1 in r1's most significant bit. 1014 __ Adds(r2, r2, 1); 1015 __ Bics(r2, r0, Operand(r1, RRX)); 1016 END(); 1017 1018 RUN(); 1019 1020 ASSERT_EQUAL_NZCV(ZCFlag); 1021 ASSERT_EQUAL_32(0, r2); 1022 1023 START(); 1024 __ Mov(r0, 0xf000); 1025 1026 __ Bics(r0, r0, 0xf000); 1027 END(); 1028 1029 RUN(); 1030 1031 ASSERT_EQUAL_NZCV(ZFlag); 1032 ASSERT_EQUAL_32(0x00000000, r0); 1033 1034 START(); 1035 __ Mov(r0, 0xff000000); 1036 1037 __ Bics(r0, r0, 0x7fffffff); 1038 END(); 1039 1040 RUN(); 1041 1042 ASSERT_EQUAL_NZCV(NFlag); 1043 ASSERT_EQUAL_32(0x80000000, r0); 1044 1045 TEARDOWN(); 1046} 1047 1048 1049TEST_T32(veneer_pool_in_delegate) { 1050 SETUP(); 1051 1052 START(); 1053 1054 Label end; 1055 1056 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1057 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1058 1059 __ Mov(r0, 1); 1060 __ Cbz(r0, &end); 1061 1062 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 1063 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1064 1065 // Generate enough code to have, after the loop, a margin of only one 16-bit 1066 // instruction that can be generated before we need to generate the veneer 1067 // pool. 1068 // Use `ExactAssemblyScope` and the assembler to generate the code. 1069 int32_t space = 1070 masm.GetMarginBeforeVeneerEmission() - k16BitT32InstructionSizeInBytes; 1071 { 1072 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1073 while (space > 0) { 1074 __ nop(); 1075 space -= k16BitT32InstructionSizeInBytes; 1076 } 1077 } 1078 1079 // We should not have emitted the veneer pool at this point. 1080 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 1081 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1082 VIXL_CHECK( 1083 masm.GetMarginBeforeVeneerEmission() == k16BitT32InstructionSizeInBytes); 1084 1085 // Now generate `Mov(r1, 0x12345678)`. It needs to 16-bit assembler 1086 // instructions, so it has to go through the `MacroAssembler` delegate. Since 1087 // there is only margin for one instruction to be generated, the pool will 1088 // have to be generated from within the `MacroAssembler` delegate. That should 1089 // not fire. 1090 Label check; 1091 __ Bind(&check); 1092 __ Mov(r1, 0x12345678); 1093 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) > 1094 2 * kMaxInstructionSizeInBytes); 1095 __ Bind(&end); 1096 1097 END(); 1098 1099 RUN(); 1100 1101 ASSERT_EQUAL_32(0x12345678, r1); 1102 1103 TEARDOWN(); 1104} 1105 1106 1107TEST_T32(literal_pool_in_delegate) { 1108 SETUP(); 1109 1110 START(); 1111 1112 PrintDisassembler disasm(std::cout); 1113 1114 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1115 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1116 1117 __ Ldrd(r0, r1, 0x1234567890abcdef); 1118 1119 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1120 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1121 1122 // Generate enough code to have, after the loop, a margin of only one 16-bit 1123 // instruction that can be generated before we need to generate the literal 1124 // pool. 1125 // Use `CodeBufferCheckScope` and the assembler to generate the code. 1126 int32_t space = masm.GetMarginBeforeLiteralEmission() - 1127 2 * k16BitT32InstructionSizeInBytes; 1128 { 1129 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1130 while (space > 0) { 1131 __ nop(); 1132 space -= k16BitT32InstructionSizeInBytes; 1133 } 1134 } 1135 1136 // We should not have emitted the literal pool at this point. 1137 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1138 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1139 VIXL_CHECK(masm.GetMarginBeforeLiteralEmission() == 1140 2 * k16BitT32InstructionSizeInBytes); 1141 1142 // Now generate `Mov(r1, 0x12345678)`. It needs to 16-bit assembler 1143 // instructions, so it has to go through the `MacroAssembler` delegate. Since 1144 // there is only margin for one instruction to be generated, the pool will 1145 // have to be generated from within the `MacroAssembler` delegate. That should 1146 // not fire. 1147 Label check; 1148 __ Bind(&check); 1149 __ Mov(r1, 0x12345678); 1150 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) > 1151 2 * kMaxInstructionSizeInBytes); 1152 1153 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 1154 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 1155 1156 END(); 1157 1158 RUN(); 1159 1160 ASSERT_EQUAL_32(0x12345678, r1); 1161 1162 TEARDOWN(); 1163} 1164 1165 1166TEST(emit_single_literal) { 1167 SETUP(); 1168 1169 START(); 1170 // Make sure the pool is empty. 1171 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1172 ASSERT_LITERAL_POOL_SIZE(0); 1173 1174 // Create one literal pool entry. 1175 __ Ldrd(r0, r1, 0x1234567890abcdef); 1176 ASSERT_LITERAL_POOL_SIZE(8); 1177 __ Vldr(s0, 1.0); 1178 __ Vldr(d1, 2.0); 1179 __ Vmov(d2, 4.1); 1180 __ Vmov(s8, 8.2); 1181 ASSERT_LITERAL_POOL_SIZE(20); 1182 END(); 1183 1184 RUN(); 1185 1186 // Check that the literals loaded correctly. 1187 ASSERT_EQUAL_32(0x90abcdef, r0); 1188 ASSERT_EQUAL_32(0x12345678, r1); 1189 ASSERT_EQUAL_FP32(1.0f, s0); 1190 ASSERT_EQUAL_FP64(2.0, d1); 1191 ASSERT_EQUAL_FP64(4.1, d2); 1192 ASSERT_EQUAL_FP32(8.2f, s8); 1193 1194 TEARDOWN(); 1195} 1196 1197 1198#undef __ 1199#define __ masm-> 1200 1201 1202void EmitLdrdLiteralTest(MacroAssembler* masm) { 1203 const int ldrd_range = masm->IsUsingA32() ? 255 : 1020; 1204 // We want to emit code up to the maximum literal load range and ensure the 1205 // pool has not been emitted. Compute the limit (end). 1206 ptrdiff_t end = 1207 AlignDown( 1208 // Align down the PC to 4 bytes as the instruction does when it's 1209 // executed. 1210 // The PC will be the cursor offset plus the architecture state PC 1211 // offset. 1212 AlignDown(masm->GetBuffer()->GetCursorOffset() + 1213 masm->GetArchitectureStatePCOffset(), 4) + 1214 // Maximum range allowed to access the constant. 1215 ldrd_range - 1216 // The literal pool has a two instruction margin. 1217 2 * kMaxInstructionSizeInBytes, 1218 // AlignDown to 4 byte as the literals will be 4 byte aligned. 1219 4); 1220 1221 // Create one literal pool entry. 1222 __ Ldrd(r0, r1, 0x1234567890abcdef); 1223 ASSERT_LITERAL_POOL_SIZE(8); 1224 1225 int32_t margin = masm->GetMarginBeforeLiteralEmission(); 1226 { 1227 ExactAssemblyScope scope(masm, margin, ExactAssemblyScope::kExactSize); 1228 // Opening the scope should not have triggered the emission of the literal 1229 // pool. 1230 VIXL_CHECK(!masm->LiteralPoolIsEmpty()); 1231 while (masm->GetCursorOffset() < end) { 1232 __ nop(); 1233 } 1234 VIXL_CHECK(masm->GetCursorOffset() == end); 1235 } 1236 1237 // Check that the pool has not been emited along the way. 1238 ASSERT_LITERAL_POOL_SIZE(8); 1239 // This extra instruction should trigger an emit of the pool. 1240 __ Nop(); 1241 // The pool should have been emitted. 1242 ASSERT_LITERAL_POOL_SIZE(0); 1243} 1244 1245 1246#undef __ 1247#define __ masm. 1248 1249 1250TEST(emit_literal) { 1251 SETUP(); 1252 1253 START(); 1254 1255 // Make sure the pool is empty. 1256 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1257 ASSERT_LITERAL_POOL_SIZE(0); 1258 1259 EmitLdrdLiteralTest(&masm); 1260 1261 const int ldrd_range = masm.IsUsingA32() ? 255 : 1020; 1262 const int string_size = AlignUp(ldrd_range + kMaxInstructionSizeInBytes, 4); 1263 std::string test_string(string_size, 'x'); 1264 StringLiteral big_literal(test_string.c_str()); 1265 __ Adr(r4, &big_literal); 1266 // This add will overflow the literal pool and force a rewind. 1267 // That means that the string will be generated then, then Ldrd and the 1268 // ldrd's value will be alone in the pool. 1269 __ Ldrd(r2, r3, 0xcafebeefdeadbaba); 1270 ASSERT_LITERAL_POOL_SIZE(8); 1271 1272 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1273 ASSERT_LITERAL_POOL_SIZE(0); 1274 __ Ldr(r4, MemOperand(r4)); // Load the first 4 characters in r4. 1275 END(); 1276 1277 RUN(); 1278 1279 // Check that the literals loaded correctly. 1280 ASSERT_EQUAL_32(0x90abcdef, r0); 1281 ASSERT_EQUAL_32(0x12345678, r1); 1282 ASSERT_EQUAL_32(0xdeadbaba, r2); 1283 ASSERT_EQUAL_32(0xcafebeef, r3); 1284 ASSERT_EQUAL_32(0x78787878, r4); 1285 1286 TEARDOWN(); 1287} 1288 1289TEST_T32(emit_literal_unaligned) { 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 // Generate a nop to break the 4 bytes alignment. 1299 __ Nop(); 1300 1301 EmitLdrdLiteralTest(&masm); 1302 1303 END(); 1304 1305 RUN(); 1306 1307 // Check that the literals loaded correctly. 1308 ASSERT_EQUAL_32(0x90abcdef, r0); 1309 ASSERT_EQUAL_32(0x12345678, r1); 1310 1311 TEARDOWN(); 1312} 1313 1314 1315TEST(literal_multiple_uses) { 1316 SETUP(); 1317 1318 START(); 1319 Literal<int32_t> lit(42); 1320 __ Ldr(r0, &lit); 1321 ASSERT_LITERAL_POOL_SIZE(4); 1322 1323 // Multiple uses of the same literal object should not make the 1324 // pool grow. 1325 __ Ldrb(r1, &lit); 1326 __ Ldrsb(r2, &lit); 1327 __ Ldrh(r3, &lit); 1328 __ Ldrsh(r4, &lit); 1329 ASSERT_LITERAL_POOL_SIZE(4); 1330 1331 END(); 1332 1333 RUN(); 1334 1335 ASSERT_EQUAL_32(42, r0); 1336 ASSERT_EQUAL_32(42, r1); 1337 ASSERT_EQUAL_32(42, r2); 1338 ASSERT_EQUAL_32(42, r3); 1339 ASSERT_EQUAL_32(42, r4); 1340 1341 TEARDOWN(); 1342} 1343 1344 1345// A test with two loads literal which go out of range at the same time. 1346TEST_A32(ldr_literal_range_same_time) { 1347 SETUP(); 1348 1349 START(); 1350 const int ldrd_range = 255; 1351 // We need to take into account the jump over the pool. 1352 const int ldrd_padding = ldrd_range - 2 * kA32InstructionSizeInBytes; 1353 const int ldr_range = 4095; 1354 // We need to take into account the ldrd padding and the ldrd instruction. 1355 const int ldr_padding = ldr_range - ldrd_padding - 2 * kA32InstructionSizeInBytes; 1356 1357 __ Ldr(r1, 0x12121212); 1358 ASSERT_LITERAL_POOL_SIZE(4); 1359 1360 { 1361 int space = AlignDown(ldr_padding, kA32InstructionSizeInBytes); 1362 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1363 int32_t end = masm.GetCursorOffset() + space; 1364 while (masm.GetCursorOffset() < end) { 1365 __ nop(); 1366 } 1367 } 1368 1369 __ Ldrd(r2, r3, 0x1234567890abcdef); 1370 ASSERT_LITERAL_POOL_SIZE(12); 1371 1372 { 1373 int space = AlignDown(ldrd_padding, kA32InstructionSizeInBytes); 1374 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1375 for (int32_t end = masm.GetCursorOffset() + space; 1376 masm.GetCursorOffset() < end;) { 1377 __ nop(); 1378 } 1379 } 1380 ASSERT_LITERAL_POOL_SIZE(12); 1381 1382 // This mov will put the two loads literal out of range and will force 1383 // the literal pool emission. 1384 __ Mov(r0, 0); 1385 ASSERT_LITERAL_POOL_SIZE(0); 1386 END(); 1387 1388 RUN(); 1389 1390 ASSERT_EQUAL_32(0x12121212, r1); 1391 ASSERT_EQUAL_32(0x90abcdef, r2); 1392 ASSERT_EQUAL_32(0x12345678, r3); 1393 1394 TEARDOWN(); 1395} 1396 1397 1398TEST(ldr_literal_mix_types) { 1399 SETUP(); 1400 1401 START(); 1402 Literal<uint64_t> l0(0x1234567890abcdef); 1403 Literal<int32_t> l1(0x12345678); 1404 Literal<uint16_t> l2(1234); 1405 Literal<int16_t> l3(-678); 1406 Literal<uint8_t> l4(42); 1407 Literal<int8_t> l5(-12); 1408 1409 __ Ldrd(r0, r1, &l0); 1410 __ Ldr(r2, &l1); 1411 __ Ldrh(r3, &l2); 1412 __ Ldrsh(r4, &l3); 1413 __ Ldrb(r5, &l4); 1414 __ Ldrsb(r6, &l5); 1415 ASSERT_LITERAL_POOL_SIZE(28); 1416 1417 END(); 1418 1419 RUN(); 1420 1421 ASSERT_EQUAL_32(0x90abcdef, r0); 1422 ASSERT_EQUAL_32(0x12345678, r1); 1423 ASSERT_EQUAL_32(0x12345678, r2); 1424 ASSERT_EQUAL_32(1234, r3); 1425 ASSERT_EQUAL_32(-678, r4); 1426 ASSERT_EQUAL_32(42, r5); 1427 ASSERT_EQUAL_32(-12, r6); 1428 1429 TEARDOWN(); 1430} 1431 1432 1433struct LdrLiteralRangeTest { 1434 void (MacroAssembler::*instruction)(Register, RawLiteral*); 1435 Register result_reg; 1436 int a32_range; 1437 int t32_range; 1438 uint32_t literal_value; 1439 uint32_t test_value; 1440}; 1441 1442 1443const LdrLiteralRangeTest kLdrLiteralRangeTestData[] = { 1444 {&MacroAssembler::Ldr, r1, 4095, 4095, 0x12345678, 0x12345678 }, 1445 {&MacroAssembler::Ldrh, r2, 255, 4095, 0xabcdefff, 0x0000efff }, 1446 {&MacroAssembler::Ldrsh, r3, 255, 4095, 0x00008765, 0xffff8765 }, 1447 {&MacroAssembler::Ldrb, r4, 4095, 4095, 0x12345678, 0x00000078 }, 1448 {&MacroAssembler::Ldrsb, r5, 255, 4095, 0x00000087, 0xffffff87 } 1449}; 1450 1451 1452void GenerateLdrLiteralTriggerPoolEmission(InstructionSet isa, 1453 bool unaligned_ldr) { 1454 SETUP(); 1455 1456 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 1457 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 1458 1459 START(); 1460 1461 if (unaligned_ldr) { 1462 // Generate a nop to break the 4-byte alignment. 1463 __ Nop(); 1464 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 1465 } 1466 1467 __ Ldr(r6, 0x12345678); 1468 ASSERT_LITERAL_POOL_SIZE(4); 1469 1470 // TODO: The MacroAssembler currently checks for more space than required 1471 // when emitting macro instructions, triggering emission of the pool before 1472 // absolutely required. For now we keep a buffer. Fix this test when the 1473 // MacroAssembler becomes precise again. 1474 int masm_check_margin = 10 * kMaxInstructionSizeInBytes; 1475 size_t expected_pool_size = 4; 1476 while ((masm.GetMarginBeforeLiteralEmission() - masm_check_margin) >= 1477 static_cast<int32_t>(kMaxInstructionSizeInBytes)) { 1478 __ Ldr(r7, 0x90abcdef); 1479 // Each ldr instruction will force a new literal value to be added 1480 // to the pool. Check that the literal pool grows accordingly. 1481 expected_pool_size += 4; 1482 ASSERT_LITERAL_POOL_SIZE(expected_pool_size); 1483 } 1484 1485 int space = masm.GetMarginBeforeLiteralEmission(); 1486 int end = masm.GetCursorOffset() + space; 1487 { 1488 // Generate nops precisely to fill the buffer. 1489 ExactAssemblyScope accurate_scope(&masm, space); // This should not trigger emission of the pool. 1490 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1491 while (masm.GetCursorOffset() < end) { 1492 __ nop(); 1493 } 1494 } 1495 1496 // This ldr will force the literal pool to be emitted before emitting 1497 // the load and will create a new pool for the new literal used by this ldr. 1498 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 1499 Literal<uint32_t> literal(test.literal_value); 1500 (masm.*test.instruction)(test.result_reg, &literal); 1501 ASSERT_LITERAL_POOL_SIZE(4); 1502 1503 END(); 1504 1505 RUN(); 1506 1507 ASSERT_EQUAL_32(0x12345678, r6); 1508 ASSERT_EQUAL_32(0x90abcdef, r7); 1509 ASSERT_EQUAL_32(test.test_value, test.result_reg); 1510 } 1511 1512 TEARDOWN(); 1513} 1514 1515 1516TEST(ldr_literal_trigger_pool_emission) { 1517 GenerateLdrLiteralTriggerPoolEmission(isa, false); 1518} 1519 1520 1521TEST_T32(ldr_literal_trigger_pool_emission_unaligned) { 1522 GenerateLdrLiteralTriggerPoolEmission(isa, true); 1523} 1524 1525 1526void GenerateLdrLiteralRangeTest(InstructionSet isa, bool unaligned_ldr) { 1527 SETUP(); 1528 1529 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 1530 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 1531 1532 START(); 1533 1534 // Make sure the pool is empty. 1535 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1536 ASSERT_LITERAL_POOL_SIZE(0); 1537 1538 if (unaligned_ldr) { 1539 // Generate a nop to break the 4-byte alignment. 1540 __ Nop(); 1541 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 1542 } 1543 1544 Literal<uint32_t> literal(test.literal_value); 1545 (masm.*test.instruction)(test.result_reg, &literal); 1546 ASSERT_LITERAL_POOL_SIZE(4); 1547 1548 // Generate enough instruction so that we go out of range for the load 1549 // literal we just emitted. 1550 ptrdiff_t end = 1551 masm.GetBuffer()->GetCursorOffset() + 1552 ((masm.IsUsingA32()) ? test.a32_range : test.t32_range); 1553 while (masm.GetBuffer()->GetCursorOffset() < end) { 1554 __ Mov(r0, 0); 1555 } 1556 1557 // The literal pool should have been emitted now. 1558 VIXL_CHECK(literal.IsBound()); 1559 ASSERT_LITERAL_POOL_SIZE(0); 1560 1561 END(); 1562 1563 RUN(); 1564 1565 ASSERT_EQUAL_32(test.test_value, test.result_reg); 1566 } 1567 1568 TEARDOWN(); 1569} 1570 1571 1572TEST(ldr_literal_range) { 1573 GenerateLdrLiteralRangeTest(isa, false); 1574} 1575 1576 1577TEST_T32(ldr_literal_range_unaligned) { 1578 GenerateLdrLiteralRangeTest(isa, true); 1579} 1580 1581 1582TEST(string_literal) { 1583 SETUP(); 1584 1585 START(); 1586 // Make sure the pool is empty. 1587 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1588 ASSERT_LITERAL_POOL_SIZE(0); 1589 1590 StringLiteral hello_string("hello"); 1591 1592 __ Ldrb(r1, &hello_string); 1593 1594 __ Adr(r0, &hello_string); 1595 __ Ldrb(r2, MemOperand(r0)); 1596 END(); 1597 1598 RUN(); 1599 1600 ASSERT_EQUAL_32('h', r1); 1601 ASSERT_EQUAL_32('h', r2); 1602 1603 TEARDOWN(); 1604} 1605 1606 1607TEST(custom_literal_in_pool) { 1608 SETUP(); 1609 1610 START(); 1611 // Make sure the pool is empty. 1612 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1613 ASSERT_LITERAL_POOL_SIZE(0); 1614 1615 Literal<uint32_t> l0(static_cast<uint32_t>(0x12345678)); 1616 __ Ldr(r0, &l0); 1617 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1618 __ Ldr(r1, &l0); 1619 ASSERT_LITERAL_POOL_SIZE(0); 1620 1621 Literal<uint64_t> cafebeefdeadbaba(0xcafebeefdeadbaba); 1622 __ Ldrd(r8, r9, &cafebeefdeadbaba); 1623 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1624 __ Ldrd(r2, r3, &cafebeefdeadbaba); 1625 ASSERT_LITERAL_POOL_SIZE(0); 1626 1627 Literal<uint32_t> l1(0x09abcdef); 1628 __ Adr(r4, &l1); 1629 __ Ldr(r4, MemOperand(r4)); 1630 masm.EmitLiteralPool(); 1631 __ Adr(r5, &l1); 1632 __ Ldr(r5, MemOperand(r5)); 1633 ASSERT_LITERAL_POOL_SIZE(0); 1634 1635 END(); 1636 1637 RUN(); 1638 1639 // Check that the literals loaded correctly. 1640 ASSERT_EQUAL_32(0x12345678, r0); 1641 ASSERT_EQUAL_32(0x12345678, r1); 1642 ASSERT_EQUAL_32(0xdeadbaba, r2); 1643 ASSERT_EQUAL_32(0xcafebeef, r3); 1644 ASSERT_EQUAL_32(0xdeadbaba, r8); 1645 ASSERT_EQUAL_32(0xcafebeef, r9); 1646 ASSERT_EQUAL_32(0x09abcdef, r4); 1647 ASSERT_EQUAL_32(0x09abcdef, r5); 1648} 1649 1650 1651TEST(custom_literal_place) { 1652 SETUP(); 1653 1654 START(); 1655 // Make sure the pool is empty. 1656 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1657 ASSERT_LITERAL_POOL_SIZE(0); 1658 1659 Literal<uint64_t> l0(0xcafebeefdeadbaba, RawLiteral::kManuallyPlaced); 1660 Literal<int32_t> l1(0x12345678, RawLiteral::kManuallyPlaced); 1661 Literal<uint16_t>l2(4567, RawLiteral::kManuallyPlaced); 1662 Literal<int16_t> l3(-4567, RawLiteral::kManuallyPlaced); 1663 Literal<uint8_t> l4(123, RawLiteral::kManuallyPlaced); 1664 Literal<int8_t> l5(-123, RawLiteral::kManuallyPlaced); 1665 1666 __ Ldrd(r0, r1, &l0); 1667 __ Ldr(r2, &l1); 1668 __ Ldrh(r3, &l2); 1669 __ Ldrsh(r4, &l3); 1670 __ Ldrb(r5, &l4); 1671 __ Ldrsb(r6, &l5); 1672 1673 ASSERT_LITERAL_POOL_SIZE(0); 1674 1675 // Manually generate a literal pool. 1676 Label after_pool; 1677 __ B(&after_pool); 1678 __ Place(&l0); 1679 __ Place(&l1); 1680 __ Place(&l2); 1681 __ Place(&l3); 1682 __ Place(&l4); 1683 __ Place(&l5); 1684 __ Bind(&after_pool); 1685 1686 UseScratchRegisterScope temps(&masm); 1687 Register temp = temps.Acquire(); 1688 VIXL_CHECK(temp.Is(r12)); 1689 1690 __ Ldrd(r8, r9, &l0); 1691 __ Ldr(r7, &l1); 1692 __ Ldrh(r10, &l2); 1693 __ Ldrsh(r11, &l3); 1694 __ Ldrb(temp, &l4); 1695 // We don't use any function call so we can use lr as an extra register. 1696 __ Ldrsb(lr, &l5); 1697 1698 ASSERT_LITERAL_POOL_SIZE(0); 1699 1700 END(); 1701 1702 RUN(); 1703 1704 // Check that the literals loaded correctly. 1705 ASSERT_EQUAL_32(0xdeadbaba, r0); 1706 ASSERT_EQUAL_32(0xcafebeef, r1); 1707 ASSERT_EQUAL_32(0x12345678, r2); 1708 ASSERT_EQUAL_32(4567, r3); 1709 ASSERT_EQUAL_32(-4567, r4); 1710 ASSERT_EQUAL_32(123, r5); 1711 ASSERT_EQUAL_32(-123, r6); 1712 1713 ASSERT_EQUAL_32(0xdeadbaba, r8); 1714 ASSERT_EQUAL_32(0xcafebeef, r9); 1715 ASSERT_EQUAL_32(0x12345678, r7); 1716 ASSERT_EQUAL_32(4567, r10); 1717 ASSERT_EQUAL_32(-4567, r11); 1718 ASSERT_EQUAL_32(123, temp); 1719 ASSERT_EQUAL_32(-123, lr); 1720 1721 TEARDOWN(); 1722} 1723 1724 1725TEST(custom_literal_place_shared) { 1726 SETUP(); 1727 1728 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 1729 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 1730 1731 START(); 1732 1733 // Make sure the pool is empty. 1734 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 1735 ASSERT_LITERAL_POOL_SIZE(0); 1736 1737 Literal<uint32_t> before(test.literal_value, RawLiteral::kManuallyPlaced); 1738 Literal<uint32_t> after(test.literal_value, RawLiteral::kManuallyPlaced); 1739 1740 VIXL_CHECK(!before.IsBound()); 1741 VIXL_CHECK(!after.IsBound()); 1742 1743 // Manually generate a pool. 1744 Label end_of_pool_before; 1745 __ B(&end_of_pool_before); 1746 __ Place(&before); 1747 __ Bind(&end_of_pool_before); 1748 1749 ASSERT_LITERAL_POOL_SIZE(0); 1750 VIXL_CHECK(before.IsBound()); 1751 VIXL_CHECK(!after.IsBound()); 1752 1753 // Load the entries several times to test that literals can be shared. 1754 for (int i = 0; i < 20; i++) { 1755 (masm.*test.instruction)(r0, &before); 1756 (masm.*test.instruction)(r1, &after); 1757 } 1758 1759 ASSERT_LITERAL_POOL_SIZE(0); 1760 VIXL_CHECK(before.IsBound()); 1761 VIXL_CHECK(!after.IsBound()); 1762 1763 // Manually generate a pool. 1764 Label end_of_pool_after; 1765 __ B(&end_of_pool_after); 1766 __ Place(&after); 1767 __ Bind(&end_of_pool_after); 1768 1769 ASSERT_LITERAL_POOL_SIZE(0); 1770 VIXL_CHECK(before.IsBound()); 1771 VIXL_CHECK(after.IsBound()); 1772 1773 END(); 1774 1775 RUN(); 1776 1777 ASSERT_EQUAL_32(test.test_value, r0); 1778 ASSERT_EQUAL_32(test.test_value, r1); 1779 } 1780 1781 TEARDOWN(); 1782} 1783 1784 1785TEST(custom_literal_place_range) { 1786 SETUP(); 1787 1788 for (size_t i = 0; i < ARRAY_SIZE(kLdrLiteralRangeTestData); ++i) { 1789 const LdrLiteralRangeTest& test = kLdrLiteralRangeTestData[i]; 1790 const int nop_size = masm.IsUsingA32() ? kA32InstructionSizeInBytes 1791 : k16BitT32InstructionSizeInBytes; 1792 const int range = masm.IsUsingA32() ? test.a32_range : test.t32_range; 1793 // On T32 the PC will be 4-byte aligned to compute the range. The 1794 // MacroAssembler might also need to align the code buffer before emitting 1795 // the literal when placing it. We keep a margin to account for this. 1796 const int margin = masm.IsUsingT32() ? 4 : 0; 1797 1798 // Take PC offset into account and make sure the literal is in the range. 1799 const int padding_before = 1800 range - masm.GetArchitectureStatePCOffset() - sizeof(uint32_t) - margin; 1801 1802 // The margin computation below is correct because the ranges are not 1803 // 4-byte aligned. Otherwise this test would insert the exact number of 1804 // instructions to cover the range and the literal would end up being 1805 // placed outside the range. 1806 VIXL_ASSERT((range % 4) != 0); 1807 1808 // The range is extended by the PC offset but we need to consider the ldr 1809 // instruction itself and the branch over the pool. 1810 const int padding_after = range + masm.GetArchitectureStatePCOffset() - 1811 (2 * kMaxInstructionSizeInBytes) - margin; 1812 START(); 1813 1814 Literal<uint32_t> before(test.literal_value, RawLiteral::kManuallyPlaced); 1815 Literal<uint32_t> after(test.literal_value, RawLiteral::kManuallyPlaced); 1816 1817 Label test_start; 1818 __ B(&test_start); 1819 __ Place(&before); 1820 1821 { 1822 int space = AlignDown(padding_before, nop_size); 1823 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1824 for (int32_t end = masm.GetCursorOffset() + space; 1825 masm.GetCursorOffset() < end;) { 1826 __ nop(); 1827 } 1828 } 1829 1830 __ Bind(&test_start); 1831 (masm.*test.instruction)(r0, &before); 1832 (masm.*test.instruction)(r1, &after); 1833 1834 { 1835 int space = AlignDown(padding_after, nop_size); 1836 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 1837 for (int32_t end = masm.GetCursorOffset() + space; 1838 masm.GetCursorOffset() < end;) { 1839 __ nop(); 1840 } 1841 } 1842 1843 Label after_pool; 1844 __ B(&after_pool); 1845 __ Place(&after); 1846 __ Bind(&after_pool); 1847 1848 END(); 1849 1850 RUN(); 1851 1852 ASSERT_EQUAL_32(test.test_value, r0); 1853 ASSERT_EQUAL_32(test.test_value, r1); 1854 } 1855 1856 TEARDOWN(); 1857} 1858 1859 1860TEST(emit_big_pool) { 1861 SETUP(); 1862 1863 START(); 1864 // Make sure the pool is empty. 1865 ASSERT_LITERAL_POOL_SIZE(0); 1866 1867 Label start; 1868 __ Bind(&start); 1869 for (int i = 1000; i > 0; --i) { 1870 __ Ldr(r0, i); 1871 } 1872 1873 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&start) == 4000); 1874 1875 ASSERT_LITERAL_POOL_SIZE(4000); 1876 END(); 1877 1878 RUN(); 1879 1880 // Check that the literals loaded correctly. 1881 ASSERT_EQUAL_32(1, r0); 1882 1883 TEARDOWN(); 1884} 1885 1886 1887TEST_T32(too_far_cbz) { 1888 SETUP(); 1889 1890 START(); 1891 Label start; 1892 Label end; 1893 Label exit; 1894 __ Mov(r0, 0); 1895 __ B(&start); 1896 __ Bind(&end); 1897 __ Mov(r0, 1); 1898 __ B(&exit); 1899 __ Bind(&start); 1900 // Cbz is only defined for forward jump. Check that it will work (substituted 1901 // by Cbnz/B). 1902 __ Cbz(r0, &end); 1903 __ Bind(&exit); 1904 END(); 1905 1906 RUN(); 1907 1908 ASSERT_EQUAL_32(1, r0); 1909} 1910 1911 1912TEST_T32(close_cbz) { 1913 SETUP(); 1914 1915 START(); 1916 Label first; 1917 Label second; 1918 __ Mov(r0, 0); 1919 __ Mov(r1, 0); 1920 __ Mov(r2, 0); 1921 __ Cbz(r0, &first); 1922 __ Bind(&first); 1923 __ Mov(r1, 1); 1924 __ Cbnz(r0, &second); 1925 __ Bind(&second); 1926 __ Mov(r2, 2); 1927 END(); 1928 1929 RUN(); 1930 1931 ASSERT_EQUAL_32(0, r0); 1932 ASSERT_EQUAL_32(1, r1); 1933 ASSERT_EQUAL_32(2, r2); 1934} 1935 1936 1937TEST_T32(close_cbz2) { 1938 SETUP(); 1939 1940 START(); 1941 Label first; 1942 Label second; 1943 __ Mov(r0, 0); 1944 __ Mov(r1, 0); 1945 __ Mov(r2, 0); 1946 __ Cmp(r0, 0); 1947 __ B(ne, &first); 1948 __ B(gt, &second); 1949 __ Cbz(r0, &first); 1950 __ Bind(&first); 1951 __ Mov(r1, 1); 1952 __ Cbnz(r0, &second); 1953 __ Bind(&second); 1954 __ Mov(r2, 2); 1955 END(); 1956 1957 RUN(); 1958 1959 ASSERT_EQUAL_32(0, r0); 1960 ASSERT_EQUAL_32(1, r1); 1961 ASSERT_EQUAL_32(2, r2); 1962} 1963 1964 1965TEST_T32(not_close_cbz) { 1966 SETUP(); 1967 1968 START(); 1969 Label first; 1970 Label second; 1971 __ Cbz(r0, &first); 1972 __ B(ne, &first); 1973 __ Bind(&first); 1974 __ Cbnz(r0, &second); 1975 __ B(gt, &second); 1976 __ Bind(&second); 1977 END(); 1978 1979 RUN(); 1980} 1981 1982 1983TEST_T32(veneers) { 1984 SETUP(); 1985 1986 START(); 1987 Label zero; 1988 Label exit; 1989 __ Mov(r0, 0); 1990 // Create one literal pool entry. 1991 __ Ldr(r1, 0x12345678); 1992 ASSERT_LITERAL_POOL_SIZE(4); 1993 __ Cbz(r0, &zero); 1994 __ Mov(r0, 1); 1995 __ B(&exit); 1996 for (int i = 32; i > 0; i--) { 1997 __ Mov(r1, 0); 1998 } 1999 // Assert that the literal pool has been generated with the veneers. 2000 ASSERT_LITERAL_POOL_SIZE(0); 2001 __ Bind(&zero); 2002 __ Mov(r0, 2); 2003 __ Bind(&exit); 2004 END(); 2005 2006 RUN(); 2007 2008 ASSERT_EQUAL_32(2, r0); 2009 ASSERT_EQUAL_32(0x12345678, r1); 2010} 2011 2012 2013// This test checks that veneers are sorted. If not, the test failed as the 2014// veneer for "exit" is emitted before the veneer for "zero" and the "zero" 2015// veneer is out of range for Cbz. 2016TEST_T32(veneers_labels_sort) { 2017 SETUP(); 2018 2019 START(); 2020 Label start; 2021 Label zero; 2022 Label exit; 2023 __ Movs(r0, 0); 2024 __ B(ne, &exit); 2025 __ B(&start); 2026 for (int i = 1048400; i > 0; i -= 4) { 2027 __ Mov(r1, 0); 2028 } 2029 __ Bind(&start); 2030 __ Cbz(r0, &zero); 2031 __ Mov(r0, 1); 2032 __ B(&exit); 2033 for (int i = 32; i > 0; i--) { 2034 __ Mov(r1, 0); 2035 } 2036 __ Bind(&zero); 2037 __ Mov(r0, 2); 2038 __ Bind(&exit); 2039 END(); 2040 2041 RUN(); 2042 2043 ASSERT_EQUAL_32(2, r0); 2044} 2045 2046// Check that a label bound within the assembler is effectively removed from 2047// the veneer pool. 2048TEST_T32(veneer_bind) { 2049 SETUP(); 2050 Label target; 2051 __ Cbz(r0, &target); 2052 __ Nop(); 2053 2054 { 2055 // Bind the target label using the `Assembler`. 2056 ExactAssemblyScope scope(&masm, 2057 kMaxInstructionSizeInBytes, 2058 ExactAssemblyScope::kMaximumSize); 2059 __ bind(&target); 2060 __ nop(); 2061 } 2062 2063 VIXL_CHECK(target.IsBound()); 2064 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 2065 2066 END(); 2067} 2068 2069 2070TEST_T32(unaligned_branch_after_literal) { 2071 SETUP(); 2072 2073 START(); 2074 2075 // This test manually places a 32-bit literal after a 16-bit branch 2076 // which branches over the literal to an unaligned PC. 2077 Literal<int32_t> l0(0x01234567, RawLiteral::kManuallyPlaced); 2078 2079 __ Ldr(r0, &l0); 2080 ASSERT_LITERAL_POOL_SIZE(0); 2081 2082 masm.EmitLiteralPool(MacroAssembler::kBranchRequired); 2083 ASSERT_LITERAL_POOL_SIZE(0); 2084 2085 // Manually generate a literal pool. 2086 { 2087 Label after_pool; 2088 ExactAssemblyScope scope(&masm, 2089 k16BitT32InstructionSizeInBytes + sizeof(int32_t), 2090 CodeBufferCheckScope::kMaximumSize); 2091 __ b(Narrow, &after_pool); 2092 __ place(&l0); 2093 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 2); 2094 __ bind(&after_pool); 2095 } 2096 2097 ASSERT_LITERAL_POOL_SIZE(0); 2098 2099 END(); 2100 2101 RUN(); 2102 2103 // Check that the literal was loaded correctly. 2104 ASSERT_EQUAL_32(0x01234567, r0); 2105 2106 TEARDOWN(); 2107} 2108 2109 2110 2111// This test check that we can update a Literal after usage. 2112TEST(literal_update) { 2113 SETUP(); 2114 2115 START(); 2116 Label exit; 2117 Literal<uint32_t>* a32 = 2118 new Literal<uint32_t>(0xabcdef01, RawLiteral::kDeletedOnPoolDestruction); 2119 Literal<uint64_t>* a64 = 2120 new Literal<uint64_t>( 2121 UINT64_C(0xabcdef01abcdef01), RawLiteral::kDeletedOnPoolDestruction); 2122 __ Ldr(r0, a32); 2123 __ Ldrd(r2, r3, a64); 2124 __ EmitLiteralPool(); 2125 Literal<uint32_t>* b32 = 2126 new Literal<uint32_t>(0x10fedcba, RawLiteral::kDeletedOnPoolDestruction); 2127 Literal<uint64_t>* b64 = 2128 new Literal<uint64_t>( 2129 UINT64_C(0x10fedcba10fedcba), RawLiteral::kDeletedOnPoolDestruction); 2130 __ Ldr(r1, b32); 2131 __ Ldrd(r4, r5, b64); 2132 // Update literals' values. "a32" and "a64" are already emitted. "b32" and 2133 // "b64" will only be emitted when "END()" will be called. 2134 a32->UpdateValue(0x12345678, masm.GetBuffer()); 2135 a64->UpdateValue(UINT64_C(0x13579bdf02468ace), masm.GetBuffer()); 2136 b32->UpdateValue(0x87654321, masm.GetBuffer()); 2137 b64->UpdateValue(UINT64_C(0x1032547698badcfe), masm.GetBuffer()); 2138 END(); 2139 2140 RUN(); 2141 2142 ASSERT_EQUAL_32(0x12345678, r0); 2143 ASSERT_EQUAL_32(0x87654321, r1); 2144 ASSERT_EQUAL_32(0x02468ace, r2); 2145 ASSERT_EQUAL_32(0x13579bdf, r3); 2146 ASSERT_EQUAL_32(0x98badcfe, r4); 2147 ASSERT_EQUAL_32(0x10325476, r5); 2148} 2149 2150 2151void SwitchCase(JumpTableBase* switch_, uint32_t case_index, 2152 InstructionSet isa, bool bind_default = true) { 2153 SETUP(); 2154 2155 START(); 2156 2157 __ Mov(r0, case_index); 2158 __ Mov(r1, case_index); 2159 __ Switch(r1, switch_); 2160 2161 __ Case(switch_, 0); 2162 __ Mov(r0, 1); 2163 __ Break(switch_); 2164 2165 __ Case(switch_, 1); 2166 __ Mov(r0, 2); 2167 __ Break(switch_); 2168 2169 __ Case(switch_, 2); 2170 __ Mov(r0, 4); 2171 __ Break(switch_); 2172 2173 __ Case(switch_, 3); 2174 __ Mov(r0, 8); 2175 __ Break(switch_); 2176 2177 if (bind_default) { 2178 __ Default(switch_); 2179 __ Mov(r0, -1); 2180 } 2181 2182 __ EndSwitch(switch_); 2183 2184 2185 END(); 2186 2187 RUN(); 2188 2189 if (case_index < 4) { 2190 ASSERT_EQUAL_32(1 << case_index, r0); 2191 } else if (bind_default) { 2192 ASSERT_EQUAL_32(-1, r0); 2193 } else { 2194 ASSERT_EQUAL_32(case_index, r0); 2195 } 2196} 2197 2198 2199TEST(switch_case_8) { 2200 for (int i = 0; i < 5; i++) { 2201 JumpTable8bitOffset switch_(5); 2202 SwitchCase(&switch_, i, isa); 2203 } 2204} 2205 2206 2207TEST(switch_case_16) { 2208 for (int i = 0; i < 5; i++) { 2209 JumpTable16bitOffset switch_(5); 2210 SwitchCase(&switch_, i, isa); 2211 } 2212} 2213 2214 2215TEST(switch_case_32) { 2216 for (int i = 0; i < 5; i++) { 2217 JumpTable32bitOffset switch_(5); 2218 SwitchCase(&switch_, i, isa); 2219 } 2220} 2221 2222 2223TEST(switch_case_8_omit_default) { 2224 for (int i = 0; i < 5; i++) { 2225 JumpTable8bitOffset switch_(5); 2226 SwitchCase(&switch_, i, isa, false); 2227 } 2228} 2229 2230 2231TEST(switch_case_16_omit_default) { 2232 for (int i = 0; i < 5; i++) { 2233 JumpTable16bitOffset switch_(5); 2234 SwitchCase(&switch_, i, isa, false); 2235 } 2236} 2237 2238 2239TEST(switch_case_32_omit_default) { 2240 for (int i = 0; i < 5; i++) { 2241 JumpTable32bitOffset switch_(5); 2242 SwitchCase(&switch_, i, isa, false); 2243 } 2244} 2245 2246TEST(claim_peek_poke) { 2247 SETUP(); 2248 2249 START(); 2250 2251 Label start; 2252 __ Bind(&start); 2253 __ Claim(0); 2254 __ Drop(0); 2255 VIXL_CHECK((masm.GetCursorOffset() - start.GetLocation()) == 0); 2256 2257 __ Claim(32); 2258 __ Ldr(r0, 0xcafe0000); 2259 __ Ldr(r1, 0xcafe0001); 2260 __ Ldr(r2, 0xcafe0002); 2261 __ Poke(r0, 0); 2262 __ Poke(r1, 4); 2263 __ Poke(r2, 8); 2264 __ Peek(r2, 0); 2265 __ Peek(r0, 4); 2266 __ Peek(r1, 8); 2267 __ Drop(32); 2268 2269 END(); 2270 2271 RUN(); 2272 2273 ASSERT_EQUAL_32(0xcafe0001, r0); 2274 ASSERT_EQUAL_32(0xcafe0002, r1); 2275 ASSERT_EQUAL_32(0xcafe0000, r2); 2276 2277 TEARDOWN(); 2278} 2279 2280 2281TEST(msr_i) { 2282 SETUP(); 2283 2284 START(); 2285 __ Mov(r0, 0xdead); 2286 __ Mov(r1, 0xdead); 2287 __ Mov(r2, 0xdead); 2288 __ Mov(r3, 0xb); 2289 __ Msr(APSR_nzcvqg, 0); 2290 __ Mrs(r0, APSR); 2291 __ Msr(APSR_nzcvqg, 0xffffffff); 2292 __ Mrs(r1, APSR); 2293 // Only modify nzcvq => keep previous g. 2294 __ Lsl(r4, r3, 28); 2295 __ Msr(APSR_nzcvq, r4); 2296 __ Mrs(r2, APSR); 2297 END(); 2298 2299 RUN(); 2300 2301 ASSERT_EQUAL_32(0x10, r0); 2302 ASSERT_EQUAL_32(0xf80f0010, r1); 2303 ASSERT_EQUAL_32(0xb00f0010, r2); 2304 2305 TEARDOWN(); 2306} 2307 2308 2309TEST(vmrs_vmsr) { 2310 SETUP(); 2311 2312 START(); 2313 // Move some value to FPSCR and get them back to test vmsr/vmrs instructions. 2314 __ Mov(r0, 0x2a000000); 2315 __ Vmsr(FPSCR, r0); 2316 __ Vmrs(RegisterOrAPSR_nzcv(r1.GetCode()), FPSCR); 2317 2318 __ Mov(r0, 0x5a000000); 2319 __ Vmsr(FPSCR, r0); 2320 __ Vmrs(RegisterOrAPSR_nzcv(r2.GetCode()), FPSCR); 2321 2322 // Move to APSR_nzcv. 2323 __ Vmrs(RegisterOrAPSR_nzcv(pc.GetCode()), FPSCR); 2324 __ Mrs(r3, APSR); 2325 __ And(r3, r3, 0xf0000000); 2326 2327 END(); 2328 2329 RUN(); 2330 2331 ASSERT_EQUAL_32(0x2a000000, r1); 2332 ASSERT_EQUAL_32(0x5a000000, r2); 2333 ASSERT_EQUAL_32(0x50000000, r3); 2334 2335 TEARDOWN(); 2336} 2337 2338 2339TEST(printf) { 2340 SETUP(); 2341 2342 START(); 2343 __ Mov(r0, 0xb00e0000); 2344 __ Msr(APSR_nzcvqg, r0); 2345 __ Mov(r0, sp); 2346 __ Printf("sp=%x\n", r0); 2347// __ Printf("Hello world!\n"); 2348 __ Mov(r0, 0x1234); 2349 __ Mov(r1, 0x5678); 2350 StringLiteral literal("extra string"); 2351 __ Adr(r2, &literal); 2352 __ Mov(r3, 5); 2353 __ Mov(r4, 0xdead4444); 2354 __ Mov(r5, 0xdead5555); 2355 __ Mov(r6, 0xdead6666); 2356 __ Mov(r7, 0xdead7777); 2357 __ Mov(r8, 0xdead8888); 2358 __ Mov(r9, 0xdead9999); 2359 __ Mov(r10, 0xdeadaaaa); 2360 __ Mov(r11, 0xdeadbbbb); 2361 __ Vldr(d0, 1.2345); 2362 __ Vldr(d1, 2.9876); 2363 __ Vldr(s4, 1.3333); 2364 __ Vldr(s5, 3.21); 2365 __ Vldr(d3, 3.333); 2366 __ Vldr(d4, 4.444); 2367 __ Vldr(d5, 5.555); 2368 __ Vldr(d6, 6.666); 2369 __ Vldr(d7, 7.777); 2370 __ Vldr(d8, 8.888); 2371 __ Vldr(d9, 9.999); 2372 __ Vldr(d10, 10.000); 2373 __ Vldr(d11, 11.111); 2374 __ Vldr(d12, 12.222); 2375 __ Vldr(d13, 13.333); 2376 __ Vldr(d14, 14.444); 2377 __ Vldr(d15, 15.555); 2378 __ Vldr(d16, 16.666); 2379 __ Vldr(d17, 17.777); 2380 __ Vldr(d18, 18.888); 2381 __ Vldr(d19, 19.999); 2382 __ Vldr(d20, 20.000); 2383 __ Vldr(d21, 21.111); 2384 __ Vldr(d22, 22.222); 2385 __ Vldr(d23, 23.333); 2386 __ Vldr(d24, 24.444); 2387 __ Vldr(d25, 25.555); 2388 __ Vldr(d26, 26.666); 2389 __ Vldr(d27, 27.777); 2390 __ Vldr(d28, 28.888); 2391 __ Vldr(d29, 29.999); 2392 __ Vldr(d30, 30.000); 2393 __ Vldr(d31, 31.111); 2394 { 2395 UseScratchRegisterScope temps(&masm); 2396 // For effective use as an inspection tool, Printf must work without any 2397 // scratch registers. 2398 VIXL_CHECK(r12.Is(temps.Acquire())); 2399 __ Mov(r12, 0xdeadcccc); 2400 VIXL_CHECK(masm.GetScratchRegisterList()->IsEmpty()); 2401 2402 __ Printf("%% r0=%x r1=%x str=<%.*s>\n", r0, r1, r3, r2); 2403 __ Printf("r0=%d r1=%d str=<%s>\n", r0, r1, r2); 2404 __ Printf("d0=%g\n", d0); 2405 __ Printf("s4=%g\n", s4); 2406 __ Printf("d0=%g d1=%g s4=%g s5=%g\n", d0, d1, s4, s5); 2407 __ Printf("d0=%g r0=%x s4=%g r1=%x\n", d0, r0, s4, r1); 2408 __ Printf("r0=%x d0=%g r1=%x s4=%g\n", r0, d0, r1, s4); 2409 __ Mov(r0, sp); 2410 __ Printf("sp=%x\n", r0); 2411 __ Mrs(r0, APSR); 2412 // Only keep R/W fields. 2413 __ Mov(r2, 0xf80f0200); 2414 __ And(r0, r0, r2); 2415 } 2416 END(); 2417 2418 RUN(); 2419 2420 ASSERT_EQUAL_32(0xb00e0000, r0); 2421 ASSERT_EQUAL_32(0x5678, r1); 2422 ASSERT_EQUAL_32(5, r3); 2423 ASSERT_EQUAL_32(0xdead4444, r4); 2424 ASSERT_EQUAL_32(0xdead5555, r5); 2425 ASSERT_EQUAL_32(0xdead6666, r6); 2426 ASSERT_EQUAL_32(0xdead7777, r7); 2427 ASSERT_EQUAL_32(0xdead8888, r8); 2428 ASSERT_EQUAL_32(0xdead9999, r9); 2429 ASSERT_EQUAL_32(0xdeadaaaa, r10); 2430 ASSERT_EQUAL_32(0xdeadbbbb, r11); 2431 ASSERT_EQUAL_32(0xdeadcccc, r12); 2432 ASSERT_EQUAL_FP64(1.2345, d0); 2433 ASSERT_EQUAL_FP64(2.9876, d1); 2434 ASSERT_EQUAL_FP32(1.3333, s4); 2435 ASSERT_EQUAL_FP32(3.21, s5); 2436 ASSERT_EQUAL_FP64(4.444, d4); 2437 ASSERT_EQUAL_FP64(5.555, d5); 2438 ASSERT_EQUAL_FP64(6.666, d6); 2439 ASSERT_EQUAL_FP64(7.777, d7); 2440 ASSERT_EQUAL_FP64(8.888, d8); 2441 ASSERT_EQUAL_FP64(9.999, d9); 2442 ASSERT_EQUAL_FP64(10.000, d10); 2443 ASSERT_EQUAL_FP64(11.111, d11); 2444 ASSERT_EQUAL_FP64(12.222, d12); 2445 ASSERT_EQUAL_FP64(13.333, d13); 2446 ASSERT_EQUAL_FP64(14.444, d14); 2447 ASSERT_EQUAL_FP64(15.555, d15); 2448 ASSERT_EQUAL_FP64(16.666, d16); 2449 ASSERT_EQUAL_FP64(17.777, d17); 2450 ASSERT_EQUAL_FP64(18.888, d18); 2451 ASSERT_EQUAL_FP64(19.999, d19); 2452 ASSERT_EQUAL_FP64(20.000, d20); 2453 ASSERT_EQUAL_FP64(21.111, d21); 2454 ASSERT_EQUAL_FP64(22.222, d22); 2455 ASSERT_EQUAL_FP64(23.333, d23); 2456 ASSERT_EQUAL_FP64(24.444, d24); 2457 ASSERT_EQUAL_FP64(25.555, d25); 2458 ASSERT_EQUAL_FP64(26.666, d26); 2459 ASSERT_EQUAL_FP64(27.777, d27); 2460 ASSERT_EQUAL_FP64(28.888, d28); 2461 ASSERT_EQUAL_FP64(29.999, d29); 2462 ASSERT_EQUAL_FP64(30.000, d30); 2463 ASSERT_EQUAL_FP64(31.111, d31); 2464 2465 TEARDOWN(); 2466} 2467 2468TEST(printf2) { 2469 SETUP(); 2470 2471 START(); 2472 __ Mov(r0, 0x1234); 2473 __ Mov(r1, 0x5678); 2474 __ Vldr(d0, 1.2345); 2475 __ Vldr(s2, 2.9876); 2476 __ Printf("d0=%g d1=%g r0=%x r1=%x\n", d0, s2, r0, r1); 2477 END(); 2478 2479 RUN(); 2480 2481 TEARDOWN(); 2482} 2483 2484 2485TEST(use_scratch_register_scope_v_registers) { 2486 SETUP(); 2487 { 2488 UseScratchRegisterScope temps(&masm); 2489 temps.Include(VRegisterList(q0, q1, q2, q3)); 2490 2491 // This test assumes that low-numbered registers are allocated first. The 2492 // implementation is allowed to use a different strategy; if it does, the 2493 // test will need to be updated. 2494 // TODO: Write more flexible (and thorough) tests. 2495 2496 VIXL_CHECK(q0.Is(temps.AcquireQ())); 2497 VIXL_CHECK(!temps.IsAvailable(q0)); 2498 VIXL_CHECK(!temps.IsAvailable(d0)); 2499 VIXL_CHECK(!temps.IsAvailable(d1)); 2500 VIXL_CHECK(!temps.IsAvailable(s0)); 2501 VIXL_CHECK(!temps.IsAvailable(s1)); 2502 VIXL_CHECK(!temps.IsAvailable(s2)); 2503 VIXL_CHECK(!temps.IsAvailable(s3)); 2504 2505 VIXL_CHECK(d2.Is(temps.AcquireV(64))); 2506 VIXL_CHECK(!temps.IsAvailable(q1)); 2507 VIXL_CHECK(!temps.IsAvailable(d2)); 2508 VIXL_CHECK(temps.IsAvailable(d3)); 2509 VIXL_CHECK(!temps.IsAvailable(s4)); 2510 VIXL_CHECK(!temps.IsAvailable(s5)); 2511 VIXL_CHECK(temps.IsAvailable(s6)); 2512 VIXL_CHECK(temps.IsAvailable(s7)); 2513 2514 VIXL_CHECK(s6.Is(temps.AcquireS())); 2515 VIXL_CHECK(!temps.IsAvailable(d3)); 2516 VIXL_CHECK(!temps.IsAvailable(s6)); 2517 VIXL_CHECK(temps.IsAvailable(s7)); 2518 2519 VIXL_CHECK(q2.Is(temps.AcquireV(128))); 2520 VIXL_CHECK(!temps.IsAvailable(q2)); 2521 VIXL_CHECK(!temps.IsAvailable(d4)); 2522 VIXL_CHECK(!temps.IsAvailable(d5)); 2523 VIXL_CHECK(!temps.IsAvailable(s8)); 2524 VIXL_CHECK(!temps.IsAvailable(s9)); 2525 VIXL_CHECK(!temps.IsAvailable(s10)); 2526 VIXL_CHECK(!temps.IsAvailable(s11)); 2527 VIXL_CHECK(temps.IsAvailable(s7)); 2528 2529 VIXL_CHECK(d6.Is(temps.AcquireD())); 2530 VIXL_CHECK(!temps.IsAvailable(q3)); 2531 VIXL_CHECK(!temps.IsAvailable(d6)); 2532 VIXL_CHECK(temps.IsAvailable(d7)); 2533 VIXL_CHECK(!temps.IsAvailable(s12)); 2534 VIXL_CHECK(!temps.IsAvailable(s13)); 2535 VIXL_CHECK(temps.IsAvailable(s14)); 2536 VIXL_CHECK(temps.IsAvailable(s15)); 2537 VIXL_CHECK(temps.IsAvailable(s7)); 2538 2539 VIXL_CHECK(s7.Is(temps.AcquireS())); 2540 } 2541 TEARDOWN(); 2542} 2543 2544 2545TEST(scratch_register_scope_include_exclude) { 2546 SETUP(); 2547 { 2548 UseScratchRegisterScope temps(&masm); 2549 temps.Include(r0, r1, r2, r3); 2550 temps.Include(s0, s1, d1, q1); 2551 2552 VIXL_CHECK(temps.IsAvailable(r0)); 2553 VIXL_CHECK(temps.IsAvailable(r1)); 2554 VIXL_CHECK(temps.IsAvailable(r2)); 2555 VIXL_CHECK(temps.IsAvailable(r3)); 2556 2557 VIXL_CHECK(temps.IsAvailable(s0)); 2558 2559 VIXL_CHECK(temps.IsAvailable(s1)); 2560 2561 VIXL_CHECK(temps.IsAvailable(d1)); 2562 VIXL_CHECK(temps.IsAvailable(s2)); 2563 VIXL_CHECK(temps.IsAvailable(s3)); 2564 2565 VIXL_CHECK(temps.IsAvailable(q1)); 2566 VIXL_CHECK(temps.IsAvailable(d2)); 2567 VIXL_CHECK(temps.IsAvailable(d3)); 2568 VIXL_CHECK(temps.IsAvailable(s4)); 2569 VIXL_CHECK(temps.IsAvailable(s5)); 2570 VIXL_CHECK(temps.IsAvailable(s6)); 2571 VIXL_CHECK(temps.IsAvailable(s7)); 2572 2573 // Test local exclusion. 2574 { 2575 UseScratchRegisterScope local_temps(&masm); 2576 local_temps.Exclude(r1, r2); 2577 local_temps.Exclude(s1, q1); 2578 2579 VIXL_CHECK(temps.IsAvailable(r0)); 2580 VIXL_CHECK(!temps.IsAvailable(r1)); 2581 VIXL_CHECK(!temps.IsAvailable(r2)); 2582 VIXL_CHECK(temps.IsAvailable(r3)); 2583 2584 VIXL_CHECK(temps.IsAvailable(s0)); 2585 2586 VIXL_CHECK(!temps.IsAvailable(s1)); 2587 2588 VIXL_CHECK(temps.IsAvailable(d1)); 2589 VIXL_CHECK(temps.IsAvailable(s2)); 2590 VIXL_CHECK(temps.IsAvailable(s3)); 2591 2592 VIXL_CHECK(!temps.IsAvailable(q1)); 2593 VIXL_CHECK(!temps.IsAvailable(d2)); 2594 VIXL_CHECK(!temps.IsAvailable(d3)); 2595 VIXL_CHECK(!temps.IsAvailable(s4)); 2596 VIXL_CHECK(!temps.IsAvailable(s5)); 2597 VIXL_CHECK(!temps.IsAvailable(s6)); 2598 VIXL_CHECK(!temps.IsAvailable(s7)); 2599 } 2600 2601 // This time, exclude part of included registers, making sure the entire 2602 // register gets excluded. 2603 { 2604 UseScratchRegisterScope local_temps(&masm); 2605 local_temps.Exclude(s2, d3); 2606 2607 VIXL_CHECK(temps.IsAvailable(r0)); 2608 VIXL_CHECK(temps.IsAvailable(r1)); 2609 VIXL_CHECK(temps.IsAvailable(r2)); 2610 VIXL_CHECK(temps.IsAvailable(r3)); 2611 2612 VIXL_CHECK(temps.IsAvailable(s0)); 2613 2614 VIXL_CHECK(temps.IsAvailable(s1)); 2615 2616 // Excluding s2 should exclude d1 but not s3. 2617 VIXL_CHECK(!temps.IsAvailable(d1)); 2618 VIXL_CHECK(!temps.IsAvailable(s2)); 2619 VIXL_CHECK(temps.IsAvailable(s3)); 2620 2621 // Excluding d3 should exclude q1, s7 and s6 but not d2, s5, s4. 2622 VIXL_CHECK(!temps.IsAvailable(q1)); 2623 VIXL_CHECK(temps.IsAvailable(d2)); 2624 VIXL_CHECK(!temps.IsAvailable(d3)); 2625 VIXL_CHECK(temps.IsAvailable(s4)); 2626 VIXL_CHECK(temps.IsAvailable(s5)); 2627 VIXL_CHECK(!temps.IsAvailable(s6)); 2628 VIXL_CHECK(!temps.IsAvailable(s7)); 2629 } 2630 2631 // Make sure the initial state was restored. 2632 2633 VIXL_CHECK(temps.IsAvailable(r0)); 2634 VIXL_CHECK(temps.IsAvailable(r1)); 2635 VIXL_CHECK(temps.IsAvailable(r2)); 2636 VIXL_CHECK(temps.IsAvailable(r3)); 2637 2638 VIXL_CHECK(temps.IsAvailable(s0)); 2639 2640 VIXL_CHECK(temps.IsAvailable(s1)); 2641 2642 VIXL_CHECK(temps.IsAvailable(d1)); 2643 VIXL_CHECK(temps.IsAvailable(s2)); 2644 VIXL_CHECK(temps.IsAvailable(s3)); 2645 2646 VIXL_CHECK(temps.IsAvailable(q1)); 2647 VIXL_CHECK(temps.IsAvailable(d2)); 2648 VIXL_CHECK(temps.IsAvailable(d3)); 2649 VIXL_CHECK(temps.IsAvailable(s4)); 2650 VIXL_CHECK(temps.IsAvailable(s5)); 2651 VIXL_CHECK(temps.IsAvailable(s6)); 2652 VIXL_CHECK(temps.IsAvailable(s7)); 2653 } 2654 TEARDOWN(); 2655} 2656 2657 2658template<typename T> 2659void CheckInstructionSetA32(const T& assm) { 2660 VIXL_CHECK(assm.IsUsingA32()); 2661 VIXL_CHECK(!assm.IsUsingT32()); 2662 VIXL_CHECK(assm.GetInstructionSetInUse() == A32); 2663} 2664 2665 2666template<typename T> 2667void CheckInstructionSetT32(const T& assm) { 2668 VIXL_CHECK(assm.IsUsingT32()); 2669 VIXL_CHECK(!assm.IsUsingA32()); 2670 VIXL_CHECK(assm.GetInstructionSetInUse() == T32); 2671} 2672 2673 2674TEST_NOASM(set_isa_constructors) { 2675 byte buffer[1024]; 2676 2677 // A32 by default. 2678 CheckInstructionSetA32(Assembler()); 2679 CheckInstructionSetA32(Assembler(1024)); 2680 CheckInstructionSetA32(Assembler(buffer, sizeof(buffer))); 2681 // Explicit A32. 2682 CheckInstructionSetA32(Assembler(A32)); 2683 CheckInstructionSetA32(Assembler(1024, A32)); 2684 CheckInstructionSetA32(Assembler(buffer, sizeof(buffer), A32)); 2685 // Explicit T32. 2686 CheckInstructionSetT32(Assembler(T32)); 2687 CheckInstructionSetT32(Assembler(1024, T32)); 2688 CheckInstructionSetT32(Assembler(buffer, sizeof(buffer), T32)); 2689 2690 // A32 by default. 2691 CheckInstructionSetA32(MacroAssembler()); 2692 CheckInstructionSetA32(MacroAssembler(1024)); 2693 CheckInstructionSetA32(MacroAssembler(buffer, sizeof(buffer))); 2694 // Explicit A32. 2695 CheckInstructionSetA32(MacroAssembler(A32)); 2696 CheckInstructionSetA32(MacroAssembler(1024, A32)); 2697 CheckInstructionSetA32(MacroAssembler(buffer, sizeof(buffer), A32)); 2698 // Explicit T32. 2699 CheckInstructionSetT32(MacroAssembler(T32)); 2700 CheckInstructionSetT32(MacroAssembler(1024, T32)); 2701 CheckInstructionSetT32(MacroAssembler(buffer, sizeof(buffer), T32)); 2702} 2703 2704 2705TEST_NOASM(set_isa_empty) { 2706 // It is possible to change the instruction set if no instructions have yet 2707 // been generated. 2708 Assembler assm; 2709 CheckInstructionSetA32(assm); 2710 assm.UseT32(); 2711 CheckInstructionSetT32(assm); 2712 assm.UseA32(); 2713 CheckInstructionSetA32(assm); 2714 assm.UseInstructionSet(T32); 2715 CheckInstructionSetT32(assm); 2716 assm.UseInstructionSet(A32); 2717 CheckInstructionSetA32(assm); 2718 2719 MacroAssembler masm; 2720 CheckInstructionSetA32(masm); 2721 masm.UseT32(); 2722 CheckInstructionSetT32(masm); 2723 masm.UseA32(); 2724 CheckInstructionSetA32(masm); 2725 masm.UseInstructionSet(T32); 2726 CheckInstructionSetT32(masm); 2727 masm.UseInstructionSet(A32); 2728 CheckInstructionSetA32(masm); 2729} 2730 2731 2732TEST_NOASM(set_isa_noop) { 2733 // It is possible to call a no-op UseA32/T32 or UseInstructionSet even if 2734 // one or more instructions have been generated. 2735 { 2736 Assembler assm(A32); 2737 CheckInstructionSetA32(assm); 2738 CodeBufferCheckScope scope(&assm, kMaxInstructionSizeInBytes); 2739 assm.bx(lr); 2740 VIXL_ASSERT(assm.GetCursorOffset() > 0); 2741 CheckInstructionSetA32(assm); 2742 assm.UseA32(); 2743 CheckInstructionSetA32(assm); 2744 assm.UseInstructionSet(A32); 2745 CheckInstructionSetA32(assm); 2746 assm.FinalizeCode(); 2747 } 2748 { 2749 Assembler assm(T32); 2750 CheckInstructionSetT32(assm); 2751 CodeBufferCheckScope scope(&assm, kMaxInstructionSizeInBytes); 2752 assm.bx(lr); 2753 VIXL_ASSERT(assm.GetCursorOffset() > 0); 2754 CheckInstructionSetT32(assm); 2755 assm.UseT32(); 2756 CheckInstructionSetT32(assm); 2757 assm.UseInstructionSet(T32); 2758 CheckInstructionSetT32(assm); 2759 assm.FinalizeCode(); 2760 } 2761 { 2762 MacroAssembler masm(A32); 2763 CheckInstructionSetA32(masm); 2764 masm.Bx(lr); 2765 VIXL_ASSERT(masm.GetCursorOffset() > 0); 2766 CheckInstructionSetA32(masm); 2767 masm.UseA32(); 2768 CheckInstructionSetA32(masm); 2769 masm.UseInstructionSet(A32); 2770 CheckInstructionSetA32(masm); 2771 masm.FinalizeCode(); 2772 } 2773 { 2774 MacroAssembler masm(T32); 2775 CheckInstructionSetT32(masm); 2776 masm.Bx(lr); 2777 VIXL_ASSERT(masm.GetCursorOffset() > 0); 2778 CheckInstructionSetT32(masm); 2779 masm.UseT32(); 2780 CheckInstructionSetT32(masm); 2781 masm.UseInstructionSet(T32); 2782 CheckInstructionSetT32(masm); 2783 masm.FinalizeCode(); 2784 } 2785} 2786 2787 2788TEST(logical_arithmetic_identities) { 2789 SETUP(); 2790 2791 START(); 2792 2793 Label blob_1; 2794 __ Bind(&blob_1); 2795 __ Add(r0, r0, 0); 2796 __ And(r0, r0, 0xffffffff); 2797 __ Bic(r0, r0, 0); 2798 __ Eor(r0, r0, 0); 2799 __ Orn(r0, r0, 0xffffffff); 2800 __ Orr(r0, r0, 0); 2801 __ Sub(r0, r0, 0); 2802 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_1) == 0); 2803 2804 Label blob_2; 2805 __ Bind(&blob_2); 2806 __ Adds(r0, r0, 0); 2807 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_2) != 0); 2808 2809 Label blob_3; 2810 __ Bind(&blob_3); 2811 __ Ands(r0, r0, 0); 2812 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_3) != 0); 2813 2814 Label blob_4; 2815 __ Bind(&blob_4); 2816 __ Bics(r0, r0, 0); 2817 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_4) != 0); 2818 2819 Label blob_5; 2820 __ Bind(&blob_5); 2821 __ Eors(r0, r0, 0); 2822 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_5) != 0); 2823 2824 Label blob_6; 2825 __ Bind(&blob_6); 2826 __ Orns(r0, r0, 0); 2827 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_6) != 0); 2828 2829 Label blob_7; 2830 __ Bind(&blob_7); 2831 __ Orrs(r0, r0, 0); 2832 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_7) != 0); 2833 2834 Label blob_8; 2835 __ Bind(&blob_8); 2836 __ Subs(r0, r0, 0); 2837 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_8) != 0); 2838 2839 __ Mov(r0, 0xbad); 2840 __ And(r1, r0, 0); 2841 __ Bic(r2, r0, 0xffffffff); 2842 __ Eor(r3, r0, 0xffffffff); 2843 __ Orn(r4, r0, 0); 2844 __ Orr(r5, r0, 0xffffffff); 2845 2846 END(); 2847 2848 RUN(); 2849 2850 ASSERT_EQUAL_32(0xbad, r0); 2851 ASSERT_EQUAL_32(0, r1); 2852 ASSERT_EQUAL_32(0, r2); 2853 ASSERT_EQUAL_32(~0xbad, r3); 2854 ASSERT_EQUAL_32(0xffffffff, r4); 2855 ASSERT_EQUAL_32(0xffffffff, r5); 2856 2857 TEARDOWN(); 2858} 2859 2860 2861TEST(scratch_register_checks) { 2862 // It is unsafe for users to use registers that the MacroAssembler is also 2863 // using as scratch registers. This test checks the MacroAssembler's checking 2864 // mechanism itself. 2865 SETUP(); 2866 START(); 2867 { 2868 UseScratchRegisterScope temps(&masm); 2869 // 'ip' is a scratch register by default. 2870 VIXL_CHECK( 2871 masm.GetScratchRegisterList()->GetList() == (1u << ip.GetCode())); 2872 VIXL_CHECK(temps.IsAvailable(ip)); 2873 2874 // Integer registers have no complicated aliasing so 2875 // masm.AliasesAvailableScratchRegister(reg) == temps.IsAvailable(reg). 2876 for (unsigned i = 0; i < kNumberOfRegisters; i++) { 2877 Register reg(i); 2878 VIXL_CHECK(masm.AliasesAvailableScratchRegister(reg) == 2879 temps.IsAvailable(reg)); 2880 } 2881 } 2882 END(); 2883 TEARDOWN(); 2884} 2885 2886 2887TEST(scratch_register_checks_v) { 2888 // It is unsafe for users to use registers that the MacroAssembler is also 2889 // using as scratch registers. This test checks the MacroAssembler's checking 2890 // mechanism itself. 2891 SETUP(); 2892 { 2893 UseScratchRegisterScope temps(&masm); 2894 // There is no default floating-point scratch register. Add temps of various 2895 // sizes to check handling of aliased registers. 2896 VIXL_CHECK(masm.GetScratchVRegisterList()->GetList() == 0); 2897 temps.Include(q15); 2898 temps.Include(d15); 2899 temps.Include(s15); 2900 temps.Include(d4); 2901 temps.Include(d5); 2902 temps.Include(s24); 2903 temps.Include(s25); 2904 temps.Include(s26); 2905 temps.Include(s27); 2906 temps.Include(q0); 2907 // See VRegisterList for details of the list encoding. 2908 VIXL_CHECK(masm.GetScratchVRegisterList()->GetList() == 2909 UINT64_C(0xf0000000cf008f0f)); 2910 // | || || | 2911 // q15 d15| || q0 2912 // s24-s27 |d4-d5 2913 // s15 2914 2915 // Simple checks: Included registers are available. 2916 VIXL_CHECK(temps.IsAvailable(q15)); 2917 VIXL_CHECK(temps.IsAvailable(d15)); 2918 VIXL_CHECK(temps.IsAvailable(s15)); 2919 VIXL_CHECK(temps.IsAvailable(d4)); 2920 VIXL_CHECK(temps.IsAvailable(d5)); 2921 VIXL_CHECK(temps.IsAvailable(s24)); 2922 VIXL_CHECK(temps.IsAvailable(s25)); 2923 VIXL_CHECK(temps.IsAvailable(s26)); 2924 VIXL_CHECK(temps.IsAvailable(s27)); 2925 VIXL_CHECK(temps.IsAvailable(q0)); 2926 2927 // Each available S register should mark the corresponding D and Q registers 2928 // as aliasing an available scratch register. 2929 for (unsigned s = 0; s < kNumberOfSRegisters; s++) { 2930 if (temps.IsAvailable(SRegister(s))) { 2931 VIXL_CHECK(masm.AliasesAvailableScratchRegister(SRegister(s))); 2932 VIXL_CHECK(masm.AliasesAvailableScratchRegister(DRegister(s / 2))); 2933 VIXL_CHECK(masm.AliasesAvailableScratchRegister(QRegister(s / 4))); 2934 } else { 2935 // AliasesAvailableScratchRegiters == IsAvailable for S registers. 2936 VIXL_CHECK(!masm.AliasesAvailableScratchRegister(SRegister(s))); 2937 } 2938 } 2939 2940 // Similar checks for high D registers. 2941 unsigned first_high_d_register = kNumberOfSRegisters / 2; 2942 for (unsigned d = first_high_d_register; d < kMaxNumberOfDRegisters; d++) { 2943 if (temps.IsAvailable(DRegister(d))) { 2944 VIXL_CHECK(masm.AliasesAvailableScratchRegister(DRegister(d))); 2945 VIXL_CHECK(masm.AliasesAvailableScratchRegister(QRegister(d / 2))); 2946 } else { 2947 // AliasesAvailableScratchRegiters == IsAvailable for high D registers. 2948 VIXL_CHECK(!masm.AliasesAvailableScratchRegister(DRegister(d))); 2949 } 2950 } 2951 } 2952 TEARDOWN(); 2953} 2954 2955 2956TEST(nop) { 2957 SETUP(); 2958 2959 Label start; 2960 __ Bind(&start); 2961 __ Nop(); 2962 size_t nop_size = (isa == T32) ? k16BitT32InstructionSizeInBytes 2963 : kA32InstructionSizeInBytes; 2964 // `MacroAssembler::Nop` must generate at least one nop. 2965 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= nop_size); 2966 2967 masm.FinalizeCode(); 2968 2969 TEARDOWN(); 2970} 2971 2972 2973// Check that `GetMarginBeforeLiteralEmission()` is precise. 2974TEST(literal_pool_margin) { 2975 SETUP(); 2976 2977 START(); 2978 2979 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 2980 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 2981 2982 // Create a single literal. 2983 __ Ldrd(r0, r1, 0x1234567890abcdef); 2984 2985 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 2986 2987 // Generate code to fill all the margin we have before generating the literal 2988 // pool. 2989 int32_t margin = masm.GetMarginBeforeLiteralEmission(); 2990 int32_t end = masm.GetCursorOffset() + margin; 2991 { 2992 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize); 2993 // Opening the scope should not have triggered the emission of the literal 2994 // pool. 2995 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 2996 while (masm.GetCursorOffset() < end) { 2997 __ nop(); 2998 } 2999 VIXL_CHECK(masm.GetCursorOffset() == end); 3000 } 3001 3002 // There should be no margin left to emit the literal pool. 3003 VIXL_CHECK(!masm.LiteralPoolIsEmpty()); 3004 VIXL_CHECK(masm.GetMarginBeforeLiteralEmission() == 0); 3005 3006 // So emitting a single instruction should force emission of the pool. 3007 __ Nop(); 3008 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3009 END(); 3010 3011 RUN(); 3012 3013 // Check that the literals loaded correctly. 3014 ASSERT_EQUAL_32(0x90abcdef, r0); 3015 ASSERT_EQUAL_32(0x12345678, r1); 3016 3017 TEARDOWN(); 3018} 3019 3020 3021// Check that `GetMarginBeforeVeneerEmission()` is precise. 3022TEST(veneer_pool_margin) { 3023 SETUP(); 3024 3025 START(); 3026 3027 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3028 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3029 3030 // Create a single veneer. 3031 Label target; 3032 __ B(eq, &target); 3033 3034 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3035 3036 // Generate code to fill all the margin we have before generating the veneer 3037 // pool. 3038 int32_t margin = masm.GetMarginBeforeVeneerEmission(); 3039 int32_t end = masm.GetCursorOffset() + margin; 3040 { 3041 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize); 3042 // Opening the scope should not have triggered the emission of the veneer 3043 // pool. 3044 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3045 while (masm.GetCursorOffset() < end) { 3046 __ nop(); 3047 } 3048 VIXL_CHECK(masm.GetCursorOffset() == end); 3049 } 3050 // There should be no margin left to emit the veneer pool. 3051 VIXL_CHECK(masm.GetMarginBeforeVeneerEmission() == 0); 3052 3053 // So emitting a single instruction should force emission of the pool. 3054 // We cannot simply check that the veneer pool is empty, because the veneer 3055 // emitted for the CBZ instruction above is itself tracked by the veneer 3056 // mechanisms. Instead, check that some 'unexpected' code is generated. 3057 Label check; 3058 __ Bind(&check); 3059 { 3060 ExactAssemblyScope scope(&masm, 2, ExactAssemblyScope::kMaximumSize); 3061 // Do not actually generate any code. 3062 } 3063 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) > 0); 3064 __ Bind(&target); 3065 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3066 3067 END(); 3068 3069 RUN(); 3070 3071 TEARDOWN(); 3072} 3073 3074 3075TEST_NOASM(code_buffer_precise_growth) { 3076 static const int kBaseBufferSize = 16; 3077 MacroAssembler masm(kBaseBufferSize, T32); 3078 3079 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3080 3081 { 3082 // Fill the buffer with nops. 3083 ExactAssemblyScope scope(&masm, kBaseBufferSize, ExactAssemblyScope::kExactSize); 3084 for (int i = 0; i < kBaseBufferSize; i += k16BitT32InstructionSizeInBytes) { 3085 __ nop(); 3086 } 3087 } 3088 3089 // The buffer should not have grown yet. 3090 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3091 3092 // Generating a single instruction should force the buffer to grow. 3093 __ Nop(); 3094 3095 VIXL_CHECK(masm.GetBuffer()->GetCapacity() > kBaseBufferSize); 3096 3097 masm.FinalizeCode(); 3098} 3099 3100 3101TEST_NOASM(out_of_space_immediately_before_PerformEnsureEmit) { 3102 static const int kBaseBufferSize = 64; 3103 MacroAssembler masm(kBaseBufferSize, T32); 3104 3105 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3106 3107 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3108 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3109 3110 // Create a veneer. 3111 Label target; 3112 __ Cbz(r0, &target); 3113 3114 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3115 3116 VIXL_CHECK(IsUint32(masm.GetBuffer()->GetRemainingBytes())); 3117 uint32_t space = static_cast<uint32_t>(masm.GetBuffer()->GetRemainingBytes()); 3118 { 3119 // Fill the buffer with nops. 3120 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize); 3121 for (uint32_t i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { 3122 __ nop(); 3123 } 3124 } 3125 3126 VIXL_CHECK(!masm.VeneerPoolIsEmpty()); 3127 3128 // The buffer should not have grown yet, and there should be no space left. 3129 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize); 3130 VIXL_CHECK(masm.GetBuffer()->GetRemainingBytes() == 0); 3131 3132 // Force emission of the veneer, at a point where there is no space available 3133 // in the buffer. 3134 int32_t past_cbz_range = masm.GetMarginBeforeVeneerEmission() + 1; 3135 masm.EnsureEmitFor(past_cbz_range); 3136 3137 __ Bind(&target); 3138 3139 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3140 3141 masm.FinalizeCode(); 3142} 3143 3144 3145TEST_T32(two_distant_literal_references) { 3146 SETUP(); 3147 START(); 3148 3149 Label end; 3150 3151 vixl::aarch32::Literal<uint64_t>* literal = 3152 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3153 RawLiteral::kPlacedWhenUsed, 3154 RawLiteral::kDeletedOnPoolDestruction); 3155 // Refer to the literal so that it is emitted early. 3156 __ Ldr(r0, literal); 3157 3158 // Add enough nops to exceed the range of both loads. 3159 int space = 5000; 3160 { 3161 ExactAssemblyScope scope(&masm, 3162 space, 3163 CodeBufferCheckScope::kExactSize); 3164 int nop_size = masm.IsUsingT32() ? k16BitT32InstructionSizeInBytes 3165 : kA32InstructionSizeInBytes; 3166 for (int i = 0; i < space; i += nop_size) { 3167 __ nop(); 3168 } 3169 } 3170 3171 __ Bind(&end); 3172 3173#define ENSURE_ALIGNED() do { \ 3174 if (!IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())) { \ 3175 ExactAssemblyScope scope(&masm, k16BitT32InstructionSizeInBytes, \ 3176 ExactAssemblyScope::kExactSize); \ 3177 __ nop(); \ 3178 } \ 3179 VIXL_ASSERT(IsMultiple<k32BitT32InstructionSizeInBytes>( \ 3180 masm.GetCursorOffset())); \ 3181} while(0) 3182 3183 // The literal has already been emitted, and is out of range of all of these 3184 // instructions. The delegates must generate fix-up code. 3185 ENSURE_ALIGNED(); 3186 __ Ldr(r1, literal); 3187 ENSURE_ALIGNED(); 3188 __ Ldrb(r2, literal); 3189 ENSURE_ALIGNED(); 3190 __ Ldrsb(r3, literal); 3191 ENSURE_ALIGNED(); 3192 __ Ldrh(r4, literal); 3193 ENSURE_ALIGNED(); 3194 __ Ldrsh(r5, literal); 3195 ENSURE_ALIGNED(); 3196 __ Ldrd(r6, r7, literal); 3197 ENSURE_ALIGNED(); 3198 __ Vldr(d0, literal); 3199 ENSURE_ALIGNED(); 3200 __ Vldr(s3, literal); 3201 3202#undef ENSURE_ALIGNED 3203 3204 END(); 3205 RUN(); 3206 3207 // Check that the literals loaded correctly. 3208 ASSERT_EQUAL_32(0x89abcdef, r0); 3209 ASSERT_EQUAL_32(0x89abcdef, r1); 3210 ASSERT_EQUAL_32(0xef, r2); 3211 ASSERT_EQUAL_32(0xffffffef, r3); 3212 ASSERT_EQUAL_32(0xcdef, r4); 3213 ASSERT_EQUAL_32(0xffffcdef, r5); 3214 ASSERT_EQUAL_32(0x89abcdef, r6); 3215 ASSERT_EQUAL_32(0x01234567, r7); 3216 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 3217 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 3218 3219 TEARDOWN(); 3220} 3221 3222 3223TEST_T32(two_distant_literal_references_unaligned_pc) { 3224 SETUP(); 3225 START(); 3226 3227 Label end; 3228 3229 vixl::aarch32::Literal<uint64_t>* literal = 3230 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef), 3231 RawLiteral::kPlacedWhenUsed, 3232 RawLiteral::kDeletedOnPoolDestruction); 3233 // Refer to the literal so that it is emitted early. 3234 __ Ldr(r0, literal); 3235 3236 // Add enough nops to exceed the range of both loads, leaving the PC aligned 3237 // to only a two-byte boundary. 3238 int space = 5002; 3239 { 3240 ExactAssemblyScope scope(&masm, 3241 space, 3242 CodeBufferCheckScope::kExactSize); 3243 int nop_size = masm.IsUsingT32() ? k16BitT32InstructionSizeInBytes 3244 : kA32InstructionSizeInBytes; 3245 for (int i = 0; i < space; i += nop_size) { 3246 __ nop(); 3247 } 3248 } 3249 3250 __ Bind(&end); 3251 3252#define ENSURE_NOT_ALIGNED() do { \ 3253 if (IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())) { \ 3254 ExactAssemblyScope scope(&masm, k16BitT32InstructionSizeInBytes, \ 3255 ExactAssemblyScope::kExactSize); \ 3256 __ nop(); \ 3257 } \ 3258 VIXL_ASSERT(!IsMultiple<k32BitT32InstructionSizeInBytes>( \ 3259 masm.GetCursorOffset())); \ 3260} while(0) 3261 3262 // The literal has already been emitted, and is out of range of all of these 3263 // instructions. The delegates must generate fix-up code. 3264 ENSURE_NOT_ALIGNED(); 3265 __ Ldr(r1, literal); 3266 ENSURE_NOT_ALIGNED(); 3267 __ Ldrb(r2, literal); 3268 ENSURE_NOT_ALIGNED(); 3269 __ Ldrsb(r3, literal); 3270 ENSURE_NOT_ALIGNED(); 3271 __ Ldrh(r4, literal); 3272 ENSURE_NOT_ALIGNED(); 3273 __ Ldrsh(r5, literal); 3274 ENSURE_NOT_ALIGNED(); 3275 __ Ldrd(r6, r7, literal); 3276 { 3277 // TODO: We currently require an extra scratch register for these cases 3278 // because MemOperandComputationHelper isn't able to fit add_sub_offset into 3279 // a single 'sub' instruction, so 'pc' gets preserved first. The same 3280 // problem technically exists for the other loads, but vldr is particularly 3281 // badly affected because vldr cannot set the low bits in its offset mask, 3282 // so the add/sub operand is likely to be difficult to encode. 3283 // 3284 // At the moment, we get this: 3285 // mov r8, pc 3286 // mov ip, #5118 3287 // sub r8, pc 3288 // vldr d0, [r8, #48] 3289 // 3290 // We should be able to generate something like this: 3291 // sub ip, pc, #0x1300 // 5118 & 0xff00 3292 // sub ip, #0xfe // 5118 & 0x00ff 3293 // vldr d0, [ip, #48] 3294 UseScratchRegisterScope temps(&masm); 3295 temps.Include(r8); 3296 ENSURE_NOT_ALIGNED(); 3297 __ Vldr(d0, literal); 3298 ENSURE_NOT_ALIGNED(); 3299 __ Vldr(s3, literal); 3300 } 3301 3302#undef ENSURE_NOT_ALIGNED 3303 3304 END(); 3305 RUN(); 3306 3307 // Check that the literals loaded correctly. 3308 ASSERT_EQUAL_32(0x89abcdef, r0); 3309 ASSERT_EQUAL_32(0x89abcdef, r1); 3310 ASSERT_EQUAL_32(0xef, r2); 3311 ASSERT_EQUAL_32(0xffffffef, r3); 3312 ASSERT_EQUAL_32(0xcdef, r4); 3313 ASSERT_EQUAL_32(0xffffcdef, r5); 3314 ASSERT_EQUAL_32(0x89abcdef, r6); 3315 ASSERT_EQUAL_32(0x01234567, r7); 3316 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0); 3317 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3); 3318 3319 TEARDOWN(); 3320} 3321 3322 3323TEST(barriers) { 3324 // Generate all supported barriers, this is just a smoke test 3325 SETUP(); 3326 3327 START(); 3328 3329 // DMB 3330 __ Dmb(SY); 3331 __ Dmb(ST); 3332 __ Dmb(ISH); 3333 __ Dmb(ISHST); 3334 __ Dmb(NSH); 3335 __ Dmb(NSHST); 3336 __ Dmb(OSH); 3337 __ Dmb(OSHST); 3338 3339 // DSB 3340 __ Dsb(SY); 3341 __ Dsb(ST); 3342 __ Dsb(ISH); 3343 __ Dsb(ISHST); 3344 __ Dsb(NSH); 3345 __ Dsb(NSHST); 3346 __ Dsb(OSH); 3347 __ Dsb(OSHST); 3348 3349 // ISB 3350 __ Isb(SY); 3351 3352 END(); 3353 3354 TEARDOWN(); 3355} 3356 3357 3358TEST(preloads) { 3359 // Smoke test for various pld/pli forms. 3360 SETUP(); 3361 3362 START(); 3363 3364 // PLD immediate 3365 __ Pld(MemOperand(sp, 0)); 3366 __ Pld(MemOperand(r0, 0)); 3367 __ Pld(MemOperand(r1, 123)); 3368 __ Pld(MemOperand(r2, 1234)); 3369 __ Pld(MemOperand(r3, 4095)); 3370 __ Pld(MemOperand(r4, -123)); 3371 __ Pld(MemOperand(r5, -255)); 3372 3373 if (masm.IsUsingA32()) { 3374 __ Pld(MemOperand(r6, -1234)); 3375 __ Pld(MemOperand(r7, -4095)); 3376 } 3377 3378 3379 // PLDW immediate 3380 __ Pldw(MemOperand(sp, 0)); 3381 __ Pldw(MemOperand(r0, 0)); 3382 __ Pldw(MemOperand(r1, 123)); 3383 __ Pldw(MemOperand(r2, 1234)); 3384 __ Pldw(MemOperand(r3, 4095)); 3385 __ Pldw(MemOperand(r4, -123)); 3386 __ Pldw(MemOperand(r5, -255)); 3387 3388 if (masm.IsUsingA32()) { 3389 __ Pldw(MemOperand(r6, -1234)); 3390 __ Pldw(MemOperand(r7, -4095)); 3391 } 3392 3393 // PLD register 3394 __ Pld(MemOperand(r0, r1)); 3395 __ Pld(MemOperand(r0, r1, LSL, 1)); 3396 __ Pld(MemOperand(r0, r1, LSL, 2)); 3397 __ Pld(MemOperand(r0, r1, LSL, 3)); 3398 3399 if (masm.IsUsingA32()) { 3400 __ Pld(MemOperand(r0, r1, LSL, 4)); 3401 __ Pld(MemOperand(r0, r1, LSL, 20)); 3402 } 3403 3404 // PLDW register 3405 __ Pldw(MemOperand(r0, r1)); 3406 __ Pldw(MemOperand(r0, r1, LSL, 1)); 3407 __ Pldw(MemOperand(r0, r1, LSL, 2)); 3408 __ Pldw(MemOperand(r0, r1, LSL, 3)); 3409 3410 if (masm.IsUsingA32()) { 3411 __ Pldw(MemOperand(r0, r1, LSL, 4)); 3412 __ Pldw(MemOperand(r0, r1, LSL, 20)); 3413 } 3414 3415 // PLD literal 3416 Label pld_label; 3417 __ Pld(&pld_label); 3418 __ Bind(&pld_label); 3419 3420 // PLI immediate 3421 __ Pli(MemOperand(sp, 0)); 3422 __ Pli(MemOperand(r0, 0)); 3423 __ Pli(MemOperand(r1, 123)); 3424 __ Pli(MemOperand(r2, 1234)); 3425 __ Pli(MemOperand(r3, 4095)); 3426 __ Pli(MemOperand(r4, -123)); 3427 __ Pli(MemOperand(r5, -255)); 3428 3429 if (masm.IsUsingA32()) { 3430 __ Pli(MemOperand(r6, -1234)); 3431 __ Pli(MemOperand(r7, -4095)); 3432 } 3433 3434 // PLI register 3435 __ Pli(MemOperand(r0, r1)); 3436 __ Pli(MemOperand(r0, r1, LSL, 1)); 3437 __ Pli(MemOperand(r0, r1, LSL, 2)); 3438 __ Pli(MemOperand(r0, r1, LSL, 3)); 3439 3440 if (masm.IsUsingA32()) { 3441 __ Pli(MemOperand(r0, r1, LSL, 4)); 3442 __ Pli(MemOperand(r0, r1, LSL, 20)); 3443 } 3444 3445 // PLI literal 3446 Label pli_label; 3447 __ Pli(&pli_label); 3448 __ Bind(&pli_label); 3449 3450 END(); 3451 3452 TEARDOWN(); 3453} 3454 3455 3456TEST_T32(veneer_mirrored_branches) { 3457 SETUP(); 3458 3459 START(); 3460 3461 const int kMaxBranchCount = 256; 3462 3463 for (int branch_count = 1; branch_count < kMaxBranchCount; branch_count++) { 3464 Label* targets = new Label[branch_count]; 3465 3466 for (int i = 0; i < branch_count; i++) { 3467 __ Cbz(r0, &targets[i]); 3468 } 3469 3470 for (int i = 0; i < branch_count; i++) { 3471 __ Bind(&targets[branch_count - i - 1]); 3472 __ Orr(r0, r0, r0); 3473 } 3474 3475 delete[] targets; 3476 } 3477 3478 END(); 3479 3480 TEARDOWN(); 3481} 3482 3483 3484TEST_T32(branch_fuzz_example) { 3485 SETUP(); 3486 3487 START(); 3488 3489 Label l[64]; 3490 __ And(r0, r0, r0); 3491 __ Cbz(r0, &l[30]); 3492 __ And(r0, r0, r0); 3493 __ Cbz(r0, &l[22]); 3494 __ And(r0, r0, r0); 3495 __ Cbz(r0, &l[1]); 3496 __ Cbz(r0, &l[15]); 3497 __ Cbz(r0, &l[9]); 3498 __ Cbz(r0, &l[6]); 3499 __ Bind(&l[26]); 3500 __ Cbz(r0, &l[29]); 3501 __ And(r0, r0, r0); 3502 __ And(r0, r0, r0); 3503 __ Cbz(r0, &l[22]); 3504 __ Bind(&l[12]); 3505 __ Bind(&l[22]); 3506 __ Cbz(r0, &l[10]); 3507 __ And(r0, r0, r0); 3508 __ Cbz(r0, &l[30]); 3509 __ Cbz(r0, &l[17]); 3510 __ Cbz(r0, &l[27]); 3511 __ Cbz(r0, &l[11]); 3512 __ Bind(&l[7]); 3513 __ Cbz(r0, &l[18]); 3514 __ Bind(&l[14]); 3515 __ Cbz(r0, &l[1]); 3516 __ Bind(&l[18]); 3517 __ Cbz(r0, &l[11]); 3518 __ Cbz(r0, &l[6]); 3519 __ Bind(&l[21]); 3520 __ Cbz(r0, &l[28]); 3521 __ And(r0, r0, r0); 3522 __ Cbz(r0, &l[28]); 3523 __ Cbz(r0, &l[22]); 3524 __ Bind(&l[23]); 3525 __ Cbz(r0, &l[21]); 3526 __ Cbz(r0, &l[28]); 3527 __ Cbz(r0, &l[9]); 3528 __ Bind(&l[9]); 3529 __ Cbz(r0, &l[4]); 3530 __ And(r0, r0, r0); 3531 __ Cbz(r0, &l[10]); 3532 __ And(r0, r0, r0); 3533 __ Bind(&l[8]); 3534 __ And(r0, r0, r0); 3535 __ Cbz(r0, &l[10]); 3536 __ And(r0, r0, r0); 3537 __ Cbz(r0, &l[17]); 3538 __ Bind(&l[10]); 3539 __ Cbz(r0, &l[8]); 3540 __ Cbz(r0, &l[25]); 3541 __ Cbz(r0, &l[4]); 3542 __ Bind(&l[28]); 3543 __ And(r0, r0, r0); 3544 __ Cbz(r0, &l[16]); 3545 __ Bind(&l[19]); 3546 __ Cbz(r0, &l[14]); 3547 __ Cbz(r0, &l[28]); 3548 __ Cbz(r0, &l[26]); 3549 __ Cbz(r0, &l[21]); 3550 __ And(r0, r0, r0); 3551 __ Bind(&l[24]); 3552 __ And(r0, r0, r0); 3553 __ Cbz(r0, &l[24]); 3554 __ Cbz(r0, &l[24]); 3555 __ Cbz(r0, &l[19]); 3556 __ Cbz(r0, &l[26]); 3557 __ Cbz(r0, &l[4]); 3558 __ And(r0, r0, r0); 3559 __ Cbz(r0, &l[27]); 3560 __ Cbz(r0, &l[14]); 3561 __ Cbz(r0, &l[5]); 3562 __ Cbz(r0, &l[18]); 3563 __ Cbz(r0, &l[5]); 3564 __ Cbz(r0, &l[6]); 3565 __ Cbz(r0, &l[28]); 3566 __ Cbz(r0, &l[15]); 3567 __ Cbz(r0, &l[0]); 3568 __ Cbz(r0, &l[10]); 3569 __ Cbz(r0, &l[16]); 3570 __ Cbz(r0, &l[30]); 3571 __ Cbz(r0, &l[8]); 3572 __ Cbz(r0, &l[16]); 3573 __ Cbz(r0, &l[22]); 3574 __ Cbz(r0, &l[27]); 3575 __ Cbz(r0, &l[12]); 3576 __ Cbz(r0, &l[0]); 3577 __ Cbz(r0, &l[23]); 3578 __ Cbz(r0, &l[27]); 3579 __ Cbz(r0, &l[16]); 3580 __ Cbz(r0, &l[24]); 3581 __ Cbz(r0, &l[17]); 3582 __ Cbz(r0, &l[4]); 3583 __ Cbz(r0, &l[11]); 3584 __ Cbz(r0, &l[6]); 3585 __ Cbz(r0, &l[23]); 3586 __ Bind(&l[16]); 3587 __ Cbz(r0, &l[10]); 3588 __ Cbz(r0, &l[17]); 3589 __ Cbz(r0, &l[12]); 3590 __ And(r0, r0, r0); 3591 __ Cbz(r0, &l[11]); 3592 __ Cbz(r0, &l[17]); 3593 __ Cbz(r0, &l[1]); 3594 __ Cbz(r0, &l[3]); 3595 __ Cbz(r0, &l[18]); 3596 __ Bind(&l[4]); 3597 __ Cbz(r0, &l[31]); 3598 __ Cbz(r0, &l[25]); 3599 __ Cbz(r0, &l[22]); 3600 __ And(r0, r0, r0); 3601 __ Cbz(r0, &l[19]); 3602 __ Cbz(r0, &l[16]); 3603 __ Cbz(r0, &l[21]); 3604 __ Cbz(r0, &l[27]); 3605 __ Bind(&l[1]); 3606 __ Cbz(r0, &l[9]); 3607 __ Cbz(r0, &l[13]); 3608 __ Cbz(r0, &l[10]); 3609 __ Cbz(r0, &l[6]); 3610 __ Cbz(r0, &l[30]); 3611 __ Cbz(r0, &l[28]); 3612 __ Cbz(r0, &l[7]); 3613 __ Cbz(r0, &l[17]); 3614 __ Bind(&l[0]); 3615 __ Cbz(r0, &l[13]); 3616 __ Cbz(r0, &l[11]); 3617 __ Cbz(r0, &l[19]); 3618 __ Cbz(r0, &l[22]); 3619 __ Cbz(r0, &l[9]); 3620 __ And(r0, r0, r0); 3621 __ Cbz(r0, &l[15]); 3622 __ Cbz(r0, &l[31]); 3623 __ Cbz(r0, &l[2]); 3624 __ And(r0, r0, r0); 3625 __ Cbz(r0, &l[6]); 3626 __ Bind(&l[27]); 3627 __ Bind(&l[13]); 3628 __ Cbz(r0, &l[23]); 3629 __ Cbz(r0, &l[7]); 3630 __ Bind(&l[2]); 3631 __ And(r0, r0, r0); 3632 __ Cbz(r0, &l[1]); 3633 __ Bind(&l[15]); 3634 __ Cbz(r0, &l[13]); 3635 __ Cbz(r0, &l[17]); 3636 __ Cbz(r0, &l[8]); 3637 __ Cbz(r0, &l[30]); 3638 __ Cbz(r0, &l[8]); 3639 __ Cbz(r0, &l[27]); 3640 __ Cbz(r0, &l[2]); 3641 __ Cbz(r0, &l[31]); 3642 __ Cbz(r0, &l[4]); 3643 __ Cbz(r0, &l[11]); 3644 __ Bind(&l[29]); 3645 __ Cbz(r0, &l[7]); 3646 __ Cbz(r0, &l[5]); 3647 __ Cbz(r0, &l[11]); 3648 __ Cbz(r0, &l[24]); 3649 __ Cbz(r0, &l[9]); 3650 __ Cbz(r0, &l[3]); 3651 __ Cbz(r0, &l[3]); 3652 __ Cbz(r0, &l[22]); 3653 __ Cbz(r0, &l[19]); 3654 __ Cbz(r0, &l[4]); 3655 __ Bind(&l[6]); 3656 __ And(r0, r0, r0); 3657 __ And(r0, r0, r0); 3658 __ Cbz(r0, &l[9]); 3659 __ Cbz(r0, &l[3]); 3660 __ Cbz(r0, &l[23]); 3661 __ Cbz(r0, &l[12]); 3662 __ Cbz(r0, &l[1]); 3663 __ Cbz(r0, &l[22]); 3664 __ Cbz(r0, &l[24]); 3665 __ And(r0, r0, r0); 3666 __ Cbz(r0, &l[16]); 3667 __ Cbz(r0, &l[19]); 3668 __ Cbz(r0, &l[20]); 3669 __ Cbz(r0, &l[1]); 3670 __ Cbz(r0, &l[4]); 3671 __ Cbz(r0, &l[1]); 3672 __ Cbz(r0, &l[25]); 3673 __ Cbz(r0, &l[21]); 3674 __ Cbz(r0, &l[20]); 3675 __ Cbz(r0, &l[29]); 3676 __ And(r0, r0, r0); 3677 __ Cbz(r0, &l[10]); 3678 __ Cbz(r0, &l[5]); 3679 __ And(r0, r0, r0); 3680 __ Cbz(r0, &l[25]); 3681 __ Cbz(r0, &l[26]); 3682 __ Cbz(r0, &l[28]); 3683 __ Cbz(r0, &l[19]); 3684 __ And(r0, r0, r0); 3685 __ Bind(&l[17]); 3686 __ And(r0, r0, r0); 3687 __ And(r0, r0, r0); 3688 __ And(r0, r0, r0); 3689 __ And(r0, r0, r0); 3690 __ Cbz(r0, &l[6]); 3691 __ And(r0, r0, r0); 3692 __ Cbz(r0, &l[5]); 3693 __ Cbz(r0, &l[26]); 3694 __ Cbz(r0, &l[28]); 3695 __ Cbz(r0, &l[24]); 3696 __ Bind(&l[20]); 3697 __ And(r0, r0, r0); 3698 __ Cbz(r0, &l[10]); 3699 __ Cbz(r0, &l[19]); 3700 __ Cbz(r0, &l[6]); 3701 __ And(r0, r0, r0); 3702 __ Cbz(r0, &l[13]); 3703 __ Cbz(r0, &l[15]); 3704 __ Cbz(r0, &l[22]); 3705 __ Cbz(r0, &l[8]); 3706 __ Cbz(r0, &l[6]); 3707 __ Cbz(r0, &l[23]); 3708 __ Cbz(r0, &l[6]); 3709 __ And(r0, r0, r0); 3710 __ Cbz(r0, &l[13]); 3711 __ Bind(&l[31]); 3712 __ Cbz(r0, &l[14]); 3713 __ Cbz(r0, &l[5]); 3714 __ Cbz(r0, &l[1]); 3715 __ Cbz(r0, &l[17]); 3716 __ Cbz(r0, &l[27]); 3717 __ Cbz(r0, &l[10]); 3718 __ Cbz(r0, &l[30]); 3719 __ Cbz(r0, &l[14]); 3720 __ Cbz(r0, &l[24]); 3721 __ Cbz(r0, &l[26]); 3722 __ And(r0, r0, r0); 3723 __ Cbz(r0, &l[2]); 3724 __ Cbz(r0, &l[21]); 3725 __ Cbz(r0, &l[5]); 3726 __ Cbz(r0, &l[24]); 3727 __ And(r0, r0, r0); 3728 __ Cbz(r0, &l[24]); 3729 __ Cbz(r0, &l[17]); 3730 __ And(r0, r0, r0); 3731 __ And(r0, r0, r0); 3732 __ Cbz(r0, &l[24]); 3733 __ And(r0, r0, r0); 3734 __ Cbz(r0, &l[17]); 3735 __ Cbz(r0, &l[12]); 3736 __ And(r0, r0, r0); 3737 __ Cbz(r0, &l[9]); 3738 __ Cbz(r0, &l[9]); 3739 __ Cbz(r0, &l[31]); 3740 __ Cbz(r0, &l[25]); 3741 __ And(r0, r0, r0); 3742 __ And(r0, r0, r0); 3743 __ Cbz(r0, &l[13]); 3744 __ Cbz(r0, &l[14]); 3745 __ Cbz(r0, &l[5]); 3746 __ Cbz(r0, &l[5]); 3747 __ Cbz(r0, &l[12]); 3748 __ Cbz(r0, &l[3]); 3749 __ Cbz(r0, &l[25]); 3750 __ Bind(&l[11]); 3751 __ Cbz(r0, &l[15]); 3752 __ Cbz(r0, &l[20]); 3753 __ Cbz(r0, &l[22]); 3754 __ Cbz(r0, &l[19]); 3755 __ And(r0, r0, r0); 3756 __ Cbz(r0, &l[19]); 3757 __ And(r0, r0, r0); 3758 __ Cbz(r0, &l[21]); 3759 __ Cbz(r0, &l[0]); 3760 __ And(r0, r0, r0); 3761 __ Cbz(r0, &l[16]); 3762 __ Cbz(r0, &l[28]); 3763 __ Cbz(r0, &l[18]); 3764 __ Cbz(r0, &l[3]); 3765 __ And(r0, r0, r0); 3766 __ Cbz(r0, &l[15]); 3767 __ Cbz(r0, &l[8]); 3768 __ Cbz(r0, &l[25]); 3769 __ Cbz(r0, &l[1]); 3770 __ Cbz(r0, &l[21]); 3771 __ Cbz(r0, &l[1]); 3772 __ Cbz(r0, &l[29]); 3773 __ Cbz(r0, &l[15]); 3774 __ And(r0, r0, r0); 3775 __ Cbz(r0, &l[24]); 3776 __ Cbz(r0, &l[3]); 3777 __ Cbz(r0, &l[9]); 3778 __ Cbz(r0, &l[9]); 3779 __ Cbz(r0, &l[24]); 3780 __ And(r0, r0, r0); 3781 __ Cbz(r0, &l[19]); 3782 __ And(r0, r0, r0); 3783 __ Cbz(r0, &l[30]); 3784 __ Bind(&l[25]); 3785 __ Bind(&l[3]); 3786 __ Bind(&l[30]); 3787 __ Bind(&l[5]); 3788 3789 END(); 3790 3791 TEARDOWN(); 3792} 3793 3794 3795// Generate a "B" and a "Cbz" which have the same checkpoint. Without proper 3796// management (i.e. if the veneers were only generated at the shared 3797// checkpoint), one one of the branches would be out of range. 3798TEST_T32(veneer_simultaneous) { 3799 SETUP(); 3800 3801 START(); 3802 3803 // `2046` max range - the size of the B.EQ itself. 3804 static const int kMaxBCondRange = 1048574; 3805 3806 Label target_1; 3807 Label target_2; 3808 3809 __ B(eq, &target_1); 3810 3811 int target_1_size_1 = 3812 kMaxBCondRange - kCbzCbnzRange - k32BitT32InstructionSizeInBytes; 3813 int end_1 = masm.GetCursorOffset() + target_1_size_1; 3814 while (masm.GetCursorOffset() < end_1) { 3815 __ Nop(); 3816 } 3817 3818 __ Cbz(r0, &target_2); 3819 3820 int target_1_size_2 = kCbzCbnzRange - k16BitT32InstructionSizeInBytes; 3821 int end_2 = masm.GetCursorOffset() + target_1_size_2; 3822 while (masm.GetCursorOffset() < end_2) { 3823 __ Nop(); 3824 } 3825 3826 __ Nop(); 3827 3828 __ Bind(&target_1); 3829 __ Bind(&target_2); 3830 3831 END(); 3832 3833 TEARDOWN(); 3834} 3835 3836 3837// Generate a "B" and a "Cbz" which have the same checkpoint and the same label. 3838TEST_T32(veneer_simultaneous_one_label) { 3839 SETUP(); 3840 3841 START(); 3842 3843 // `2046` max range - the size of the B.EQ itself. 3844 static const int kMaxBCondRange = 1048574; 3845 3846 Label target; 3847 3848 __ B(eq, &target); 3849 3850 int target_1_size_1 = 3851 kMaxBCondRange - kCbzCbnzRange - k32BitT32InstructionSizeInBytes; 3852 int end_1 = masm.GetCursorOffset() + target_1_size_1; 3853 while (masm.GetCursorOffset() < end_1) { 3854 __ Nop(); 3855 } 3856 3857 __ Cbz(r0, &target); 3858 3859 int target_1_size_2 = kCbzCbnzRange - k16BitT32InstructionSizeInBytes; 3860 int end_2 = masm.GetCursorOffset() + target_1_size_2; 3861 while (masm.GetCursorOffset() < end_2) { 3862 __ Nop(); 3863 } 3864 3865 __ Nop(); 3866 3867 __ Bind(&target); 3868 3869 END(); 3870 3871 TEARDOWN(); 3872} 3873 3874 3875// The literal pool will be emitted early because we keep a margin to always be 3876// able to generate the veneers before the literal. 3877TEST_T32(veneer_and_literal) { 3878 SETUP(); 3879 3880 START(); 3881 3882 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3883 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3884 3885 const uint32_t ldrd_range = 1020; 3886 const uint32_t cbz_range = 126; 3887 const uint32_t kLabelsCount = 20; 3888 Label labels[kLabelsCount]; 3889 3890 // Create one literal pool entry. 3891 __ Ldrd(r0, r1, 0x1234567890abcdef); 3892 3893 // Generate some nops. 3894 uint32_t i = 0; 3895 for (; i < ldrd_range - cbz_range - 40; 3896 i += k16BitT32InstructionSizeInBytes) { 3897 __ Nop(); 3898 } 3899 3900 // At this point, it remains cbz_range + 40 => 166 bytes before ldrd becomes 3901 // out of range. 3902 // We generate kLabelsCount * 4 => 80 bytes. We shouldn't generate the 3903 // literal pool. 3904 for (uint32_t j = 0; j < kLabelsCount; j++) { 3905 __ Cbz(r0, &labels[j]); 3906 __ Nop(); 3907 i += 2 * k16BitT32InstructionSizeInBytes; 3908 } 3909 3910 // However as we have pending veneer, the range is shrinken and the literal 3911 // pool is generated. 3912 VIXL_ASSERT(masm.LiteralPoolIsEmpty()); 3913 // However, we didn't generate the veneer pool. 3914 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() < 3915 static_cast<int32_t>(cbz_range)); 3916 3917 // We generate a few more instructions. 3918 for (; i < ldrd_range - 4 * kA32InstructionSizeInBytes; 3919 i += k16BitT32InstructionSizeInBytes) { 3920 __ Nop(); 3921 } 3922 3923 // And a veneer pool has been generated. 3924 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() > 3925 static_cast<int32_t>(cbz_range)); 3926 3927 // Bind all the used labels. 3928 for (uint32_t j = 0; j < kLabelsCount; j++) { 3929 __ Bind(&labels[j]); 3930 __ Nop(); 3931 } 3932 3933 // Now that all the labels have been bound, we have no more veneer. 3934 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3935 3936 END(); 3937 3938 RUN(); 3939 3940 // Check that the literals loaded correctly. 3941 ASSERT_EQUAL_32(0x90abcdef, r0); 3942 ASSERT_EQUAL_32(0x12345678, r1); 3943 3944 TEARDOWN(); 3945} 3946 3947 3948// The literal pool will be emitted early and, as the emission of the literal 3949// pool would have put veneer out of range, the veneers are emitted first. 3950TEST_T32(veneer_and_literal2) { 3951 SETUP(); 3952 3953 START(); 3954 3955 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 3956 VIXL_CHECK(masm.LiteralPoolIsEmpty()); 3957 3958 const uint32_t ldrd_range = 1020; 3959 const uint32_t cbz_range = 126; 3960 const uint32_t kLabelsCount = 20; 3961 const int32_t kTypicalMacroInstructionMaxSize = 3962 8 * kMaxInstructionSizeInBytes; 3963 Label labels[kLabelsCount]; 3964 3965 // Create one literal pool entry. 3966 __ Ldrd(r0, r1, 0x1234567890abcdef); 3967 3968 for (uint32_t i = 0; i < ldrd_range - cbz_range - 4 * kLabelsCount; 3969 i += k16BitT32InstructionSizeInBytes) { 3970 __ Nop(); 3971 } 3972 3973 // Add entries to the veneer pool. 3974 for (uint32_t i = 0; i < kLabelsCount; i++) { 3975 __ Cbz(r0, &labels[i]); 3976 __ Nop(); 3977 } 3978 3979 // Generate nops up to the literal pool limit. 3980 while (masm.GetMarginBeforeLiteralEmission() >= 3981 kTypicalMacroInstructionMaxSize) { 3982 __ Nop(); 3983 } 3984 3985 // At this point, no literals and no veneers have been generated. 3986 VIXL_ASSERT(!masm.LiteralPoolIsEmpty()); 3987 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() < 3988 static_cast<int32_t>(cbz_range)); 3989 // The literal pool needs to be generated. 3990 VIXL_ASSERT(masm.GetMarginBeforeLiteralEmission() < 3991 kTypicalMacroInstructionMaxSize); 3992 // But not the veneer pool. 3993 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() >= 3994 kTypicalMacroInstructionMaxSize); 3995 // However, as the literal emission would put veneers out of range. 3996 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() < 3997 kTypicalMacroInstructionMaxSize + 3998 static_cast<int32_t>(masm.GetLiteralPoolSize())); 3999 4000 // This extra Nop will generate the literal pool and before that the veneer 4001 // pool. 4002 __ Nop(); 4003 // Now the literal pool has been generated. 4004 VIXL_ASSERT(masm.LiteralPoolIsEmpty()); 4005 // And also the veneer pool. 4006 VIXL_ASSERT(masm.GetMarginBeforeVeneerEmission() > 1000); 4007 4008 // Bind all the used labels. 4009 for (uint32_t j = 0; j < kLabelsCount; j++) { 4010 __ Bind(&labels[j]); 4011 __ Nop(); 4012 } 4013 4014 // Now that all the labels have been bound, we have no more veneer. 4015 VIXL_CHECK(masm.VeneerPoolIsEmpty()); 4016 4017 END(); 4018 4019 RUN(); 4020 4021 // Check that the literals loaded correctly. 4022 ASSERT_EQUAL_32(0x90abcdef, r0); 4023 ASSERT_EQUAL_32(0x12345678, r1); 4024 4025 TEARDOWN(); 4026} 4027 4028 4029// Use a literal when we already have a veneer pool potential size greater than 4030// the literal range => generate the literal immediately (not optimum but it 4031// works). 4032TEST_T32(veneer_and_literal3) { 4033 SETUP(); 4034 4035 START(); 4036 4037 static const int kLabelsCount = 1000; 4038 4039 Label labels[kLabelsCount]; 4040 4041 // Set the Z flag so that the following branches are not taken. 4042 __ Movs(r0, 0); 4043 4044 for (int i = 0; i < kLabelsCount; i++) { 4045 __ B(ne, &labels[i]); 4046 } 4047 4048 // Create one literal pool entry. 4049 __ Ldrd(r0, r1, 0x1234567890abcdef); 4050 4051 for (int i = 0; i < 10; i++) { 4052 __ Nop(); 4053 } 4054 4055 for (int i = 0; i < kLabelsCount; i++) { 4056 __ Bind(&labels[i]); 4057 } 4058 4059 END(); 4060 4061 RUN(); 4062 4063 // Check that the literals loaded correctly. 4064 ASSERT_EQUAL_32(0x90abcdef, r0); 4065 ASSERT_EQUAL_32(0x12345678, r1); 4066 4067 TEARDOWN(); 4068} 4069 4070 4071// Literal has to be generated sooner than veneers. However, as the literal 4072// pool generation would make the veneers out of range, generate the veneers 4073// first. 4074TEST_T32(veneer_and_literal4) { 4075 SETUP(); 4076 4077 START(); 4078 4079 Label end; 4080 4081 // Set the Z flag so that the following branch is not taken. 4082 __ Movs(r0, 0); 4083 __ B(ne, &end); 4084 4085 uint32_t value = 0x1234567; 4086 vixl::aarch32::Literal<uint32_t>* literal = 4087 new Literal<uint32_t>(value, RawLiteral::kPlacedWhenUsed, RawLiteral::kDeletedOnPoolDestruction); 4088 4089 __ Ldr(r11, literal); 4090 4091 // The range for ldr is 4095, the range for cbz is 127. Generate nops 4092 // to have the ldr becomming out of range just before the cbz. 4093 const int NUM_NOPS = 2044; 4094 const int NUM_RANGE = 58; 4095 4096 const int NUM1 = NUM_NOPS - NUM_RANGE; 4097 const int NUM2 = NUM_RANGE ; 4098 4099 { 4100 ExactAssemblyScope aas(&masm, 4101 2 * NUM1, 4102 CodeBufferCheckScope::kMaximumSize); 4103 for (int i = 0; i < NUM1; i++) { 4104 __ nop(); 4105 } 4106 } 4107 4108 __ Cbz(r1, &end); 4109 4110 { 4111 ExactAssemblyScope aas(&masm, 4112 2 * NUM2, 4113 CodeBufferCheckScope::kMaximumSize); 4114 for (int i = 0; i < NUM2; i++) { 4115 __ nop(); 4116 } 4117 } 4118 4119 { 4120 ExactAssemblyScope aas(&masm, 4121 4, 4122 CodeBufferCheckScope::kMaximumSize); 4123 __ add(r1, r1, 3); 4124 } 4125 __ Bind(&end); 4126 4127 END(); 4128 4129 RUN(); 4130 4131 // Check that the literals loaded correctly. 4132 ASSERT_EQUAL_32(0x1234567, r11); 4133 4134 TEARDOWN(); 4135} 4136 4137 4138// Literal has to be generated sooner than veneers. However, as the literal 4139// pool generation would make the veneers out of range, generate the veneers 4140// first. 4141TEST_T32(veneer_and_literal5) { 4142 SETUP(); 4143 4144 START(); 4145 4146 static const int kTestCount = 100; 4147 Label labels[kTestCount]; 4148 4149 int first_test = 2000; 4150 // Test on both sizes of the Adr range which is 4095. 4151 for (int test = 0; test < kTestCount; test++) { 4152 4153 const int string_size = 1000; // A lot more than the cbz range. 4154 std::string test_string(string_size, 'x'); 4155 StringLiteral big_literal(test_string.c_str()); 4156 4157 __ Adr(r11, &big_literal); 4158 4159 { 4160 int num_nops = first_test + test; 4161 ExactAssemblyScope aas(&masm, 4162 2 * num_nops, 4163 CodeBufferCheckScope::kMaximumSize); 4164 for (int i = 0; i < num_nops; i++) { 4165 __ nop(); 4166 } 4167 } 4168 4169 __ Cbz(r1, &labels[test]); 4170 4171 { 4172 ExactAssemblyScope aas(&masm, 4173 4, 4174 CodeBufferCheckScope::kMaximumSize); 4175 __ add(r1, r1, 3); 4176 } 4177 __ Bind(&labels[test]); 4178 // Emit the literal pool if it has not beeen emitted (it's the case for 4179 // the lower values of test). 4180 __ EmitLiteralPool(MacroAssembler::kBranchRequired); 4181 } 4182 4183 END(); 4184 4185 TEARDOWN(); 4186} 4187 4188 4189// Check that a label which is just bound during the MacroEmissionCheckScope 4190// can be used. 4191TEST(ldr_label_bound_during_scope) { 4192 SETUP(); 4193 START(); 4194 4195 const int32_t kTypicalMacroInstructionMaxSize = 4196 8 * kMaxInstructionSizeInBytes; 4197 4198 vixl::aarch32::Literal<uint64_t>* literal = 4199 new Literal<uint64_t>(UINT64_C(0x1234567890abcdef), 4200 RawLiteral::kPlacedWhenUsed, 4201 RawLiteral::kDeletedOnPoolDestruction); 4202 __ Ldrd(r0, r1, literal); 4203 4204 while (masm.GetMarginBeforeLiteralEmission() >= 4205 kTypicalMacroInstructionMaxSize) { 4206 __ Nop(); 4207 } 4208 4209 VIXL_ASSERT(!masm.LiteralPoolIsEmpty()); 4210 4211 // This Ldrd will first generate the pool and then use literal which has just 4212 // been bound. 4213 __ Ldrd(r2, r3, literal); 4214 4215 VIXL_ASSERT(masm.LiteralPoolIsEmpty()); 4216 4217 END(); 4218 4219 RUN(); 4220 4221 // Check that the literals loaded correctly. 4222 ASSERT_EQUAL_32(0x90abcdef, r0); 4223 ASSERT_EQUAL_32(0x12345678, r1); 4224 ASSERT_EQUAL_32(0x90abcdef, r2); 4225 ASSERT_EQUAL_32(0x12345678, r3); 4226 4227 TEARDOWN(); 4228} 4229 4230 4231// TODO: Remove this limitation by having a sandboxing mechanism. 4232#if defined(VIXL_HOST_POINTER_32) 4233TEST(ldm_stm_no_writeback) { 4234 SETUP(); 4235 4236 START(); 4237 4238 const uint32_t src[4] = { 0x12345678, 0x09abcdef, 0xc001c0de, 0xdeadbeef }; 4239 uint32_t dst1[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 4240 uint32_t dst2[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 4241 4242 __ Mov(r0, reinterpret_cast<uintptr_t>(src)); 4243 __ Ldm(r0, NO_WRITE_BACK, RegisterList(r1, r2, r3, r4));; 4244 __ Ldm(r0, NO_WRITE_BACK, RegisterList(r5, r6, r9, r11)); 4245 4246 __ Mov(r0, reinterpret_cast<uintptr_t>(dst1)); 4247 __ Stm(r0, NO_WRITE_BACK, RegisterList(r1, r2, r3, r4));; 4248 4249 __ Mov(r0, reinterpret_cast<uintptr_t>(dst2)); 4250 __ Stm(r0, NO_WRITE_BACK, RegisterList(r5, r6, r9, r11)); 4251 4252 END(); 4253 4254 RUN(); 4255 4256 ASSERT_EQUAL_32(0x12345678, r1); 4257 ASSERT_EQUAL_32(0x09abcdef, r2); 4258 ASSERT_EQUAL_32(0xc001c0de, r3); 4259 ASSERT_EQUAL_32(0xdeadbeef, r4); 4260 4261 ASSERT_EQUAL_32(0x12345678, r5); 4262 ASSERT_EQUAL_32(0x09abcdef, r6); 4263 ASSERT_EQUAL_32(0xc001c0de, r9); 4264 ASSERT_EQUAL_32(0xdeadbeef, r11); 4265 4266 ASSERT_EQUAL_32(0x12345678, dst1[0]); 4267 ASSERT_EQUAL_32(0x09abcdef, dst1[1]); 4268 ASSERT_EQUAL_32(0xc001c0de, dst1[2]); 4269 ASSERT_EQUAL_32(0xdeadbeef, dst1[3]); 4270 4271 ASSERT_EQUAL_32(0x12345678, dst2[0]); 4272 ASSERT_EQUAL_32(0x09abcdef, dst2[1]); 4273 ASSERT_EQUAL_32(0xc001c0de, dst2[2]); 4274 ASSERT_EQUAL_32(0xdeadbeef, dst2[3]); 4275 4276 TEARDOWN(); 4277} 4278 4279 4280TEST(ldm_stm_writeback) { 4281 SETUP(); 4282 4283 START(); 4284 4285 const uint32_t src[4] = { 0x12345678, 0x09abcdef, 0xc001c0de, 0xdeadbeef }; 4286 uint32_t dst[8] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4287 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 4288 4289 __ Mov(r0, reinterpret_cast<uintptr_t>(src)); 4290 __ Ldm(r0, WRITE_BACK, RegisterList(r2, r3));; 4291 __ Ldm(r0, WRITE_BACK, RegisterList(r4, r5));; 4292 4293 __ Mov(r1, reinterpret_cast<uintptr_t>(dst)); 4294 __ Stm(r1, WRITE_BACK, RegisterList(r2, r3, r4, r5)); 4295 __ Stm(r1, WRITE_BACK, RegisterList(r2, r3, r4, r5)); 4296 4297 END(); 4298 4299 RUN(); 4300 4301 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src + 4), r0); 4302 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst + 8), r1); 4303 4304 ASSERT_EQUAL_32(0x12345678, r2); 4305 ASSERT_EQUAL_32(0x09abcdef, r3); 4306 ASSERT_EQUAL_32(0xc001c0de, r4); 4307 ASSERT_EQUAL_32(0xdeadbeef, r5); 4308 4309 ASSERT_EQUAL_32(0x12345678, dst[0]); 4310 ASSERT_EQUAL_32(0x09abcdef, dst[1]); 4311 ASSERT_EQUAL_32(0xc001c0de, dst[2]); 4312 ASSERT_EQUAL_32(0xdeadbeef, dst[3]); 4313 ASSERT_EQUAL_32(0x12345678, dst[4]); 4314 ASSERT_EQUAL_32(0x09abcdef, dst[5]); 4315 ASSERT_EQUAL_32(0xc001c0de, dst[6]); 4316 ASSERT_EQUAL_32(0xdeadbeef, dst[7]); 4317 4318 TEARDOWN(); 4319} 4320 4321 4322TEST_A32(ldm_stm_da_ib) { 4323 SETUP(); 4324 4325 START(); 4326 4327 const uint32_t src1[4] = { 0x33333333, 0x44444444, 0x11111111, 0x22222222 }; 4328 const uint32_t src2[4] = { 0x11111111, 0x22222222, 0x33333333, 0x44444444 }; 4329 4330 uint32_t dst1[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 4331 uint32_t dst2[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 4332 4333 __ Mov(r11, reinterpret_cast<uintptr_t>(src1 + 3)); 4334 __ Ldmda(r11, WRITE_BACK, RegisterList(r0, r1)); 4335 __ Ldmda(r11, NO_WRITE_BACK, RegisterList(r2, r3)); 4336 4337 __ Mov(r10, reinterpret_cast<uintptr_t>(src2 - 1)); 4338 __ Ldmib(r10, WRITE_BACK, RegisterList(r4, r5)); 4339 __ Ldmib(r10, NO_WRITE_BACK, RegisterList(r6, r7)); 4340 4341 __ Mov(r9, reinterpret_cast<uintptr_t>(dst1 + 3)); 4342 __ Stmda(r9, WRITE_BACK, RegisterList(r0, r1)); 4343 __ Stmda(r9, NO_WRITE_BACK, RegisterList(r2, r3)); 4344 4345 __ Mov(r8, reinterpret_cast<uintptr_t>(dst2 - 1)); 4346 __ Stmib(r8, WRITE_BACK, RegisterList(r4, r5)); 4347 __ Stmib(r8, NO_WRITE_BACK, RegisterList(r6, r7)); 4348 4349 4350 END(); 4351 4352 RUN(); 4353 4354 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src1 + 1), r11); 4355 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src2 + 1), r10); 4356 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst1 + 1), r9); 4357 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst2 + 1), r8); 4358 4359 ASSERT_EQUAL_32(0x11111111, r0); 4360 ASSERT_EQUAL_32(0x22222222, r1); 4361 ASSERT_EQUAL_32(0x33333333, r2); 4362 ASSERT_EQUAL_32(0x44444444, r3); 4363 4364 ASSERT_EQUAL_32(0x11111111, r4); 4365 ASSERT_EQUAL_32(0x22222222, r5); 4366 ASSERT_EQUAL_32(0x33333333, r6); 4367 ASSERT_EQUAL_32(0x44444444, r7); 4368 4369 ASSERT_EQUAL_32(0x33333333, dst1[0]); 4370 ASSERT_EQUAL_32(0x44444444, dst1[1]); 4371 ASSERT_EQUAL_32(0x11111111, dst1[2]); 4372 ASSERT_EQUAL_32(0x22222222, dst1[3]); 4373 4374 ASSERT_EQUAL_32(0x11111111, dst2[0]); 4375 ASSERT_EQUAL_32(0x22222222, dst2[1]); 4376 ASSERT_EQUAL_32(0x33333333, dst2[2]); 4377 ASSERT_EQUAL_32(0x44444444, dst2[3]); 4378 4379 TEARDOWN(); 4380} 4381 4382 4383TEST(ldmdb_stmdb) { 4384 SETUP(); 4385 4386 START(); 4387 4388 const uint32_t src[6] = { 0x55555555, 0x66666666, 4389 0x33333333, 0x44444444, 4390 0x11111111, 0x22222222 }; 4391 4392 uint32_t dst[6] = { 0x00000000, 0x00000000, 0x00000000, 4393 0x00000000, 0x00000000, 0x00000000 }; 4394 4395 __ Mov(r11, reinterpret_cast<uintptr_t>(src + 6)); 4396 __ Ldmdb(r11, WRITE_BACK, RegisterList(r1, r2)); 4397 __ Ldmdb(r11, WRITE_BACK, RegisterList(r3, r4)); 4398 __ Ldmdb(r11, NO_WRITE_BACK, RegisterList(r5, r6)); 4399 4400 __ Mov(r10, reinterpret_cast<uintptr_t>(dst + 6)); 4401 __ Stmdb(r10, WRITE_BACK, RegisterList(r5, r6)); 4402 __ Stmdb(r10, WRITE_BACK, RegisterList(r3, r4)); 4403 __ Stmdb(r10, NO_WRITE_BACK, RegisterList(r1, r2)); 4404 4405 END(); 4406 4407 RUN(); 4408 4409 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src + 2), r11); 4410 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst + 2), r10); 4411 4412 ASSERT_EQUAL_32(0x11111111, r1); 4413 ASSERT_EQUAL_32(0x22222222, r2); 4414 ASSERT_EQUAL_32(0x33333333, r3); 4415 ASSERT_EQUAL_32(0x44444444, r4); 4416 ASSERT_EQUAL_32(0x55555555, r5); 4417 ASSERT_EQUAL_32(0x66666666, r6); 4418 4419 ASSERT_EQUAL_32(0x11111111, dst[0]); 4420 ASSERT_EQUAL_32(0x22222222, dst[1]); 4421 ASSERT_EQUAL_32(0x33333333, dst[2]); 4422 ASSERT_EQUAL_32(0x44444444, dst[3]); 4423 ASSERT_EQUAL_32(0x55555555, dst[4]); 4424 ASSERT_EQUAL_32(0x66666666, dst[5]); 4425 4426 TEARDOWN(); 4427} 4428#endif 4429 4430 4431} // namespace aarch32 4432} // namespace vixl 4433