blob: fd07a342324f0ba9dee81f8b124cd62f21b419ee [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 */
24static void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc,
25 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;
256
257 switch (opcode) {
258 case OP_INT_TO_FLOAT:
259 longSrc = false;
260 longDest = false;
261 op = kMipsFcvtsw;
262 break;
263 case OP_DOUBLE_TO_FLOAT:
264 longSrc = true;
265 longDest = false;
266 op = kMipsFcvtsd;
267 break;
268 case OP_FLOAT_TO_DOUBLE:
269 longSrc = false;
270 longDest = true;
271 op = kMipsFcvtds;
272 break;
273 case OP_INT_TO_DOUBLE:
274 longSrc = false;
275 longDest = true;
276 op = kMipsFcvtdw;
277 break;
278 case OP_FLOAT_TO_INT:
279 case OP_DOUBLE_TO_INT:
280 case OP_LONG_TO_DOUBLE:
281 case OP_FLOAT_TO_LONG:
282 case OP_LONG_TO_FLOAT:
283 case OP_DOUBLE_TO_LONG:
284 return genConversionPortable(cUnit, mir);
285 default:
286 return true;
287 }
288 if (longSrc) {
289 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
290 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
291 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
292 } else {
293 rlSrc = oatGetSrc(cUnit, mir, 0);
294 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
295 srcReg = rlSrc.lowReg;
296 }
297 if (longDest) {
298 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
299 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
300 newLIR2(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
301 storeValueWide(cUnit, rlDest, rlResult);
302 } else {
303 rlDest = oatGetDest(cUnit, mir, 0);
304 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
305 newLIR2(cUnit, (MipsOpCode)op, rlResult.lowReg, srcReg);
306 storeValue(cUnit, rlDest, rlResult);
307 }
308 return false;
309#else
310 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
311 return false;
312#if 0
313 TemplateOpcode templateOpcode;
314 switch (opcode) {
315 case OP_INT_TO_FLOAT:
316 longSrc = false;
317 longDest = false;
318 templateOpcode = TEMPLATE_INT_TO_FLOAT_VFP;
319 break;
320 case OP_FLOAT_TO_INT:
321 longSrc = false;
322 longDest = false;
323 templateOpcode = TEMPLATE_FLOAT_TO_INT_VFP;
324 break;
325 case OP_DOUBLE_TO_FLOAT:
326 longSrc = true;
327 longDest = false;
328 templateOpcode = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
329 break;
330 case OP_FLOAT_TO_DOUBLE:
331 longSrc = false;
332 longDest = true;
333 templateOpcode = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
334 break;
335 case OP_INT_TO_DOUBLE:
336 longSrc = false;
337 longDest = true;
338 templateOpcode = TEMPLATE_INT_TO_DOUBLE_VFP;
339 break;
340 case OP_DOUBLE_TO_INT:
341 longSrc = true;
342 longDest = false;
343 templateOpcode = TEMPLATE_DOUBLE_TO_INT_VFP;
344 break;
345 case OP_LONG_TO_DOUBLE:
346 case OP_FLOAT_TO_LONG:
347 case OP_LONG_TO_FLOAT:
348 case OP_DOUBLE_TO_LONG:
349 return genConversionPortable(cUnit, mir);
350 default:
351 return true;
352 }
353
354 if (longSrc) {
355 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
356 } else {
357 rlSrc = oatGetSrc(cUnit, mir, 0);
358 }
359
360 if (longDest) {
361 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
362 } else {
363 rlDest = oatGetDest(cUnit, mir, 0);
364 }
365 loadValueAddress(cUnit, rlDest, r_A0);
366 oatClobber(cUnit, r_A0);
367 loadValueAddress(cUnit, rlSrc, r_A1);
368 UNIMP(FATAL) << "Need callout to handler";
369#if 0
370 genDispatchToHandler(cUnit, templateOpcode);
371#endif
372 if (rlDest.wide) {
373 rlDest = oatUpdateLocWide(cUnit, rlDest);
374 oatClobber(cUnit, rlDest.highReg);
375 } else {
376 rlDest = oatUpdateLoc(cUnit, rlDest);
377 }
378 oatClobber(cUnit, rlDest.lowReg);
379 return false;
380#endif
381#endif
382}
383
384static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
385 RegLocation rlSrc1, RegLocation rlSrc2)
386{
387 UNIMPLEMENTED(FATAL) << "Need Mips implementation";
388 return false;
389#if 0
390 TemplateOpcode templateOpcode;
391 RegLocation rlResult = oatGetReturn(cUnit);
392 bool wide = true;
393
394 switch(mir->dalvikInsn.opcode) {
395 case OP_CMPL_FLOAT:
396 templateOpcode = TEMPLATE_CMPL_FLOAT_VFP;
397 wide = false;
398 break;
399 case OP_CMPG_FLOAT:
400 templateOpcode = TEMPLATE_CMPG_FLOAT_VFP;
401 wide = false;
402 break;
403 case OP_CMPL_DOUBLE:
404 templateOpcode = TEMPLATE_CMPL_DOUBLE_VFP;
405 break;
406 case OP_CMPG_DOUBLE:
407 templateOpcode = TEMPLATE_CMPG_DOUBLE_VFP;
408 break;
409 default:
410 return true;
411 }
412 loadValueAddress(cUnit, rlSrc1, r_A0);
413 oatClobber(cUnit, r_A0);
414 loadValueAddress(cUnit, rlSrc2, r_A1);
415 UNIMP(FATAL) << "Need callout to handler";
416#if 0
417 genDispatchToHandler(cUnit, templateOpcode);
418#endif
419 storeValue(cUnit, rlDest, rlResult);
420 return false;
421#endif
422}
423
424} // namespace art