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