blob: b2d4dcd9f692dff5e4945d6b1f7e76059851e59d [file] [log] [blame]
Dave Allison65fcc2c2014-04-28 13:45:27 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010017#include <dirent.h>
Andreas Gampefd114702015-05-13 17:00:41 -070018#include <errno.h>
Andreas Gampefd114702015-05-13 17:00:41 -070019#include <string.h>
20#include <sys/types.h>
David Srbeckyb461b532020-07-13 17:45:22 +000021
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include <fstream>
23#include <map>
David Srbeckyb461b532020-07-13 17:45:22 +000024#include <regex>
Dave Allison65fcc2c2014-04-28 13:45:27 -070025
26#include "gtest/gtest.h"
Artem Serov12e097c2016-08-08 15:13:26 +010027
28#include "jni/quick/calling_convention.h"
29#include "utils/arm/jni_macro_assembler_arm_vixl.h"
David Srbecky194f5552020-07-07 01:10:07 +010030#include "utils/assembler_test_base.h"
Artem Serov12e097c2016-08-08 15:13:26 +010031
Dave Allison65fcc2c2014-04-28 13:45:27 -070032#include "base/hex_dump.h"
David Sehr3215fff2018-04-03 17:10:12 -070033#include "base/malloc_arena_pool.h"
Dave Allison65fcc2c2014-04-28 13:45:27 -070034#include "common_runtime_test.h"
35
36namespace art {
37namespace arm {
38
39// Include results file (generated manually)
40#include "assembler_thumb_test_expected.cc.inc"
41
David Srbecky194f5552020-07-07 01:10:07 +010042class ArmVIXLAssemblerTest : public AssemblerTestBase {
Artem Serov12e097c2016-08-08 15:13:26 +010043 public:
Vladimir Marko69d310e2017-10-09 14:12:23 +010044 ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { }
Artem Serov12e097c2016-08-08 15:13:26 +010045
David Srbecky194f5552020-07-07 01:10:07 +010046 protected:
47 InstructionSet GetIsa() override { return InstructionSet::kThumb2; }
48
49 void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const std::string& expected) {
50#ifndef ART_TARGET_ANDROID
51 std::string obj_file = scratch_dir_->GetPath() + testname + ".o";
52 WriteElf</*IsElf64=*/false>(obj_file, InstructionSet::kThumb2, code);
53 std::string disassembly;
54 ASSERT_TRUE(Disassemble(obj_file, &disassembly));
55
David Srbeckyb461b532020-07-13 17:45:22 +000056 // objdump on buildbot seems to sometimes add annotation like in "bne #226 <.text+0x1e8>".
57 // It is unclear why it does not reproduce locally. As work-around, remove the annotation.
58 std::regex annotation_re(" <\\.text\\+\\w+>");
59 disassembly = std::regex_replace(disassembly, annotation_re, "");
60
David Srbecky194f5552020-07-07 01:10:07 +010061 std::string expected2 = "\n" +
Yabin Cui668daf82021-08-10 15:42:10 +000062 obj_file + ": file format elf32-littlearm\n\n"
David Srbecky194f5552020-07-07 01:10:07 +010063 "Disassembly of section .text:\n\n"
Stephen Hines331c8e32020-09-11 17:03:58 -070064 "00000000 <.text>:\n" +
David Srbecky194f5552020-07-07 01:10:07 +010065 expected;
66 EXPECT_EQ(expected2, disassembly);
67 if (expected2 != disassembly) {
68 std::string out = " \"" + Replace(disassembly, "\n", "\\n\"\n \"") + "\"";
69 printf("C++ formatted disassembler output for %s:\n%s\n", testname, out.c_str());
70 }
71#endif // ART_TARGET_ANDROID
72 }
73
74#define __ assembler.
75
76 void EmitAndCheck(const char* testname, const char* expected) {
77 __ FinalizeCode();
78 size_t cs = __ CodeSize();
79 std::vector<uint8_t> managed_code(cs);
80 MemoryRegion code(&managed_code[0], managed_code.size());
81 __ FinalizeInstructions(code);
82
83 DumpAndCheck(managed_code, testname, expected);
84 }
85
86#undef __
87
88#define __ assembler.
89
David Sehr3215fff2018-04-03 17:10:12 -070090 MallocArenaPool pool;
Vladimir Marko69d310e2017-10-09 14:12:23 +010091 ArenaAllocator allocator;
Roland Levillainc043d002017-07-14 16:39:16 +010092 ArmVIXLJNIMacroAssembler assembler;
Artem Serov12e097c2016-08-08 15:13:26 +010093};
94
Vladimir Marko0e851e22016-08-25 18:17:56 +010095TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) {
Roland Levillain6d729a72017-06-30 18:34:01 +010096 // Run the test only with Baker read barriers, as the expected
97 // generated code contains a Marking Register refresh instruction.
98 TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS();
99
Artem Serov12e097c2016-08-08 15:13:26 +0100100 const bool is_static = true;
101 const bool is_synchronized = false;
Vladimir Marko46a89102021-10-21 13:05:46 +0000102 const bool is_fast_native = false;
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700103 const bool is_critical_native = false;
Artem Serov12e097c2016-08-08 15:13:26 +0100104 const char* shorty = "IIFII";
105
Artem Serov12e097c2016-08-08 15:13:26 +0100106 std::unique_ptr<JniCallingConvention> jni_conv(
Vladimir Marko69d310e2017-10-09 14:12:23 +0100107 JniCallingConvention::Create(&allocator,
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700108 is_static,
109 is_synchronized,
Vladimir Marko46a89102021-10-21 13:05:46 +0000110 is_fast_native,
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700111 is_critical_native,
112 shorty,
Vladimir Marko33bff252017-11-01 14:35:42 +0000113 InstructionSet::kThumb2));
Artem Serov12e097c2016-08-08 15:13:26 +0100114 std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv(
Vladimir Marko69d310e2017-10-09 14:12:23 +0100115 ManagedRuntimeCallingConvention::Create(
Vladimir Marko33bff252017-11-01 14:35:42 +0000116 &allocator, is_static, is_synchronized, shorty, InstructionSet::kThumb2));
Artem Serov12e097c2016-08-08 15:13:26 +0100117 const int frame_size(jni_conv->FrameSize());
118 ArrayRef<const ManagedRegister> callee_save_regs = jni_conv->CalleeSaveRegisters();
119
120 const ManagedRegister method_register = ArmManagedRegister::FromCoreRegister(R0);
Vladimir Marko662f12e2020-02-26 12:46:09 +0000121 const ManagedRegister hidden_arg_register = ArmManagedRegister::FromCoreRegister(R4);
Artem Serov12e097c2016-08-08 15:13:26 +0100122 const ManagedRegister scratch_register = ArmManagedRegister::FromCoreRegister(R12);
123
Vladimir Marko662f12e2020-02-26 12:46:09 +0000124 __ BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs);
125
126 // Spill arguments.
127 mr_conv->ResetIterator(FrameOffset(frame_size));
128 for (; mr_conv->HasNext(); mr_conv->Next()) {
129 if (mr_conv->IsCurrentParamInRegister()) {
130 size_t size = mr_conv->IsCurrentParamALongOrDouble() ? 8u : 4u;
131 __ Store(mr_conv->CurrentParamStackOffset(), mr_conv->CurrentParamRegister(), size);
132 }
133 }
Artem Serov12e097c2016-08-08 15:13:26 +0100134 __ IncreaseFrameSize(32);
135
136 // Loads
137 __ IncreaseFrameSize(4096);
138 __ Load(method_register, FrameOffset(32), 4);
139 __ Load(method_register, FrameOffset(124), 4);
140 __ Load(method_register, FrameOffset(132), 4);
141 __ Load(method_register, FrameOffset(1020), 4);
142 __ Load(method_register, FrameOffset(1024), 4);
143 __ Load(scratch_register, FrameOffset(4092), 4);
144 __ Load(scratch_register, FrameOffset(4096), 4);
145 __ LoadRawPtrFromThread(scratch_register, ThreadOffset32(512));
Andreas Gampe3db70682018-12-26 15:12:03 -0800146 __ LoadRef(method_register, scratch_register, MemberOffset(128), /* unpoison_reference= */ false);
Artem Serov12e097c2016-08-08 15:13:26 +0100147
148 // Stores
149 __ Store(FrameOffset(32), method_register, 4);
150 __ Store(FrameOffset(124), method_register, 4);
151 __ Store(FrameOffset(132), method_register, 4);
152 __ Store(FrameOffset(1020), method_register, 4);
153 __ Store(FrameOffset(1024), method_register, 4);
154 __ Store(FrameOffset(4092), scratch_register, 4);
155 __ Store(FrameOffset(4096), scratch_register, 4);
Vladimir Marko662f12e2020-02-26 12:46:09 +0000156 __ StoreImmediateToFrame(FrameOffset(48), 0xFF);
157 __ StoreImmediateToFrame(FrameOffset(48), 0xFFFFFF);
Artem Serov12e097c2016-08-08 15:13:26 +0100158 __ StoreRawPtr(FrameOffset(48), scratch_register);
159 __ StoreRef(FrameOffset(48), scratch_register);
Vladimir Marko662f12e2020-02-26 12:46:09 +0000160 __ StoreSpanning(FrameOffset(48), method_register, FrameOffset(48));
161 __ StoreStackOffsetToThread(ThreadOffset32(512), FrameOffset(4096));
Artem Serov12e097c2016-08-08 15:13:26 +0100162 __ StoreStackPointerToThread(ThreadOffset32(512));
163
164 // Other
Vladimir Marko662f12e2020-02-26 12:46:09 +0000165 __ Call(method_register, FrameOffset(48));
166 __ Copy(FrameOffset(48), FrameOffset(44), 4);
167 __ CopyRawPtrFromThread(FrameOffset(44), ThreadOffset32(512));
168 __ CopyRef(FrameOffset(48), FrameOffset(44));
Artem Serov12e097c2016-08-08 15:13:26 +0100169 __ GetCurrentThread(method_register);
Vladimir Marko662f12e2020-02-26 12:46:09 +0000170 __ GetCurrentThread(FrameOffset(48));
171 __ Move(hidden_arg_register, method_register, 4);
Artem Serov12e097c2016-08-08 15:13:26 +0100172 __ VerifyObject(scratch_register, false);
173
Vladimir Markod3aaf942021-11-02 10:51:57 +0000174 // Note: `CreateJObject()` may need the scratch register IP. Test with another high register.
175 const ManagedRegister high_register = ArmManagedRegister::FromCoreRegister(R11);
176 __ CreateJObject(high_register, FrameOffset(48), high_register, true);
177 __ CreateJObject(high_register, FrameOffset(48), high_register, false);
178 __ CreateJObject(method_register, FrameOffset(48), high_register, true);
Vladimir Markocedec9d2021-02-08 16:16:13 +0000179 __ CreateJObject(FrameOffset(48), FrameOffset(64), true);
Vladimir Markod3aaf942021-11-02 10:51:57 +0000180 __ CreateJObject(method_register, FrameOffset(0), high_register, true);
181 __ CreateJObject(method_register, FrameOffset(1028), high_register, true);
182 __ CreateJObject(high_register, FrameOffset(1028), high_register, true);
Artem Serov12e097c2016-08-08 15:13:26 +0100183
Vladimir Markoc8c2bb62021-10-15 09:33:09 +0100184 std::unique_ptr<JNIMacroLabel> exception_slow_path = __ CreateLabel();
185 __ ExceptionPoll(exception_slow_path.get());
Artem Serov12e097c2016-08-08 15:13:26 +0100186
Artem Serov8f840f82016-12-15 17:56:27 +0000187 // Push the target out of range of branch emitted by ExceptionPoll.
188 for (int i = 0; i < 64; i++) {
189 __ Store(FrameOffset(2047), scratch_register, 4);
190 }
191
Artem Serov12e097c2016-08-08 15:13:26 +0100192 __ DecreaseFrameSize(4096);
193 __ DecreaseFrameSize(32);
Andreas Gampe3db70682018-12-26 15:12:03 -0800194 __ RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true);
Artem Serov12e097c2016-08-08 15:13:26 +0100195
Vladimir Markoc8c2bb62021-10-15 09:33:09 +0100196 __ Bind(exception_slow_path.get());
197 __ DeliverPendingException();
198
David Srbecky194f5552020-07-07 01:10:07 +0100199 EmitAndCheck("VixlJniHelpers", VixlJniHelpersResults);
Artem Serov12e097c2016-08-08 15:13:26 +0100200}
201
Roland Levillainc043d002017-07-14 16:39:16 +0100202#undef __
203
204// TODO: Avoid these macros.
Artem Serov12e097c2016-08-08 15:13:26 +0100205#define R0 vixl::aarch32::r0
206#define R2 vixl::aarch32::r2
207#define R4 vixl::aarch32::r4
208#define R12 vixl::aarch32::r12
Roland Levillainc043d002017-07-14 16:39:16 +0100209
Artem Serov12e097c2016-08-08 15:13:26 +0100210#define __ assembler.asm_.
Artem Serov12e097c2016-08-08 15:13:26 +0100211
Vladimir Marko0e851e22016-08-25 18:17:56 +0100212TEST_F(ArmVIXLAssemblerTest, VixlLoadFromOffset) {
Artem Serov12e097c2016-08-08 15:13:26 +0100213 __ LoadFromOffset(kLoadWord, R2, R4, 12);
214 __ LoadFromOffset(kLoadWord, R2, R4, 0xfff);
215 __ LoadFromOffset(kLoadWord, R2, R4, 0x1000);
216 __ LoadFromOffset(kLoadWord, R2, R4, 0x1000a4);
217 __ LoadFromOffset(kLoadWord, R2, R4, 0x101000);
218 __ LoadFromOffset(kLoadWord, R4, R4, 0x101000);
219 __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 12);
220 __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0xfff);
221 __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0x1000);
222 __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0x1000a4);
223 __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0x101000);
224 __ LoadFromOffset(kLoadUnsignedHalfword, R4, R4, 0x101000);
225 __ LoadFromOffset(kLoadWordPair, R2, R4, 12);
226 __ LoadFromOffset(kLoadWordPair, R2, R4, 0x3fc);
227 __ LoadFromOffset(kLoadWordPair, R2, R4, 0x400);
228 __ LoadFromOffset(kLoadWordPair, R2, R4, 0x400a4);
229 __ LoadFromOffset(kLoadWordPair, R2, R4, 0x40400);
230 __ LoadFromOffset(kLoadWordPair, R4, R4, 0x40400);
231
Scott Wakelingb77051e2016-11-21 19:46:00 +0000232 vixl::aarch32::UseScratchRegisterScope temps(assembler.asm_.GetVIXLAssembler());
233 temps.Exclude(R12);
Artem Serov12e097c2016-08-08 15:13:26 +0100234 __ LoadFromOffset(kLoadWord, R0, R12, 12); // 32-bit because of R12.
Scott Wakelingb77051e2016-11-21 19:46:00 +0000235 temps.Include(R12);
Artem Serov12e097c2016-08-08 15:13:26 +0100236 __ LoadFromOffset(kLoadWord, R2, R4, 0xa4 - 0x100000);
237
238 __ LoadFromOffset(kLoadSignedByte, R2, R4, 12);
239 __ LoadFromOffset(kLoadUnsignedByte, R2, R4, 12);
240 __ LoadFromOffset(kLoadSignedHalfword, R2, R4, 12);
241
David Srbecky194f5552020-07-07 01:10:07 +0100242 EmitAndCheck("VixlLoadFromOffset", VixlLoadFromOffsetResults);
Artem Serov12e097c2016-08-08 15:13:26 +0100243}
244
Vladimir Marko0e851e22016-08-25 18:17:56 +0100245TEST_F(ArmVIXLAssemblerTest, VixlStoreToOffset) {
Artem Serov12e097c2016-08-08 15:13:26 +0100246 __ StoreToOffset(kStoreWord, R2, R4, 12);
247 __ StoreToOffset(kStoreWord, R2, R4, 0xfff);
248 __ StoreToOffset(kStoreWord, R2, R4, 0x1000);
249 __ StoreToOffset(kStoreWord, R2, R4, 0x1000a4);
250 __ StoreToOffset(kStoreWord, R2, R4, 0x101000);
251 __ StoreToOffset(kStoreWord, R4, R4, 0x101000);
252 __ StoreToOffset(kStoreHalfword, R2, R4, 12);
253 __ StoreToOffset(kStoreHalfword, R2, R4, 0xfff);
254 __ StoreToOffset(kStoreHalfword, R2, R4, 0x1000);
255 __ StoreToOffset(kStoreHalfword, R2, R4, 0x1000a4);
256 __ StoreToOffset(kStoreHalfword, R2, R4, 0x101000);
257 __ StoreToOffset(kStoreHalfword, R4, R4, 0x101000);
258 __ StoreToOffset(kStoreWordPair, R2, R4, 12);
259 __ StoreToOffset(kStoreWordPair, R2, R4, 0x3fc);
260 __ StoreToOffset(kStoreWordPair, R2, R4, 0x400);
261 __ StoreToOffset(kStoreWordPair, R2, R4, 0x400a4);
262 __ StoreToOffset(kStoreWordPair, R2, R4, 0x40400);
263 __ StoreToOffset(kStoreWordPair, R4, R4, 0x40400);
264
Scott Wakelingb77051e2016-11-21 19:46:00 +0000265 vixl::aarch32::UseScratchRegisterScope temps(assembler.asm_.GetVIXLAssembler());
266 temps.Exclude(R12);
Artem Serov12e097c2016-08-08 15:13:26 +0100267 __ StoreToOffset(kStoreWord, R0, R12, 12); // 32-bit because of R12.
Scott Wakelingb77051e2016-11-21 19:46:00 +0000268 temps.Include(R12);
Artem Serov12e097c2016-08-08 15:13:26 +0100269 __ StoreToOffset(kStoreWord, R2, R4, 0xa4 - 0x100000);
270
271 __ StoreToOffset(kStoreByte, R2, R4, 12);
272
David Srbecky194f5552020-07-07 01:10:07 +0100273 EmitAndCheck("VixlStoreToOffset", VixlStoreToOffsetResults);
Artem Serov12e097c2016-08-08 15:13:26 +0100274}
275
276#undef __
Dave Allison65fcc2c2014-04-28 13:45:27 -0700277} // namespace arm
278} // namespace art