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