• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
26 namespace art {
27 
28 class EmitSwapMipsTest : public ::testing::Test {
29  public:
SetUp()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 
TearDown()49   void TearDown() OVERRIDE {
50     allocator_.reset();
51     test_helper_.reset();
52   }
53 
54   // Get the typically used name for this architecture.
GetArchitectureString()55   std::string GetArchitectureString() {
56     return "mips";
57   }
58 
59   // Get the name of the assembler.
GetAssemblerCmdName()60   std::string GetAssemblerCmdName() {
61     return "as";
62   }
63 
64   // Switches to the assembler command.
GetAssemblerParameters()65   std::string GetAssemblerParameters() {
66     return " --no-warn -32 -march=mips32r2";
67   }
68 
69   // Get the name of the objdump.
GetObjdumpCmdName()70   std::string GetObjdumpCmdName() {
71     return "objdump";
72   }
73 
74   // Switches to the objdump command.
GetObjdumpParameters()75   std::string GetObjdumpParameters() {
76     return " -h";
77   }
78 
79   // Get the name of the objdump.
GetDisassembleCmdName()80   std::string GetDisassembleCmdName() {
81     return "objdump";
82   }
83 
84   // Switches to the objdump command.
GetDisassembleParameters()85   std::string GetDisassembleParameters() {
86     return " -D -bbinary -mmips:isa32r2";
87   }
88 
89   // No need for assembly header here.
GetAssemblyHeader()90   const char* GetAssemblyHeader() {
91     return nullptr;
92   }
93 
DriverWrapper(HParallelMove * move,std::string assembly_text,std::string test_name)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 
TEST_F(EmitSwapMipsTest,TwoRegisters)115 TEST_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 
TEST_F(EmitSwapMipsTest,TwoRegisterPairs)133 TEST_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 
TEST_F(EmitSwapMipsTest,TwoFpuRegistersFloat)154 TEST_F(EmitSwapMipsTest, TwoFpuRegistersFloat) {
155   moves_->AddMove(
156       Location::FpuRegisterLocation(4),
157       Location::FpuRegisterLocation(2),
158       Primitive::kPrimFloat,
159       nullptr);
160   moves_->AddMove(
161       Location::FpuRegisterLocation(2),
162       Location::FpuRegisterLocation(4),
163       Primitive::kPrimFloat,
164       nullptr);
165   const char* expected =
166       "mov.s $f6, $f2\n"
167       "mov.s $f2, $f4\n"
168       "mov.s $f4, $f6\n";
169   DriverWrapper(moves_, expected, "TwoFpuRegistersFloat");
170 }
171 
TEST_F(EmitSwapMipsTest,TwoFpuRegistersDouble)172 TEST_F(EmitSwapMipsTest, TwoFpuRegistersDouble) {
173   moves_->AddMove(
174       Location::FpuRegisterLocation(4),
175       Location::FpuRegisterLocation(2),
176       Primitive::kPrimDouble,
177       nullptr);
178   moves_->AddMove(
179       Location::FpuRegisterLocation(2),
180       Location::FpuRegisterLocation(4),
181       Primitive::kPrimDouble,
182       nullptr);
183   const char* expected =
184       "mov.d $f6, $f2\n"
185       "mov.d $f2, $f4\n"
186       "mov.d $f4, $f6\n";
187   DriverWrapper(moves_, expected, "TwoFpuRegistersDouble");
188 }
189 
TEST_F(EmitSwapMipsTest,RegisterAndFpuRegister)190 TEST_F(EmitSwapMipsTest, RegisterAndFpuRegister) {
191   moves_->AddMove(
192       Location::RegisterLocation(4),
193       Location::FpuRegisterLocation(2),
194       Primitive::kPrimFloat,
195       nullptr);
196   moves_->AddMove(
197       Location::FpuRegisterLocation(2),
198       Location::RegisterLocation(4),
199       Primitive::kPrimFloat,
200       nullptr);
201   const char* expected =
202       "or $t8, $a0, $zero\n"
203       "mfc1 $a0, $f2\n"
204       "mtc1 $t8, $f2\n";
205   DriverWrapper(moves_, expected, "RegisterAndFpuRegister");
206 }
207 
TEST_F(EmitSwapMipsTest,RegisterPairAndFpuRegister)208 TEST_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 
TEST_F(EmitSwapMipsTest,TwoStackSlots)229 TEST_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 
TEST_F(EmitSwapMipsTest,TwoDoubleStackSlots)252 TEST_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 
TEST_F(EmitSwapMipsTest,RegisterAndStackSlot)279 TEST_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 
TEST_F(EmitSwapMipsTest,RegisterPairAndDoubleStackSlot)297 TEST_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 
TEST_F(EmitSwapMipsTest,FpuRegisterAndStackSlot)318 TEST_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 $f6, $f4\n"
331       "lwc1 $f4, 48($sp)\n"
332       "swc1 $f6, 48($sp)\n";
333   DriverWrapper(moves_, expected, "FpuRegisterAndStackSlot");
334 }
335 
TEST_F(EmitSwapMipsTest,FpuRegisterAndDoubleStackSlot)336 TEST_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 $f6, $f4\n"
349       "ldc1 $f4, 48($sp)\n"
350       "sdc1 $f6, 48($sp)\n";
351   DriverWrapper(moves_, expected, "FpuRegisterAndDoubleStackSlot");
352 }
353 
354 }  // namespace art
355