• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 "codegen_mips.h"
18 #include "dex/quick/mir_to_lir-inl.h"
19 #include "entrypoints/quick/quick_entrypoints.h"
20 #include "mips_lir.h"
21 
22 namespace art {
23 
GenArithOpFloat(Instruction::Code opcode,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)24 void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode,
25                                   RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
26   int op = kMipsNop;
27   RegLocation rl_result;
28 
29   /*
30    * Don't attempt to optimize register usage since these opcodes call out to
31    * the handlers.
32    */
33   switch (opcode) {
34     case Instruction::ADD_FLOAT_2ADDR:
35     case Instruction::ADD_FLOAT:
36       op = kMipsFadds;
37       break;
38     case Instruction::SUB_FLOAT_2ADDR:
39     case Instruction::SUB_FLOAT:
40       op = kMipsFsubs;
41       break;
42     case Instruction::DIV_FLOAT_2ADDR:
43     case Instruction::DIV_FLOAT:
44       op = kMipsFdivs;
45       break;
46     case Instruction::MUL_FLOAT_2ADDR:
47     case Instruction::MUL_FLOAT:
48       op = kMipsFmuls;
49       break;
50     case Instruction::REM_FLOAT_2ADDR:
51     case Instruction::REM_FLOAT:
52       FlushAllRegs();   // Send everything to home location
53       CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
54       rl_result = GetReturn(kFPReg);
55       StoreValue(rl_dest, rl_result);
56       return;
57     case Instruction::NEG_FLOAT:
58       GenNegFloat(rl_dest, rl_src1);
59       return;
60     default:
61       LOG(FATAL) << "Unexpected opcode: " << opcode;
62   }
63   rl_src1 = LoadValue(rl_src1, kFPReg);
64   rl_src2 = LoadValue(rl_src2, kFPReg);
65   rl_result = EvalLoc(rl_dest, kFPReg, true);
66   NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
67   StoreValue(rl_dest, rl_result);
68 }
69 
GenArithOpDouble(Instruction::Code opcode,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)70 void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode,
71                                    RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
72   int op = kMipsNop;
73   RegLocation rl_result;
74 
75   switch (opcode) {
76     case Instruction::ADD_DOUBLE_2ADDR:
77     case Instruction::ADD_DOUBLE:
78       op = kMipsFaddd;
79       break;
80     case Instruction::SUB_DOUBLE_2ADDR:
81     case Instruction::SUB_DOUBLE:
82       op = kMipsFsubd;
83       break;
84     case Instruction::DIV_DOUBLE_2ADDR:
85     case Instruction::DIV_DOUBLE:
86       op = kMipsFdivd;
87       break;
88     case Instruction::MUL_DOUBLE_2ADDR:
89     case Instruction::MUL_DOUBLE:
90       op = kMipsFmuld;
91       break;
92     case Instruction::REM_DOUBLE_2ADDR:
93     case Instruction::REM_DOUBLE:
94       FlushAllRegs();   // Send everything to home location
95       CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
96       rl_result = GetReturnWide(kFPReg);
97       StoreValueWide(rl_dest, rl_result);
98       return;
99     case Instruction::NEG_DOUBLE:
100       GenNegDouble(rl_dest, rl_src1);
101       return;
102     default:
103       LOG(FATAL) << "Unpexpected opcode: " << opcode;
104   }
105   rl_src1 = LoadValueWide(rl_src1, kFPReg);
106   DCHECK(rl_src1.wide);
107   rl_src2 = LoadValueWide(rl_src2, kFPReg);
108   DCHECK(rl_src2.wide);
109   rl_result = EvalLoc(rl_dest, kFPReg, true);
110   DCHECK(rl_dest.wide);
111   DCHECK(rl_result.wide);
112   NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
113   StoreValueWide(rl_dest, rl_result);
114 }
115 
GenConversion(Instruction::Code opcode,RegLocation rl_dest,RegLocation rl_src)116 void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
117                                 RegLocation rl_src) {
118   int op = kMipsNop;
119   RegLocation rl_result;
120   switch (opcode) {
121     case Instruction::INT_TO_FLOAT:
122       op = kMipsFcvtsw;
123       break;
124     case Instruction::DOUBLE_TO_FLOAT:
125       op = kMipsFcvtsd;
126       break;
127     case Instruction::FLOAT_TO_DOUBLE:
128       op = kMipsFcvtds;
129       break;
130     case Instruction::INT_TO_DOUBLE:
131       op = kMipsFcvtdw;
132       break;
133     case Instruction::FLOAT_TO_INT:
134       GenConversionCall(kQuickF2iz, rl_dest, rl_src);
135       return;
136     case Instruction::DOUBLE_TO_INT:
137       GenConversionCall(kQuickD2iz, rl_dest, rl_src);
138       return;
139     case Instruction::LONG_TO_DOUBLE:
140       GenConversionCall(kQuickL2d, rl_dest, rl_src);
141       return;
142     case Instruction::FLOAT_TO_LONG:
143       GenConversionCall(kQuickF2l, rl_dest, rl_src);
144       return;
145     case Instruction::LONG_TO_FLOAT:
146       GenConversionCall(kQuickL2f, rl_dest, rl_src);
147       return;
148     case Instruction::DOUBLE_TO_LONG:
149       GenConversionCall(kQuickD2l, rl_dest, rl_src);
150       return;
151     default:
152       LOG(FATAL) << "Unexpected opcode: " << opcode;
153   }
154   if (rl_src.wide) {
155     rl_src = LoadValueWide(rl_src, kFPReg);
156   } else {
157     rl_src = LoadValue(rl_src, kFPReg);
158   }
159   rl_result = EvalLoc(rl_dest, kFPReg, true);
160   NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
161   if (rl_dest.wide) {
162     StoreValueWide(rl_dest, rl_result);
163   } else {
164     StoreValue(rl_dest, rl_result);
165   }
166 }
167 
GenCmpFP(Instruction::Code opcode,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)168 void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
169                            RegLocation rl_src1, RegLocation rl_src2) {
170   bool wide = true;
171   QuickEntrypointEnum target;
172 
173   switch (opcode) {
174     case Instruction::CMPL_FLOAT:
175       target = kQuickCmplFloat;
176       wide = false;
177       break;
178     case Instruction::CMPG_FLOAT:
179       target = kQuickCmpgFloat;
180       wide = false;
181       break;
182     case Instruction::CMPL_DOUBLE:
183       target = kQuickCmplDouble;
184       break;
185     case Instruction::CMPG_DOUBLE:
186       target = kQuickCmpgDouble;
187       break;
188     default:
189       LOG(FATAL) << "Unexpected opcode: " << opcode;
190       target = kQuickCmplFloat;
191   }
192   FlushAllRegs();
193   LockCallTemps();
194   if (wide) {
195     RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
196     RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
197     LoadValueDirectWideFixed(rl_src1, r_tmp1);
198     LoadValueDirectWideFixed(rl_src2, r_tmp2);
199   } else {
200     LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
201     LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
202   }
203   RegStorage r_tgt = LoadHelper(target);
204   // NOTE: not a safepoint
205   OpReg(kOpBlx, r_tgt);
206   RegLocation rl_result = GetReturn(kCoreReg);
207   StoreValue(rl_dest, rl_result);
208 }
209 
GenFusedFPCmpBranch(BasicBlock * bb,MIR * mir,bool gt_bias,bool is_double)210 void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir,
211                                 bool gt_bias, bool is_double) {
212   UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
213 }
214 
GenNegFloat(RegLocation rl_dest,RegLocation rl_src)215 void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
216   RegLocation rl_result;
217   rl_src = LoadValue(rl_src, kCoreReg);
218   rl_result = EvalLoc(rl_dest, kCoreReg, true);
219   OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
220   StoreValue(rl_dest, rl_result);
221 }
222 
GenNegDouble(RegLocation rl_dest,RegLocation rl_src)223 void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
224   RegLocation rl_result;
225   rl_src = LoadValueWide(rl_src, kCoreReg);
226   rl_result = EvalLoc(rl_dest, kCoreReg, true);
227   OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
228   OpRegCopy(rl_result.reg, rl_src.reg);
229   StoreValueWide(rl_dest, rl_result);
230 }
231 
GenInlinedMinMax(CallInfo * info,bool is_min,bool is_long)232 bool MipsMir2Lir::GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) {
233   // TODO: need Mips implementation
234   return false;
235 }
236 
237 }  // namespace art
238