blob: 0e9c81dae36350406e8817cc6616f2491997a586 [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
28class EmitSwapMipsTest : public ::testing::Test {
29 public:
30 void SetUp() OVERRIDE {
31 allocator_.reset(new ArenaAllocator(&pool_));
32 graph_ = CreateGraph(allocator_.get());
33 isa_features_ = MipsInstructionSetFeatures::FromCppDefines();
34 codegen_ = new (graph_->GetArena()) mips::CodeGeneratorMIPS(graph_,
35 *isa_features_.get(),
36 CompilerOptions());
37 moves_ = new (allocator_.get()) HParallelMove(allocator_.get());
38 test_helper_.reset(
39 new AssemblerTestInfrastructure(GetArchitectureString(),
40 GetAssemblerCmdName(),
41 GetAssemblerParameters(),
42 GetObjdumpCmdName(),
43 GetObjdumpParameters(),
44 GetDisassembleCmdName(),
45 GetDisassembleParameters(),
46 GetAssemblyHeader()));
47 }
48
49 void TearDown() OVERRIDE {
50 allocator_.reset();
51 test_helper_.reset();
52 }
53
54 // Get the typically used name for this architecture.
55 std::string GetArchitectureString() {
56 return "mips";
57 }
58
59 // Get the name of the assembler.
60 std::string GetAssemblerCmdName() {
61 return "as";
62 }
63
64 // Switches to the assembler command.
65 std::string GetAssemblerParameters() {
66 return " --no-warn -32 -march=mips32r2";
67 }
68
69 // Get the name of the objdump.
70 std::string GetObjdumpCmdName() {
71 return "objdump";
72 }
73
74 // Switches to the objdump command.
75 std::string GetObjdumpParameters() {
76 return " -h";
77 }
78
79 // Get the name of the objdump.
80 std::string GetDisassembleCmdName() {
81 return "objdump";
82 }
83
84 // Switches to the objdump command.
85 std::string GetDisassembleParameters() {
86 return " -D -bbinary -mmips:isa32r2";
87 }
88
89 // No need for assembly header here.
90 const char* GetAssemblyHeader() {
91 return nullptr;
92 }
93
Andreas Gampe641a4732017-08-24 13:21:35 -070094 void DriverWrapper(HParallelMove* move,
95 const std::string& assembly_text,
96 const std::string& test_name) {
Goran Jakovljevic35dfcaa2016-09-22 09:26:01 +020097 codegen_->GetMoveResolver()->EmitNativeCode(move);
98 assembler_ = codegen_->GetAssembler();
99 assembler_->FinalizeCode();
100 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(assembler_->CodeSize()));
101 MemoryRegion code(&(*data)[0], data->size());
102 assembler_->FinalizeInstructions(code);
103 test_helper_->Driver(*data, assembly_text, test_name);
104 }
105
106 protected:
107 ArenaPool pool_;
108 HGraph* graph_;
109 HParallelMove* moves_;
110 mips::CodeGeneratorMIPS* codegen_;
111 mips::MipsAssembler* assembler_;
112 std::unique_ptr<ArenaAllocator> allocator_;
113 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
114 std::unique_ptr<const MipsInstructionSetFeatures> isa_features_;
115};
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 =
243 "addiu $sp, $sp, -4\n"
244 "sw $v0, 0($sp)\n"
245 "lw $v0, 56($sp)\n"
246 "lw $t8, 52($sp)\n"
247 "sw $v0, 52($sp)\n"
248 "sw $t8, 56($sp)\n"
249 "lw $v0, 0($sp)\n"
250 "addiu $sp, $sp, 4\n";
251 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 =
266 "addiu $sp, $sp, -4\n"
267 "sw $v0, 0($sp)\n"
268 "lw $v0, 60($sp)\n"
269 "lw $t8, 52($sp)\n"
270 "sw $v0, 52($sp)\n"
271 "sw $t8, 60($sp)\n"
272 "lw $v0, 64($sp)\n"
273 "lw $t8, 56($sp)\n"
274 "sw $v0, 56($sp)\n"
275 "sw $t8, 64($sp)\n"
276 "lw $v0, 0($sp)\n"
277 "addiu $sp, $sp, 4\n";
278 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