1// Copyright 2017, VIXL authors
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7//   * Redistributions of source code must retain the above copyright notice,
8//     this list of conditions and the following disclaimer.
9//   * Redistributions in binary form must reproduce the above copyright notice,
10//     this list of conditions and the following disclaimer in the documentation
11//     and/or other materials provided with the distribution.
12//   * Neither the name of ARM Limited nor the names of its contributors may be
13//     used to endorse or promote products derived from this software without
14//     specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#include "test-runner.h"
28
29#ifdef VIXL_INCLUDE_TARGET_AARCH32
30#include "aarch32/macro-assembler-aarch32.h"
31#include "aarch32/test-utils-aarch32.h"
32#endif
33
34#ifdef VIXL_INCLUDE_TARGET_AARCH64
35#include "aarch64/macro-assembler-aarch64.h"
36#endif
37
38#define TEST(name) TEST_(SCOPES_##name)
39
40#ifdef VIXL_INCLUDE_TARGET_A32
41#define TEST_A32(name) TEST(name)
42#else
43// Do not add this test to the harness.
44#define TEST_A32(name) void Test##name()
45#endif
46
47#define __ masm.
48
49namespace vixl {
50
51// This file contains tests for code generation scopes.
52
53#ifdef VIXL_INCLUDE_TARGET_AARCH32
54TEST(CodeBufferCheckScope_basic_32) {
55  aarch32::MacroAssembler masm;
56
57  {
58    CodeBufferCheckScope scope(&masm, aarch32::kA32InstructionSizeInBytes);
59    __ Mov(aarch32::r0, 0);
60  }
61
62  masm.FinalizeCode();
63}
64#endif  // VIXL_INCLUDE_TARGET_AARCH32
65
66
67#ifdef VIXL_INCLUDE_TARGET_AARCH64
68TEST(CodeBufferCheckScope_basic_64) {
69  aarch64::MacroAssembler masm;
70
71  {
72    CodeBufferCheckScope scope(&masm, aarch64::kInstructionSize);
73    __ Mov(aarch64::x0, 0);
74  }
75
76  masm.FinalizeCode();
77}
78#endif  // VIXL_INCLUDE_TARGET_AARCH64
79
80
81#ifdef VIXL_INCLUDE_TARGET_AARCH32
82TEST(CodeBufferCheckScope_assembler_use_32) {
83  aarch32::MacroAssembler masm;
84
85  {
86    CodeBufferCheckScope scope(&masm, 2 * aarch32::kA32InstructionSizeInBytes);
87    __ Mov(aarch32::r0, 0);
88    __ mov(aarch32::r1, 1);
89  }
90
91  masm.FinalizeCode();
92}
93#endif  // VIXL_INCLUDE_TARGET_AARCH32
94
95
96#ifdef VIXL_INCLUDE_TARGET_AARCH64
97TEST(CodeBufferCheckScope_assembler_use_64) {
98  aarch64::MacroAssembler masm;
99
100  {
101    CodeBufferCheckScope scope(&masm, 2 * aarch64::kInstructionSize);
102    __ Mov(aarch64::x0, 0);
103    __ movz(aarch64::x1, 1);
104  }
105
106  masm.FinalizeCode();
107}
108#endif  // VIXL_INCLUDE_TARGET_AARCH64
109
110
111#ifdef VIXL_INCLUDE_TARGET_AARCH32
112TEST(CodeBufferCheckScope_Open_32) {
113  aarch32::MacroAssembler masm;
114
115  {
116    CodeBufferCheckScope scope;
117    __ Mov(aarch32::r0, 0);
118    scope.Open(&masm, aarch32::kA32InstructionSizeInBytes);
119    __ Mov(aarch32::r1, 1);
120  }
121
122  masm.FinalizeCode();
123}
124#endif  // VIXL_INCLUDE_TARGET_AARCH32
125
126
127#ifdef VIXL_INCLUDE_TARGET_AARCH64
128TEST(CodeBufferCheckScope_Open_64) {
129  aarch64::MacroAssembler masm;
130
131  {
132    CodeBufferCheckScope scope;
133    __ Mov(aarch64::x0, 0);
134    scope.Open(&masm, aarch64::kInstructionSize);
135    __ Mov(aarch64::x1, 1);
136  }
137
138  masm.FinalizeCode();
139}
140#endif  // VIXL_INCLUDE_TARGET_AARCH64
141
142
143#ifdef VIXL_INCLUDE_TARGET_AARCH32
144TEST(CodeBufferCheckScope_Close_32) {
145  aarch32::MacroAssembler masm;
146
147  {
148    CodeBufferCheckScope scope(&masm, aarch32::kA32InstructionSizeInBytes);
149    __ Mov(aarch32::r0, 0);
150    scope.Close();
151    __ Mov(aarch32::r1, 1);
152  }
153
154  masm.FinalizeCode();
155}
156#endif  // VIXL_INCLUDE_TARGET_AARCH32
157
158
159#ifdef VIXL_INCLUDE_TARGET_AARCH64
160TEST(CodeBufferCheckScope_Close_64) {
161  aarch64::MacroAssembler masm;
162
163  {
164    CodeBufferCheckScope scope(&masm, aarch64::kInstructionSize);
165    __ Mov(aarch64::x0, 0);
166    scope.Close();
167    __ Mov(aarch64::x1, 1);
168  }
169
170  masm.FinalizeCode();
171}
172#endif  // VIXL_INCLUDE_TARGET_AARCH64
173
174
175#ifdef VIXL_INCLUDE_TARGET_AARCH32
176TEST(CodeBufferCheckScope_Open_Close_32) {
177  aarch32::MacroAssembler masm;
178
179  {
180    CodeBufferCheckScope scope;
181    __ Mov(aarch32::r0, 0);
182    scope.Open(&masm, aarch32::kA32InstructionSizeInBytes);
183    __ Mov(aarch32::r1, 1);
184    scope.Close();
185    __ Mov(aarch32::r2, 2);
186  }
187
188  masm.FinalizeCode();
189}
190#endif  // VIXL_INCLUDE_TARGET_AARCH32
191
192
193#ifdef VIXL_INCLUDE_TARGET_AARCH64
194TEST(CodeBufferCheckScope_Open_Close_64) {
195  aarch64::MacroAssembler masm;
196
197  {
198    CodeBufferCheckScope scope;
199    __ Mov(aarch64::x0, 0);
200    scope.Open(&masm, aarch64::kInstructionSize);
201    __ Mov(aarch64::x1, 1);
202    scope.Close();
203    __ Mov(aarch64::x2, 2);
204  }
205
206  masm.FinalizeCode();
207}
208#endif  // VIXL_INCLUDE_TARGET_AARCH64
209
210
211#ifdef VIXL_INCLUDE_TARGET_AARCH32
212TEST(EmissionCheckScope_basic_32) {
213  aarch32::MacroAssembler masm;
214
215  {
216    EmissionCheckScope scope(&masm, aarch32::kA32InstructionSizeInBytes);
217    __ Mov(aarch32::r0, 0);
218  }
219
220  masm.FinalizeCode();
221}
222#endif  // VIXL_INCLUDE_TARGET_AARCH32
223
224
225#ifdef VIXL_INCLUDE_TARGET_AARCH64
226TEST(EmissionCheckScope_basic_64) {
227  aarch64::MacroAssembler masm;
228
229  {
230    EmissionCheckScope scope(&masm, aarch64::kInstructionSize);
231    __ Mov(aarch64::x0, 0);
232  }
233
234  masm.FinalizeCode();
235}
236#endif  // VIXL_INCLUDE_TARGET_AARCH64
237
238
239#ifdef VIXL_INCLUDE_TARGET_AARCH32
240TEST(EmissionCheckScope_Open_32) {
241  aarch32::MacroAssembler masm;
242
243  {
244    EmissionCheckScope scope;
245    __ Mov(aarch32::r0, 0);
246    scope.Open(&masm, aarch32::kA32InstructionSizeInBytes);
247    __ Mov(aarch32::r1, 1);
248  }
249
250  masm.FinalizeCode();
251}
252#endif  // VIXL_INCLUDE_TARGET_AARCH32
253
254
255#ifdef VIXL_INCLUDE_TARGET_AARCH64
256TEST(EmissionCheckScope_Open_64) {
257  aarch64::MacroAssembler masm;
258
259  {
260    EmissionCheckScope scope;
261    __ Mov(aarch64::x0, 0);
262    scope.Open(&masm, aarch64::kInstructionSize);
263    __ Mov(aarch64::x1, 1);
264  }
265
266  masm.FinalizeCode();
267}
268#endif  // VIXL_INCLUDE_TARGET_AARCH64
269
270
271#ifdef VIXL_INCLUDE_TARGET_AARCH32
272TEST(EmissionCheckScope_Close_32) {
273  aarch32::MacroAssembler masm;
274
275  {
276    EmissionCheckScope scope(&masm, aarch32::kA32InstructionSizeInBytes);
277    __ Mov(aarch32::r0, 0);
278    scope.Close();
279    __ Mov(aarch32::r1, 1);
280  }
281
282  masm.FinalizeCode();
283}
284#endif  // VIXL_INCLUDE_TARGET_AARCH32
285
286
287#ifdef VIXL_INCLUDE_TARGET_AARCH64
288TEST(EmissionCheckScope_Close_64) {
289  aarch64::MacroAssembler masm;
290
291  {
292    EmissionCheckScope scope(&masm, aarch64::kInstructionSize);
293    __ Mov(aarch64::x0, 0);
294    scope.Close();
295    __ Mov(aarch64::x1, 1);
296  }
297
298  masm.FinalizeCode();
299}
300#endif  // VIXL_INCLUDE_TARGET_AARCH64
301
302
303#ifdef VIXL_INCLUDE_TARGET_AARCH32
304TEST(EmissionCheckScope_Open_Close_32) {
305  aarch32::MacroAssembler masm;
306
307  {
308    EmissionCheckScope scope;
309    __ Mov(aarch32::r0, 0);
310    scope.Open(&masm, aarch32::kA32InstructionSizeInBytes);
311    __ Mov(aarch32::r1, 1);
312    scope.Close();
313    __ Mov(aarch32::r2, 2);
314  }
315
316  masm.FinalizeCode();
317}
318#endif  // VIXL_INCLUDE_TARGET_AARCH32
319
320
321#ifdef VIXL_INCLUDE_TARGET_AARCH64
322TEST(EmissionCheckScope_Open_Close_64) {
323  aarch64::MacroAssembler masm;
324
325  {
326    EmissionCheckScope scope;
327    __ Mov(aarch64::x0, 0);
328    scope.Open(&masm, aarch64::kInstructionSize);
329    __ Mov(aarch64::x1, 1);
330    scope.Close();
331    __ Mov(aarch64::x2, 2);
332  }
333
334  masm.FinalizeCode();
335}
336#endif  // VIXL_INCLUDE_TARGET_AARCH64
337
338
339#ifdef VIXL_INCLUDE_TARGET_AARCH32
340
341#define ASSERT_LITERAL_POOL_SIZE_32(expected)     \
342  {                                               \
343    aarch32::TestMacroAssembler test(&masm);      \
344    VIXL_CHECK((expected) == test.GetPoolSize()); \
345  }
346
347TEST_A32(EmissionCheckScope_emit_pool_32) {
348  aarch32::MacroAssembler masm;
349
350  // Make sure the pool is empty;
351  masm.EmitLiteralPool(PoolManager<int32_t>::kBranchRequired);
352  ASSERT_LITERAL_POOL_SIZE_32(0);
353
354  __ Ldrd(aarch32::r0, aarch32::r1, 0x1234567890abcdef);
355  ASSERT_LITERAL_POOL_SIZE_32(8);
356
357  const int kLdrdRange = 255;
358  const int kLessThanLdrdRange = 100;
359
360  {
361    // Check that opening the scope with a reserved space well below the limit
362    // at which can generate the literal pool does not force the emission of
363    // the pool.
364    EmissionCheckScope scope(&masm,
365                             kLessThanLdrdRange,
366                             EmissionCheckScope::kMaximumSize);
367    ASSERT_LITERAL_POOL_SIZE_32(8);
368  }
369
370  {
371    // Check that the scope forces emission of the pool if necessary.
372    EmissionCheckScope scope(&masm,
373                             kLdrdRange + 1,
374                             EmissionCheckScope::kMaximumSize);
375    ASSERT_LITERAL_POOL_SIZE_32(0);
376  }
377
378  masm.FinalizeCode();
379}
380#endif  // VIXL_INCLUDE_TARGET_AARCH32
381
382
383#ifdef VIXL_INCLUDE_TARGET_AARCH64
384
385#define ASSERT_LITERAL_POOL_SIZE_64(expected)          \
386  VIXL_CHECK((expected + aarch64::kInstructionSize) == \
387             masm.GetLiteralPoolSize())
388
389TEST(EmissionCheckScope_emit_pool_64) {
390  aarch64::MacroAssembler masm;
391
392  // Make sure the pool is empty;
393  masm.EmitLiteralPool(aarch64::LiteralPool::kBranchRequired);
394  ASSERT_LITERAL_POOL_SIZE_64(0);
395
396  __ Ldr(aarch64::x0, 0x1234567890abcdef);
397  ASSERT_LITERAL_POOL_SIZE_64(8);
398
399  {
400    // Check that opening the scope with a reserved space well below the limit
401    // at which can generate the literal pool does not force the emission of
402    // the pool.
403    EmissionCheckScope scope(&masm,
404                             10 * aarch64::kInstructionSize,
405                             EmissionCheckScope::kMaximumSize);
406    ASSERT_LITERAL_POOL_SIZE_64(8);
407  }
408
409  {
410    // Check that the scope forces emission of the pool if necessary.
411    EmissionCheckScope scope(&masm,
412                             aarch64::kMaxLoadLiteralRange + 1,
413                             EmissionCheckScope::kMaximumSize);
414    ASSERT_LITERAL_POOL_SIZE_64(0);
415  }
416
417  masm.FinalizeCode();
418}
419#endif  // VIXL_INCLUDE_TARGET_AARCH64
420
421
422#ifdef VIXL_INCLUDE_TARGET_AARCH32
423TEST_A32(EmissionCheckScope_emit_pool_on_Open_32) {
424  aarch32::MacroAssembler masm;
425
426  // Make sure the pool is empty;
427  masm.EmitLiteralPool(PoolManager<int32_t>::kBranchRequired);
428  ASSERT_LITERAL_POOL_SIZE_32(0);
429
430  __ Ldrd(aarch32::r0, aarch32::r1, 0x1234567890abcdef);
431  ASSERT_LITERAL_POOL_SIZE_32(8);
432
433  const int kLdrdRange = 255;
434  const int kLessThanLdrdRange = 100;
435
436  {
437    // Check that opening the scope with a reserved space well below the limit
438    // at which can generate the literal pool does not force the emission of
439    // the pool.
440    EmissionCheckScope scope(&masm,
441                             kLessThanLdrdRange,
442                             EmissionCheckScope::kMaximumSize);
443    ASSERT_LITERAL_POOL_SIZE_32(8);
444  }
445
446  {
447    // Check that the scope forces emission of the pool if necessary.
448    EmissionCheckScope scope(&masm,
449                             kLdrdRange + 1,
450                             EmissionCheckScope::kMaximumSize);
451    ASSERT_LITERAL_POOL_SIZE_32(0);
452  }
453
454  masm.FinalizeCode();
455}
456#endif  // VIXL_INCLUDE_TARGET_AARCH32
457
458
459#ifdef VIXL_INCLUDE_TARGET_AARCH64
460TEST(EmissionCheckScope_emit_pool_on_Open_64) {
461  aarch64::MacroAssembler masm;
462
463  // Make sure the pool is empty;
464  masm.EmitLiteralPool(aarch64::LiteralPool::kBranchRequired);
465  ASSERT_LITERAL_POOL_SIZE_64(0);
466
467  __ Ldr(aarch64::x0, 0x1234567890abcdef);
468  ASSERT_LITERAL_POOL_SIZE_64(8);
469
470  {
471    // Check that opening the scope with a reserved space well below the limit
472    // at which can generate the literal pool does not force the emission of
473    // the pool.
474    EmissionCheckScope scope;
475    scope.Open(&masm,
476               10 * aarch64::kInstructionSize,
477               EmissionCheckScope::kMaximumSize);
478    ASSERT_LITERAL_POOL_SIZE_64(8);
479  }
480
481  {
482    // Check that the scope forces emission of the pool if necessary.
483    EmissionCheckScope scope;
484    scope.Open(&masm,
485               aarch64::kMaxLoadLiteralRange + 1,
486               EmissionCheckScope::kMaximumSize);
487    ASSERT_LITERAL_POOL_SIZE_64(0);
488  }
489
490  masm.FinalizeCode();
491}
492#endif  // VIXL_INCLUDE_TARGET_AARCH64
493
494
495#ifdef VIXL_INCLUDE_TARGET_AARCH32
496TEST_A32(ExactAssemblyScope_basic_32) {
497  aarch32::MacroAssembler masm;
498
499  {
500    ExactAssemblyScope scope(&masm, aarch32::kA32InstructionSizeInBytes);
501    __ nop();
502  }
503
504  masm.FinalizeCode();
505}
506#endif  // VIXL_INCLUDE_TARGET_AARCH32
507
508
509#ifdef VIXL_INCLUDE_TARGET_AARCH64
510TEST(ExactAssemblyScope_basic_64) {
511  aarch64::MacroAssembler masm;
512
513  {
514    ExactAssemblyScope scope(&masm, aarch64::kInstructionSize);
515    __ nop();
516  }
517
518  masm.FinalizeCode();
519}
520#endif  // VIXL_INCLUDE_TARGET_AARCH64
521
522
523#ifdef VIXL_INCLUDE_TARGET_AARCH32
524TEST_A32(ExactAssemblyScope_Open_32) {
525  aarch32::MacroAssembler masm;
526
527  {
528    ExactAssemblyScope scope;
529    __ Mov(aarch32::r0, 0);
530    scope.Open(&masm, aarch32::kA32InstructionSizeInBytes);
531    __ mov(aarch32::r1, 1);
532  }
533
534  masm.FinalizeCode();
535}
536#endif  // VIXL_INCLUDE_TARGET_AARCH32
537
538
539#ifdef VIXL_INCLUDE_TARGET_AARCH64
540TEST(ExactAssemblyScope_Open_64) {
541  aarch64::MacroAssembler masm;
542
543  {
544    ExactAssemblyScope scope;
545    __ Mov(aarch64::x0, 0);
546    scope.Open(&masm, aarch64::kInstructionSize);
547    __ movz(aarch64::x1, 1);
548  }
549
550  masm.FinalizeCode();
551}
552#endif  // VIXL_INCLUDE_TARGET_AARCH64
553
554
555#ifdef VIXL_INCLUDE_TARGET_AARCH32
556TEST_A32(ExactAssemblyScope_Close_32) {
557  aarch32::MacroAssembler masm;
558
559  {
560    ExactAssemblyScope scope(&masm, aarch32::kA32InstructionSizeInBytes);
561    __ mov(aarch32::r0, 0);
562    scope.Close();
563    __ Mov(aarch32::r1, 1);
564  }
565
566  masm.FinalizeCode();
567}
568#endif  // VIXL_INCLUDE_TARGET_AARCH32
569
570
571#ifdef VIXL_INCLUDE_TARGET_AARCH64
572TEST(ExactAssemblyScope_Close_64) {
573  aarch64::MacroAssembler masm;
574
575  {
576    ExactAssemblyScope scope(&masm, aarch64::kInstructionSize);
577    __ movz(aarch64::x0, 0);
578    scope.Close();
579    __ Mov(aarch64::x1, 1);
580  }
581
582  masm.FinalizeCode();
583}
584#endif  // VIXL_INCLUDE_TARGET_AARCH64
585
586
587#ifdef VIXL_INCLUDE_TARGET_AARCH32
588TEST_A32(ExactAssemblyScope_Open_Close_32) {
589  aarch32::MacroAssembler masm;
590
591  {
592    ExactAssemblyScope scope;
593    __ Mov(aarch32::r0, 0);
594    scope.Open(&masm, aarch32::kA32InstructionSizeInBytes);
595    __ mov(aarch32::r1, 1);
596    scope.Close();
597    __ Mov(aarch32::r2, 2);
598  }
599
600  masm.FinalizeCode();
601}
602#endif  // VIXL_INCLUDE_TARGET_AARCH32
603
604
605#ifdef VIXL_INCLUDE_TARGET_AARCH64
606TEST(ExactAssemblyScope_Open_Close_64) {
607  aarch64::MacroAssembler masm;
608
609  {
610    ExactAssemblyScope scope;
611    __ Mov(aarch64::x0, 0);
612    scope.Open(&masm, aarch64::kInstructionSize);
613    __ movz(aarch64::x1, 1);
614    scope.Close();
615    __ Mov(aarch64::x2, 2);
616  }
617
618  masm.FinalizeCode();
619}
620#endif  // VIXL_INCLUDE_TARGET_AARCH64
621
622
623#ifdef VIXL_INCLUDE_TARGET_AARCH32
624TEST_A32(ExactAssemblyScope_32) {
625  aarch32::MacroAssembler masm;
626
627  // By default macro instructions are allowed.
628  VIXL_CHECK(!masm.ArePoolsBlocked());
629  VIXL_ASSERT(!masm.AllowAssembler());
630  VIXL_ASSERT(masm.AllowMacroInstructions());
631  {
632    ExactAssemblyScope scope1(&masm, 2 * aarch32::kA32InstructionSizeInBytes);
633    VIXL_CHECK(masm.ArePoolsBlocked());
634    VIXL_ASSERT(masm.AllowAssembler());
635    VIXL_ASSERT(!masm.AllowMacroInstructions());
636    __ nop();
637    {
638      ExactAssemblyScope scope2(&masm, 1 * aarch32::kA32InstructionSizeInBytes);
639      VIXL_CHECK(masm.ArePoolsBlocked());
640      VIXL_ASSERT(masm.AllowAssembler());
641      VIXL_ASSERT(!masm.AllowMacroInstructions());
642      __ nop();
643    }
644    VIXL_CHECK(masm.ArePoolsBlocked());
645    VIXL_ASSERT(masm.AllowAssembler());
646    VIXL_ASSERT(!masm.AllowMacroInstructions());
647  }
648  VIXL_CHECK(!masm.ArePoolsBlocked());
649  VIXL_ASSERT(!masm.AllowAssembler());
650  VIXL_ASSERT(masm.AllowMacroInstructions());
651
652  {
653    ExactAssemblyScope scope(&masm, 2 * aarch32::kA32InstructionSizeInBytes);
654    __ add(aarch32::r0, aarch32::r0, aarch32::r0);
655    __ sub(aarch32::r0, aarch32::r0, aarch32::r0);
656  }
657
658  masm.FinalizeCode();
659}
660#endif  // VIXL_INCLUDE_TARGET_AARCH32
661
662
663#ifdef VIXL_INCLUDE_TARGET_AARCH64
664TEST(ExactAssemblyScope_64) {
665  aarch64::MacroAssembler masm;
666
667  // By default macro instructions are allowed.
668  VIXL_CHECK(!masm.ArePoolsBlocked());
669  VIXL_ASSERT(!masm.AllowAssembler());
670  VIXL_ASSERT(masm.AllowMacroInstructions());
671  {
672    ExactAssemblyScope scope1(&masm, 2 * aarch64::kInstructionSize);
673    VIXL_CHECK(masm.ArePoolsBlocked());
674    VIXL_ASSERT(masm.AllowAssembler());
675    VIXL_ASSERT(!masm.AllowMacroInstructions());
676    __ nop();
677    {
678      ExactAssemblyScope scope2(&masm, 1 * aarch64::kInstructionSize);
679      VIXL_CHECK(masm.ArePoolsBlocked());
680      VIXL_ASSERT(masm.AllowAssembler());
681      VIXL_ASSERT(!masm.AllowMacroInstructions());
682      __ nop();
683    }
684    VIXL_CHECK(masm.ArePoolsBlocked());
685    VIXL_ASSERT(masm.AllowAssembler());
686    VIXL_ASSERT(!masm.AllowMacroInstructions());
687  }
688  VIXL_CHECK(!masm.ArePoolsBlocked());
689  VIXL_ASSERT(!masm.AllowAssembler());
690  VIXL_ASSERT(masm.AllowMacroInstructions());
691
692  {
693    ExactAssemblyScope scope(&masm, 2 * aarch64::kInstructionSize);
694    __ add(aarch64::x0, aarch64::x0, aarch64::x0);
695    __ sub(aarch64::x0, aarch64::x0, aarch64::x0);
696  }
697
698  masm.FinalizeCode();
699}
700#endif  // VIXL_INCLUDE_TARGET_AARCH64
701
702
703#ifdef VIXL_INCLUDE_TARGET_AARCH32
704TEST_A32(ExactAssemblyScope_scope_with_pools_32) {
705  aarch32::MacroAssembler masm;
706
707  ASSERT_LITERAL_POOL_SIZE_32(0);
708
709  __ Ldrd(aarch32::r0, aarch32::r1, 0x1234567890abcdef);
710
711  ASSERT_LITERAL_POOL_SIZE_32(8);
712
713  const int32_t kLdrdRange = 255;
714  const int32_t n_nops = (kLdrdRange / aarch32::kA32InstructionSizeInBytes) + 1;
715  {
716    // The literal pool should be generated when opening this scope, as
717    // otherwise the `Ldrd` will run out of range when we generate the `nop`
718    // instructions below.
719    ExactAssemblyScope scope(&masm,
720                             n_nops * aarch32::kA32InstructionSizeInBytes);
721
722    // Although it must be, we do not check that the literal pool size is zero
723    // here, because we want this regression test to fail while or after we
724    // generate the nops.
725
726    for (int32_t i = 0; i < n_nops; ++i) {
727      __ nop();
728    }
729  }
730
731  ASSERT_LITERAL_POOL_SIZE_32(0);
732
733  masm.FinalizeCode();
734}
735#endif  // VIXL_INCLUDE_TARGET_AARCH32
736
737
738#ifdef VIXL_INCLUDE_TARGET_AARCH64
739TEST(ExactAssemblyScope_scope_with_pools_64) {
740  aarch64::MacroAssembler masm;
741
742  ASSERT_LITERAL_POOL_SIZE_64(0);
743
744  __ Ldr(aarch64::x10, 0x1234567890abcdef);
745
746  ASSERT_LITERAL_POOL_SIZE_64(8);
747
748  const int64_t n_nops =
749      aarch64::kMaxLoadLiteralRange / aarch64::kInstructionSize;
750  {
751    // The literal pool should be generated when opening this scope, as
752    // otherwise the `Ldr` will run out of range when we generate the `nop`
753    // instructions below.
754    ExactAssemblyScope scope(&masm, n_nops * aarch64::kInstructionSize);
755
756    // Although it must be, we do not check that the literal pool size is zero
757    // here, because we want this regression test to fail while or after we
758    // generate the nops.
759
760    for (int64_t i = 0; i < n_nops; ++i) {
761      __ nop();
762    }
763  }
764
765  ASSERT_LITERAL_POOL_SIZE_64(0);
766
767  masm.FinalizeCode();
768}
769#endif  // VIXL_INCLUDE_TARGET_AARCH64
770
771
772}  // namespace vixl
773