blob: 63a370a47b5690ff76b28e9d6e972ff27f5c79bd [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"
18#include "code_generator_mips.h"
19#include "optimizing_unit_test.h"
20#include "parallel_move_resolver.h"
21#include "utils/assembler_test_base.h"
22#include "utils/mips/assembler_mips.h"
23
24#include "gtest/gtest.h"
25
26namespace art {
27
Vladimir Markoca6fff82017-10-03 14:49:14 +010028class EmitSwapMipsTest : public OptimizingUnitTest {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020029 public:
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010030 void SetUp() override {
Vladimir Markoa0431112018-06-25 09:32:54 +010031 instruction_set_ = InstructionSet::kMips;
32 instruction_set_features_ = MipsInstructionSetFeatures::FromCppDefines();
33 OptimizingUnitTest::SetUp();
Vladimir Markoca6fff82017-10-03 14:49:14 +010034 graph_ = CreateGraph();
Vladimir Markoa0431112018-06-25 09:32:54 +010035 codegen_.reset(
36 new (graph_->GetAllocator()) mips::CodeGeneratorMIPS(graph_, *compiler_options_));
Vladimir Markoca6fff82017-10-03 14:49:14 +010037 moves_ = new (GetAllocator()) HParallelMove(GetAllocator());
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020038 test_helper_.reset(
39 new AssemblerTestInfrastructure(GetArchitectureString(),
40 GetAssemblerCmdName(),
41 GetAssemblerParameters(),
42 GetObjdumpCmdName(),
43 GetObjdumpParameters(),
44 GetDisassembleCmdName(),
45 GetDisassembleParameters(),
46 GetAssemblyHeader()));
47 }
48
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010049 void TearDown() override {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020050 test_helper_.reset();
Vladimir Markoa0431112018-06-25 09:32:54 +010051 codegen_.reset();
52 graph_ = nullptr;
Vladimir Markoca6fff82017-10-03 14:49:14 +010053 ResetPoolAndAllocator();
Vladimir Markoa0431112018-06-25 09:32:54 +010054 OptimizingUnitTest::TearDown();
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020055 }
56
57 // Get the typically used name for this architecture.
58 std::string GetArchitectureString() {
59 return "mips";
60 }
61
62 // Get the name of the assembler.
63 std::string GetAssemblerCmdName() {
64 return "as";
65 }
66
67 // Switches to the assembler command.
68 std::string GetAssemblerParameters() {
69 return " --no-warn -32 -march=mips32r2";
70 }
71
72 // Get the name of the objdump.
73 std::string GetObjdumpCmdName() {
74 return "objdump";
75 }
76
77 // Switches to the objdump command.
78 std::string GetObjdumpParameters() {
79 return " -h";
80 }
81
82 // Get the name of the objdump.
83 std::string GetDisassembleCmdName() {
84 return "objdump";
85 }
86
87 // Switches to the objdump command.
88 std::string GetDisassembleParameters() {
89 return " -D -bbinary -mmips:isa32r2";
90 }
91
92 // No need for assembly header here.
93 const char* GetAssemblyHeader() {
94 return nullptr;
95 }
96
Andreas Gampe641a4732017-08-24 13:21:35 -070097 void DriverWrapper(HParallelMove* move,
98 const std::string& assembly_text,
99 const std::string& test_name) {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200100 codegen_->GetMoveResolver()->EmitNativeCode(move);
101 assembler_ = codegen_->GetAssembler();
102 assembler_->FinalizeCode();
103 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(assembler_->CodeSize()));
104 MemoryRegion code(&(*data)[0], data->size());
105 assembler_->FinalizeInstructions(code);
106 test_helper_->Driver(*data, assembly_text, test_name);
107 }
108
109 protected:
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200110 HGraph* graph_;
111 HParallelMove* moves_;
Vladimir Markoa0431112018-06-25 09:32:54 +0100112 std::unique_ptr<mips::CodeGeneratorMIPS> codegen_;
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200113 mips::MipsAssembler* assembler_;
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200114 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200115};
116
117TEST_F(EmitSwapMipsTest, TwoRegisters) {
118 moves_->AddMove(
119 Location::RegisterLocation(4),
120 Location::RegisterLocation(5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100121 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200122 nullptr);
123 moves_->AddMove(
124 Location::RegisterLocation(5),
125 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100126 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200127 nullptr);
128 const char* expected =
129 "or $t8, $a1, $zero\n"
130 "or $a1, $a0, $zero\n"
131 "or $a0, $t8, $zero\n";
132 DriverWrapper(moves_, expected, "TwoRegisters");
133}
134
135TEST_F(EmitSwapMipsTest, TwoRegisterPairs) {
136 moves_->AddMove(
137 Location::RegisterPairLocation(4, 5),
138 Location::RegisterPairLocation(6, 7),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100139 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200140 nullptr);
141 moves_->AddMove(
142 Location::RegisterPairLocation(6, 7),
143 Location::RegisterPairLocation(4, 5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100144 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200145 nullptr);
146 const char* expected =
147 "or $t8, $a2, $zero\n"
148 "or $a2, $a0, $zero\n"
149 "or $a0, $t8, $zero\n"
150 "or $t8, $a3, $zero\n"
151 "or $a3, $a1, $zero\n"
152 "or $a1, $t8, $zero\n";
153 DriverWrapper(moves_, expected, "TwoRegisterPairs");
154}
155
156TEST_F(EmitSwapMipsTest, TwoFpuRegistersFloat) {
157 moves_->AddMove(
158 Location::FpuRegisterLocation(4),
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800159 Location::FpuRegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100160 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200161 nullptr);
162 moves_->AddMove(
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800163 Location::FpuRegisterLocation(2),
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200164 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100165 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200166 nullptr);
167 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800168 "mov.s $f6, $f2\n"
169 "mov.s $f2, $f4\n"
170 "mov.s $f4, $f6\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200171 DriverWrapper(moves_, expected, "TwoFpuRegistersFloat");
172}
173
174TEST_F(EmitSwapMipsTest, TwoFpuRegistersDouble) {
175 moves_->AddMove(
176 Location::FpuRegisterLocation(4),
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800177 Location::FpuRegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100178 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200179 nullptr);
180 moves_->AddMove(
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800181 Location::FpuRegisterLocation(2),
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200182 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100183 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200184 nullptr);
185 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800186 "mov.d $f6, $f2\n"
187 "mov.d $f2, $f4\n"
188 "mov.d $f4, $f6\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200189 DriverWrapper(moves_, expected, "TwoFpuRegistersDouble");
190}
191
192TEST_F(EmitSwapMipsTest, RegisterAndFpuRegister) {
193 moves_->AddMove(
194 Location::RegisterLocation(4),
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800195 Location::FpuRegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100196 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200197 nullptr);
198 moves_->AddMove(
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800199 Location::FpuRegisterLocation(2),
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200200 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100201 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200202 nullptr);
203 const char* expected =
204 "or $t8, $a0, $zero\n"
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800205 "mfc1 $a0, $f2\n"
206 "mtc1 $t8, $f2\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200207 DriverWrapper(moves_, expected, "RegisterAndFpuRegister");
208}
209
210TEST_F(EmitSwapMipsTest, RegisterPairAndFpuRegister) {
211 moves_->AddMove(
212 Location::RegisterPairLocation(4, 5),
213 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100214 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200215 nullptr);
216 moves_->AddMove(
217 Location::FpuRegisterLocation(4),
218 Location::RegisterPairLocation(4, 5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100219 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200220 nullptr);
221 const char* expected =
222 "mfc1 $t8, $f4\n"
223 "mfc1 $at, $f5\n"
224 "mtc1 $a0, $f4\n"
225 "mtc1 $a1, $f5\n"
226 "or $a0, $t8, $zero\n"
227 "or $a1, $at, $zero\n";
228 DriverWrapper(moves_, expected, "RegisterPairAndFpuRegister");
229}
230
231TEST_F(EmitSwapMipsTest, TwoStackSlots) {
232 moves_->AddMove(
233 Location::StackSlot(52),
234 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100235 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200236 nullptr);
237 moves_->AddMove(
238 Location::StackSlot(48),
239 Location::StackSlot(52),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100240 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200241 nullptr);
242 const char* expected =
Chris Larsen715f43e2017-10-23 11:00:32 -0700243 "addiu $sp, $sp, -16\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200244 "sw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700245 "lw $v0, 68($sp)\n"
246 "lw $t8, 64($sp)\n"
247 "sw $v0, 64($sp)\n"
248 "sw $t8, 68($sp)\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200249 "lw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700250 "addiu $sp, $sp, 16\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200251 DriverWrapper(moves_, expected, "TwoStackSlots");
252}
253
254TEST_F(EmitSwapMipsTest, TwoDoubleStackSlots) {
255 moves_->AddMove(
256 Location::DoubleStackSlot(56),
257 Location::DoubleStackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100258 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200259 nullptr);
260 moves_->AddMove(
261 Location::DoubleStackSlot(48),
262 Location::DoubleStackSlot(56),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100263 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200264 nullptr);
265 const char* expected =
Chris Larsen715f43e2017-10-23 11:00:32 -0700266 "addiu $sp, $sp, -16\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200267 "sw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700268 "lw $v0, 72($sp)\n"
269 "lw $t8, 64($sp)\n"
270 "sw $v0, 64($sp)\n"
271 "sw $t8, 72($sp)\n"
272 "lw $v0, 76($sp)\n"
273 "lw $t8, 68($sp)\n"
274 "sw $v0, 68($sp)\n"
275 "sw $t8, 76($sp)\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200276 "lw $v0, 0($sp)\n"
Chris Larsen715f43e2017-10-23 11:00:32 -0700277 "addiu $sp, $sp, 16\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200278 DriverWrapper(moves_, expected, "TwoDoubleStackSlots");
279}
280
281TEST_F(EmitSwapMipsTest, RegisterAndStackSlot) {
282 moves_->AddMove(
283 Location::RegisterLocation(4),
284 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100285 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200286 nullptr);
287 moves_->AddMove(
288 Location::StackSlot(48),
289 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100290 DataType::Type::kInt32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200291 nullptr);
292 const char* expected =
293 "or $t8, $a0, $zero\n"
294 "lw $a0, 48($sp)\n"
295 "sw $t8, 48($sp)\n";
296 DriverWrapper(moves_, expected, "RegisterAndStackSlot");
297}
298
299TEST_F(EmitSwapMipsTest, RegisterPairAndDoubleStackSlot) {
300 moves_->AddMove(
301 Location::RegisterPairLocation(4, 5),
302 Location::DoubleStackSlot(32),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100303 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200304 nullptr);
305 moves_->AddMove(
306 Location::DoubleStackSlot(32),
307 Location::RegisterPairLocation(4, 5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100308 DataType::Type::kInt64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200309 nullptr);
310 const char* expected =
311 "or $t8, $a0, $zero\n"
312 "lw $a0, 32($sp)\n"
313 "sw $t8, 32($sp)\n"
314 "or $t8, $a1, $zero\n"
315 "lw $a1, 36($sp)\n"
316 "sw $t8, 36($sp)\n";
317 DriverWrapper(moves_, expected, "RegisterPairAndDoubleStackSlot");
318}
319
320TEST_F(EmitSwapMipsTest, FpuRegisterAndStackSlot) {
321 moves_->AddMove(
322 Location::FpuRegisterLocation(4),
323 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100324 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200325 nullptr);
326 moves_->AddMove(
327 Location::StackSlot(48),
328 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100329 DataType::Type::kFloat32,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200330 nullptr);
331 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800332 "mov.s $f6, $f4\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200333 "lwc1 $f4, 48($sp)\n"
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800334 "swc1 $f6, 48($sp)\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200335 DriverWrapper(moves_, expected, "FpuRegisterAndStackSlot");
336}
337
338TEST_F(EmitSwapMipsTest, FpuRegisterAndDoubleStackSlot) {
339 moves_->AddMove(
340 Location::FpuRegisterLocation(4),
341 Location::DoubleStackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100342 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200343 nullptr);
344 moves_->AddMove(
345 Location::DoubleStackSlot(48),
346 Location::FpuRegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100347 DataType::Type::kFloat64,
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200348 nullptr);
349 const char* expected =
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800350 "mov.d $f6, $f4\n"
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200351 "ldc1 $f4, 48($sp)\n"
Alexey Frunze1b8464d2016-11-12 17:22:05 -0800352 "sdc1 $f6, 48($sp)\n";
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +0200353 DriverWrapper(moves_, expected, "FpuRegisterAndDoubleStackSlot");
354}
355
356} // namespace art