blob: f8578abdf3ea88d89b59be569de38f943d6a8682 [file] [log] [blame]
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +02001/*
2 * Copyright (C) 2016 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
17#include "base/arena_allocator.h"
Vladimir Markoe2727152019-10-10 10:46:42 +010018#include "base/macros.h"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020019#include "code_generator_mips.h"
20#include "optimizing_unit_test.h"
21#include "parallel_move_resolver.h"
22#include "utils/assembler_test_base.h"
23#include "utils/mips/assembler_mips.h"
24
25#include "gtest/gtest.h"
26
Vladimir Markoe2727152019-10-10 10:46:42 +010027namespace art HIDDEN {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020028
Vladimir Markoca6fff82017-10-03 14:49:14 +010029class EmitSwapMipsTest : public OptimizingUnitTest {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020030 public:
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010031 void SetUp() override {
Vladimir Markoa0431112018-06-25 09:32:54 +010032 instruction_set_ = InstructionSet::kMips;
33 instruction_set_features_ = MipsInstructionSetFeatures::FromCppDefines();
34 OptimizingUnitTest::SetUp();
Vladimir Markoca6fff82017-10-03 14:49:14 +010035 graph_ = CreateGraph();
Vladimir Markoa0431112018-06-25 09:32:54 +010036 codegen_.reset(
37 new (graph_->GetAllocator()) mips::CodeGeneratorMIPS(graph_, *compiler_options_));
Vladimir Markoca6fff82017-10-03 14:49:14 +010038 moves_ = new (GetAllocator()) HParallelMove(GetAllocator());
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020039 test_helper_.reset(
40 new AssemblerTestInfrastructure(GetArchitectureString(),
41 GetAssemblerCmdName(),
42 GetAssemblerParameters(),
43 GetObjdumpCmdName(),
44 GetObjdumpParameters(),
45 GetDisassembleCmdName(),
46 GetDisassembleParameters(),
47 GetAssemblyHeader()));
48 }
49
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010050 void TearDown() override {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020051 test_helper_.reset();
Vladimir Markoa0431112018-06-25 09:32:54 +010052 codegen_.reset();
53 graph_ = nullptr;
Vladimir Markoca6fff82017-10-03 14:49:14 +010054 ResetPoolAndAllocator();
Vladimir Markoa0431112018-06-25 09:32:54 +010055 OptimizingUnitTest::TearDown();
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020056 }
57
58 // Get the typically used name for this architecture.
59 std::string GetArchitectureString() {
60 return "mips";
61 }
62
63 // Get the name of the assembler.
64 std::string GetAssemblerCmdName() {
65 return "as";
66 }
67
68 // Switches to the assembler command.
69 std::string GetAssemblerParameters() {
70 return " --no-warn -32 -march=mips32r2";
71 }
72
73 // Get the name of the objdump.
74 std::string GetObjdumpCmdName() {
75 return "objdump";
76 }
77
78 // Switches to the objdump command.
79 std::string GetObjdumpParameters() {
80 return " -h";
81 }
82
83 // Get the name of the objdump.
84 std::string GetDisassembleCmdName() {
85 return "objdump";
86 }
87
88 // Switches to the objdump command.
89 std::string GetDisassembleParameters() {
90 return " -D -bbinary -mmips:isa32r2";
91 }
92
93 // No need for assembly header here.
94 const char* GetAssemblyHeader() {
95 return nullptr;
96 }
97
Andreas Gampe641a4732017-08-24 13:21:35 -070098 void DriverWrapper(HParallelMove* move,
99 const std::string& assembly_text,
100 const std::string& test_name) {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200101 codegen_->GetMoveResolver()->EmitNativeCode(move);
102 assembler_ = codegen_->GetAssembler();
103 assembler_->FinalizeCode();
104 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(assembler_->CodeSize()));
105 MemoryRegion code(&(*data)[0], data->size());
106 assembler_->FinalizeInstructions(code);
107 test_helper_->Driver(*data, assembly_text, test_name);
108 }
109
110 protected:
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200111 HGraph* graph_;
112 HParallelMove* moves_;
Vladimir Markoa0431112018-06-25 09:32:54 +0100113 std::unique_ptr<mips::CodeGeneratorMIPS> codegen_;
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200114 mips::MipsAssembler* assembler_;
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200115 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200116};
117
118TEST_F(EmitSwapMipsTest, TwoRegisters) {
119 moves_->AddMove(
120 Location::RegisterLocation(4),
121 Location::RegisterLocation(5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100122 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200123 nullptr);
124 moves_->AddMove(
125 Location::RegisterLocation(5),
126 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100127 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200128 nullptr);
129 const char* expected =
130 "or $t8, $a1, $zero\n"
131 "or $a1, $a0, $zero\n"
132 "or $a0, $t8, $zero\n";
133 DriverWrapper(moves_, expected, "TwoRegisters");
134}
135
136TEST_F(EmitSwapMipsTest, TwoRegisterPairs) {
137 moves_->AddMove(
138 Location::RegisterPairLocation(4, 5),
139 Location::RegisterPairLocation(6, 7),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100140 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200141 nullptr);
142 moves_->AddMove(
143 Location::RegisterPairLocation(6, 7),
144 Location::RegisterPairLocation(4, 5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100145 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200146 nullptr);
147 const char* expected =
148 "or $t8, $a2, $zero\n"
149 "or $a2, $a0, $zero\n"
150 "or $a0, $t8, $zero\n"
151 "or $t8, $a3, $zero\n"
152 "or $a3, $a1, $zero\n"
153 "or $a1, $t8, $zero\n";
154 DriverWrapper(moves_, expected, "TwoRegisterPairs");
155}
156
157TEST_F(EmitSwapMipsTest, TwoFpuRegistersFloat) {
158 moves_->AddMove(
159 Location::FpuRegisterLocation(4),
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800160 Location::FpuRegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100161 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200162 nullptr);
163 moves_->AddMove(
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800164 Location::FpuRegisterLocation(2),
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200165 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100166 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200167 nullptr);
168 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800169 "mov.s $f6, $f2\n"
170 "mov.s $f2, $f4\n"
171 "mov.s $f4, $f6\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200172 DriverWrapper(moves_, expected, "TwoFpuRegistersFloat");
173}
174
175TEST_F(EmitSwapMipsTest, TwoFpuRegistersDouble) {
176 moves_->AddMove(
177 Location::FpuRegisterLocation(4),
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800178 Location::FpuRegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100179 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200180 nullptr);
181 moves_->AddMove(
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800182 Location::FpuRegisterLocation(2),
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200183 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100184 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200185 nullptr);
186 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800187 "mov.d $f6, $f2\n"
188 "mov.d $f2, $f4\n"
189 "mov.d $f4, $f6\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200190 DriverWrapper(moves_, expected, "TwoFpuRegistersDouble");
191}
192
193TEST_F(EmitSwapMipsTest, RegisterAndFpuRegister) {
194 moves_->AddMove(
195 Location::RegisterLocation(4),
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800196 Location::FpuRegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100197 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200198 nullptr);
199 moves_->AddMove(
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800200 Location::FpuRegisterLocation(2),
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200201 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100202 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200203 nullptr);
204 const char* expected =
205 "or $t8, $a0, $zero\n"
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800206 "mfc1 $a0, $f2\n"
207 "mtc1 $t8, $f2\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200208 DriverWrapper(moves_, expected, "RegisterAndFpuRegister");
209}
210
211TEST_F(EmitSwapMipsTest, RegisterPairAndFpuRegister) {
212 moves_->AddMove(
213 Location::RegisterPairLocation(4, 5),
214 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100215 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200216 nullptr);
217 moves_->AddMove(
218 Location::FpuRegisterLocation(4),
219 Location::RegisterPairLocation(4, 5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100220 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200221 nullptr);
222 const char* expected =
223 "mfc1 $t8, $f4\n"
224 "mfc1 $at, $f5\n"
225 "mtc1 $a0, $f4\n"
226 "mtc1 $a1, $f5\n"
227 "or $a0, $t8, $zero\n"
228 "or $a1, $at, $zero\n";
229 DriverWrapper(moves_, expected, "RegisterPairAndFpuRegister");
230}
231
232TEST_F(EmitSwapMipsTest, TwoStackSlots) {
233 moves_->AddMove(
234 Location::StackSlot(52),
235 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100236 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200237 nullptr);
238 moves_->AddMove(
239 Location::StackSlot(48),
240 Location::StackSlot(52),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100241 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200242 nullptr);
243 const char* expected =
Chris Larsen715f43e2017-10-23 11:00:32 -0700244 "addiu $sp, $sp, -16\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200245 "sw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700246 "lw $v0, 68($sp)\n"
247 "lw $t8, 64($sp)\n"
248 "sw $v0, 64($sp)\n"
249 "sw $t8, 68($sp)\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200250 "lw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700251 "addiu $sp, $sp, 16\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200252 DriverWrapper(moves_, expected, "TwoStackSlots");
253}
254
255TEST_F(EmitSwapMipsTest, TwoDoubleStackSlots) {
256 moves_->AddMove(
257 Location::DoubleStackSlot(56),
258 Location::DoubleStackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100259 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200260 nullptr);
261 moves_->AddMove(
262 Location::DoubleStackSlot(48),
263 Location::DoubleStackSlot(56),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100264 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200265 nullptr);
266 const char* expected =
Chris Larsen715f43e2017-10-23 11:00:32 -0700267 "addiu $sp, $sp, -16\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200268 "sw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700269 "lw $v0, 72($sp)\n"
270 "lw $t8, 64($sp)\n"
271 "sw $v0, 64($sp)\n"
272 "sw $t8, 72($sp)\n"
273 "lw $v0, 76($sp)\n"
274 "lw $t8, 68($sp)\n"
275 "sw $v0, 68($sp)\n"
276 "sw $t8, 76($sp)\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200277 "lw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700278 "addiu $sp, $sp, 16\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200279 DriverWrapper(moves_, expected, "TwoDoubleStackSlots");
280}
281
282TEST_F(EmitSwapMipsTest, RegisterAndStackSlot) {
283 moves_->AddMove(
284 Location::RegisterLocation(4),
285 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100286 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200287 nullptr);
288 moves_->AddMove(
289 Location::StackSlot(48),
290 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100291 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200292 nullptr);
293 const char* expected =
294 "or $t8, $a0, $zero\n"
295 "lw $a0, 48($sp)\n"
296 "sw $t8, 48($sp)\n";
297 DriverWrapper(moves_, expected, "RegisterAndStackSlot");
298}
299
300TEST_F(EmitSwapMipsTest, RegisterPairAndDoubleStackSlot) {
301 moves_->AddMove(
302 Location::RegisterPairLocation(4, 5),
303 Location::DoubleStackSlot(32),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100304 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200305 nullptr);
306 moves_->AddMove(
307 Location::DoubleStackSlot(32),
308 Location::RegisterPairLocation(4, 5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100309 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200310 nullptr);
311 const char* expected =
312 "or $t8, $a0, $zero\n"
313 "lw $a0, 32($sp)\n"
314 "sw $t8, 32($sp)\n"
315 "or $t8, $a1, $zero\n"
316 "lw $a1, 36($sp)\n"
317 "sw $t8, 36($sp)\n";
318 DriverWrapper(moves_, expected, "RegisterPairAndDoubleStackSlot");
319}
320
321TEST_F(EmitSwapMipsTest, FpuRegisterAndStackSlot) {
322 moves_->AddMove(
323 Location::FpuRegisterLocation(4),
324 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100325 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200326 nullptr);
327 moves_->AddMove(
328 Location::StackSlot(48),
329 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100330 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200331 nullptr);
332 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800333 "mov.s $f6, $f4\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200334 "lwc1 $f4, 48($sp)\n"
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800335 "swc1 $f6, 48($sp)\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200336 DriverWrapper(moves_, expected, "FpuRegisterAndStackSlot");
337}
338
339TEST_F(EmitSwapMipsTest, FpuRegisterAndDoubleStackSlot) {
340 moves_->AddMove(
341 Location::FpuRegisterLocation(4),
342 Location::DoubleStackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100343 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200344 nullptr);
345 moves_->AddMove(
346 Location::DoubleStackSlot(48),
347 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100348 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200349 nullptr);
350 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800351 "mov.d $f6, $f4\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200352 "ldc1 $f4, 48($sp)\n"
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800353 "sdc1 $f6, 48($sp)\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200354 DriverWrapper(moves_, expected, "FpuRegisterAndDoubleStackSlot");
355}
356
357} // namespace art