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