• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 /*
18  * This file is included by Codegen-armv5te-vfp.c, and implements architecture
19  * variant-specific code.
20  */
21 
22 extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
23                                               int reg1, int reg2);
24 extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg);
25 
26 /*
27  * Take the address of a Dalvik register and store it into rDest.
28  * Clobber any live values associated either with the Dalvik value
29  * or the target register and lock the target fixed register.
30  */
loadValueAddressDirect(CompilationUnit * cUnit,RegLocation rlSrc,int rDest)31 static void loadValueAddressDirect(CompilationUnit *cUnit, RegLocation rlSrc,
32                                    int rDest)
33 {
34      rlSrc = rlSrc.wide ? dvmCompilerUpdateLocWide(cUnit, rlSrc) :
35                           dvmCompilerUpdateLoc(cUnit, rlSrc);
36      if (rlSrc.location == kLocPhysReg) {
37          if (rlSrc.wide) {
38              dvmCompilerFlushRegWideForV5TEVFP(cUnit, rlSrc.lowReg,
39                                                rlSrc.highReg);
40          } else {
41              dvmCompilerFlushRegForV5TEVFP(cUnit, rlSrc.lowReg);
42          }
43      }
44      dvmCompilerClobber(cUnit, rDest);
45      dvmCompilerLockTemp(cUnit, rDest);
46      opRegRegImm(cUnit, kOpAdd, rDest, rFP,
47                  dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2);
48 }
49 
genInlineSqrt(CompilationUnit * cUnit,MIR * mir)50 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
51 {
52     RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
53     RegLocation rlResult = LOC_C_RETURN_WIDE;
54     RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
55     loadValueAddressDirect(cUnit, rlSrc, r2);
56     genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
57     storeValueWide(cUnit, rlDest, rlResult);
58     return false;
59 }
60 
61 /*
62  * TUNING: On some implementations, it is quicker to pass addresses
63  * to the handlers rather than load the operands into core registers
64  * and then move the values to FP regs in the handlers.  Other implementations
65  * may prefer passing data in registers (and the latter approach would
66  * yeild cleaner register handling - avoiding the requirement that operands
67  * be flushed to memory prior to the call).
68  */
genArithOpFloat(CompilationUnit * cUnit,MIR * mir,RegLocation rlDest,RegLocation rlSrc1,RegLocation rlSrc2)69 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
70                             RegLocation rlDest, RegLocation rlSrc1,
71                             RegLocation rlSrc2)
72 {
73     TemplateOpCode opCode;
74 
75     /*
76      * Don't attempt to optimize register usage since these opcodes call out to
77      * the handlers.
78      */
79     switch (mir->dalvikInsn.opCode) {
80         case OP_ADD_FLOAT_2ADDR:
81         case OP_ADD_FLOAT:
82             opCode = TEMPLATE_ADD_FLOAT_VFP;
83             break;
84         case OP_SUB_FLOAT_2ADDR:
85         case OP_SUB_FLOAT:
86             opCode = TEMPLATE_SUB_FLOAT_VFP;
87             break;
88         case OP_DIV_FLOAT_2ADDR:
89         case OP_DIV_FLOAT:
90             opCode = TEMPLATE_DIV_FLOAT_VFP;
91             break;
92         case OP_MUL_FLOAT_2ADDR:
93         case OP_MUL_FLOAT:
94             opCode = TEMPLATE_MUL_FLOAT_VFP;
95             break;
96         case OP_REM_FLOAT_2ADDR:
97         case OP_REM_FLOAT:
98         case OP_NEG_FLOAT: {
99             return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
100         }
101         default:
102             return true;
103     }
104     loadValueAddressDirect(cUnit, rlDest, r0);
105     loadValueAddressDirect(cUnit, rlSrc1, r1);
106     loadValueAddressDirect(cUnit, rlSrc2, r2);
107     genDispatchToHandler(cUnit, opCode);
108     rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
109     if (rlDest.location == kLocPhysReg) {
110         dvmCompilerClobber(cUnit, rlDest.lowReg);
111     }
112     return false;
113 }
114 
genArithOpDouble(CompilationUnit * cUnit,MIR * mir,RegLocation rlDest,RegLocation rlSrc1,RegLocation rlSrc2)115 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
116                              RegLocation rlDest, RegLocation rlSrc1,
117                              RegLocation rlSrc2)
118 {
119     TemplateOpCode opCode;
120 
121     switch (mir->dalvikInsn.opCode) {
122         case OP_ADD_DOUBLE_2ADDR:
123         case OP_ADD_DOUBLE:
124             opCode = TEMPLATE_ADD_DOUBLE_VFP;
125             break;
126         case OP_SUB_DOUBLE_2ADDR:
127         case OP_SUB_DOUBLE:
128             opCode = TEMPLATE_SUB_DOUBLE_VFP;
129             break;
130         case OP_DIV_DOUBLE_2ADDR:
131         case OP_DIV_DOUBLE:
132             opCode = TEMPLATE_DIV_DOUBLE_VFP;
133             break;
134         case OP_MUL_DOUBLE_2ADDR:
135         case OP_MUL_DOUBLE:
136             opCode = TEMPLATE_MUL_DOUBLE_VFP;
137             break;
138         case OP_REM_DOUBLE_2ADDR:
139         case OP_REM_DOUBLE:
140         case OP_NEG_DOUBLE: {
141             return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
142                                                rlSrc2);
143         }
144         default:
145             return true;
146     }
147     loadValueAddressDirect(cUnit, rlDest, r0);
148     loadValueAddressDirect(cUnit, rlSrc1, r1);
149     loadValueAddressDirect(cUnit, rlSrc2, r2);
150     genDispatchToHandler(cUnit, opCode);
151     rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
152     if (rlDest.location == kLocPhysReg) {
153         dvmCompilerClobber(cUnit, rlDest.lowReg);
154         dvmCompilerClobber(cUnit, rlDest.highReg);
155     }
156     return false;
157 }
158 
genConversion(CompilationUnit * cUnit,MIR * mir)159 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
160 {
161     OpCode opCode = mir->dalvikInsn.opCode;
162     bool longSrc = false;
163     bool longDest = false;
164     RegLocation rlSrc;
165     RegLocation rlDest;
166     TemplateOpCode template;
167     switch (opCode) {
168         case OP_INT_TO_FLOAT:
169             longSrc = false;
170             longDest = false;
171             template = TEMPLATE_INT_TO_FLOAT_VFP;
172             break;
173         case OP_FLOAT_TO_INT:
174             longSrc = false;
175             longDest = false;
176             template = TEMPLATE_FLOAT_TO_INT_VFP;
177             break;
178         case OP_DOUBLE_TO_FLOAT:
179             longSrc = true;
180             longDest = false;
181             template = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
182             break;
183         case OP_FLOAT_TO_DOUBLE:
184             longSrc = false;
185             longDest = true;
186             template = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
187             break;
188         case OP_INT_TO_DOUBLE:
189             longSrc = false;
190             longDest = true;
191             template = TEMPLATE_INT_TO_DOUBLE_VFP;
192             break;
193         case OP_DOUBLE_TO_INT:
194             longSrc = true;
195             longDest = false;
196             template = TEMPLATE_DOUBLE_TO_INT_VFP;
197             break;
198         case OP_LONG_TO_DOUBLE:
199         case OP_FLOAT_TO_LONG:
200         case OP_LONG_TO_FLOAT:
201         case OP_DOUBLE_TO_LONG:
202             return genConversionPortable(cUnit, mir);
203         default:
204             return true;
205     }
206 
207     if (longSrc) {
208         rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
209     } else {
210         rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
211     }
212 
213     if (longDest) {
214         rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
215     } else {
216         rlDest = dvmCompilerGetDest(cUnit, mir, 0);
217     }
218     loadValueAddressDirect(cUnit, rlDest, r0);
219     loadValueAddressDirect(cUnit, rlSrc, r1);
220     genDispatchToHandler(cUnit, template);
221     if (rlDest.wide) {
222         rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
223         dvmCompilerClobber(cUnit, rlDest.highReg);
224     } else {
225         rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
226     }
227     dvmCompilerClobber(cUnit, rlDest.lowReg);
228     return false;
229 }
230 
genCmpFP(CompilationUnit * cUnit,MIR * mir,RegLocation rlDest,RegLocation rlSrc1,RegLocation rlSrc2)231 static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
232                      RegLocation rlSrc1, RegLocation rlSrc2)
233 {
234     TemplateOpCode template;
235     RegLocation rlResult = dvmCompilerGetReturn(cUnit);
236     bool wide = true;
237 
238     switch(mir->dalvikInsn.opCode) {
239         case OP_CMPL_FLOAT:
240             template = TEMPLATE_CMPL_FLOAT_VFP;
241             wide = false;
242             break;
243         case OP_CMPG_FLOAT:
244             template = TEMPLATE_CMPG_FLOAT_VFP;
245             wide = false;
246             break;
247         case OP_CMPL_DOUBLE:
248             template = TEMPLATE_CMPL_DOUBLE_VFP;
249             break;
250         case OP_CMPG_DOUBLE:
251             template = TEMPLATE_CMPG_DOUBLE_VFP;
252             break;
253         default:
254             return true;
255     }
256     loadValueAddressDirect(cUnit, rlSrc1, r0);
257     loadValueAddressDirect(cUnit, rlSrc2, r1);
258     genDispatchToHandler(cUnit, template);
259     storeValue(cUnit, rlDest, rlResult);
260     return false;
261 }
262