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