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