blob: 9dc53e68117e74b744e1725d9e919803c8e3dab3 [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
94 void DriverWrapper(HParallelMove* move, std::string assembly_text, std::string test_name) {
95 codegen_->GetMoveResolver()->EmitNativeCode(move);
96 assembler_ = codegen_->GetAssembler();
97 assembler_->FinalizeCode();
98 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(assembler_->CodeSize()));
99 MemoryRegion code(&(*data)[0], data->size());
100 assembler_->FinalizeInstructions(code);
101 test_helper_->Driver(*data, assembly_text, test_name);
102 }
103
104 protected:
105 ArenaPool pool_;
106 HGraph* graph_;
107 HParallelMove* moves_;
108 mips::CodeGeneratorMIPS* codegen_;
109 mips::MipsAssembler* assembler_;
110 std::unique_ptr<ArenaAllocator> allocator_;
111 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
112 std::unique_ptr<const MipsInstructionSetFeatures> isa_features_;
113};
114
115TEST_F(EmitSwapMipsTest, TwoRegisters) {
116 moves_->AddMove(
117 Location::RegisterLocation(4),
118 Location::RegisterLocation(5),
119 Primitive::kPrimInt,
120 nullptr);
121 moves_->AddMove(
122 Location::RegisterLocation(5),
123 Location::RegisterLocation(4),
124 Primitive::kPrimInt,
125 nullptr);
126 const char* expected =
127 "or $t8, $a1, $zero\n"
128 "or $a1, $a0, $zero\n"
129 "or $a0, $t8, $zero\n";
130 DriverWrapper(moves_, expected, "TwoRegisters");
131}
132
133TEST_F(EmitSwapMipsTest, TwoRegisterPairs) {
134 moves_->AddMove(
135 Location::RegisterPairLocation(4, 5),
136 Location::RegisterPairLocation(6, 7),
137 Primitive::kPrimLong,
138 nullptr);
139 moves_->AddMove(
140 Location::RegisterPairLocation(6, 7),
141 Location::RegisterPairLocation(4, 5),
142 Primitive::kPrimLong,
143 nullptr);
144 const char* expected =
145 "or $t8, $a2, $zero\n"
146 "or $a2, $a0, $zero\n"
147 "or $a0, $t8, $zero\n"
148 "or $t8, $a3, $zero\n"
149 "or $a3, $a1, $zero\n"
150 "or $a1, $t8, $zero\n";
151 DriverWrapper(moves_, expected, "TwoRegisterPairs");
152}
153
154TEST_F(EmitSwapMipsTest, TwoFpuRegistersFloat) {
155 moves_->AddMove(
156 Location::FpuRegisterLocation(4),
157 Location::FpuRegisterLocation(6),
158 Primitive::kPrimFloat,
159 nullptr);
160 moves_->AddMove(
161 Location::FpuRegisterLocation(6),
162 Location::FpuRegisterLocation(4),
163 Primitive::kPrimFloat,
164 nullptr);
165 const char* expected =
166 "mov.s $f8, $f6\n"
167 "mov.s $f6, $f4\n"
168 "mov.s $f4, $f8\n";
169 DriverWrapper(moves_, expected, "TwoFpuRegistersFloat");
170}
171
172TEST_F(EmitSwapMipsTest, TwoFpuRegistersDouble) {
173 moves_->AddMove(
174 Location::FpuRegisterLocation(4),
175 Location::FpuRegisterLocation(6),
176 Primitive::kPrimDouble,
177 nullptr);
178 moves_->AddMove(
179 Location::FpuRegisterLocation(6),
180 Location::FpuRegisterLocation(4),
181 Primitive::kPrimDouble,
182 nullptr);
183 const char* expected =
184 "mov.d $f8, $f6\n"
185 "mov.d $f6, $f4\n"
186 "mov.d $f4, $f8\n";
187 DriverWrapper(moves_, expected, "TwoFpuRegistersDouble");
188}
189
190TEST_F(EmitSwapMipsTest, RegisterAndFpuRegister) {
191 moves_->AddMove(
192 Location::RegisterLocation(4),
193 Location::FpuRegisterLocation(6),
194 Primitive::kPrimFloat,
195 nullptr);
196 moves_->AddMove(
197 Location::FpuRegisterLocation(6),
198 Location::RegisterLocation(4),
199 Primitive::kPrimFloat,
200 nullptr);
201 const char* expected =
202 "or $t8, $a0, $zero\n"
203 "mfc1 $a0, $f6\n"
204 "mtc1 $t8, $f6\n";
205 DriverWrapper(moves_, expected, "RegisterAndFpuRegister");
206}
207
208TEST_F(EmitSwapMipsTest, RegisterPairAndFpuRegister) {
209 moves_->AddMove(
210 Location::RegisterPairLocation(4, 5),
211 Location::FpuRegisterLocation(4),
212 Primitive::kPrimDouble,
213 nullptr);
214 moves_->AddMove(
215 Location::FpuRegisterLocation(4),
216 Location::RegisterPairLocation(4, 5),
217 Primitive::kPrimDouble,
218 nullptr);
219 const char* expected =
220 "mfc1 $t8, $f4\n"
221 "mfc1 $at, $f5\n"
222 "mtc1 $a0, $f4\n"
223 "mtc1 $a1, $f5\n"
224 "or $a0, $t8, $zero\n"
225 "or $a1, $at, $zero\n";
226 DriverWrapper(moves_, expected, "RegisterPairAndFpuRegister");
227}
228
229TEST_F(EmitSwapMipsTest, TwoStackSlots) {
230 moves_->AddMove(
231 Location::StackSlot(52),
232 Location::StackSlot(48),
233 Primitive::kPrimInt,
234 nullptr);
235 moves_->AddMove(
236 Location::StackSlot(48),
237 Location::StackSlot(52),
238 Primitive::kPrimInt,
239 nullptr);
240 const char* expected =
241 "addiu $sp, $sp, -4\n"
242 "sw $v0, 0($sp)\n"
243 "lw $v0, 56($sp)\n"
244 "lw $t8, 52($sp)\n"
245 "sw $v0, 52($sp)\n"
246 "sw $t8, 56($sp)\n"
247 "lw $v0, 0($sp)\n"
248 "addiu $sp, $sp, 4\n";
249 DriverWrapper(moves_, expected, "TwoStackSlots");
250}
251
252TEST_F(EmitSwapMipsTest, TwoDoubleStackSlots) {
253 moves_->AddMove(
254 Location::DoubleStackSlot(56),
255 Location::DoubleStackSlot(48),
256 Primitive::kPrimLong,
257 nullptr);
258 moves_->AddMove(
259 Location::DoubleStackSlot(48),
260 Location::DoubleStackSlot(56),
261 Primitive::kPrimLong,
262 nullptr);
263 const char* expected =
264 "addiu $sp, $sp, -4\n"
265 "sw $v0, 0($sp)\n"
266 "lw $v0, 60($sp)\n"
267 "lw $t8, 52($sp)\n"
268 "sw $v0, 52($sp)\n"
269 "sw $t8, 60($sp)\n"
270 "lw $v0, 64($sp)\n"
271 "lw $t8, 56($sp)\n"
272 "sw $v0, 56($sp)\n"
273 "sw $t8, 64($sp)\n"
274 "lw $v0, 0($sp)\n"
275 "addiu $sp, $sp, 4\n";
276 DriverWrapper(moves_, expected, "TwoDoubleStackSlots");
277}
278
279TEST_F(EmitSwapMipsTest, RegisterAndStackSlot) {
280 moves_->AddMove(
281 Location::RegisterLocation(4),
282 Location::StackSlot(48),
283 Primitive::kPrimInt,
284 nullptr);
285 moves_->AddMove(
286 Location::StackSlot(48),
287 Location::RegisterLocation(4),
288 Primitive::kPrimInt,
289 nullptr);
290 const char* expected =
291 "or $t8, $a0, $zero\n"
292 "lw $a0, 48($sp)\n"
293 "sw $t8, 48($sp)\n";
294 DriverWrapper(moves_, expected, "RegisterAndStackSlot");
295}
296
297TEST_F(EmitSwapMipsTest, RegisterPairAndDoubleStackSlot) {
298 moves_->AddMove(
299 Location::RegisterPairLocation(4, 5),
300 Location::DoubleStackSlot(32),
301 Primitive::kPrimLong,
302 nullptr);
303 moves_->AddMove(
304 Location::DoubleStackSlot(32),
305 Location::RegisterPairLocation(4, 5),
306 Primitive::kPrimLong,
307 nullptr);
308 const char* expected =
309 "or $t8, $a0, $zero\n"
310 "lw $a0, 32($sp)\n"
311 "sw $t8, 32($sp)\n"
312 "or $t8, $a1, $zero\n"
313 "lw $a1, 36($sp)\n"
314 "sw $t8, 36($sp)\n";
315 DriverWrapper(moves_, expected, "RegisterPairAndDoubleStackSlot");
316}
317
318TEST_F(EmitSwapMipsTest, FpuRegisterAndStackSlot) {
319 moves_->AddMove(
320 Location::FpuRegisterLocation(4),
321 Location::StackSlot(48),
322 Primitive::kPrimFloat,
323 nullptr);
324 moves_->AddMove(
325 Location::StackSlot(48),
326 Location::FpuRegisterLocation(4),
327 Primitive::kPrimFloat,
328 nullptr);
329 const char* expected =
330 "mov.s $f8, $f4\n"
331 "lwc1 $f4, 48($sp)\n"
332 "swc1 $f8, 48($sp)\n";
333 DriverWrapper(moves_, expected, "FpuRegisterAndStackSlot");
334}
335
336TEST_F(EmitSwapMipsTest, FpuRegisterAndDoubleStackSlot) {
337 moves_->AddMove(
338 Location::FpuRegisterLocation(4),
339 Location::DoubleStackSlot(48),
340 Primitive::kPrimDouble,
341 nullptr);
342 moves_->AddMove(
343 Location::DoubleStackSlot(48),
344 Location::FpuRegisterLocation(4),
345 Primitive::kPrimDouble,
346 nullptr);
347 const char* expected =
348 "mov.d $f8, $f4\n"
349 "ldc1 $f4, 48($sp)\n"
350 "sdc1 $f8, 48($sp)\n";
351 DriverWrapper(moves_, expected, "FpuRegisterAndDoubleStackSlot");
352}
353
354} // namespace art