blob: 7eb2a1ae684efc1f7875002af461d47ff7a59620 [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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
17namespace art {
18
19extern void oatFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
20 int reg1, int reg2);
21extern void oatFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg);
22
23/* First, flush any registers associated with this value */
buzbee31a4a6f2012-02-28 15:36:15 -080024void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc,
buzbeee3acd072012-02-25 17:03:10 -080025 int rDest)
26{
27 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
28#if 0
29 rlSrc = rlSrc.wide ? oatUpdateLocWide(cUnit, rlSrc) :
30 oatUpdateLoc(cUnit, rlSrc);
31 if (rlSrc.location == kLocPhysReg) {
32 if (rlSrc.wide) {
33 oatFlushRegWideForV5TEVFP(cUnit, rlSrc.lowReg,
34 rlSrc.highReg);
35 } else {
36 oatFlushRegForV5TEVFP(cUnit, rlSrc.lowReg);
37 }
38 }
39 opRegRegImm(cUnit, kOpAdd, rDest, rFP,
40 oatS2VReg(cUnit, rlSrc.sRegLow) << 2);
41#endif
42}
43
44/*
45 * TUNING: On some implementations, it is quicker to pass addresses
46 * to the handlers rather than load the operands into core registers
47 * and then move the values to FP regs in the handlers. Other implementations
48 * may prefer passing data in registers (and the latter approach would
49 * yeild cleaner register handling - avoiding the requirement that operands
50 * be flushed to memory prior to the call).
51 */
52static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
53 RegLocation rlDest, RegLocation rlSrc1,
54 RegLocation rlSrc2)
55{
56#ifdef __mips_hard_float
57 int op = kMipsNop;
58 RegLocation rlResult;
59
60 /*
61 * Don't attempt to optimize register usage since these opcodes call out to
62 * the handlers.
63 */
64 switch (mir->dalvikInsn.opcode) {
65 case OP_ADD_FLOAT_2ADDR:
66 case OP_ADD_FLOAT:
67 op = kMipsFadds;
68 break;
69 case OP_SUB_FLOAT_2ADDR:
70 case OP_SUB_FLOAT:
71 op = kMipsFsubs;
72 break;
73 case OP_DIV_FLOAT_2ADDR:
74 case OP_DIV_FLOAT:
75 op = kMipsFdivs;
76 break;
77 case OP_MUL_FLOAT_2ADDR:
78 case OP_MUL_FLOAT:
79 op = kMipsFmuls;
80 break;
81 case OP_REM_FLOAT_2ADDR:
82 case OP_REM_FLOAT:
83 case OP_NEG_FLOAT: {
84 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
85 }
86 default:
87 return true;
88 }
89 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
90 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
91 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
92 newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
93 storeValue(cUnit, rlDest, rlResult);
94
95 return false;
96#else
97 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
98 return false;
99#if 0
100 TemplateOpcode opcode;
101
102 /*
103 * Don't attempt to optimize register usage since these opcodes call out to
104 * the handlers.
105 */
106 switch (mir->dalvikInsn.opcode) {
107 case OP_ADD_FLOAT_2ADDR:
108 case OP_ADD_FLOAT:
109 opcode = TEMPLATE_ADD_FLOAT_VFP;
110 break;
111 case OP_SUB_FLOAT_2ADDR:
112 case OP_SUB_FLOAT:
113 opcode = TEMPLATE_SUB_FLOAT_VFP;
114 break;
115 case OP_DIV_FLOAT_2ADDR:
116 case OP_DIV_FLOAT:
117 opcode = TEMPLATE_DIV_FLOAT_VFP;
118 break;
119 case OP_MUL_FLOAT_2ADDR:
120 case OP_MUL_FLOAT:
121 opcode = TEMPLATE_MUL_FLOAT_VFP;
122 break;
123 case OP_REM_FLOAT_2ADDR:
124 case OP_REM_FLOAT:
125 case OP_NEG_FLOAT: {
126 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
127 }
128 default:
129 return true;
130 }
131 loadValueAddress(cUnit, rlDest, r_A0);
132 oatClobber(cUnit, r_A0);
133 loadValueAddress(cUnit, rlSrc1, r_A1);
134 oatClobber(cUnit, r_A1);
135 loadValueAddress(cUnit, rlSrc2, r_A2);
136 UNIMP(FATAL) << "Need callout to handler";
137#if 0
138 genDispatchToHandler(cUnit, opcode);
139#endif
140 rlDest = oatUpdateLoc(cUnit, rlDest);
141 if (rlDest.location == kLocPhysReg) {
142 oatClobber(cUnit, rlDest.lowReg);
143 }
144 return false;
145#endif
146#endif
147}
148
149static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
150 RegLocation rlDest, RegLocation rlSrc1,
151 RegLocation rlSrc2)
152{
153#ifdef __mips_hard_float
154 int op = kMipsNop;
155 RegLocation rlResult;
156
157 switch (mir->dalvikInsn.opcode) {
158 case OP_ADD_DOUBLE_2ADDR:
159 case OP_ADD_DOUBLE:
160 op = kMipsFaddd;
161 break;
162 case OP_SUB_DOUBLE_2ADDR:
163 case OP_SUB_DOUBLE:
164 op = kMipsFsubd;
165 break;
166 case OP_DIV_DOUBLE_2ADDR:
167 case OP_DIV_DOUBLE:
168 op = kMipsFdivd;
169 break;
170 case OP_MUL_DOUBLE_2ADDR:
171 case OP_MUL_DOUBLE:
172 op = kMipsFmuld;
173 break;
174 case OP_REM_DOUBLE_2ADDR:
175 case OP_REM_DOUBLE:
176 case OP_NEG_DOUBLE: {
177 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
178 }
179 default:
180 return true;
181 }
182 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
183 DCHECK(rlSrc1.wide);
184 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
185 DCHECK(rlSrc2.wide);
186 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
187 DCHECK(rlDest.wide);
188 DCHECK(rlResult.wide);
189 newLIR3(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg),
190 S2D(rlSrc1.lowReg, rlSrc1.highReg),
191 S2D(rlSrc2.lowReg, rlSrc2.highReg));
192 storeValueWide(cUnit, rlDest, rlResult);
193 return false;
194#else
195 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
196 return false;
197#if 0
198 TemplateOpcode opcode;
199
200 switch (mir->dalvikInsn.opcode) {
201 case OP_ADD_DOUBLE_2ADDR:
202 case OP_ADD_DOUBLE:
203 opcode = TEMPLATE_ADD_DOUBLE_VFP;
204 break;
205 case OP_SUB_DOUBLE_2ADDR:
206 case OP_SUB_DOUBLE:
207 opcode = TEMPLATE_SUB_DOUBLE_VFP;
208 break;
209 case OP_DIV_DOUBLE_2ADDR:
210 case OP_DIV_DOUBLE:
211 opcode = TEMPLATE_DIV_DOUBLE_VFP;
212 break;
213 case OP_MUL_DOUBLE_2ADDR:
214 case OP_MUL_DOUBLE:
215 opcode = TEMPLATE_MUL_DOUBLE_VFP;
216 break;
217 case OP_REM_DOUBLE_2ADDR:
218 case OP_REM_DOUBLE:
219 case OP_NEG_DOUBLE: {
220 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
221 rlSrc2);
222 }
223 default:
224 return true;
225 }
226 loadValueAddress(cUnit, rlDest, r_A0);
227 oatClobber(cUnit, r_A0);
228 loadValueAddress(cUnit, rlSrc1, r_A1);
229 oatClobber(cUnit, r_A1);
230 loadValueAddress(cUnit, rlSrc2, r_A2);
231 UNIMP(FATAL) << "Need callout to handler";
232#if 0
233 genDispatchToHandler(cUnit, opcode);
234#endif
235 rlDest = oatUpdateLocWide(cUnit, rlDest);
236 if (rlDest.location == kLocPhysReg) {
237 oatClobber(cUnit, rlDest.lowReg);
238 oatClobber(cUnit, rlDest.highReg);
239 }
240 return false;
241#endif
242#endif
243}
244
245static bool genConversion(CompilationUnit *cUnit, MIR *mir)
246{
247 Opcode opcode = mir->dalvikInsn.opcode;
248 bool longSrc = false;
249 bool longDest = false;
250 RegLocation rlSrc;
251 RegLocation rlDest;
252#ifdef __mips_hard_float
253 int op = kMipsNop;
254 int srcReg;
255 RegLocation rlResult;
buzbeee3acd072012-02-25 17:03:10 -0800256 switch (opcode) {
257 case OP_INT_TO_FLOAT:
258 longSrc = false;
259 longDest = false;
260 op = kMipsFcvtsw;
261 break;
262 case OP_DOUBLE_TO_FLOAT:
263 longSrc = true;
264 longDest = false;
265 op = kMipsFcvtsd;
266 break;
267 case OP_FLOAT_TO_DOUBLE:
268 longSrc = false;
269 longDest = true;
270 op = kMipsFcvtds;
271 break;
272 case OP_INT_TO_DOUBLE:
273 longSrc = false;
274 longDest = true;
275 op = kMipsFcvtdw;
276 break;
277 case OP_FLOAT_TO_INT:
278 case OP_DOUBLE_TO_INT:
279 case OP_LONG_TO_DOUBLE:
280 case OP_FLOAT_TO_LONG:
281 case OP_LONG_TO_FLOAT:
282 case OP_DOUBLE_TO_LONG:
283 return genConversionPortable(cUnit, mir);
284 default:
285 return true;
286 }
287 if (longSrc) {
288 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
289 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
290 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
291 } else {
292 rlSrc = oatGetSrc(cUnit, mir, 0);
293 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
294 srcReg = rlSrc.lowReg;
295 }
296 if (longDest) {
297 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
298 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
299 newLIR2(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
300 storeValueWide(cUnit, rlDest, rlResult);
301 } else {
302 rlDest = oatGetDest(cUnit, mir, 0);
303 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
304 newLIR2(cUnit, (MipsOpCode)op, rlResult.lowReg, srcReg);
305 storeValue(cUnit, rlDest, rlResult);
306 }
307 return false;
308#else
309 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
310 return false;
311#if 0
312 TemplateOpcode templateOpcode;
313 switch (opcode) {
314 case OP_INT_TO_FLOAT:
315 longSrc = false;
316 longDest = false;
317 templateOpcode = TEMPLATE_INT_TO_FLOAT_VFP;
318 break;
319 case OP_FLOAT_TO_INT:
320 longSrc = false;
321 longDest = false;
322 templateOpcode = TEMPLATE_FLOAT_TO_INT_VFP;
323 break;
324 case OP_DOUBLE_TO_FLOAT:
325 longSrc = true;
326 longDest = false;
327 templateOpcode = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
328 break;
329 case OP_FLOAT_TO_DOUBLE:
330 longSrc = false;
331 longDest = true;
332 templateOpcode = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
333 break;
334 case OP_INT_TO_DOUBLE:
335 longSrc = false;
336 longDest = true;
337 templateOpcode = TEMPLATE_INT_TO_DOUBLE_VFP;
338 break;
339 case OP_DOUBLE_TO_INT:
340 longSrc = true;
341 longDest = false;
342 templateOpcode = TEMPLATE_DOUBLE_TO_INT_VFP;
343 break;
344 case OP_LONG_TO_DOUBLE:
345 case OP_FLOAT_TO_LONG:
346 case OP_LONG_TO_FLOAT:
347 case OP_DOUBLE_TO_LONG:
348 return genConversionPortable(cUnit, mir);
349 default:
350 return true;
351 }
352
353 if (longSrc) {
354 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
355 } else {
356 rlSrc = oatGetSrc(cUnit, mir, 0);
357 }
358
359 if (longDest) {
360 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
361 } else {
362 rlDest = oatGetDest(cUnit, mir, 0);
363 }
364 loadValueAddress(cUnit, rlDest, r_A0);
365 oatClobber(cUnit, r_A0);
366 loadValueAddress(cUnit, rlSrc, r_A1);
367 UNIMP(FATAL) << "Need callout to handler";
368#if 0
369 genDispatchToHandler(cUnit, templateOpcode);
370#endif
371 if (rlDest.wide) {
372 rlDest = oatUpdateLocWide(cUnit, rlDest);
373 oatClobber(cUnit, rlDest.highReg);
374 } else {
375 rlDest = oatUpdateLoc(cUnit, rlDest);
376 }
377 oatClobber(cUnit, rlDest.lowReg);
378 return false;
379#endif
380#endif
381}
382
383static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
384 RegLocation rlSrc1, RegLocation rlSrc2)
385{
386 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
387 return false;
388#if 0
389 TemplateOpcode templateOpcode;
390 RegLocation rlResult = oatGetReturn(cUnit);
391 bool wide = true;
392
393 switch(mir->dalvikInsn.opcode) {
394 case OP_CMPL_FLOAT:
395 templateOpcode = TEMPLATE_CMPL_FLOAT_VFP;
396 wide = false;
397 break;
398 case OP_CMPG_FLOAT:
399 templateOpcode = TEMPLATE_CMPG_FLOAT_VFP;
400 wide = false;
401 break;
402 case OP_CMPL_DOUBLE:
403 templateOpcode = TEMPLATE_CMPL_DOUBLE_VFP;
404 break;
405 case OP_CMPG_DOUBLE:
406 templateOpcode = TEMPLATE_CMPG_DOUBLE_VFP;
407 break;
408 default:
409 return true;
410 }
411 loadValueAddress(cUnit, rlSrc1, r_A0);
412 oatClobber(cUnit, r_A0);
413 loadValueAddress(cUnit, rlSrc2, r_A1);
414 UNIMP(FATAL) << "Need callout to handler";
415#if 0
416 genDispatchToHandler(cUnit, templateOpcode);
417#endif
418 storeValue(cUnit, rlDest, rlResult);
419 return false;
420#endif
421}
422
423} // namespace art