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 j = 0; j < 20; j++) {
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
3195 // clang-format off
TEST_NOASM(set_isa_noop)3196 TEST_NOASM(set_isa_noop) {
3197 // It is possible to call a no-op UseA32/T32 or UseInstructionSet even if
3198 // one or more instructions have been generated.
3199 #ifdef VIXL_INCLUDE_TARGET_A32
3200 {
3201 Assembler assm(A32);
3202 CheckInstructionSetA32(assm);
3203 CodeBufferCheckScope scope(&assm, kMaxInstructionSizeInBytes);
3204 assm.bx(lr);
3205 VIXL_ASSERT(assm.GetCursorOffset() > 0);
3206 CheckInstructionSetA32(assm);
3207 assm.UseA32();
3208 CheckInstructionSetA32(assm);
3209 assm.UseInstructionSet(A32);
3210 CheckInstructionSetA32(assm);
3211 assm.FinalizeCode();
3212 }
3213 {
3214 MacroAssembler masm(A32);
3215 CheckInstructionSetA32(masm);
3216 masm.Bx(lr);
3217 VIXL_ASSERT(masm.GetCursorOffset() > 0);
3218 CheckInstructionSetA32(masm);
3219 masm.UseA32();
3220 CheckInstructionSetA32(masm);
3221 masm.UseInstructionSet(A32);
3222 CheckInstructionSetA32(masm);
3223 masm.FinalizeCode();
3224 }
3225 #endif
3226
3227 #ifdef VIXL_INCLUDE_TARGET_T32
3228 {
3229 Assembler assm(T32);
3230 CheckInstructionSetT32(assm);
3231 CodeBufferCheckScope scope(&assm, kMaxInstructionSizeInBytes);
3232 assm.bx(lr);
3233 VIXL_ASSERT(assm.GetCursorOffset() > 0);
3234 CheckInstructionSetT32(assm);
3235 assm.UseT32();
3236 CheckInstructionSetT32(assm);
3237 assm.UseInstructionSet(T32);
3238 CheckInstructionSetT32(assm);
3239 assm.FinalizeCode();
3240 }
3241 {
3242 MacroAssembler masm(T32);
3243 CheckInstructionSetT32(masm);
3244 masm.Bx(lr);
3245 VIXL_ASSERT(masm.GetCursorOffset() > 0);
3246 CheckInstructionSetT32(masm);
3247 masm.UseT32();
3248 CheckInstructionSetT32(masm);
3249 masm.UseInstructionSet(T32);
3250 CheckInstructionSetT32(masm);
3251 masm.FinalizeCode();
3252 }
3253 #endif
3254 }
3255 // clang-format on
3256
3257
TEST(logical_arithmetic_identities)3258 TEST(logical_arithmetic_identities) {
3259 SETUP();
3260
3261 START();
3262
3263 Label blob_1;
3264 __ Bind(&blob_1);
3265 __ Add(r0, r0, 0);
3266 __ And(r0, r0, 0xffffffff);
3267 __ Bic(r0, r0, 0);
3268 __ Eor(r0, r0, 0);
3269 __ Orn(r0, r0, 0xffffffff);
3270 __ Orr(r0, r0, 0);
3271 __ Sub(r0, r0, 0);
3272 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_1) == 0);
3273
3274 Label blob_2;
3275 __ Bind(&blob_2);
3276 __ Adds(r0, r0, 0);
3277 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_2) != 0);
3278
3279 Label blob_3;
3280 __ Bind(&blob_3);
3281 __ Ands(r0, r0, 0);
3282 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_3) != 0);
3283
3284 Label blob_4;
3285 __ Bind(&blob_4);
3286 __ Bics(r0, r0, 0);
3287 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_4) != 0);
3288
3289 Label blob_5;
3290 __ Bind(&blob_5);
3291 __ Eors(r0, r0, 0);
3292 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_5) != 0);
3293
3294 Label blob_6;
3295 __ Bind(&blob_6);
3296 __ Orns(r0, r0, 0);
3297 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_6) != 0);
3298
3299 Label blob_7;
3300 __ Bind(&blob_7);
3301 __ Orrs(r0, r0, 0);
3302 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_7) != 0);
3303
3304 Label blob_8;
3305 __ Bind(&blob_8);
3306 __ Subs(r0, r0, 0);
3307 VIXL_ASSERT(masm.GetSizeOfCodeGeneratedSince(&blob_8) != 0);
3308
3309 __ Mov(r0, 0xbad);
3310 __ And(r1, r0, 0);
3311 __ Bic(r2, r0, 0xffffffff);
3312 __ Eor(r3, r0, 0xffffffff);
3313 __ Orn(r4, r0, 0);
3314 __ Orr(r5, r0, 0xffffffff);
3315
3316 END();
3317
3318 RUN();
3319
3320 ASSERT_EQUAL_32(0xbad, r0);
3321 ASSERT_EQUAL_32(0, r1);
3322 ASSERT_EQUAL_32(0, r2);
3323 ASSERT_EQUAL_32(~0xbad, r3);
3324 ASSERT_EQUAL_32(0xffffffff, r4);
3325 ASSERT_EQUAL_32(0xffffffff, r5);
3326 }
3327
3328
TEST(scratch_register_checks)3329 TEST(scratch_register_checks) {
3330 // It is unsafe for users to use registers that the MacroAssembler is also
3331 // using as scratch registers. This test checks the MacroAssembler's checking
3332 // mechanism itself.
3333 SETUP();
3334 START();
3335 {
3336 UseScratchRegisterScope temps(&masm);
3337 // 'ip' is a scratch register by default.
3338 VIXL_CHECK(masm.GetScratchRegisterList()->GetList() ==
3339 (1u << ip.GetCode()));
3340 VIXL_CHECK(temps.IsAvailable(ip));
3341
3342 // Integer registers have no complicated aliasing so
3343 // masm.AliasesAvailableScratchRegister(reg) == temps.IsAvailable(reg).
3344 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
3345 Register reg(i);
3346 VIXL_CHECK(masm.AliasesAvailableScratchRegister(reg) ==
3347 temps.IsAvailable(reg));
3348 }
3349 }
3350 END();
3351 }
3352
3353
TEST(scratch_register_checks_v)3354 TEST(scratch_register_checks_v) {
3355 // It is unsafe for users to use registers that the MacroAssembler is also
3356 // using as scratch registers. This test checks the MacroAssembler's checking
3357 // mechanism itself.
3358 SETUP();
3359 {
3360 UseScratchRegisterScope temps(&masm);
3361 // There is no default floating-point scratch register. Add temps of various
3362 // sizes to check handling of aliased registers.
3363 VIXL_CHECK(masm.GetScratchVRegisterList()->GetList() == 0);
3364 temps.Include(q15);
3365 temps.Include(d15);
3366 temps.Include(s15);
3367 temps.Include(d4);
3368 temps.Include(d5);
3369 temps.Include(s24);
3370 temps.Include(s25);
3371 temps.Include(s26);
3372 temps.Include(s27);
3373 temps.Include(q0);
3374 // See VRegisterList for details of the list encoding.
3375 VIXL_CHECK(masm.GetScratchVRegisterList()->GetList() ==
3376 UINT64_C(0xf0000000cf008f0f));
3377 // | || || |
3378 // q15 d15| || q0
3379 // s24-s27 |d4-d5
3380 // s15
3381
3382 // Simple checks: Included registers are available.
3383 VIXL_CHECK(temps.IsAvailable(q15));
3384 VIXL_CHECK(temps.IsAvailable(d15));
3385 VIXL_CHECK(temps.IsAvailable(s15));
3386 VIXL_CHECK(temps.IsAvailable(d4));
3387 VIXL_CHECK(temps.IsAvailable(d5));
3388 VIXL_CHECK(temps.IsAvailable(s24));
3389 VIXL_CHECK(temps.IsAvailable(s25));
3390 VIXL_CHECK(temps.IsAvailable(s26));
3391 VIXL_CHECK(temps.IsAvailable(s27));
3392 VIXL_CHECK(temps.IsAvailable(q0));
3393
3394 // Each available S register should mark the corresponding D and Q registers
3395 // as aliasing an available scratch register.
3396 for (unsigned s = 0; s < kNumberOfSRegisters; s++) {
3397 if (temps.IsAvailable(SRegister(s))) {
3398 VIXL_CHECK(masm.AliasesAvailableScratchRegister(SRegister(s)));
3399 VIXL_CHECK(masm.AliasesAvailableScratchRegister(DRegister(s / 2)));
3400 VIXL_CHECK(masm.AliasesAvailableScratchRegister(QRegister(s / 4)));
3401 } else {
3402 // AliasesAvailableScratchRegiters == IsAvailable for S registers.
3403 VIXL_CHECK(!masm.AliasesAvailableScratchRegister(SRegister(s)));
3404 }
3405 }
3406
3407 // Similar checks for high D registers.
3408 unsigned first_high_d_register = kNumberOfSRegisters / 2;
3409 for (unsigned d = first_high_d_register; d < kMaxNumberOfDRegisters; d++) {
3410 if (temps.IsAvailable(DRegister(d))) {
3411 VIXL_CHECK(masm.AliasesAvailableScratchRegister(DRegister(d)));
3412 VIXL_CHECK(masm.AliasesAvailableScratchRegister(QRegister(d / 2)));
3413 } else {
3414 // AliasesAvailableScratchRegiters == IsAvailable for high D registers.
3415 VIXL_CHECK(!masm.AliasesAvailableScratchRegister(DRegister(d)));
3416 }
3417 }
3418 }
3419 }
3420
3421
TEST(nop)3422 TEST(nop) {
3423 SETUP();
3424
3425 Label start;
3426 __ Bind(&start);
3427 __ Nop();
3428 size_t nop_size = (isa == T32) ? k16BitT32InstructionSizeInBytes
3429 : kA32InstructionSizeInBytes;
3430 // `MacroAssembler::Nop` must generate at least one nop.
3431 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&start) >= nop_size);
3432
3433 masm.FinalizeCode();
3434 }
3435
3436 // Check that `GetPoolCheckpoint()` is precise.
TEST(literal_pool_margin)3437 TEST(literal_pool_margin) {
3438 SETUP();
3439
3440 START();
3441
3442 VIXL_CHECK(test.PoolIsEmpty());
3443
3444 // Create a single literal.
3445 __ Ldrd(r0, r1, 0x1234567890abcdef);
3446
3447 VIXL_CHECK(!test.PoolIsEmpty());
3448
3449 // Generate code to fill all the margin we have before generating the literal
3450 // pool.
3451 int32_t margin = test.GetPoolCheckpoint() - masm.GetCursorOffset();
3452 int32_t end = test.GetPoolCheckpoint();
3453 {
3454 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize);
3455 // Opening the scope should not have triggered the emission of the literal
3456 // pool.
3457 VIXL_CHECK(!test.PoolIsEmpty());
3458 while (masm.GetCursorOffset() < end) {
3459 __ nop();
3460 }
3461 VIXL_CHECK(masm.GetCursorOffset() == end);
3462 }
3463
3464 // There should be no margin left to emit the literal pool.
3465 VIXL_CHECK(!test.PoolIsEmpty());
3466 VIXL_CHECK(test.GetPoolCheckpoint() == masm.GetCursorOffset());
3467
3468 // So emitting a single instruction should force emission of the pool.
3469 __ Nop();
3470 VIXL_CHECK(test.PoolIsEmpty());
3471 END();
3472
3473 RUN();
3474
3475 // Check that the literals loaded correctly.
3476 ASSERT_EQUAL_32(0x90abcdef, r0);
3477 ASSERT_EQUAL_32(0x12345678, r1);
3478 }
3479
3480
3481 // Check that `GetPoolCheckpoint()` is precise.
TEST(veneer_pool_margin)3482 TEST(veneer_pool_margin) {
3483 SETUP();
3484
3485 START();
3486
3487 VIXL_CHECK(test.PoolIsEmpty());
3488
3489 // Create a single veneer.
3490 Label target;
3491 __ B(eq, &target);
3492
3493 VIXL_CHECK(!test.PoolIsEmpty());
3494
3495 // Generate code to fill all the margin we have before generating the veneer
3496 // pool.
3497 int32_t margin = test.GetPoolCheckpoint() - masm.GetCursorOffset();
3498 int32_t end = test.GetPoolCheckpoint();
3499 {
3500 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize);
3501 // Opening the scope should not have triggered the emission of the veneer
3502 // pool.
3503 VIXL_CHECK(!test.PoolIsEmpty());
3504 while (masm.GetCursorOffset() < end) {
3505 __ nop();
3506 }
3507 VIXL_CHECK(masm.GetCursorOffset() == end);
3508 }
3509 // There should be no margin left to emit the veneer pool.
3510 VIXL_CHECK(test.GetPoolCheckpoint() == masm.GetCursorOffset());
3511
3512 // So emitting a single instruction should force emission of the pool.
3513 // We cannot simply check that the veneer pool is empty, because the veneer
3514 // emitted for the CBZ instruction above is itself tracked by the veneer
3515 // mechanisms. Instead, check that some 'unexpected' code is generated.
3516 Label check;
3517 __ Bind(&check);
3518 {
3519 ExactAssemblyScope scope(&masm, 2, ExactAssemblyScope::kMaximumSize);
3520 // Do not actually generate any code.
3521 }
3522 VIXL_CHECK(masm.GetSizeOfCodeGeneratedSince(&check) > 0);
3523 __ Bind(&target);
3524 VIXL_CHECK(test.PoolIsEmpty());
3525
3526 END();
3527
3528 RUN();
3529 }
3530
TEST_T32(near_branch_fuzz)3531 TEST_T32(near_branch_fuzz) {
3532 SETUP();
3533 START();
3534
3535 uint16_t seed[3] = {1, 2, 3};
3536 seed48(seed);
3537
3538 const int label_count = 31;
3539 Label* l;
3540
3541 // Use multiple iterations, as each produces a different predictably random
3542 // sequence.
3543 const int iterations = 64;
3544
3545 int loop_count = 0;
3546 __ Mov(r1, 0);
3547
3548 // Initialise the status flags to Z set.
3549 __ Cmp(r1, r1);
3550
3551 // Gradually increasing the number of cases effectively increases the
3552 // probability of nops being emitted in the sequence. The branch-to-bind
3553 // ratio in the sequence is fixed at 4:1 by the ratio of cases.
3554 for (int case_count = 6; case_count < 37; case_count++) {
3555 for (int iter = 0; iter < iterations; iter++) {
3556 l = new Label[label_count];
3557
3558 // Set r0 != 0 to force no branches to be taken. Also acts as a marker
3559 // between each iteration in the disassembly.
3560 __ Mov(r0, 1);
3561
3562 for (;;) {
3563 uint32_t inst_case = static_cast<uint32_t>(mrand48()) % case_count;
3564 uint32_t label_index = static_cast<uint32_t>(mrand48()) % label_count;
3565
3566 switch (inst_case) {
3567 case 0: // Bind.
3568 if (!l[label_index].IsBound()) {
3569 __ Bind(&l[label_index]);
3570
3571 // We should hit each label exactly once (because the branches are
3572 // never taken). Keep a counter to verify this.
3573 loop_count++;
3574 __ Add(r1, r1, 1);
3575 }
3576 break;
3577 case 1: // Compare and branch if zero (untaken as r0 == 1).
3578 __ Cbz(r0, &l[label_index]);
3579 break;
3580 case 2: { // Compare and branch if not zero.
3581 Label past_branch;
3582 __ B(eq, &past_branch, kNear);
3583 __ Cbnz(r0, &l[label_index]);
3584 __ Bind(&past_branch);
3585 break;
3586 }
3587 case 3: { // Unconditional branch preferred near.
3588 Label past_branch;
3589 __ B(eq, &past_branch, kNear);
3590 __ B(&l[label_index], kNear);
3591 __ Bind(&past_branch);
3592 break;
3593 }
3594 case 4: // Conditional branch (untaken as Z set) preferred near.
3595 __ B(ne, &l[label_index], kNear);
3596 break;
3597 default: // Nop.
3598 __ Nop();
3599 break;
3600 }
3601
3602 // If all labels have been bound, exit the inner loop and finalise the
3603 // code.
3604 bool all_bound = true;
3605 for (int i = 0; i < label_count; i++) {
3606 all_bound = all_bound && l[i].IsBound();
3607 }
3608 if (all_bound) break;
3609 }
3610
3611 // Ensure that the veneer pools are emitted, to keep each branch/bind test
3612 // independent. We will generate more code following this.
3613 masm.FinalizeCode(MacroAssembler::kFallThrough);
3614 delete[] l;
3615 }
3616 }
3617
3618 END();
3619 RUN();
3620
3621 ASSERT_EQUAL_32(loop_count, r1);
3622 }
3623
3624
NearBranchAndLiteralFuzzHelper(InstructionSet isa,int shard_count,int shard_offset)3625 static void NearBranchAndLiteralFuzzHelper(InstructionSet isa,
3626 int shard_count,
3627 int shard_offset) {
3628 SETUP();
3629 START();
3630
3631 uint16_t seed[3] = {1, 2, 3};
3632 seed48(seed);
3633
3634 const int label_count = 15;
3635 const int literal_count = 31;
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 VIXL_CHECK((iterations % shard_count) == 0);
3645
3646 int loop_count = 0;
3647 __ Mov(r1, 0);
3648
3649 // If the value of r4 changes then the test fails.
3650 __ Mov(r4, 42);
3651
3652 // This test generates a mix of 20 different code sequences (see switch case
3653 // below). The cases are split in 4 groups:
3654 //
3655 // - 0..3: Generate various amount of nops.
3656 // - 4..7: Generate various load intstructions with literals.
3657 // - 8..14: Generate various branch instructions.
3658 // - 15..19: Generate various amount of nops.
3659 //
3660 // The idea behind this is that we can have a window of size N which we can
3661 // slide across these cases. And as a result, randomly generate sequences with
3662 // a different ratio of:
3663 // - "nops vs literals"
3664 // - "literal vs veneers"
3665 // - "veneers vs nops"
3666 //
3667 // In this test, we grow a window from 5 to 14, and then slide this window
3668 // across all cases each time. We call this sliding a "ratio", which is in
3669 // fact an offset from the first case of the switch.
3670
3671 for (uint32_t window = 5; window < 14; window++) {
3672 for (uint32_t ratio = 0; ratio < static_cast<uint32_t>(n_cases - window);
3673 ratio++) {
3674 for (int iter = shard_offset; iter < iterations; iter += shard_count) {
3675 Label fail;
3676 Label end;
3677
3678 // Reset local state.
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 bool all_bound = true;
3862 for (int i = 0; i < label_count; i++) {
3863 all_bound = all_bound && labels[i].IsBound();
3864 }
3865 if (all_bound) 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
TEST_T32(near_branch_and_literal_fuzz_0)3892 TEST_T32(near_branch_and_literal_fuzz_0) {
3893 NearBranchAndLiteralFuzzHelper(isa, 4, 0);
3894 }
3895
TEST_T32(near_branch_and_literal_fuzz_1)3896 TEST_T32(near_branch_and_literal_fuzz_1) {
3897 NearBranchAndLiteralFuzzHelper(isa, 4, 1);
3898 }
3899
TEST_T32(near_branch_and_literal_fuzz_2)3900 TEST_T32(near_branch_and_literal_fuzz_2) {
3901 NearBranchAndLiteralFuzzHelper(isa, 4, 2);
3902 }
3903
TEST_T32(near_branch_and_literal_fuzz_3)3904 TEST_T32(near_branch_and_literal_fuzz_3) {
3905 NearBranchAndLiteralFuzzHelper(isa, 4, 3);
3906 }
3907
3908 #ifdef VIXL_INCLUDE_TARGET_T32
TEST_NOASM(code_buffer_precise_growth)3909 TEST_NOASM(code_buffer_precise_growth) {
3910 static const int kBaseBufferSize = 16;
3911 MacroAssembler masm(kBaseBufferSize, T32);
3912
3913 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize);
3914
3915 {
3916 // Fill the buffer with nops.
3917 ExactAssemblyScope scope(&masm,
3918 kBaseBufferSize,
3919 ExactAssemblyScope::kExactSize);
3920 for (int i = 0; i < kBaseBufferSize; i += k16BitT32InstructionSizeInBytes) {
3921 __ nop();
3922 }
3923 }
3924
3925 // The buffer should not have grown yet.
3926 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize);
3927
3928 // Generating a single instruction should force the buffer to grow.
3929 __ Nop();
3930
3931 VIXL_CHECK(masm.GetBuffer()->GetCapacity() > kBaseBufferSize);
3932
3933 masm.FinalizeCode();
3934 }
3935 #endif
3936
3937 #ifdef VIXL_INCLUDE_TARGET_T32
TEST_NOASM(out_of_space_immediately_before_EnsureEmitFor)3938 TEST_NOASM(out_of_space_immediately_before_EnsureEmitFor) {
3939 static const int kBaseBufferSize = 64;
3940 MacroAssembler masm(kBaseBufferSize, T32);
3941 TestMacroAssembler test(&masm);
3942
3943 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize);
3944
3945 VIXL_CHECK(test.PoolIsEmpty());
3946
3947 // Create a veneer.
3948 Label target;
3949 __ Cbz(r0, &target);
3950
3951 VIXL_CHECK(!test.PoolIsEmpty());
3952
3953 VIXL_CHECK(IsUint32(masm.GetBuffer()->GetRemainingBytes()));
3954 uint32_t space = static_cast<uint32_t>(masm.GetBuffer()->GetRemainingBytes());
3955 {
3956 // Fill the buffer with nops.
3957 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize);
3958 for (uint32_t i = 0; i < space; i += k16BitT32InstructionSizeInBytes) {
3959 __ nop();
3960 }
3961 }
3962
3963 VIXL_CHECK(!test.PoolIsEmpty());
3964
3965 // The buffer should not have grown yet, and there should be no space left.
3966 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize);
3967 VIXL_CHECK(masm.GetBuffer()->GetRemainingBytes() == 0);
3968
3969 // Force emission of the veneer, at a point where there is no space available
3970 // in the buffer.
3971 int32_t past_cbz_range =
3972 test.GetPoolCheckpoint() - masm.GetCursorOffset() + 1;
3973 masm.EnsureEmitFor(past_cbz_range);
3974
3975 __ Bind(&target);
3976
3977 VIXL_CHECK(test.PoolIsEmpty());
3978
3979 masm.FinalizeCode();
3980 }
3981 #endif
3982
3983
TEST_NOASM(EnsureEmitFor)3984 TEST_NOASM(EnsureEmitFor) {
3985 static const int kBaseBufferSize = 32;
3986 MacroAssembler masm(kBaseBufferSize);
3987
3988 VIXL_CHECK(masm.GetBuffer()->GetCapacity() == kBaseBufferSize);
3989
3990 VIXL_CHECK(IsUint32(masm.GetBuffer()->GetRemainingBytes()));
3991 int32_t space = static_cast<int32_t>(masm.GetBuffer()->GetRemainingBytes());
3992 int32_t end = __ GetCursorOffset() + space;
3993 {
3994 // Fill the buffer with nops.
3995 ExactAssemblyScope scope(&masm, space, ExactAssemblyScope::kExactSize);
3996 while (__ GetCursorOffset() != end) {
3997 __ nop();
3998 }
3999 }
4000
4001 // Test that EnsureEmitFor works.
4002 VIXL_CHECK(!masm.GetBuffer()->HasSpaceFor(4));
4003 masm.EnsureEmitFor(4);
4004 VIXL_CHECK(masm.GetBuffer()->HasSpaceFor(4));
4005 __ Nop();
4006
4007 masm.FinalizeCode();
4008 }
4009
TEST_T32(distant_literal_references)4010 TEST_T32(distant_literal_references) {
4011 SETUP();
4012 START();
4013
4014 Literal<uint64_t>* literal =
4015 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef),
4016 RawLiteral::kPlacedWhenUsed,
4017 RawLiteral::kDeletedOnPoolDestruction);
4018 // Refer to the literal so that it is emitted early.
4019 __ Ldr(r0, literal);
4020
4021 // Add enough nops to exceed the range of all loads.
4022 int space = 5000;
4023 {
4024 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize);
4025 VIXL_ASSERT(masm.IsUsingT32());
4026 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) {
4027 __ nop();
4028 }
4029 }
4030
4031 #define ENSURE_ALIGNED() \
4032 do { \
4033 if (!IsMultiple<k32BitT32InstructionSizeInBytes>( \
4034 masm.GetCursorOffset())) { \
4035 ExactAssemblyScope scope(&masm, \
4036 k16BitT32InstructionSizeInBytes, \
4037 ExactAssemblyScope::kExactSize); \
4038 __ nop(); \
4039 } \
4040 VIXL_ASSERT( \
4041 IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \
4042 } while (0)
4043
4044 // The literal has already been emitted, and is out of range of all of these
4045 // instructions. The delegates must generate fix-up code.
4046 ENSURE_ALIGNED();
4047 __ Ldr(r1, literal);
4048 ENSURE_ALIGNED();
4049 __ Ldrb(r2, literal);
4050 ENSURE_ALIGNED();
4051 __ Ldrsb(r3, literal);
4052 ENSURE_ALIGNED();
4053 __ Ldrh(r4, literal);
4054 ENSURE_ALIGNED();
4055 __ Ldrsh(r5, literal);
4056 ENSURE_ALIGNED();
4057 __ Ldrd(r6, r7, literal);
4058 ENSURE_ALIGNED();
4059 __ Vldr(d0, literal);
4060 ENSURE_ALIGNED();
4061 __ Vldr(s3, literal);
4062
4063 #undef ENSURE_ALIGNED
4064
4065 END();
4066 RUN();
4067
4068 // Check that the literals loaded correctly.
4069 ASSERT_EQUAL_32(0x89abcdef, r0);
4070 ASSERT_EQUAL_32(0x89abcdef, r1);
4071 ASSERT_EQUAL_32(0xef, r2);
4072 ASSERT_EQUAL_32(0xffffffef, r3);
4073 ASSERT_EQUAL_32(0xcdef, r4);
4074 ASSERT_EQUAL_32(0xffffcdef, r5);
4075 ASSERT_EQUAL_32(0x89abcdef, r6);
4076 ASSERT_EQUAL_32(0x01234567, r7);
4077 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0);
4078 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3);
4079 }
4080
4081
TEST_T32(distant_literal_references_unaligned_pc)4082 TEST_T32(distant_literal_references_unaligned_pc) {
4083 SETUP();
4084 START();
4085
4086 Literal<uint64_t>* literal =
4087 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef),
4088 RawLiteral::kPlacedWhenUsed,
4089 RawLiteral::kDeletedOnPoolDestruction);
4090 // Refer to the literal so that it is emitted early.
4091 __ Ldr(r0, literal);
4092
4093 // Add enough nops to exceed the range of all loads, leaving the PC aligned
4094 // to only a two-byte boundary.
4095 int space = 5002;
4096 {
4097 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize);
4098 VIXL_ASSERT(masm.IsUsingT32());
4099 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) {
4100 __ nop();
4101 }
4102 }
4103
4104 #define ENSURE_NOT_ALIGNED() \
4105 do { \
4106 if (IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())) { \
4107 ExactAssemblyScope scope(&masm, \
4108 k16BitT32InstructionSizeInBytes, \
4109 ExactAssemblyScope::kExactSize); \
4110 __ nop(); \
4111 } \
4112 VIXL_ASSERT( \
4113 !IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \
4114 } while (0)
4115
4116 // The literal has already been emitted, and is out of range of all of these
4117 // instructions. The delegates must generate fix-up code.
4118 ENSURE_NOT_ALIGNED();
4119 __ Ldr(r1, literal);
4120 ENSURE_NOT_ALIGNED();
4121 __ Ldrb(r2, literal);
4122 ENSURE_NOT_ALIGNED();
4123 __ Ldrsb(r3, literal);
4124 ENSURE_NOT_ALIGNED();
4125 __ Ldrh(r4, literal);
4126 ENSURE_NOT_ALIGNED();
4127 __ Ldrsh(r5, literal);
4128 ENSURE_NOT_ALIGNED();
4129 __ Ldrd(r6, r7, literal);
4130 {
4131 // TODO: We currently require an extra scratch register for these cases
4132 // because MemOperandComputationHelper isn't able to fit add_sub_offset into
4133 // a single 'sub' instruction, so 'pc' gets preserved first. The same
4134 // problem technically exists for the other loads, but vldr is particularly
4135 // badly affected because vldr cannot set the low bits in its offset mask,
4136 // so the add/sub operand is likely to be difficult to encode.
4137 //
4138 // At the moment, we get this:
4139 // mov r8, pc
4140 // mov ip, #5118
4141 // sub r8, pc
4142 // vldr d0, [r8, #48]
4143 //
4144 // We should be able to generate something like this:
4145 // sub ip, pc, #0x1300 // 5118 & 0xff00
4146 // sub ip, #0xfe // 5118 & 0x00ff
4147 // vldr d0, [ip, #48]
4148 UseScratchRegisterScope temps(&masm);
4149 temps.Include(r8);
4150 ENSURE_NOT_ALIGNED();
4151 __ Vldr(d0, literal);
4152 ENSURE_NOT_ALIGNED();
4153 __ Vldr(s3, literal);
4154 }
4155
4156 #undef ENSURE_NOT_ALIGNED
4157
4158 END();
4159 RUN();
4160
4161 // Check that the literals loaded correctly.
4162 ASSERT_EQUAL_32(0x89abcdef, r0);
4163 ASSERT_EQUAL_32(0x89abcdef, r1);
4164 ASSERT_EQUAL_32(0xef, r2);
4165 ASSERT_EQUAL_32(0xffffffef, r3);
4166 ASSERT_EQUAL_32(0xcdef, r4);
4167 ASSERT_EQUAL_32(0xffffcdef, r5);
4168 ASSERT_EQUAL_32(0x89abcdef, r6);
4169 ASSERT_EQUAL_32(0x01234567, r7);
4170 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0);
4171 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3);
4172 }
4173
4174
TEST_T32(distant_literal_references_short_range)4175 TEST_T32(distant_literal_references_short_range) {
4176 SETUP();
4177 START();
4178
4179 Literal<uint64_t>* literal =
4180 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef),
4181 RawLiteral::kPlacedWhenUsed,
4182 RawLiteral::kDeletedOnPoolDestruction);
4183 // Refer to the literal so that it is emitted early.
4184 __ Vldr(s4, literal);
4185
4186 // Add enough nops to exceed the range of the loads, but not the adr that will
4187 // be generated to read the PC.
4188 int space = 4000;
4189 {
4190 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize);
4191 VIXL_ASSERT(masm.IsUsingT32());
4192 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) {
4193 __ nop();
4194 }
4195 }
4196
4197 #define ENSURE_ALIGNED() \
4198 do { \
4199 if (!IsMultiple<k32BitT32InstructionSizeInBytes>( \
4200 masm.GetCursorOffset())) { \
4201 ExactAssemblyScope scope(&masm, \
4202 k16BitT32InstructionSizeInBytes, \
4203 ExactAssemblyScope::kExactSize); \
4204 __ nop(); \
4205 } \
4206 VIXL_ASSERT( \
4207 IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \
4208 } while (0)
4209
4210 // The literal has already been emitted, and is out of range of all of these
4211 // instructions. The delegates must generate fix-up code.
4212 ENSURE_ALIGNED();
4213 __ Ldr(r1, literal);
4214 ENSURE_ALIGNED();
4215 __ Ldrb(r2, literal);
4216 ENSURE_ALIGNED();
4217 __ Ldrsb(r3, literal);
4218 ENSURE_ALIGNED();
4219 __ Ldrh(r4, literal);
4220 ENSURE_ALIGNED();
4221 __ Ldrsh(r5, literal);
4222 ENSURE_ALIGNED();
4223 __ Ldrd(r6, r7, literal);
4224 ENSURE_ALIGNED();
4225 __ Vldr(d0, literal);
4226 ENSURE_ALIGNED();
4227 __ Vldr(s3, literal);
4228
4229 #undef ENSURE_ALIGNED
4230
4231 END();
4232 RUN();
4233
4234 // Check that the literals loaded correctly.
4235 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s4);
4236 ASSERT_EQUAL_32(0x89abcdef, r1);
4237 ASSERT_EQUAL_32(0xef, r2);
4238 ASSERT_EQUAL_32(0xffffffef, r3);
4239 ASSERT_EQUAL_32(0xcdef, r4);
4240 ASSERT_EQUAL_32(0xffffcdef, r5);
4241 ASSERT_EQUAL_32(0x89abcdef, r6);
4242 ASSERT_EQUAL_32(0x01234567, r7);
4243 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0);
4244 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3);
4245 }
4246
4247
TEST_T32(distant_literal_references_short_range_unaligned_pc)4248 TEST_T32(distant_literal_references_short_range_unaligned_pc) {
4249 SETUP();
4250 START();
4251
4252 Literal<uint64_t>* literal =
4253 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef),
4254 RawLiteral::kPlacedWhenUsed,
4255 RawLiteral::kDeletedOnPoolDestruction);
4256 // Refer to the literal so that it is emitted early.
4257 __ Vldr(s4, literal);
4258
4259 // Add enough nops to exceed the range of the loads, but not the adr that will
4260 // be generated to read the PC.
4261 int space = 4000;
4262 {
4263 ExactAssemblyScope scope(&masm, space, CodeBufferCheckScope::kExactSize);
4264 VIXL_ASSERT(masm.IsUsingT32());
4265 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) {
4266 __ nop();
4267 }
4268 }
4269
4270 #define ENSURE_NOT_ALIGNED() \
4271 do { \
4272 if (IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())) { \
4273 ExactAssemblyScope scope(&masm, \
4274 k16BitT32InstructionSizeInBytes, \
4275 ExactAssemblyScope::kExactSize); \
4276 __ nop(); \
4277 } \
4278 VIXL_ASSERT( \
4279 !IsMultiple<k32BitT32InstructionSizeInBytes>(masm.GetCursorOffset())); \
4280 } while (0)
4281
4282 // The literal has already been emitted, and is out of range of all of these
4283 // instructions. The delegates must generate fix-up code.
4284 ENSURE_NOT_ALIGNED();
4285 __ Ldr(r1, literal);
4286 ENSURE_NOT_ALIGNED();
4287 __ Ldrb(r2, literal);
4288 ENSURE_NOT_ALIGNED();
4289 __ Ldrsb(r3, literal);
4290 ENSURE_NOT_ALIGNED();
4291 __ Ldrh(r4, literal);
4292 ENSURE_NOT_ALIGNED();
4293 __ Ldrsh(r5, literal);
4294 ENSURE_NOT_ALIGNED();
4295 __ Ldrd(r6, r7, literal);
4296 ENSURE_NOT_ALIGNED();
4297 __ Vldr(d0, literal);
4298 ENSURE_NOT_ALIGNED();
4299 __ Vldr(s3, literal);
4300
4301 #undef ENSURE_NOT_ALIGNED
4302
4303 END();
4304 RUN();
4305
4306 // Check that the literals loaded correctly.
4307 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s4);
4308 ASSERT_EQUAL_32(0x89abcdef, r1);
4309 ASSERT_EQUAL_32(0xef, r2);
4310 ASSERT_EQUAL_32(0xffffffef, r3);
4311 ASSERT_EQUAL_32(0xcdef, r4);
4312 ASSERT_EQUAL_32(0xffffcdef, r5);
4313 ASSERT_EQUAL_32(0x89abcdef, r6);
4314 ASSERT_EQUAL_32(0x01234567, r7);
4315 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0);
4316 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3);
4317 }
4318
4319
TEST_T32(distant_literal_references_long_range)4320 TEST_T32(distant_literal_references_long_range) {
4321 SETUP();
4322 START();
4323
4324 Literal<uint64_t>* literal =
4325 new Literal<uint64_t>(UINT64_C(0x0123456789abcdef),
4326 RawLiteral::kPlacedWhenUsed,
4327 RawLiteral::kDeletedOnPoolDestruction);
4328 // Refer to the literal so that it is emitted early.
4329 __ Ldr(r0, literal);
4330
4331 #define PAD_WITH_NOPS(space) \
4332 do { \
4333 { \
4334 ExactAssemblyScope scope(&masm, \
4335 space, \
4336 CodeBufferCheckScope::kExactSize); \
4337 VIXL_ASSERT(masm.IsUsingT32()); \
4338 for (int i = 0; i < space; i += k16BitT32InstructionSizeInBytes) { \
4339 __ nop(); \
4340 } \
4341 } \
4342 } while (0)
4343
4344 // Add enough nops to exceed the range of all loads.
4345 PAD_WITH_NOPS(5000);
4346
4347 // The literal has already been emitted, and is out of range of all of these
4348 // instructions. The delegates must generate fix-up code.
4349 __ Ldr(r1, literal);
4350 __ Ldrb(r2, literal);
4351 __ Ldrsb(r3, literal);
4352 __ Ldrh(r4, literal);
4353 __ Ldrsh(r5, literal);
4354 __ Ldrd(r6, r7, literal);
4355 __ Vldr(d0, literal);
4356 __ Vldr(s3, literal);
4357
4358 // Add enough nops to exceed the range of the adr+sub sequence.
4359 PAD_WITH_NOPS(0x421000);
4360
4361 __ Ldr(r1, literal);
4362 __ Ldrb(r2, literal);
4363 __ Ldrsb(r3, literal);
4364 __ Ldrh(r4, literal);
4365 __ Ldrsh(r5, literal);
4366 __ Ldrd(r6, r7, literal);
4367 {
4368 // TODO: We currently require an extra scratch register for these cases. We
4369 // should be able to optimise the code generation to avoid this requirement
4370 // (and in many cases avoid a 32-bit instruction).
4371 UseScratchRegisterScope temps(&masm);
4372 temps.Include(r8);
4373 __ Vldr(d0, literal);
4374 __ Vldr(s3, literal);
4375 }
4376
4377 #undef PAD_WITH_NOPS
4378
4379 END();
4380 RUN();
4381
4382 // Check that the literals loaded correctly.
4383 ASSERT_EQUAL_32(0x89abcdef, r0);
4384 ASSERT_EQUAL_32(0x89abcdef, r1);
4385 ASSERT_EQUAL_32(0xef, r2);
4386 ASSERT_EQUAL_32(0xffffffef, r3);
4387 ASSERT_EQUAL_32(0xcdef, r4);
4388 ASSERT_EQUAL_32(0xffffcdef, r5);
4389 ASSERT_EQUAL_32(0x89abcdef, r6);
4390 ASSERT_EQUAL_32(0x01234567, r7);
4391 ASSERT_EQUAL_FP64(RawbitsToDouble(0x0123456789abcdef), d0);
4392 ASSERT_EQUAL_FP32(RawbitsToFloat(0x89abcdef), s3);
4393 }
4394
4395
TEST(barriers)4396 TEST(barriers) {
4397 // Generate all supported barriers, this is just a smoke test
4398 SETUP();
4399
4400 START();
4401
4402 // DMB
4403 __ Dmb(SY);
4404 __ Dmb(ST);
4405 __ Dmb(ISH);
4406 __ Dmb(ISHST);
4407 __ Dmb(NSH);
4408 __ Dmb(NSHST);
4409 __ Dmb(OSH);
4410 __ Dmb(OSHST);
4411
4412 // DSB
4413 __ Dsb(SY);
4414 __ Dsb(ST);
4415 __ Dsb(ISH);
4416 __ Dsb(ISHST);
4417 __ Dsb(NSH);
4418 __ Dsb(NSHST);
4419 __ Dsb(OSH);
4420 __ Dsb(OSHST);
4421
4422 // ISB
4423 __ Isb(SY);
4424
4425 END();
4426 }
4427
4428
TEST(preloads)4429 TEST(preloads) {
4430 // Smoke test for various pld/pli forms.
4431 SETUP();
4432
4433 START();
4434
4435 // PLD immediate
4436 __ Pld(MemOperand(sp, 0));
4437 __ Pld(MemOperand(r0, 0));
4438 __ Pld(MemOperand(r1, 123));
4439 __ Pld(MemOperand(r2, 1234));
4440 __ Pld(MemOperand(r3, 4095));
4441 __ Pld(MemOperand(r4, -123));
4442 __ Pld(MemOperand(r5, -255));
4443
4444 if (masm.IsUsingA32()) {
4445 __ Pld(MemOperand(r6, -1234));
4446 __ Pld(MemOperand(r7, -4095));
4447 }
4448
4449
4450 // PLDW immediate
4451 __ Pldw(MemOperand(sp, 0));
4452 __ Pldw(MemOperand(r0, 0));
4453 __ Pldw(MemOperand(r1, 123));
4454 __ Pldw(MemOperand(r2, 1234));
4455 __ Pldw(MemOperand(r3, 4095));
4456 __ Pldw(MemOperand(r4, -123));
4457 __ Pldw(MemOperand(r5, -255));
4458
4459 if (masm.IsUsingA32()) {
4460 __ Pldw(MemOperand(r6, -1234));
4461 __ Pldw(MemOperand(r7, -4095));
4462 }
4463
4464 // PLD register
4465 __ Pld(MemOperand(r0, r1));
4466 __ Pld(MemOperand(r0, r1, LSL, 1));
4467 __ Pld(MemOperand(r0, r1, LSL, 2));
4468 __ Pld(MemOperand(r0, r1, LSL, 3));
4469
4470 if (masm.IsUsingA32()) {
4471 __ Pld(MemOperand(r0, r1, LSL, 4));
4472 __ Pld(MemOperand(r0, r1, LSL, 20));
4473 }
4474
4475 // PLDW register
4476 __ Pldw(MemOperand(r0, r1));
4477 __ Pldw(MemOperand(r0, r1, LSL, 1));
4478 __ Pldw(MemOperand(r0, r1, LSL, 2));
4479 __ Pldw(MemOperand(r0, r1, LSL, 3));
4480
4481 if (masm.IsUsingA32()) {
4482 __ Pldw(MemOperand(r0, r1, LSL, 4));
4483 __ Pldw(MemOperand(r0, r1, LSL, 20));
4484 }
4485
4486 // PLI immediate
4487 __ Pli(MemOperand(sp, 0));
4488 __ Pli(MemOperand(r0, 0));
4489 __ Pli(MemOperand(r1, 123));
4490 __ Pli(MemOperand(r2, 1234));
4491 __ Pli(MemOperand(r3, 4095));
4492 __ Pli(MemOperand(r4, -123));
4493 __ Pli(MemOperand(r5, -255));
4494
4495 if (masm.IsUsingA32()) {
4496 __ Pli(MemOperand(r6, -1234));
4497 __ Pli(MemOperand(r7, -4095));
4498 }
4499
4500 // PLI register
4501 __ Pli(MemOperand(r0, r1));
4502 __ Pli(MemOperand(r0, r1, LSL, 1));
4503 __ Pli(MemOperand(r0, r1, LSL, 2));
4504 __ Pli(MemOperand(r0, r1, LSL, 3));
4505
4506 if (masm.IsUsingA32()) {
4507 __ Pli(MemOperand(r0, r1, LSL, 4));
4508 __ Pli(MemOperand(r0, r1, LSL, 20));
4509 }
4510
4511 END();
4512 }
4513
4514
TEST_T32(veneer_mirrored_branches)4515 TEST_T32(veneer_mirrored_branches) {
4516 SETUP();
4517
4518 START();
4519
4520 const int kMaxBranchCount = 256;
4521
4522 for (int branch_count = 1; branch_count < kMaxBranchCount; branch_count++) {
4523 Label* targets = new Label[branch_count];
4524
4525 for (int i = 0; i < branch_count; i++) {
4526 __ Cbz(r0, &targets[i]);
4527 }
4528
4529 for (int i = 0; i < branch_count; i++) {
4530 __ Bind(&targets[branch_count - i - 1]);
4531 __ Orr(r0, r0, r0);
4532 }
4533
4534 delete[] targets;
4535 }
4536
4537 END();
4538 }
4539
4540
TEST_T32(branch_fuzz_example)4541 TEST_T32(branch_fuzz_example) {
4542 SETUP();
4543
4544 START();
4545
4546 Label l[64];
4547 __ And(r0, r0, r0);
4548 __ Cbz(r0, &l[30]);
4549 __ And(r0, r0, r0);
4550 __ Cbz(r0, &l[22]);
4551 __ And(r0, r0, r0);
4552 __ Cbz(r0, &l[1]);
4553 __ Cbz(r0, &l[15]);
4554 __ Cbz(r0, &l[9]);
4555 __ Cbz(r0, &l[6]);
4556 __ Bind(&l[26]);
4557 __ Cbz(r0, &l[29]);
4558 __ And(r0, r0, r0);
4559 __ And(r0, r0, r0);
4560 __ Cbz(r0, &l[22]);
4561 __ Bind(&l[12]);
4562 __ Bind(&l[22]);
4563 __ Cbz(r0, &l[10]);
4564 __ And(r0, r0, r0);
4565 __ Cbz(r0, &l[30]);
4566 __ Cbz(r0, &l[17]);
4567 __ Cbz(r0, &l[27]);
4568 __ Cbz(r0, &l[11]);
4569 __ Bind(&l[7]);
4570 __ Cbz(r0, &l[18]);
4571 __ Bind(&l[14]);
4572 __ Cbz(r0, &l[1]);
4573 __ Bind(&l[18]);
4574 __ Cbz(r0, &l[11]);
4575 __ Cbz(r0, &l[6]);
4576 __ Bind(&l[21]);
4577 __ Cbz(r0, &l[28]);
4578 __ And(r0, r0, r0);
4579 __ Cbz(r0, &l[28]);
4580 __ Cbz(r0, &l[22]);
4581 __ Bind(&l[23]);
4582 __ Cbz(r0, &l[21]);
4583 __ Cbz(r0, &l[28]);
4584 __ Cbz(r0, &l[9]);
4585 __ Bind(&l[9]);
4586 __ Cbz(r0, &l[4]);
4587 __ And(r0, r0, r0);
4588 __ Cbz(r0, &l[10]);
4589 __ And(r0, r0, r0);
4590 __ Bind(&l[8]);
4591 __ And(r0, r0, r0);
4592 __ Cbz(r0, &l[10]);
4593 __ And(r0, r0, r0);
4594 __ Cbz(r0, &l[17]);
4595 __ Bind(&l[10]);
4596 __ Cbz(r0, &l[8]);
4597 __ Cbz(r0, &l[25]);
4598 __ Cbz(r0, &l[4]);
4599 __ Bind(&l[28]);
4600 __ And(r0, r0, r0);
4601 __ Cbz(r0, &l[16]);
4602 __ Bind(&l[19]);
4603 __ Cbz(r0, &l[14]);
4604 __ Cbz(r0, &l[28]);
4605 __ Cbz(r0, &l[26]);
4606 __ Cbz(r0, &l[21]);
4607 __ And(r0, r0, r0);
4608 __ Bind(&l[24]);
4609 __ And(r0, r0, r0);
4610 __ Cbz(r0, &l[24]);
4611 __ Cbz(r0, &l[24]);
4612 __ Cbz(r0, &l[19]);
4613 __ Cbz(r0, &l[26]);
4614 __ Cbz(r0, &l[4]);
4615 __ And(r0, r0, r0);
4616 __ Cbz(r0, &l[27]);
4617 __ Cbz(r0, &l[14]);
4618 __ Cbz(r0, &l[5]);
4619 __ Cbz(r0, &l[18]);
4620 __ Cbz(r0, &l[5]);
4621 __ Cbz(r0, &l[6]);
4622 __ Cbz(r0, &l[28]);
4623 __ Cbz(r0, &l[15]);
4624 __ Cbz(r0, &l[0]);
4625 __ Cbz(r0, &l[10]);
4626 __ Cbz(r0, &l[16]);
4627 __ Cbz(r0, &l[30]);
4628 __ Cbz(r0, &l[8]);
4629 __ Cbz(r0, &l[16]);
4630 __ Cbz(r0, &l[22]);
4631 __ Cbz(r0, &l[27]);
4632 __ Cbz(r0, &l[12]);
4633 __ Cbz(r0, &l[0]);
4634 __ Cbz(r0, &l[23]);
4635 __ Cbz(r0, &l[27]);
4636 __ Cbz(r0, &l[16]);
4637 __ Cbz(r0, &l[24]);
4638 __ Cbz(r0, &l[17]);
4639 __ Cbz(r0, &l[4]);
4640 __ Cbz(r0, &l[11]);
4641 __ Cbz(r0, &l[6]);
4642 __ Cbz(r0, &l[23]);
4643 __ Bind(&l[16]);
4644 __ Cbz(r0, &l[10]);
4645 __ Cbz(r0, &l[17]);
4646 __ Cbz(r0, &l[12]);
4647 __ And(r0, r0, r0);
4648 __ Cbz(r0, &l[11]);
4649 __ Cbz(r0, &l[17]);
4650 __ Cbz(r0, &l[1]);
4651 __ Cbz(r0, &l[3]);
4652 __ Cbz(r0, &l[18]);
4653 __ Bind(&l[4]);
4654 __ Cbz(r0, &l[31]);
4655 __ Cbz(r0, &l[25]);
4656 __ Cbz(r0, &l[22]);
4657 __ And(r0, r0, r0);
4658 __ Cbz(r0, &l[19]);
4659 __ Cbz(r0, &l[16]);
4660 __ Cbz(r0, &l[21]);
4661 __ Cbz(r0, &l[27]);
4662 __ Bind(&l[1]);
4663 __ Cbz(r0, &l[9]);
4664 __ Cbz(r0, &l[13]);
4665 __ Cbz(r0, &l[10]);
4666 __ Cbz(r0, &l[6]);
4667 __ Cbz(r0, &l[30]);
4668 __ Cbz(r0, &l[28]);
4669 __ Cbz(r0, &l[7]);
4670 __ Cbz(r0, &l[17]);
4671 __ Bind(&l[0]);
4672 __ Cbz(r0, &l[13]);
4673 __ Cbz(r0, &l[11]);
4674 __ Cbz(r0, &l[19]);
4675 __ Cbz(r0, &l[22]);
4676 __ Cbz(r0, &l[9]);
4677 __ And(r0, r0, r0);
4678 __ Cbz(r0, &l[15]);
4679 __ Cbz(r0, &l[31]);
4680 __ Cbz(r0, &l[2]);
4681 __ And(r0, r0, r0);
4682 __ Cbz(r0, &l[6]);
4683 __ Bind(&l[27]);
4684 __ Bind(&l[13]);
4685 __ Cbz(r0, &l[23]);
4686 __ Cbz(r0, &l[7]);
4687 __ Bind(&l[2]);
4688 __ And(r0, r0, r0);
4689 __ Cbz(r0, &l[1]);
4690 __ Bind(&l[15]);
4691 __ Cbz(r0, &l[13]);
4692 __ Cbz(r0, &l[17]);
4693 __ Cbz(r0, &l[8]);
4694 __ Cbz(r0, &l[30]);
4695 __ Cbz(r0, &l[8]);
4696 __ Cbz(r0, &l[27]);
4697 __ Cbz(r0, &l[2]);
4698 __ Cbz(r0, &l[31]);
4699 __ Cbz(r0, &l[4]);
4700 __ Cbz(r0, &l[11]);
4701 __ Bind(&l[29]);
4702 __ Cbz(r0, &l[7]);
4703 __ Cbz(r0, &l[5]);
4704 __ Cbz(r0, &l[11]);
4705 __ Cbz(r0, &l[24]);
4706 __ Cbz(r0, &l[9]);
4707 __ Cbz(r0, &l[3]);
4708 __ Cbz(r0, &l[3]);
4709 __ Cbz(r0, &l[22]);
4710 __ Cbz(r0, &l[19]);
4711 __ Cbz(r0, &l[4]);
4712 __ Bind(&l[6]);
4713 __ And(r0, r0, r0);
4714 __ And(r0, r0, r0);
4715 __ Cbz(r0, &l[9]);
4716 __ Cbz(r0, &l[3]);
4717 __ Cbz(r0, &l[23]);
4718 __ Cbz(r0, &l[12]);
4719 __ Cbz(r0, &l[1]);
4720 __ Cbz(r0, &l[22]);
4721 __ Cbz(r0, &l[24]);
4722 __ And(r0, r0, r0);
4723 __ Cbz(r0, &l[16]);
4724 __ Cbz(r0, &l[19]);
4725 __ Cbz(r0, &l[20]);
4726 __ Cbz(r0, &l[1]);
4727 __ Cbz(r0, &l[4]);
4728 __ Cbz(r0, &l[1]);
4729 __ Cbz(r0, &l[25]);
4730 __ Cbz(r0, &l[21]);
4731 __ Cbz(r0, &l[20]);
4732 __ Cbz(r0, &l[29]);
4733 __ And(r0, r0, r0);
4734 __ Cbz(r0, &l[10]);
4735 __ Cbz(r0, &l[5]);
4736 __ And(r0, r0, r0);
4737 __ Cbz(r0, &l[25]);
4738 __ Cbz(r0, &l[26]);
4739 __ Cbz(r0, &l[28]);
4740 __ Cbz(r0, &l[19]);
4741 __ And(r0, r0, r0);
4742 __ Bind(&l[17]);
4743 __ And(r0, r0, r0);
4744 __ And(r0, r0, r0);
4745 __ And(r0, r0, r0);
4746 __ And(r0, r0, r0);
4747 __ Cbz(r0, &l[6]);
4748 __ And(r0, r0, r0);
4749 __ Cbz(r0, &l[5]);
4750 __ Cbz(r0, &l[26]);
4751 __ Cbz(r0, &l[28]);
4752 __ Cbz(r0, &l[24]);
4753 __ Bind(&l[20]);
4754 __ And(r0, r0, r0);
4755 __ Cbz(r0, &l[10]);
4756 __ Cbz(r0, &l[19]);
4757 __ Cbz(r0, &l[6]);
4758 __ And(r0, r0, r0);
4759 __ Cbz(r0, &l[13]);
4760 __ Cbz(r0, &l[15]);
4761 __ Cbz(r0, &l[22]);
4762 __ Cbz(r0, &l[8]);
4763 __ Cbz(r0, &l[6]);
4764 __ Cbz(r0, &l[23]);
4765 __ Cbz(r0, &l[6]);
4766 __ And(r0, r0, r0);
4767 __ Cbz(r0, &l[13]);
4768 __ Bind(&l[31]);
4769 __ Cbz(r0, &l[14]);
4770 __ Cbz(r0, &l[5]);
4771 __ Cbz(r0, &l[1]);
4772 __ Cbz(r0, &l[17]);
4773 __ Cbz(r0, &l[27]);
4774 __ Cbz(r0, &l[10]);
4775 __ Cbz(r0, &l[30]);
4776 __ Cbz(r0, &l[14]);
4777 __ Cbz(r0, &l[24]);
4778 __ Cbz(r0, &l[26]);
4779 __ And(r0, r0, r0);
4780 __ Cbz(r0, &l[2]);
4781 __ Cbz(r0, &l[21]);
4782 __ Cbz(r0, &l[5]);
4783 __ Cbz(r0, &l[24]);
4784 __ And(r0, r0, r0);
4785 __ Cbz(r0, &l[24]);
4786 __ Cbz(r0, &l[17]);
4787 __ And(r0, r0, r0);
4788 __ And(r0, r0, r0);
4789 __ Cbz(r0, &l[24]);
4790 __ And(r0, r0, r0);
4791 __ Cbz(r0, &l[17]);
4792 __ Cbz(r0, &l[12]);
4793 __ And(r0, r0, r0);
4794 __ Cbz(r0, &l[9]);
4795 __ Cbz(r0, &l[9]);
4796 __ Cbz(r0, &l[31]);
4797 __ Cbz(r0, &l[25]);
4798 __ And(r0, r0, r0);
4799 __ And(r0, r0, r0);
4800 __ Cbz(r0, &l[13]);
4801 __ Cbz(r0, &l[14]);
4802 __ Cbz(r0, &l[5]);
4803 __ Cbz(r0, &l[5]);
4804 __ Cbz(r0, &l[12]);
4805 __ Cbz(r0, &l[3]);
4806 __ Cbz(r0, &l[25]);
4807 __ Bind(&l[11]);
4808 __ Cbz(r0, &l[15]);
4809 __ Cbz(r0, &l[20]);
4810 __ Cbz(r0, &l[22]);
4811 __ Cbz(r0, &l[19]);
4812 __ And(r0, r0, r0);
4813 __ Cbz(r0, &l[19]);
4814 __ And(r0, r0, r0);
4815 __ Cbz(r0, &l[21]);
4816 __ Cbz(r0, &l[0]);
4817 __ And(r0, r0, r0);
4818 __ Cbz(r0, &l[16]);
4819 __ Cbz(r0, &l[28]);
4820 __ Cbz(r0, &l[18]);
4821 __ Cbz(r0, &l[3]);
4822 __ And(r0, r0, r0);
4823 __ Cbz(r0, &l[15]);
4824 __ Cbz(r0, &l[8]);
4825 __ Cbz(r0, &l[25]);
4826 __ Cbz(r0, &l[1]);
4827 __ Cbz(r0, &l[21]);
4828 __ Cbz(r0, &l[1]);
4829 __ Cbz(r0, &l[29]);
4830 __ Cbz(r0, &l[15]);
4831 __ And(r0, r0, r0);
4832 __ Cbz(r0, &l[24]);
4833 __ Cbz(r0, &l[3]);
4834 __ Cbz(r0, &l[9]);
4835 __ Cbz(r0, &l[9]);
4836 __ Cbz(r0, &l[24]);
4837 __ And(r0, r0, r0);
4838 __ Cbz(r0, &l[19]);
4839 __ And(r0, r0, r0);
4840 __ Cbz(r0, &l[30]);
4841 __ Bind(&l[25]);
4842 __ Bind(&l[3]);
4843 __ Bind(&l[30]);
4844 __ Bind(&l[5]);
4845
4846 END();
4847 }
4848
4849
4850 // Generate a "B" and a "Cbz" which have the same checkpoint. Without proper
4851 // management (i.e. if the veneers were only generated at the shared
4852 // checkpoint), one one of the branches would be out of range.
TEST_T32(veneer_simultaneous)4853 TEST_T32(veneer_simultaneous) {
4854 SETUP();
4855
4856 START();
4857
4858 // `2046` max range - the size of the B.EQ itself.
4859 static const int kMaxBCondRange = 1048574;
4860
4861 Label target_1;
4862 Label target_2;
4863
4864 __ B(eq, &target_1);
4865
4866 int target_1_size_1 =
4867 kMaxBCondRange - kCbzCbnzRange - k32BitT32InstructionSizeInBytes;
4868 int end_1 = masm.GetCursorOffset() + target_1_size_1;
4869 while (masm.GetCursorOffset() < end_1) {
4870 __ Nop();
4871 }
4872
4873 __ Cbz(r0, &target_2);
4874
4875 int target_1_size_2 = kCbzCbnzRange - k16BitT32InstructionSizeInBytes;
4876 int end_2 = masm.GetCursorOffset() + target_1_size_2;
4877 while (masm.GetCursorOffset() < end_2) {
4878 __ Nop();
4879 }
4880
4881 __ Nop();
4882
4883 __ Bind(&target_1);
4884 __ Bind(&target_2);
4885
4886 END();
4887 }
4888
4889
4890 // Generate a "B" and a "Cbz" which have the same checkpoint and the same label.
TEST_T32(veneer_simultaneous_one_label)4891 TEST_T32(veneer_simultaneous_one_label) {
4892 SETUP();
4893
4894 START();
4895
4896 // `2046` max range - the size of the B.EQ itself.
4897 static const int kMaxBCondRange = 1048574;
4898
4899 Label target;
4900
4901 __ B(eq, &target);
4902
4903 int target_1_size_1 =
4904 kMaxBCondRange - kCbzCbnzRange - k32BitT32InstructionSizeInBytes;
4905 int end_1 = masm.GetCursorOffset() + target_1_size_1;
4906 while (masm.GetCursorOffset() < end_1) {
4907 __ Nop();
4908 }
4909
4910 __ Cbz(r0, &target);
4911
4912 int target_1_size_2 = kCbzCbnzRange - k16BitT32InstructionSizeInBytes;
4913 int end_2 = masm.GetCursorOffset() + target_1_size_2;
4914 while (masm.GetCursorOffset() < end_2) {
4915 __ Nop();
4916 }
4917
4918 __ Nop();
4919
4920 __ Bind(&target);
4921
4922 END();
4923 }
4924
4925 // NOTE: This test has needed modifications for the new pool manager, as it
4926 // was testing a corner case of the previous pool managers. We keep it as
4927 // another testcase.
TEST_T32(veneer_and_literal)4928 TEST_T32(veneer_and_literal) {
4929 SETUP();
4930
4931 START();
4932
4933 VIXL_CHECK(test.PoolIsEmpty());
4934
4935 const uint32_t ldrd_range = 1020;
4936 const uint32_t cbz_range = 126;
4937 const uint32_t kLabelsCount = 20;
4938 Label labels[kLabelsCount];
4939
4940 // Create one literal pool entry.
4941 __ Ldrd(r0, r1, 0x1234567890abcdef);
4942
4943 // Generate some nops.
4944 uint32_t i = 0;
4945 for (; i < ldrd_range - cbz_range - 40;
4946 i += k16BitT32InstructionSizeInBytes) {
4947 __ Nop();
4948 }
4949
4950 // At this point, it remains cbz_range + 40 => 166 bytes before ldrd becomes
4951 // out of range.
4952 // We generate kLabelsCount * 4 => 80 bytes. We shouldn't generate the
4953 // literal pool.
4954 for (uint32_t j = 0; j < kLabelsCount; j++) {
4955 __ Cbz(r0, &labels[j]);
4956 __ Nop();
4957 i += 2 * k16BitT32InstructionSizeInBytes;
4958 }
4959
4960 // We generate a few more instructions.
4961 for (; i < ldrd_range - 4 * kA32InstructionSizeInBytes;
4962 i += k16BitT32InstructionSizeInBytes) {
4963 __ Nop();
4964 }
4965
4966 // Bind all the used labels.
4967 for (uint32_t j = 0; j < kLabelsCount; j++) {
4968 __ Bind(&labels[j]);
4969 __ Nop();
4970 }
4971
4972 // Now that all the labels have been bound, we have no more veneers.
4973 VIXL_CHECK(test.PoolIsEmpty());
4974
4975 END();
4976
4977 RUN();
4978
4979 // Check that the literals loaded correctly.
4980 ASSERT_EQUAL_32(0x90abcdef, r0);
4981 ASSERT_EQUAL_32(0x12345678, r1);
4982 }
4983
4984 // NOTE: This test has needed modifications for the new pool manager, as it
4985 // was testing a corner case of the previous pool managers. We keep it as
4986 // another testcase.
TEST_T32(veneer_and_literal2)4987 TEST_T32(veneer_and_literal2) {
4988 SETUP();
4989
4990 START();
4991
4992 VIXL_CHECK(test.PoolIsEmpty());
4993
4994 const uint32_t ldrd_range = 1020;
4995 const uint32_t cbz_range = 126;
4996 const uint32_t kLabelsCount = 20;
4997 const int32_t kTypicalMacroInstructionMaxSize =
4998 8 * kMaxInstructionSizeInBytes;
4999 Label labels[kLabelsCount];
5000
5001 // Create one literal pool entry.
5002 __ Ldrd(r0, r1, 0x1234567890abcdef);
5003
5004 for (uint32_t i = 0; i < ldrd_range - cbz_range - 4 * kLabelsCount;
5005 i += k16BitT32InstructionSizeInBytes) {
5006 __ Nop();
5007 }
5008
5009 // Add entries to the veneer pool.
5010 for (uint32_t i = 0; i < kLabelsCount; i++) {
5011 __ Cbz(r0, &labels[i]);
5012 __ Nop();
5013 }
5014
5015 // Generate nops up to the literal pool limit.
5016 while (test.GetPoolCheckpoint() - masm.GetCursorOffset() >=
5017 kTypicalMacroInstructionMaxSize) {
5018 __ Nop();
5019 }
5020
5021 // At this point, no literals and no veneers have been generated.
5022 VIXL_ASSERT(!test.PoolIsEmpty());
5023 // The literal pool needs to be generated.
5024 VIXL_ASSERT(test.GetPoolCheckpoint() - masm.GetCursorOffset() <
5025 kTypicalMacroInstructionMaxSize);
5026
5027 // This extra Nop will generate the pools.
5028 __ Nop();
5029
5030 // Bind all the used labels.
5031 for (uint32_t j = 0; j < kLabelsCount; j++) {
5032 __ Bind(&labels[j]);
5033 __ Nop();
5034 }
5035
5036 // Now that all the labels have been bound, we have no more veneers.
5037 VIXL_CHECK(test.PoolIsEmpty());
5038
5039 END();
5040
5041 RUN();
5042
5043 // Check that the literals loaded correctly.
5044 ASSERT_EQUAL_32(0x90abcdef, r0);
5045 ASSERT_EQUAL_32(0x12345678, r1);
5046 }
5047
5048
5049 // Use a literal when we already have a veneer pool potential size greater than
5050 // the literal range => generate the literal immediately (not optimum but it
5051 // works).
TEST_T32(veneer_and_literal3)5052 TEST_T32(veneer_and_literal3) {
5053 SETUP();
5054
5055 START();
5056
5057 static const int kLabelsCount = 1000;
5058
5059 Label labels[kLabelsCount];
5060
5061 // Set the Z flag so that the following branches are not taken.
5062 __ Movs(r0, 0);
5063
5064 for (int i = 0; i < kLabelsCount; i++) {
5065 __ B(ne, &labels[i]);
5066 }
5067
5068 // Create one literal pool entry.
5069 __ Ldrd(r0, r1, 0x1234567890abcdef);
5070
5071 for (int i = 0; i < 10; i++) {
5072 __ Nop();
5073 }
5074
5075 for (int i = 0; i < kLabelsCount; i++) {
5076 __ Bind(&labels[i]);
5077 }
5078
5079 END();
5080
5081 RUN();
5082
5083 // Check that the literals loaded correctly.
5084 ASSERT_EQUAL_32(0x90abcdef, r0);
5085 ASSERT_EQUAL_32(0x12345678, r1);
5086 }
5087
5088
5089 // Literal has to be generated sooner than veneers. However, as the literal
5090 // pool generation would make the veneers out of range, generate the veneers
5091 // first.
TEST_T32(veneer_and_literal4)5092 TEST_T32(veneer_and_literal4) {
5093 SETUP();
5094
5095 START();
5096
5097 Label end;
5098
5099 // Set the Z flag so that the following branch is not taken.
5100 __ Movs(r0, 0);
5101 __ B(ne, &end);
5102
5103 uint32_t value = 0x1234567;
5104 Literal<uint32_t>* literal =
5105 new Literal<uint32_t>(value,
5106 RawLiteral::kPlacedWhenUsed,
5107 RawLiteral::kDeletedOnPoolDestruction);
5108
5109 __ Ldr(r11, literal);
5110
5111 // The range for ldr is 4095, the range for cbz is 127. Generate nops
5112 // to have the ldr becomming out of range just before the cbz.
5113 const int NUM_NOPS = 2044;
5114 const int NUM_RANGE = 58;
5115
5116 const int NUM1 = NUM_NOPS - NUM_RANGE;
5117 const int NUM2 = NUM_RANGE;
5118
5119 {
5120 ExactAssemblyScope aas(&masm, 2 * NUM1, CodeBufferCheckScope::kMaximumSize);
5121 for (int i = 0; i < NUM1; i++) {
5122 __ nop();
5123 }
5124 }
5125
5126 __ Cbz(r1, &end);
5127
5128 {
5129 ExactAssemblyScope aas(&masm, 2 * NUM2, CodeBufferCheckScope::kMaximumSize);
5130 for (int i = 0; i < NUM2; i++) {
5131 __ nop();
5132 }
5133 }
5134
5135 {
5136 ExactAssemblyScope aas(&masm, 4, CodeBufferCheckScope::kMaximumSize);
5137 __ add(r1, r1, 3);
5138 }
5139 __ Bind(&end);
5140
5141 END();
5142
5143 RUN();
5144
5145 // Check that the literals loaded correctly.
5146 ASSERT_EQUAL_32(0x1234567, r11);
5147 }
5148
5149
5150 // Literal has to be generated sooner than veneers. However, as the literal
5151 // pool generation would make the veneers out of range, generate the veneers
5152 // first.
TEST_T32(veneer_and_literal5)5153 TEST_T32(veneer_and_literal5) {
5154 SETUP();
5155
5156 START();
5157
5158 static const int kTestCount = 100;
5159 Label labels[kTestCount];
5160
5161 int first_test = 2000;
5162 // Test on both sizes of the Adr range which is 4095.
5163 for (int test_num = 0; test_num < kTestCount; test_num++) {
5164 const int string_size = 1000; // A lot more than the cbz range.
5165 std::string test_string(string_size, 'x');
5166 StringLiteral big_literal(test_string.c_str());
5167
5168 __ Adr(r11, &big_literal);
5169
5170 {
5171 int num_nops = first_test + test_num;
5172 ExactAssemblyScope aas(&masm,
5173 2 * num_nops,
5174 CodeBufferCheckScope::kMaximumSize);
5175 for (int i = 0; i < num_nops; i++) {
5176 __ nop();
5177 }
5178 }
5179
5180 __ Cbz(r1, &labels[test_num]);
5181
5182 {
5183 ExactAssemblyScope aas(&masm, 4, CodeBufferCheckScope::kMaximumSize);
5184 __ add(r1, r1, 3);
5185 }
5186 __ Bind(&labels[test_num]);
5187 // Emit the literal pool if it has not beeen emitted (it's the case for
5188 // the lower values of test_num).
5189 __ EmitLiteralPool(PoolManager<int32_t>::kBranchRequired);
5190 }
5191
5192 END();
5193 }
5194
5195 // Check that veneer and literals are well generated when they are out of
5196 // range at the same time.
TEST_T32(veneer_and_literal6)5197 TEST_T32(veneer_and_literal6) {
5198 SETUP();
5199
5200 START();
5201
5202 Label t1, t2, t3, t4, t5;
5203 static const int kLdrdRange = 1020;
5204 static const int kSizeForCbz = k16BitT32InstructionSizeInBytes;
5205
5206 __ Ldrd(r0, r1, 0x1111111111111111);
5207 __ Ldrd(r2, r3, 0x2222222222222222);
5208 __ Ldrd(r4, r5, 0x3333333333333333);
5209 __ Ldrd(r6, r7, 0x4444444444444444);
5210 __ Ldrd(r8, r9, 0x5555555555555555);
5211 __ Ldrd(r10, r11, 0x6666666666666666);
5212 __ Ldrd(r10, r11, 0x1234567890abcdef);
5213
5214 // Ldrd has a bigger range that cbz. Generate some nops before the cbzs in
5215 // order to reach the maximum range of ldrd and cbz at the same time.
5216 {
5217 int nop_size = kLdrdRange - kCbzCbnzRange - 5 * kSizeForCbz;
5218 ExactAssemblyScope scope(&masm, nop_size, CodeBufferCheckScope::kExactSize);
5219 for (int i = 0; i < nop_size; i += k16BitT32InstructionSizeInBytes) {
5220 __ nop();
5221 }
5222 }
5223
5224 __ Cbz(r2, &t1);
5225 __ Cbz(r2, &t2);
5226 __ Cbz(r2, &t3);
5227 __ Cbz(r2, &t4);
5228 __ Cbz(r2, &t5);
5229
5230 // At this point, the ldrds are not out of range. It remains a kCbzCbnzRange
5231 // margin (minus the size of the veneers).
5232
5233 // At this point, the literal and the veneer pools are not emitted.
5234 const int kLdrdLiteralSize = 8;
5235 const int kVeneerSize = 4;
5236 CHECK_POOL_SIZE(7 * kLdrdLiteralSize + 5 * kVeneerSize);
5237 VIXL_CHECK(test.GetPoolCheckpoint() - masm.GetCursorOffset() < kCbzCbnzRange);
5238
5239 // This scope will generate both veneers (they are both out of range).
5240 {
5241 int nop_size = kCbzCbnzRange;
5242 ExactAssemblyScope scope(&masm, nop_size, CodeBufferCheckScope::kExactSize);
5243 for (int i = 0; i < nop_size; i += k16BitT32InstructionSizeInBytes) {
5244 __ nop();
5245 }
5246 }
5247
5248 // Check that both literals and veneers have been emitted.
5249 CHECK_POOL_SIZE(5 * kVeneerSize);
5250 VIXL_CHECK(test.GetPoolCheckpoint() - masm.GetCursorOffset() > kCbzCbnzRange);
5251
5252 __ Bind(&t1);
5253 __ Bind(&t2);
5254 __ Bind(&t3);
5255 __ Bind(&t4);
5256 __ Bind(&t5);
5257
5258 CHECK_POOL_SIZE(0);
5259
5260 END();
5261
5262 RUN();
5263
5264 // Check that the literals loaded correctly.
5265 ASSERT_EQUAL_32(0x11111111, r0);
5266 ASSERT_EQUAL_32(0x11111111, r1);
5267 ASSERT_EQUAL_32(0x22222222, r2);
5268 ASSERT_EQUAL_32(0x22222222, r3);
5269 ASSERT_EQUAL_32(0x33333333, r4);
5270 ASSERT_EQUAL_32(0x33333333, r5);
5271 ASSERT_EQUAL_32(0x44444444, r6);
5272 ASSERT_EQUAL_32(0x44444444, r7);
5273 ASSERT_EQUAL_32(0x55555555, r8);
5274 ASSERT_EQUAL_32(0x55555555, r9);
5275 ASSERT_EQUAL_32(0x90abcdef, r10);
5276 ASSERT_EQUAL_32(0x12345678, r11);
5277 }
5278
5279 // Check that a label which is just bound during the MacroEmissionCheckScope
5280 // can be used.
TEST(ldr_label_bound_during_scope)5281 TEST(ldr_label_bound_during_scope) {
5282 SETUP();
5283 START();
5284
5285 Literal<uint64_t>* literal =
5286 new Literal<uint64_t>(UINT64_C(0x1234567890abcdef),
5287 RawLiteral::kPlacedWhenUsed,
5288 RawLiteral::kDeletedOnPoolDestruction);
5289 __ Ldrd(r0, r1, literal);
5290
5291 const int nop_size = masm.IsUsingA32() ? 4 : 2;
5292 while (test.GetPoolCheckpoint() >=
5293 (masm.GetCursorOffset() +
5294 static_cast<int32_t>(kMaxInstructionSizeInBytes))) {
5295 ExactAssemblyScope scope(&masm, nop_size, ExactAssemblyScope::kExactSize);
5296 __ nop();
5297 }
5298
5299 VIXL_ASSERT(!test.PoolIsEmpty());
5300
5301 // This Ldrd will first generate the pool and then use literal which has just
5302 // been bound.
5303 __ Ldrd(r2, r3, literal);
5304
5305 VIXL_ASSERT(test.PoolIsEmpty());
5306
5307 END();
5308
5309 RUN();
5310
5311 // Check that the literals loaded correctly.
5312 ASSERT_EQUAL_32(0x90abcdef, r0);
5313 ASSERT_EQUAL_32(0x12345678, r1);
5314 ASSERT_EQUAL_32(0x90abcdef, r2);
5315 ASSERT_EQUAL_32(0x12345678, r3);
5316 }
5317
5318
TEST_T32(test_it_scope_and_literal_pool)5319 TEST_T32(test_it_scope_and_literal_pool) {
5320 // This test stresses the ITScope to make sure the number of bytes it tries
5321 // to emit is in sync with the MacroEmissionCheckScope that is around it.
5322 SETUP();
5323
5324 START();
5325
5326 // Make sure the pool is empty.
5327 masm.EmitLiteralPool(PoolManager<int32_t>::kBranchRequired);
5328 VIXL_CHECK(test.PoolIsEmpty());
5329
5330 Literal<uint64_t> l0(0xcafebeefdeadbaba);
5331 __ Ldrd(r0, r1, &l0);
5332 // Leave exactly as many bytes between cursor and pool emission checkpoint as
5333 // the typical macro instruction needs (and MacroEmissionCheckScope allows
5334 // for).
5335 const int32_t kTypicalMacroInstructionMaxSize =
5336 8 * kMaxInstructionSizeInBytes;
5337 int32_t margin = test.GetPoolCheckpoint() - masm.GetCursorOffset() -
5338 kTypicalMacroInstructionMaxSize;
5339 int32_t end = masm.GetCursorOffset() + margin;
5340
5341 {
5342 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize);
5343 while (masm.GetCursorOffset() < end) {
5344 __ nop();
5345 }
5346 }
5347 VIXL_CHECK((test.GetPoolCheckpoint() - masm.GetCursorOffset()) ==
5348 kTypicalMacroInstructionMaxSize);
5349
5350 // We cannot use an IT block for this instruction, hence ITScope will
5351 // generate a branch over it.
5352 __ Add(ne, r8, r9, 256);
5353
5354 END();
5355
5356 RUN();
5357
5358 // Check that the literals loaded correctly.
5359 ASSERT_EQUAL_32(0xdeadbaba, r0);
5360 ASSERT_EQUAL_32(0xcafebeef, r1);
5361 }
5362
5363
5364 // TODO: Remove this limitation by having a sandboxing mechanism.
5365 #if defined(VIXL_HOST_POINTER_32)
TEST(ldm_stm_no_writeback)5366 TEST(ldm_stm_no_writeback) {
5367 SETUP();
5368
5369 START();
5370
5371 const uint32_t src[4] = {0x12345678, 0x09abcdef, 0xc001c0de, 0xdeadbeef};
5372 uint32_t dst1[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
5373 uint32_t dst2[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
5374
5375 __ Mov(r0, reinterpret_cast<uintptr_t>(src));
5376 __ Ldm(r0, NO_WRITE_BACK, RegisterList(r1, r2, r3, r4));
5377 __ Ldm(r0, NO_WRITE_BACK, RegisterList(r5, r6, r9, r11));
5378
5379 __ Mov(r0, reinterpret_cast<uintptr_t>(dst1));
5380 __ Stm(r0, NO_WRITE_BACK, RegisterList(r1, r2, r3, r4));
5381
5382 __ Mov(r0, reinterpret_cast<uintptr_t>(dst2));
5383 __ Stm(r0, NO_WRITE_BACK, RegisterList(r5, r6, r9, r11));
5384
5385 END();
5386
5387 RUN();
5388
5389 ASSERT_EQUAL_32(0x12345678, r1);
5390 ASSERT_EQUAL_32(0x09abcdef, r2);
5391 ASSERT_EQUAL_32(0xc001c0de, r3);
5392 ASSERT_EQUAL_32(0xdeadbeef, r4);
5393
5394 ASSERT_EQUAL_32(0x12345678, r5);
5395 ASSERT_EQUAL_32(0x09abcdef, r6);
5396 ASSERT_EQUAL_32(0xc001c0de, r9);
5397 ASSERT_EQUAL_32(0xdeadbeef, r11);
5398
5399 ASSERT_EQUAL_32(0x12345678, dst1[0]);
5400 ASSERT_EQUAL_32(0x09abcdef, dst1[1]);
5401 ASSERT_EQUAL_32(0xc001c0de, dst1[2]);
5402 ASSERT_EQUAL_32(0xdeadbeef, dst1[3]);
5403
5404 ASSERT_EQUAL_32(0x12345678, dst2[0]);
5405 ASSERT_EQUAL_32(0x09abcdef, dst2[1]);
5406 ASSERT_EQUAL_32(0xc001c0de, dst2[2]);
5407 ASSERT_EQUAL_32(0xdeadbeef, dst2[3]);
5408 }
5409
5410
TEST(ldm_stm_writeback)5411 TEST(ldm_stm_writeback) {
5412 SETUP();
5413
5414 START();
5415
5416 const uint32_t src[4] = {0x12345678, 0x09abcdef, 0xc001c0de, 0xdeadbeef};
5417 uint32_t dst[8] = {0x00000000,
5418 0x00000000,
5419 0x00000000,
5420 0x00000000,
5421 0x00000000,
5422 0x00000000,
5423 0x00000000,
5424 0x00000000};
5425
5426 __ Mov(r0, reinterpret_cast<uintptr_t>(src));
5427 __ Ldm(r0, WRITE_BACK, RegisterList(r2, r3));
5428 __ Ldm(r0, WRITE_BACK, RegisterList(r4, r5));
5429
5430 __ Mov(r1, reinterpret_cast<uintptr_t>(dst));
5431 __ Stm(r1, WRITE_BACK, RegisterList(r2, r3, r4, r5));
5432 __ Stm(r1, WRITE_BACK, RegisterList(r2, r3, r4, r5));
5433
5434 END();
5435
5436 RUN();
5437
5438 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src + 4), r0);
5439 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst + 8), r1);
5440
5441 ASSERT_EQUAL_32(0x12345678, r2);
5442 ASSERT_EQUAL_32(0x09abcdef, r3);
5443 ASSERT_EQUAL_32(0xc001c0de, r4);
5444 ASSERT_EQUAL_32(0xdeadbeef, r5);
5445
5446 ASSERT_EQUAL_32(0x12345678, dst[0]);
5447 ASSERT_EQUAL_32(0x09abcdef, dst[1]);
5448 ASSERT_EQUAL_32(0xc001c0de, dst[2]);
5449 ASSERT_EQUAL_32(0xdeadbeef, dst[3]);
5450 ASSERT_EQUAL_32(0x12345678, dst[4]);
5451 ASSERT_EQUAL_32(0x09abcdef, dst[5]);
5452 ASSERT_EQUAL_32(0xc001c0de, dst[6]);
5453 ASSERT_EQUAL_32(0xdeadbeef, dst[7]);
5454 }
5455
5456
TEST_A32(ldm_stm_da_ib)5457 TEST_A32(ldm_stm_da_ib) {
5458 SETUP();
5459
5460 START();
5461
5462 const uint32_t src1[4] = {0x33333333, 0x44444444, 0x11111111, 0x22222222};
5463 const uint32_t src2[4] = {0x11111111, 0x22222222, 0x33333333, 0x44444444};
5464
5465 uint32_t dst1[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
5466 uint32_t dst2[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
5467
5468 __ Mov(r11, reinterpret_cast<uintptr_t>(src1 + 3));
5469 __ Ldmda(r11, WRITE_BACK, RegisterList(r0, r1));
5470 __ Ldmda(r11, NO_WRITE_BACK, RegisterList(r2, r3));
5471
5472 __ Mov(r10, reinterpret_cast<uintptr_t>(src2) - sizeof(src2[0]));
5473 __ Ldmib(r10, WRITE_BACK, RegisterList(r4, r5));
5474 __ Ldmib(r10, NO_WRITE_BACK, RegisterList(r6, r7));
5475
5476 __ Mov(r9, reinterpret_cast<uintptr_t>(dst1 + 3));
5477 __ Stmda(r9, WRITE_BACK, RegisterList(r0, r1));
5478 __ Stmda(r9, NO_WRITE_BACK, RegisterList(r2, r3));
5479
5480 __ Mov(r8, reinterpret_cast<uintptr_t>(dst2) - sizeof(dst2[0]));
5481 __ Stmib(r8, WRITE_BACK, RegisterList(r4, r5));
5482 __ Stmib(r8, NO_WRITE_BACK, RegisterList(r6, r7));
5483
5484
5485 END();
5486
5487 RUN();
5488
5489 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src1 + 1), r11);
5490 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src2 + 1), r10);
5491 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst1 + 1), r9);
5492 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst2 + 1), r8);
5493
5494 ASSERT_EQUAL_32(0x11111111, r0);
5495 ASSERT_EQUAL_32(0x22222222, r1);
5496 ASSERT_EQUAL_32(0x33333333, r2);
5497 ASSERT_EQUAL_32(0x44444444, r3);
5498
5499 ASSERT_EQUAL_32(0x11111111, r4);
5500 ASSERT_EQUAL_32(0x22222222, r5);
5501 ASSERT_EQUAL_32(0x33333333, r6);
5502 ASSERT_EQUAL_32(0x44444444, r7);
5503
5504 ASSERT_EQUAL_32(0x33333333, dst1[0]);
5505 ASSERT_EQUAL_32(0x44444444, dst1[1]);
5506 ASSERT_EQUAL_32(0x11111111, dst1[2]);
5507 ASSERT_EQUAL_32(0x22222222, dst1[3]);
5508
5509 ASSERT_EQUAL_32(0x11111111, dst2[0]);
5510 ASSERT_EQUAL_32(0x22222222, dst2[1]);
5511 ASSERT_EQUAL_32(0x33333333, dst2[2]);
5512 ASSERT_EQUAL_32(0x44444444, dst2[3]);
5513 }
5514
5515
TEST(ldmdb_stmdb)5516 TEST(ldmdb_stmdb) {
5517 SETUP();
5518
5519 START();
5520
5521 const uint32_t src[6] =
5522 {0x55555555, 0x66666666, 0x33333333, 0x44444444, 0x11111111, 0x22222222};
5523
5524 uint32_t dst[6] =
5525 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
5526
5527 __ Mov(r11, reinterpret_cast<uintptr_t>(src + 6));
5528 __ Ldmdb(r11, WRITE_BACK, RegisterList(r1, r2));
5529 __ Ldmdb(r11, WRITE_BACK, RegisterList(r3, r4));
5530 __ Ldmdb(r11, NO_WRITE_BACK, RegisterList(r5, r6));
5531
5532 __ Mov(r10, reinterpret_cast<uintptr_t>(dst + 6));
5533 __ Stmdb(r10, WRITE_BACK, RegisterList(r5, r6));
5534 __ Stmdb(r10, WRITE_BACK, RegisterList(r3, r4));
5535 __ Stmdb(r10, NO_WRITE_BACK, RegisterList(r1, r2));
5536
5537 END();
5538
5539 RUN();
5540
5541 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(src + 2), r11);
5542 ASSERT_EQUAL_32(reinterpret_cast<uintptr_t>(dst + 2), r10);
5543
5544 ASSERT_EQUAL_32(0x11111111, r1);
5545 ASSERT_EQUAL_32(0x22222222, r2);
5546 ASSERT_EQUAL_32(0x33333333, r3);
5547 ASSERT_EQUAL_32(0x44444444, r4);
5548 ASSERT_EQUAL_32(0x55555555, r5);
5549 ASSERT_EQUAL_32(0x66666666, r6);
5550
5551 ASSERT_EQUAL_32(0x11111111, dst[0]);
5552 ASSERT_EQUAL_32(0x22222222, dst[1]);
5553 ASSERT_EQUAL_32(0x33333333, dst[2]);
5554 ASSERT_EQUAL_32(0x44444444, dst[3]);
5555 ASSERT_EQUAL_32(0x55555555, dst[4]);
5556 ASSERT_EQUAL_32(0x66666666, dst[5]);
5557 }
5558 #endif
5559
5560
TEST(blx)5561 TEST(blx) {
5562 SETUP();
5563
5564 START();
5565
5566 // TODO(all): Ideally this test should jump back and forth between ARM and
5567 // Thumb mode and should also cover BLX immediate. Update this test if we
5568 // allow VIXL assembler to change ISA anywhere in the code buffer.
5569
5570 Label test_start;
5571 Label func1;
5572 Label func2;
5573
5574 __ B(&test_start);
5575
5576 __ Bind(&func1);
5577 __ Mov(r0, 0x11111111);
5578 __ Push(lr);
5579 {
5580 size_t size_of_generated_code;
5581 if (masm.IsUsingA32()) {
5582 size_of_generated_code = 7 * kA32InstructionSizeInBytes;
5583 } else {
5584 size_of_generated_code = 5 * k32BitT32InstructionSizeInBytes +
5585 3 * k16BitT32InstructionSizeInBytes;
5586 }
5587 ExactAssemblyScope scope(&masm,
5588 size_of_generated_code,
5589 ExactAssemblyScope::kExactSize);
5590 __ adr(r11, &func2);
5591 if (masm.IsUsingT32()) {
5592 // The jump target needs to have its least significant bit set to indicate
5593 // that we are jumping into thumb mode.
5594 __ orr(r11, r11, 1);
5595 }
5596 __ blx(r11);
5597 __ pop(lr);
5598 __ bx(lr);
5599
5600 __ bind(&func2);
5601 __ movw(r1, 0x2222);
5602 __ movt(r1, 0x2222);
5603 __ bx(lr);
5604 }
5605
5606 __ Bind(&test_start);
5607 __ Mov(r0, 0xdeadc0de);
5608 __ Mov(r1, 0xdeadc0de);
5609 __ Bl(&func1);
5610
5611 END();
5612
5613 RUN();
5614
5615 // Really basic test to check that we reached the different parts of the test.
5616 ASSERT_EQUAL_32(0x11111111, r0);
5617 ASSERT_EQUAL_32(0x22222222, r1);
5618 }
5619
5620 // Check that B with a near hint use a narrow branch when it can.
TEST_T32(b_near_hint)5621 TEST_T32(b_near_hint) {
5622 SETUP();
5623 START();
5624
5625 Label start;
5626 Label end;
5627
5628 __ Bind(&start);
5629 __ Nop();
5630
5631 {
5632 // Generate a branch which should be narrow.
5633 EmissionCheckScope scope(&masm,
5634 k16BitT32InstructionSizeInBytes,
5635 EmissionCheckScope::kExactSize);
5636 __ B(&start, kNear);
5637 }
5638 {
5639 ExactAssemblyScope scope(&masm,
5640 kBNarrowRange,
5641 ExactAssemblyScope::kExactSize);
5642 for (int32_t i = 0; i < kBNarrowRange;
5643 i += k16BitT32InstructionSizeInBytes) {
5644 __ nop();
5645 }
5646 }
5647 {
5648 // Generate a branch which should be wide.
5649 EmissionCheckScope scope(&masm,
5650 k32BitT32InstructionSizeInBytes,
5651 EmissionCheckScope::kExactSize);
5652 __ B(&start, kNear);
5653 }
5654 {
5655 // Generate a forward branch which should be narrow.
5656 EmissionCheckScope scope(&masm,
5657 k16BitT32InstructionSizeInBytes,
5658 EmissionCheckScope::kExactSize);
5659 __ B(&end, kNear);
5660 }
5661
5662 int32_t margin = test.GetPoolCheckpoint() - masm.GetCursorOffset();
5663 VIXL_CHECK(margin < kBNarrowRange);
5664
5665 {
5666 ExactAssemblyScope scope(&masm,
5667 kBNarrowRange,
5668 ExactAssemblyScope::kExactSize);
5669 for (int32_t i = 0; i < kBNarrowRange;
5670 i += k16BitT32InstructionSizeInBytes) {
5671 __ nop();
5672 }
5673 }
5674
5675 // A veneer should have been generated.
5676 margin = test.GetPoolCheckpoint() - masm.GetCursorOffset();
5677 VIXL_CHECK(margin > kBNarrowRange);
5678
5679 __ Bind(&end);
5680
5681 END();
5682
5683 DISASSEMBLE();
5684 }
5685
5686 // Check that B with a far hint use a narrow branch only for a near backward
5687 // branch.
TEST_T32(b_far_hint)5688 TEST_T32(b_far_hint) {
5689 SETUP();
5690 START();
5691
5692 Label start;
5693 Label end;
5694
5695 __ Bind(&start);
5696 __ Nop();
5697
5698 {
5699 // Generate a branch which should be narrow.
5700 EmissionCheckScope scope(&masm,
5701 k16BitT32InstructionSizeInBytes,
5702 EmissionCheckScope::kExactSize);
5703 __ B(&start, kFar);
5704 }
5705 {
5706 ExactAssemblyScope scope(&masm,
5707 kBNarrowRange,
5708 ExactAssemblyScope::kExactSize);
5709 for (int32_t i = 0; i < kBNarrowRange;
5710 i += k16BitT32InstructionSizeInBytes) {
5711 __ nop();
5712 }
5713 }
5714 {
5715 // Generate a branch which should be wide.
5716 EmissionCheckScope scope(&masm,
5717 k32BitT32InstructionSizeInBytes,
5718 EmissionCheckScope::kExactSize);
5719 __ B(&start, kFar);
5720 }
5721 {
5722 // Generate a forward branch which should be wide.
5723 EmissionCheckScope scope(&masm,
5724 k32BitT32InstructionSizeInBytes,
5725 EmissionCheckScope::kExactSize);
5726 __ B(&end, kFar);
5727 }
5728
5729 __ Bind(&end);
5730
5731 END();
5732
5733 DISASSEMBLE();
5734 }
5735
5736 // Check that conditional B with a near hint use a narrow branch when it can.
TEST_T32(b_conditional_near_hint)5737 TEST_T32(b_conditional_near_hint) {
5738 SETUP();
5739 START();
5740
5741 Label start;
5742 Label end;
5743
5744 __ Bind(&start);
5745 __ Nop();
5746 {
5747 // Generate a branch which should be narrow.
5748 EmissionCheckScope scope(&masm,
5749 k16BitT32InstructionSizeInBytes,
5750 EmissionCheckScope::kExactSize);
5751 __ B(eq, &start, kNear);
5752 }
5753 {
5754 ExactAssemblyScope scope(&masm,
5755 kBConditionalNarrowRange,
5756 ExactAssemblyScope::kExactSize);
5757 for (int32_t i = 0; i < kBConditionalNarrowRange;
5758 i += k16BitT32InstructionSizeInBytes) {
5759 __ nop();
5760 }
5761 }
5762 {
5763 // Generate a branch which should be wide.
5764 EmissionCheckScope scope(&masm,
5765 k32BitT32InstructionSizeInBytes,
5766 EmissionCheckScope::kExactSize);
5767 __ B(eq, &start, kNear);
5768 }
5769 {
5770 // Generate a forward branch which should be narrow.
5771 EmissionCheckScope scope(&masm,
5772 k16BitT32InstructionSizeInBytes,
5773 EmissionCheckScope::kExactSize);
5774 __ B(eq, &end, kNear);
5775 }
5776
5777 int32_t margin = test.GetPoolCheckpoint() - masm.GetCursorOffset();
5778 VIXL_CHECK(margin < kBConditionalNarrowRange);
5779
5780 {
5781 ExactAssemblyScope scope(&masm,
5782 kBConditionalNarrowRange,
5783 ExactAssemblyScope::kExactSize);
5784 for (int32_t i = 0; i < kBConditionalNarrowRange;
5785 i += k16BitT32InstructionSizeInBytes) {
5786 __ nop();
5787 }
5788 }
5789
5790 // A veneer should have been generated.
5791 margin = test.GetPoolCheckpoint() - masm.GetCursorOffset();
5792 VIXL_CHECK(margin > kBConditionalNarrowRange);
5793
5794 __ Bind(&end);
5795
5796 END();
5797
5798 DISASSEMBLE();
5799 }
5800
5801 // Check that conditional B with a far hint use a narrow branch only for a
5802 // near backward branch.
TEST_T32(b_conditional_far_hint)5803 TEST_T32(b_conditional_far_hint) {
5804 SETUP();
5805 START();
5806
5807 Label start;
5808 Label end;
5809
5810 __ Bind(&start);
5811 __ Nop();
5812
5813 {
5814 // Generate a branch which should be narrow.
5815 EmissionCheckScope scope(&masm,
5816 k16BitT32InstructionSizeInBytes,
5817 EmissionCheckScope::kExactSize);
5818 __ B(eq, &start, kFar);
5819 }
5820 {
5821 ExactAssemblyScope scope(&masm,
5822 kBConditionalNarrowRange,
5823 ExactAssemblyScope::kExactSize);
5824 for (int32_t i = 0; i < kBConditionalNarrowRange;
5825 i += k16BitT32InstructionSizeInBytes) {
5826 __ nop();
5827 }
5828 }
5829 {
5830 // Generate a branch which should be wide.
5831 EmissionCheckScope scope(&masm,
5832 k32BitT32InstructionSizeInBytes,
5833 EmissionCheckScope::kExactSize);
5834 __ B(eq, &start, kFar);
5835 }
5836 {
5837 // Generate a forward branch which should be wide.
5838 EmissionCheckScope scope(&masm,
5839 k32BitT32InstructionSizeInBytes,
5840 EmissionCheckScope::kExactSize);
5841 __ B(eq, &end, kFar);
5842 }
5843
5844 __ Bind(&end);
5845
5846 END();
5847
5848 DISASSEMBLE();
5849 }
5850
5851
5852 // Check that the veneer pool is correctly emitted even if we do a lot of narrow
5853 // branches.
TEST_T32(b_narrow_many)5854 TEST_T32(b_narrow_many) {
5855 SETUP();
5856 START();
5857
5858 static const int kLabelsCount = kBNarrowRange / 2;
5859
5860 Label labels[kLabelsCount];
5861
5862 __ Mov(r0, 0);
5863
5864 for (int i = 0; i < kLabelsCount; i++) {
5865 __ B(&labels[i], kNear);
5866 }
5867
5868 __ Mov(r0, 1);
5869 for (int i = 0; i < kLabelsCount; i++) {
5870 __ Bind(&labels[i]);
5871 }
5872 __ Nop();
5873
5874 END();
5875
5876 RUN();
5877
5878 ASSERT_EQUAL_32(0, r0);
5879 }
5880
5881
5882 // Check that the veneer pool is correctly emitted even if we do a lot of narrow
5883 // branches and cbz.
TEST_T32(b_narrow_and_cbz)5884 TEST_T32(b_narrow_and_cbz) {
5885 SETUP();
5886 START();
5887
5888 static const int kLabelsCount = kBNarrowRange / 4;
5889
5890 Label b_labels[kLabelsCount];
5891 Label cbz_labels[kLabelsCount];
5892
5893 __ Mov(r0, 0);
5894
5895 for (int i = 0; i < kLabelsCount; i++) {
5896 __ B(&b_labels[i], kNear);
5897 __ Cbz(r0, &cbz_labels[i]);
5898 }
5899
5900 __ Mov(r0, 1);
5901 for (int i = 0; i < kLabelsCount; i++) {
5902 __ Bind(&b_labels[i]);
5903 }
5904
5905 __ Mov(r0, 2);
5906 for (int i = 0; i < kLabelsCount; i++) {
5907 __ Bind(&cbz_labels[i]);
5908 }
5909
5910 __ Nop();
5911
5912 END();
5913
5914 RUN();
5915
5916 ASSERT_EQUAL_32(2, r0);
5917 }
5918
5919
5920 #define CHECK_SIZE_MATCH(ASM1, ASM2) \
5921 { \
5922 MacroAssembler masm1(BUF_SIZE); \
5923 masm1.UseInstructionSet(isa); \
5924 VIXL_ASSERT(masm1.GetCursorOffset() == 0); \
5925 masm1.ASM1; \
5926 masm1.FinalizeCode(); \
5927 int size1 = masm1.GetCursorOffset(); \
5928 \
5929 MacroAssembler masm2(BUF_SIZE); \
5930 masm2.UseInstructionSet(isa); \
5931 VIXL_ASSERT(masm2.GetCursorOffset() == 0); \
5932 masm2.ASM2; \
5933 masm2.FinalizeCode(); \
5934 int size2 = masm2.GetCursorOffset(); \
5935 \
5936 bool disassemble = Test::disassemble(); \
5937 if (size1 != size2) { \
5938 printf("Sizes did not match:\n"); \
5939 disassemble = true; \
5940 } \
5941 if (disassemble) { \
5942 PrintDisassembler dis(std::cout, 0); \
5943 printf("// " #ASM1 "\n"); \
5944 if (masm1.IsUsingT32()) { \
5945 dis.DisassembleT32Buffer(masm1.GetBuffer() \
5946 ->GetStartAddress<uint16_t*>(), \
5947 size1); \
5948 } else { \
5949 dis.DisassembleA32Buffer(masm1.GetBuffer() \
5950 ->GetStartAddress<uint32_t*>(), \
5951 size1); \
5952 } \
5953 printf("\n"); \
5954 \
5955 dis.SetCodeAddress(0); \
5956 printf("// " #ASM2 "\n"); \
5957 if (masm2.IsUsingT32()) { \
5958 dis.DisassembleT32Buffer(masm2.GetBuffer() \
5959 ->GetStartAddress<uint16_t*>(), \
5960 size2); \
5961 } else { \
5962 dis.DisassembleA32Buffer(masm2.GetBuffer() \
5963 ->GetStartAddress<uint32_t*>(), \
5964 size2); \
5965 } \
5966 printf("\n"); \
5967 } \
5968 VIXL_CHECK(size1 == size2); \
5969 }
5970
5971
TEST_T32(macro_assembler_commute)5972 TEST_T32(macro_assembler_commute) {
5973 // Test that the MacroAssembler will commute operands if it means it can use a
5974 // 16-bit instruction with the same effect.
5975
5976 // TODO: The commented-out tests should pass, but don't. When they are fixed,
5977 // we should update this test.
5978
5979 // CHECK_SIZE_MATCH(Adc(DontCare, r7, r6, r7),
5980 // Adc(DontCare, r7, r7, r6));
5981
5982 // CHECK_SIZE_MATCH(Adc(DontCare, eq, r7, r6, r7),
5983 // Adc(DontCare, eq, r7, r7, r6));
5984
5985 CHECK_SIZE_MATCH(Add(DontCare, r1, r2, r7), Add(DontCare, r1, r7, r2));
5986
5987 CHECK_SIZE_MATCH(Add(DontCare, lt, r1, r2, r7),
5988 Add(DontCare, lt, r1, r7, r2));
5989
5990 // CHECK_SIZE_MATCH(Add(DontCare, r4, r4, r10),
5991 // Add(DontCare, r4, r10, r4));
5992
5993 // CHECK_SIZE_MATCH(Add(DontCare, eq, r4, r4, r10),
5994 // Add(DontCare, eq, r4, r10, r4));
5995
5996 // CHECK_SIZE_MATCH(Add(DontCare, r7, sp, r7),
5997 // Add(DontCare, r7, r7, sp));
5998
5999 // CHECK_SIZE_MATCH(Add(DontCare, eq, r7, sp, r7),
6000 // Add(DontCare, eq, r7, r7, sp));
6001
6002 // CHECK_SIZE_MATCH(Add(DontCare, sp, sp, r10),
6003 // Add(DontCare, sp, r10, sp));
6004
6005 // CHECK_SIZE_MATCH(Add(DontCare, eq, sp, sp, r10),
6006 // Add(DontCare, eq, sp, r10, sp));
6007
6008 // CHECK_SIZE_MATCH(And(DontCare, r7, r7, r6),
6009 // And(DontCare, r7, r6, r7));
6010
6011 // CHECK_SIZE_MATCH(And(DontCare, eq, r7, r7, r6),
6012 // And(DontCare, eq, r7, r6, r7));
6013
6014 // CHECK_SIZE_MATCH(Eor(DontCare, r7, r7, r6),
6015 // Eor(DontCare, r7, r6, r7));
6016
6017 // CHECK_SIZE_MATCH(Eor(DontCare, eq, r7, r7, r6),
6018 // Eor(DontCare, eq, r7, r6, r7));
6019
6020 // CHECK_SIZE_MATCH(Mul(DontCare, r0, r1, r0),
6021 // Mul(DontCare, r0, r0, r1));
6022
6023 // CHECK_SIZE_MATCH(Mul(DontCare, eq, r0, r1, r0),
6024 // Mul(DontCare, eq, r0, r0, r1));
6025
6026 // CHECK_SIZE_MATCH(Orr(DontCare, r7, r7, r6),
6027 // Orr(DontCare, r7, r6, r7));
6028
6029 // CHECK_SIZE_MATCH(Orr(DontCare, eq, r7, r7, r6),
6030 // Orr(DontCare, eq, r7, r6, r7));
6031
6032
6033 CHECK_SIZE_MATCH(Adc(r7, r6, r7), Adc(r7, r7, r6));
6034
6035 // CHECK_SIZE_MATCH(Adc(eq, r7, r6, r7),
6036 // Adc(eq, r7, r7, r6));
6037
6038 CHECK_SIZE_MATCH(Add(r1, r2, r7), Add(r1, r7, r2));
6039
6040 CHECK_SIZE_MATCH(Add(lt, r1, r2, r7), Add(lt, r1, r7, r2));
6041
6042 // CHECK_SIZE_MATCH(Add(r4, r4, r10),
6043 // Add(r4, r10, r4));
6044
6045 // CHECK_SIZE_MATCH(Add(eq, r4, r4, r10),
6046 // Add(eq, r4, r10, r4));
6047
6048 // CHECK_SIZE_MATCH(Add(r7, sp, r7),
6049 // Add(r7, r7, sp));
6050
6051 // CHECK_SIZE_MATCH(Add(eq, r7, sp, r7),
6052 // Add(eq, r7, r7, sp));
6053
6054 // CHECK_SIZE_MATCH(Add(sp, sp, r10),
6055 // Add(sp, r10, sp));
6056
6057 // CHECK_SIZE_MATCH(Add(eq, sp, sp, r10),
6058 // Add(eq, sp, r10, sp));
6059
6060 CHECK_SIZE_MATCH(And(r7, r7, r6), And(r7, r6, r7));
6061
6062 // CHECK_SIZE_MATCH(And(eq, r7, r7, r6),
6063 // And(eq, r7, r6, r7));
6064
6065 CHECK_SIZE_MATCH(Eor(r7, r7, r6), Eor(r7, r6, r7));
6066
6067 // CHECK_SIZE_MATCH(Eor(eq, r7, r7, r6),
6068 // Eor(eq, r7, r6, r7));
6069
6070 CHECK_SIZE_MATCH(Mul(r0, r1, r0), Mul(r0, r0, r1));
6071
6072 // CHECK_SIZE_MATCH(Mul(eq, r0, r1, r0),
6073 // Mul(eq, r0, r0, r1));
6074
6075 CHECK_SIZE_MATCH(Orr(r7, r7, r6), Orr(r7, r6, r7));
6076
6077 // CHECK_SIZE_MATCH(Orr(eq, r7, r7, r6),
6078 // Orr(eq, r7, r6, r7));
6079
6080
6081 // CHECK_SIZE_MATCH(Adcs(r7, r6, r7),
6082 // Adcs(r7, r7, r6));
6083
6084 // CHECK_SIZE_MATCH(Adcs(eq, r7, r6, r7),
6085 // Adcs(eq, r7, r7, r6));
6086
6087 CHECK_SIZE_MATCH(Adds(r1, r2, r7), Adds(r1, r7, r2));
6088
6089 CHECK_SIZE_MATCH(Adds(lt, r1, r2, r7), Adds(lt, r1, r7, r2));
6090
6091 CHECK_SIZE_MATCH(Adds(r4, r4, r10), Adds(r4, r10, r4));
6092
6093 CHECK_SIZE_MATCH(Adds(eq, r4, r4, r10), Adds(eq, r4, r10, r4));
6094
6095 CHECK_SIZE_MATCH(Adds(r7, sp, r7), Adds(r7, r7, sp));
6096
6097 CHECK_SIZE_MATCH(Adds(eq, r7, sp, r7), Adds(eq, r7, r7, sp));
6098
6099 CHECK_SIZE_MATCH(Adds(sp, sp, r10), Adds(sp, r10, sp));
6100
6101 CHECK_SIZE_MATCH(Adds(eq, sp, sp, r10), Adds(eq, sp, r10, sp));
6102
6103 // CHECK_SIZE_MATCH(Ands(r7, r7, r6),
6104 // Ands(r7, r6, r7));
6105
6106 // CHECK_SIZE_MATCH(Ands(eq, r7, r7, r6),
6107 // Ands(eq, r7, r6, r7));
6108
6109 // CHECK_SIZE_MATCH(Eors(r7, r7, r6),
6110 // Eors(r7, r6, r7));
6111
6112 // CHECK_SIZE_MATCH(Eors(eq, r7, r7, r6),
6113 // Eors(eq, r7, r6, r7));
6114
6115 // CHECK_SIZE_MATCH(Muls(r0, r1, r0),
6116 // Muls(r0, r0, r1));
6117
6118 // CHECK_SIZE_MATCH(Muls(eq, r0, r1, r0),
6119 // Muls(eq, r0, r0, r1));
6120
6121 // CHECK_SIZE_MATCH(Orrs(r7, r7, r6),
6122 // Orrs(r7, r6, r7));
6123
6124 // CHECK_SIZE_MATCH(Orrs(eq, r7, r7, r6),
6125 // Orrs(eq, r7, r6, r7));
6126 }
6127
TEST(emit_pool_when_manually_placing_literal)6128 TEST(emit_pool_when_manually_placing_literal) {
6129 SETUP();
6130 START();
6131
6132 // Literal that will be manually placed.
6133 Literal<uint64_t> l0(0xcafebeefdeadbaba, RawLiteral::kManuallyPlaced);
6134
6135 // Create one literal pool entry.
6136 __ Ldrd(r0, r1, 0x1234567890abcdef);
6137
6138 // Branch using the assembler, to avoid introducing a veneer.
6139 Label over_literal;
6140 const int kBranchSize = 4;
6141 {
6142 ExactAssemblyScope scope(&masm,
6143 kBranchSize,
6144 ExactAssemblyScope::kExactSize);
6145 __ b(&over_literal);
6146 }
6147
6148 // Almost reach the pool checkpoint.
6149 int32_t margin =
6150 test.GetPoolCheckpoint() - masm.GetCursorOffset() - l0.GetSize() / 2;
6151 int32_t end = masm.GetCursorOffset() + margin;
6152 {
6153 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize);
6154 while (masm.GetCursorOffset() < end) {
6155 __ nop();
6156 }
6157 }
6158
6159 VIXL_CHECK(!test.PoolIsEmpty());
6160 __ Place(&l0);
6161 // The pool must now have been emitted.
6162 VIXL_CHECK(test.PoolIsEmpty());
6163
6164 __ Bind(&over_literal);
6165
6166 __ Ldrd(r2, r3, &l0);
6167
6168 END();
6169
6170 RUN();
6171
6172 ASSERT_EQUAL_32(0x90abcdef, r0);
6173 ASSERT_EQUAL_32(0x12345678, r1);
6174 ASSERT_EQUAL_32(0xdeadbaba, r2);
6175 ASSERT_EQUAL_32(0xcafebeef, r3);
6176 }
6177
6178
6179 // The addition of padding only happens for T32.
TEST_T32(emit_pool_when_adding_padding_due_to_bind)6180 TEST_T32(emit_pool_when_adding_padding_due_to_bind) {
6181 SETUP();
6182 START();
6183
6184 // Make sure we start with a 4-byte aligned address, in order for the
6185 // location where we will call Bind() to be 4-byte aligned.
6186 {
6187 ExactAssemblyScope scope(&masm,
6188 k16BitT32InstructionSizeInBytes,
6189 ExactAssemblyScope::kMaximumSize);
6190 while (masm.GetCursorOffset() % 4 != 0) {
6191 __ nop();
6192 }
6193 }
6194
6195 // Create one literal pool entry.
6196 __ Ldrd(r0, r1, 0x1234567890abcdef);
6197
6198 // Almost reach the pool checkpoint.
6199 const int kPaddingBytes = 2;
6200 int32_t margin =
6201 test.GetPoolCheckpoint() - masm.GetCursorOffset() - kPaddingBytes;
6202 int32_t end = masm.GetCursorOffset() + margin;
6203 {
6204 ExactAssemblyScope scope(&masm, margin, ExactAssemblyScope::kExactSize);
6205 while (masm.GetCursorOffset() < end) {
6206 __ nop();
6207 }
6208 }
6209
6210 Label label;
6211 __ Cbz(r0, &label);
6212
6213 VIXL_CHECK(!test.PoolIsEmpty());
6214 // In order to hit the case where binding the label needs to add padding,
6215 // we need this to be a 4-byte aligned address.
6216 VIXL_ASSERT((masm.GetBuffer()->GetCursorOffset() % 4) == 0);
6217
6218 __ Bind(&label);
6219 // The pool must now have been emitted.
6220 VIXL_CHECK(test.PoolIsEmpty());
6221
6222 END();
6223
6224 RUN();
6225
6226 ASSERT_EQUAL_32(0x90abcdef, r0);
6227 ASSERT_EQUAL_32(0x12345678, r1);
6228 }
6229
AddBranchesAndGetCloseToCheckpoint(MacroAssembler * masm,TestMacroAssembler * test,const int kLabelsCount,Label b_labels[],int32_t margin)6230 static void AddBranchesAndGetCloseToCheckpoint(MacroAssembler* masm,
6231 TestMacroAssembler* test,
6232 const int kLabelsCount,
6233 Label b_labels[],
6234 int32_t margin) {
6235 // Add many veneers to the pool.
6236 for (int i = 0; i < kLabelsCount; i++) {
6237 masm->B(&b_labels[i]);
6238 }
6239
6240 // Get close to the veneer emission margin (considering the heuristic).
6241 // Use add instead of nop to make viewing the disassembled code easier.
6242 const int kAddSize = masm->IsUsingT32() ? k16BitT32InstructionSizeInBytes
6243 : kA32InstructionSizeInBytes;
6244 int32_t end = test->GetPoolCheckpoint();
6245 int32_t space = end - masm->GetCursorOffset() - margin;
6246 {
6247 ExactAssemblyScope scope(masm, space, ExactAssemblyScope::kExactSize);
6248 while (space > 0) {
6249 masm->add(r0, r0, r0);
6250 space -= kAddSize;
6251 }
6252 }
6253
6254 // Make sure the veneers have not yet been emitted.
6255 const int kVeneerSize = 4;
6256 VIXL_CHECK(test->GetPoolSize() == kLabelsCount * kVeneerSize);
6257 }
6258
EmitIndividualNops(MacroAssembler * masm,const int kNops)6259 static void EmitIndividualNops(MacroAssembler* masm, const int kNops) {
6260 for (int i = 0; i < kNops; ++i) {
6261 masm->Nop();
6262 }
6263 }
6264
EmitNopsInExactAssemblyScope(MacroAssembler * masm,const int kNops)6265 static void EmitNopsInExactAssemblyScope(MacroAssembler* masm,
6266 const int kNops) {
6267 const int kNopSize = masm->IsUsingT32() ? k16BitT32InstructionSizeInBytes
6268 : kA32InstructionSizeInBytes;
6269 {
6270 ExactAssemblyScope scope(masm,
6271 kNops * kNopSize,
6272 ExactAssemblyScope::kExactSize);
6273 for (int i = 0; i < kNops; i++) {
6274 masm->nop();
6275 }
6276 }
6277 }
6278
TEST_A32(literal_and_veneer_interaction_1)6279 TEST_A32(literal_and_veneer_interaction_1) {
6280 SETUP();
6281 START();
6282
6283 static const int kLabelsCount = 100;
6284
6285 Label b_labels[kLabelsCount];
6286
6287 AddBranchesAndGetCloseToCheckpoint(&masm,
6288 &test,
6289 kLabelsCount,
6290 b_labels,
6291 1 * KBytes);
6292
6293 // Emit a load of a large string. In the past, we have attempted to emit
6294 // the literal load without emitting the veneers, which meant that we were
6295 // left with an impossible scheduling problem for the pool objects (due to
6296 // the short range of the ldrd).
6297 std::string test_string(2 * KBytes, 'x');
6298 StringLiteral big_literal(test_string.c_str());
6299 __ Ldrd(r0, r1, &big_literal);
6300
6301 EmitIndividualNops(&masm, 1000);
6302
6303 // We can now safely bind the labels.
6304 for (int i = 0; i < kLabelsCount; i++) {
6305 __ Bind(&b_labels[i]);
6306 }
6307
6308 END();
6309
6310 RUN();
6311 }
6312
6313
TEST_A32(literal_and_veneer_interaction_2)6314 TEST_A32(literal_and_veneer_interaction_2) {
6315 SETUP();
6316 START();
6317
6318 static const int kLabelsCount = 100;
6319
6320 Label b_labels[kLabelsCount];
6321
6322 AddBranchesAndGetCloseToCheckpoint(&masm,
6323 &test,
6324 kLabelsCount,
6325 b_labels,
6326 1 * KBytes);
6327
6328 // This is similar to the test above. The Ldr instruction can be emitted with
6329 // no problems. The Ldrd used to force emission of the literal pool, pushing
6330 // the veneers out of range - we make sure this does not happen anymore.
6331 std::string test_string(2 * KBytes, 'z');
6332 StringLiteral big_literal(test_string.c_str());
6333 __ Ldr(r2, &big_literal);
6334
6335 const int kVeneerSize = 4;
6336 CHECK_POOL_SIZE(kLabelsCount * kVeneerSize + big_literal.GetSize());
6337
6338 std::string test_string2(2 * KBytes, 'x');
6339 StringLiteral big_literal2(test_string.c_str());
6340 __ Ldrd(r0, r1, &big_literal2);
6341
6342 EmitIndividualNops(&masm, 1000);
6343
6344 for (int i = 0; i < kLabelsCount; i++) {
6345 __ Bind(&b_labels[i]);
6346 }
6347
6348 END();
6349
6350 RUN();
6351 }
6352
6353
TEST_A32(literal_and_veneer_interaction_3)6354 TEST_A32(literal_and_veneer_interaction_3) {
6355 SETUP();
6356 START();
6357
6358 static const int kLabelsCount = 100;
6359 Label b_labels[kLabelsCount];
6360
6361 AddBranchesAndGetCloseToCheckpoint(&masm,
6362 &test,
6363 kLabelsCount,
6364 b_labels,
6365 1 * KBytes);
6366
6367 // Here, we used to emit the Ldrd instruction and then emit the veneers
6368 // before the literal is emitted, hence pushing the Ldrd out of range.
6369 // Make sure this does not happen anymore.
6370 __ Ldrd(r2, r3, 0x12345678);
6371
6372 // The issue would only appear when emitting the nops in a single scope.
6373 EmitNopsInExactAssemblyScope(&masm, 4096);
6374
6375 for (int i = 0; i < kLabelsCount; i++) {
6376 __ Bind(&b_labels[i]);
6377 }
6378
6379 END();
6380
6381 RUN();
6382 }
6383
6384
6385 // Equivalent to literal_and_veneer_interaction_1, but for T32.
TEST_T32(literal_and_veneer_interaction_4)6386 TEST_T32(literal_and_veneer_interaction_4) {
6387 SETUP();
6388 START();
6389
6390 static const int kLabelsCount = 550;
6391
6392 Label b_labels[kLabelsCount];
6393
6394 AddBranchesAndGetCloseToCheckpoint(&masm,
6395 &test,
6396 kLabelsCount,
6397 b_labels,
6398 KBytes / 2);
6399
6400 std::string test_string(3 * KBytes, 'x');
6401 StringLiteral big_literal(test_string.c_str());
6402 __ Ldrd(r0, r1, &big_literal);
6403
6404 EmitIndividualNops(&masm, 2000);
6405
6406 for (int i = 0; i < kLabelsCount; i++) {
6407 __ Bind(&b_labels[i]);
6408 }
6409
6410 END();
6411
6412 RUN();
6413 }
6414
6415 // Equivalent to literal_and_veneer_interaction_3, but for T32.
TEST_T32(literal_and_veneer_interaction_5)6416 TEST_T32(literal_and_veneer_interaction_5) {
6417 SETUP();
6418 START();
6419
6420 static const int kLabelsCount = 550;
6421 Label b_labels[kLabelsCount];
6422
6423 AddBranchesAndGetCloseToCheckpoint(&masm,
6424 &test,
6425 kLabelsCount,
6426 b_labels,
6427 1 * KBytes);
6428
6429 __ Ldrd(r2, r3, 0x12345678);
6430
6431 EmitNopsInExactAssemblyScope(&masm, 4096);
6432
6433 for (int i = 0; i < kLabelsCount; i++) {
6434 __ Bind(&b_labels[i]);
6435 }
6436
6437 END();
6438
6439 RUN();
6440 }
6441
TEST_T32(assembler_bind_label)6442 TEST_T32(assembler_bind_label) {
6443 SETUP();
6444 START();
6445
6446 Label label;
6447 __ B(eq, &label, kNear);
6448
6449 // At this point we keep track of the veneer in the pool.
6450 VIXL_CHECK(!test.PoolIsEmpty());
6451
6452 {
6453 // Bind the label with the assembler.
6454 ExactAssemblyScope scope(&masm, 2, ExactAssemblyScope::kMaximumSize);
6455 __ bind(&label);
6456 }
6457
6458 // Make sure the pool is now empty.
6459 VIXL_CHECK(test.PoolIsEmpty());
6460
6461 EmitNopsInExactAssemblyScope(&masm, 4096);
6462
6463 END();
6464
6465 RUN();
6466 }
6467
6468 #ifdef VIXL_DEBUG
6469 #define TEST_FORWARD_REFERENCE_INFO(INST, INFO, ASM) \
6470 POSITIVE_TEST_FORWARD_REFERENCE_INFO(INST, INFO, ASM) \
6471 NEGATIVE_TEST_FORWARD_REFERENCE_INFO(INST, ASM)
6472 #else
6473 // Skip the negative tests for release builds, as they require debug-only checks
6474 // in ExactAssemblyScope.
6475 #define TEST_FORWARD_REFERENCE_INFO(INST, INFO, ASM) \
6476 POSITIVE_TEST_FORWARD_REFERENCE_INFO(INST, INFO, ASM)
6477 #endif
6478
6479 #define POSITIVE_TEST_FORWARD_REFERENCE_INFO(INST, INFO, ASM) \
6480 can_encode = masm.INFO; \
6481 VIXL_CHECK(can_encode); \
6482 { \
6483 ExactAssemblyScope scope(&masm, \
6484 info->size, \
6485 ExactAssemblyScope::kExactSize); \
6486 int32_t program_counter = \
6487 masm.GetCursorOffset() + __ GetArchitectureStatePCOffset(); \
6488 if (info->pc_needs_aligning == ReferenceInfo::kAlignPc) { \
6489 program_counter = AlignDown(program_counter, 4); \
6490 } \
6491 Label label(program_counter + info->min_offset); \
6492 masm.ASM; \
6493 } \
6494 { \
6495 ExactAssemblyScope scope(&masm, \
6496 info->size, \
6497 ExactAssemblyScope::kExactSize); \
6498 int32_t program_counter = \
6499 masm.GetCursorOffset() + __ GetArchitectureStatePCOffset(); \
6500 if (info->pc_needs_aligning == ReferenceInfo::kAlignPc) { \
6501 program_counter = AlignDown(program_counter, 4); \
6502 } \
6503 Label label(program_counter + info->max_offset); \
6504 masm.ASM; \
6505 }
6506
6507 #ifdef VIXL_NEGATIVE_TESTING
6508 #define NEGATIVE_TEST_FORWARD_REFERENCE_INFO(INST, ASM) \
6509 try { \
6510 ExactAssemblyScope scope(&masm, \
6511 info->size, \
6512 ExactAssemblyScope::kMaximumSize); \
6513 int32_t program_counter = \
6514 masm.GetCursorOffset() + __ GetArchitectureStatePCOffset(); \
6515 if (info->pc_needs_aligning == ReferenceInfo::kAlignPc) { \
6516 program_counter = AlignDown(program_counter, 4); \
6517 } \
6518 Label label(program_counter + info->max_offset + info->alignment); \
6519 masm.ASM; \
6520 printf("Negative test for forward reference failed for %s.\n", INST); \
6521 abort(); \
6522 } catch (const std::runtime_error&) { \
6523 } \
6524 try { \
6525 ExactAssemblyScope scope(&masm, \
6526 info->size, \
6527 ExactAssemblyScope::kMaximumSize); \
6528 int32_t program_counter = \
6529 masm.GetCursorOffset() + __ GetArchitectureStatePCOffset(); \
6530 if (info->pc_needs_aligning == ReferenceInfo::kAlignPc) { \
6531 program_counter = AlignDown(program_counter, 4); \
6532 } \
6533 Label label(program_counter + info->min_offset - info->alignment); \
6534 masm.ASM; \
6535 printf("Negative test for forward reference failed for %s.\n", INST); \
6536 abort(); \
6537 } catch (const std::runtime_error&) { \
6538 }
6539 #else
6540 #define NEGATIVE_TEST_FORWARD_REFERENCE_INFO(INST, ASM)
6541 #endif
6542
TEST_T32(forward_reference_info_T32)6543 TEST_T32(forward_reference_info_T32) {
6544 MacroAssembler masm(BUF_SIZE, T32);
6545
6546 Label unbound;
6547 const ReferenceInfo* info;
6548 bool can_encode;
6549
6550 // clang-format off
6551
6552 TEST_FORWARD_REFERENCE_INFO(
6553 "adr",
6554 adr_info(al, Narrow, r0, &unbound, &info),
6555 adr(al, Narrow, r0, &label));
6556
6557 TEST_FORWARD_REFERENCE_INFO(
6558 "adr",
6559 adr_info(al, Wide, r0, &unbound, &info),
6560 adr(al, Wide, r0, &label));
6561
6562 TEST_FORWARD_REFERENCE_INFO(
6563 "adr",
6564 adr_info(al, Best, r0, &unbound, &info),
6565 adr(al, Best, r0, &label));
6566
6567 TEST_FORWARD_REFERENCE_INFO(
6568 "b",
6569 b_info(al, Narrow, &unbound, &info),
6570 b(al, Narrow, &label));
6571
6572 TEST_FORWARD_REFERENCE_INFO(
6573 "b",
6574 b_info(al, Wide, &unbound, &info),
6575 b(al, Wide, &label));
6576
6577 TEST_FORWARD_REFERENCE_INFO(
6578 "b",
6579 b_info(al, Best, &unbound, &info),
6580 b(al, Best, &label));
6581
6582 TEST_FORWARD_REFERENCE_INFO(
6583 "b",
6584 b_info(gt, Narrow, &unbound, &info),
6585 b(gt, Narrow, &label));
6586
6587 TEST_FORWARD_REFERENCE_INFO(
6588 "b",
6589 b_info(gt, Wide, &unbound, &info),
6590 b(gt, Wide, &label));
6591
6592 TEST_FORWARD_REFERENCE_INFO(
6593 "b",
6594 b_info(gt, Best, &unbound, &info),
6595 b(gt, Best, &label));
6596
6597 TEST_FORWARD_REFERENCE_INFO(
6598 "bl",
6599 bl_info(al, &unbound, &info),
6600 bl(al, &label));
6601
6602 TEST_FORWARD_REFERENCE_INFO(
6603 "blx",
6604 blx_info(al, &unbound, &info),
6605 blx(al, &label));
6606
6607 TEST_FORWARD_REFERENCE_INFO(
6608 "cbnz",
6609 cbnz_info(r0, &unbound, &info),
6610 cbnz(r0, &label));
6611
6612 TEST_FORWARD_REFERENCE_INFO(
6613 "cbz",
6614 cbz_info(r0, &unbound, &info),
6615 cbz(r0, &label));
6616
6617 TEST_FORWARD_REFERENCE_INFO(
6618 "ldr",
6619 ldr_info(al, Narrow, r0, &unbound, &info),
6620 ldr(al, Narrow, r0, &label));
6621
6622 TEST_FORWARD_REFERENCE_INFO(
6623 "ldr",
6624 ldr_info(al, Wide, r0, &unbound, &info),
6625 ldr(al, Wide, r0, &label));
6626
6627 TEST_FORWARD_REFERENCE_INFO(
6628 "ldr",
6629 ldr_info(al, Best, r0, &unbound, &info),
6630 ldr(al, Best, r0, &label));
6631
6632 TEST_FORWARD_REFERENCE_INFO(
6633 "ldrb",
6634 ldrb_info(al, r0, &unbound, &info),
6635 ldrb(al, r0, &label));
6636
6637 TEST_FORWARD_REFERENCE_INFO(
6638 "ldrd",
6639 ldrd_info(al, r0, r1, &unbound, &info),
6640 ldrd(al, r0, r1, &label));
6641
6642 TEST_FORWARD_REFERENCE_INFO(
6643 "ldrh",
6644 ldrh_info(al, r0, &unbound, &info),
6645 ldrh(al, r0, &label));
6646
6647 TEST_FORWARD_REFERENCE_INFO(
6648 "ldrsb",
6649 ldrsb_info(al, r0, &unbound, &info),
6650 ldrsb(al, r0, &label));
6651
6652 TEST_FORWARD_REFERENCE_INFO(
6653 "ldrsh",
6654 ldrsh_info(al, r0, &unbound, &info),
6655 ldrsh(al, r0, &label));
6656
6657 TEST_FORWARD_REFERENCE_INFO(
6658 "pld",
6659 pld_info(al, &unbound, &info),
6660 pld(al, &label));
6661
6662 TEST_FORWARD_REFERENCE_INFO(
6663 "pli",
6664 pli_info(al, &unbound, &info),
6665 pli(al, &label));
6666
6667 TEST_FORWARD_REFERENCE_INFO(
6668 "vldr",
6669 vldr_info(al, Untyped64, d0, &unbound, &info),
6670 vldr(al, Untyped64, d0, &label));
6671
6672 TEST_FORWARD_REFERENCE_INFO(
6673 "vldr",
6674 vldr_info(al, Untyped32, s0, &unbound, &info),
6675 vldr(al, Untyped32, s0, &label));
6676
6677 // clang-format on
6678
6679 masm.FinalizeCode();
6680 }
6681
TEST_A32(forward_reference_info_A32)6682 TEST_A32(forward_reference_info_A32) {
6683 MacroAssembler masm(BUF_SIZE, A32);
6684 Label unbound;
6685 const ReferenceInfo* info;
6686 bool can_encode;
6687
6688 // clang-format off
6689
6690 TEST_FORWARD_REFERENCE_INFO(
6691 "adr",
6692 adr_info(al, Best, r0, &unbound, &info),
6693 adr(al, Best, r0, &label));
6694
6695 TEST_FORWARD_REFERENCE_INFO(
6696 "b",
6697 b_info(al, Best, &unbound, &info),
6698 b(al, Best, &label));
6699
6700 TEST_FORWARD_REFERENCE_INFO(
6701 "b",
6702 b_info(gt, Best, &unbound, &info),
6703 b(gt, Best, &label));
6704
6705 TEST_FORWARD_REFERENCE_INFO(
6706 "bl",
6707 bl_info(al, &unbound, &info),
6708 bl(al, &label));
6709
6710 TEST_FORWARD_REFERENCE_INFO(
6711 "blx",
6712 blx_info(al, &unbound, &info),
6713 blx(al, &label));
6714
6715 TEST_FORWARD_REFERENCE_INFO(
6716 "ldr",
6717 ldr_info(al, Best, r0, &unbound, &info),
6718 ldr(al, Best, r0, &label));
6719
6720 TEST_FORWARD_REFERENCE_INFO(
6721 "ldrb",
6722 ldrb_info(al, r0, &unbound, &info),
6723 ldrb(al, r0, &label));
6724
6725 TEST_FORWARD_REFERENCE_INFO(
6726 "ldrd",
6727 ldrd_info(al, r0, r1, &unbound, &info),
6728 ldrd(al, r0, r1, &label));
6729
6730 TEST_FORWARD_REFERENCE_INFO(
6731 "ldrh",
6732 ldrh_info(al, r0, &unbound, &info),
6733 ldrh(al, r0, &label));
6734
6735 TEST_FORWARD_REFERENCE_INFO(
6736 "ldrsb",
6737 ldrsb_info(al, r0, &unbound, &info),
6738 ldrsb(al, r0, &label));
6739
6740 TEST_FORWARD_REFERENCE_INFO(
6741 "ldrsh",
6742 ldrsh_info(al, r0, &unbound, &info),
6743 ldrsh(al, r0, &label));
6744
6745 TEST_FORWARD_REFERENCE_INFO(
6746 "pld",
6747 pld_info(al, &unbound, &info),
6748 pld(al, &label));
6749
6750 TEST_FORWARD_REFERENCE_INFO(
6751 "pli",
6752 pli_info(al, &unbound, &info),
6753 pli(al, &label));
6754
6755 TEST_FORWARD_REFERENCE_INFO(
6756 "vldr",
6757 vldr_info(al, Untyped64, d0, &unbound, &info),
6758 vldr(al, Untyped64, d0, &label));
6759
6760 TEST_FORWARD_REFERENCE_INFO(
6761 "vldr",
6762 vldr_info(al, Untyped32, s0, &unbound, &info),
6763 vldr(al, Untyped32, s0, &label));
6764
6765 // clang-format on
6766
6767 masm.FinalizeCode();
6768 }
6769
6770 } // namespace aarch32
6771 } // namespace vixl
6772