2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This file is included by Codegen-armv5te-vfp.c, and implements architecture
19 * variant-specific code.
22 extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
24 extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg);
26 /* First, flush any registers associated with this value */
27 static void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc,
30 rlSrc = rlSrc.wide ? dvmCompilerUpdateLocWide(cUnit, rlSrc) :
31 dvmCompilerUpdateLoc(cUnit, rlSrc);
32 if (rlSrc.location == kLocPhysReg) {
34 dvmCompilerFlushRegWideForV5TEVFP(cUnit, rlSrc.lowReg,
37 dvmCompilerFlushRegForV5TEVFP(cUnit, rlSrc.lowReg);
40 opRegRegImm(cUnit, kOpAdd, rDest, rFP,
41 dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2);
44 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
46 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
47 #ifdef __mips_hard_float
48 RegLocation rlResult = LOC_C_RETURN_WIDE_ALT;
50 RegLocation rlResult = LOC_C_RETURN_WIDE;
52 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
53 loadValueAddress(cUnit, rlSrc, r_A2);
54 genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
55 storeValueWide(cUnit, rlDest, rlResult);
60 * TUNING: On some implementations, it is quicker to pass addresses
61 * to the handlers rather than load the operands into core registers
62 * and then move the values to FP regs in the handlers. Other implementations
63 * may prefer passing data in registers (and the latter approach would
64 * yeild cleaner register handling - avoiding the requirement that operands
65 * be flushed to memory prior to the call).
67 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
68 RegLocation rlDest, RegLocation rlSrc1,
71 #ifdef __mips_hard_float
76 * Don't attempt to optimize register usage since these opcodes call out to
79 switch (mir->dalvikInsn.opcode) {
80 case OP_ADD_FLOAT_2ADDR:
84 case OP_SUB_FLOAT_2ADDR:
88 case OP_DIV_FLOAT_2ADDR:
92 case OP_MUL_FLOAT_2ADDR:
96 case OP_REM_FLOAT_2ADDR:
99 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
104 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
105 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
106 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
107 newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
108 storeValue(cUnit, rlDest, rlResult);
112 TemplateOpcode opcode;
115 * Don't attempt to optimize register usage since these opcodes call out to
118 switch (mir->dalvikInsn.opcode) {
119 case OP_ADD_FLOAT_2ADDR:
121 opcode = TEMPLATE_ADD_FLOAT_VFP;
123 case OP_SUB_FLOAT_2ADDR:
125 opcode = TEMPLATE_SUB_FLOAT_VFP;
127 case OP_DIV_FLOAT_2ADDR:
129 opcode = TEMPLATE_DIV_FLOAT_VFP;
131 case OP_MUL_FLOAT_2ADDR:
133 opcode = TEMPLATE_MUL_FLOAT_VFP;
135 case OP_REM_FLOAT_2ADDR:
138 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
143 loadValueAddress(cUnit, rlDest, r_A0);
144 dvmCompilerClobber(cUnit, r_A0);
145 loadValueAddress(cUnit, rlSrc1, r_A1);
146 dvmCompilerClobber(cUnit, r_A1);
147 loadValueAddress(cUnit, rlSrc2, r_A2);
148 genDispatchToHandler(cUnit, opcode);
149 rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
150 if (rlDest.location == kLocPhysReg) {
151 dvmCompilerClobber(cUnit, rlDest.lowReg);
157 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
158 RegLocation rlDest, RegLocation rlSrc1,
161 #ifdef __mips_hard_float
163 RegLocation rlResult;
165 switch (mir->dalvikInsn.opcode) {
166 case OP_ADD_DOUBLE_2ADDR:
170 case OP_SUB_DOUBLE_2ADDR:
174 case OP_DIV_DOUBLE_2ADDR:
178 case OP_MUL_DOUBLE_2ADDR:
182 case OP_REM_DOUBLE_2ADDR:
184 case OP_NEG_DOUBLE: {
185 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
190 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
192 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
194 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
196 assert(rlResult.wide);
197 newLIR3(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg),
198 S2D(rlSrc1.lowReg, rlSrc1.highReg),
199 S2D(rlSrc2.lowReg, rlSrc2.highReg));
200 storeValueWide(cUnit, rlDest, rlResult);
203 TemplateOpcode opcode;
205 switch (mir->dalvikInsn.opcode) {
206 case OP_ADD_DOUBLE_2ADDR:
208 opcode = TEMPLATE_ADD_DOUBLE_VFP;
210 case OP_SUB_DOUBLE_2ADDR:
212 opcode = TEMPLATE_SUB_DOUBLE_VFP;
214 case OP_DIV_DOUBLE_2ADDR:
216 opcode = TEMPLATE_DIV_DOUBLE_VFP;
218 case OP_MUL_DOUBLE_2ADDR:
220 opcode = TEMPLATE_MUL_DOUBLE_VFP;
222 case OP_REM_DOUBLE_2ADDR:
224 case OP_NEG_DOUBLE: {
225 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
231 loadValueAddress(cUnit, rlDest, r_A0);
232 dvmCompilerClobber(cUnit, r_A0);
233 loadValueAddress(cUnit, rlSrc1, r_A1);
234 dvmCompilerClobber(cUnit, r_A1);
235 loadValueAddress(cUnit, rlSrc2, r_A2);
236 genDispatchToHandler(cUnit, opcode);
237 rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
238 if (rlDest.location == kLocPhysReg) {
239 dvmCompilerClobber(cUnit, rlDest.lowReg);
240 dvmCompilerClobber(cUnit, rlDest.highReg);
246 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
248 Opcode opcode = mir->dalvikInsn.opcode;
249 bool longSrc = false;
250 bool longDest = false;
253 #ifdef __mips_hard_float
256 RegLocation rlResult;
259 case OP_INT_TO_FLOAT:
264 case OP_DOUBLE_TO_FLOAT:
269 case OP_FLOAT_TO_DOUBLE:
274 case OP_INT_TO_DOUBLE:
279 case OP_FLOAT_TO_INT:
280 case OP_DOUBLE_TO_INT:
281 case OP_LONG_TO_DOUBLE:
282 case OP_FLOAT_TO_LONG:
283 case OP_LONG_TO_FLOAT:
284 case OP_DOUBLE_TO_LONG:
285 return genConversionPortable(cUnit, mir);
290 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
291 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
292 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
294 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
295 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
296 srcReg = rlSrc.lowReg;
299 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
300 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
301 newLIR2(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
302 storeValueWide(cUnit, rlDest, rlResult);
304 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
305 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
306 newLIR2(cUnit, (MipsOpCode)op, rlResult.lowReg, srcReg);
307 storeValue(cUnit, rlDest, rlResult);
311 TemplateOpcode templateOpcode;
313 case OP_INT_TO_FLOAT:
316 templateOpcode = TEMPLATE_INT_TO_FLOAT_VFP;
318 case OP_FLOAT_TO_INT:
321 templateOpcode = TEMPLATE_FLOAT_TO_INT_VFP;
323 case OP_DOUBLE_TO_FLOAT:
326 templateOpcode = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
328 case OP_FLOAT_TO_DOUBLE:
331 templateOpcode = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
333 case OP_INT_TO_DOUBLE:
336 templateOpcode = TEMPLATE_INT_TO_DOUBLE_VFP;
338 case OP_DOUBLE_TO_INT:
341 templateOpcode = TEMPLATE_DOUBLE_TO_INT_VFP;
343 case OP_LONG_TO_DOUBLE:
344 case OP_FLOAT_TO_LONG:
345 case OP_LONG_TO_FLOAT:
346 case OP_DOUBLE_TO_LONG:
347 return genConversionPortable(cUnit, mir);
353 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
355 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
359 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
361 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
363 loadValueAddress(cUnit, rlDest, r_A0);
364 dvmCompilerClobber(cUnit, r_A0);
365 loadValueAddress(cUnit, rlSrc, r_A1);
366 genDispatchToHandler(cUnit, templateOpcode);
368 rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
369 dvmCompilerClobber(cUnit, rlDest.highReg);
371 rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
373 dvmCompilerClobber(cUnit, rlDest.lowReg);
378 static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
379 RegLocation rlSrc1, RegLocation rlSrc2)
381 TemplateOpcode templateOpcode;
382 RegLocation rlResult = dvmCompilerGetReturn(cUnit);
385 switch(mir->dalvikInsn.opcode) {
387 templateOpcode = TEMPLATE_CMPL_FLOAT_VFP;
391 templateOpcode = TEMPLATE_CMPG_FLOAT_VFP;
395 templateOpcode = TEMPLATE_CMPL_DOUBLE_VFP;
398 templateOpcode = TEMPLATE_CMPG_DOUBLE_VFP;
403 loadValueAddress(cUnit, rlSrc1, r_A0);
404 dvmCompilerClobber(cUnit, r_A0);
405 loadValueAddress(cUnit, rlSrc2, r_A1);
406 genDispatchToHandler(cUnit, templateOpcode);
407 storeValue(cUnit, rlDest, rlResult);