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