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