• 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 
genArithOpFloat(CompilationUnit * cUnit,MIR * mir,RegLocation rlDest,RegLocation rlSrc1,RegLocation rlSrc2)17 static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
18                             RegLocation rlDest, RegLocation rlSrc1,
19                             RegLocation rlSrc2)
20 {
21     int op = kThumbBkpt;
22     RegLocation rlResult;
23 
24     /*
25      * Don't attempt to optimize register usage since these opcodes call out to
26      * the handlers.
27      */
28     switch (mir->dalvikInsn.opCode) {
29         case OP_ADD_FLOAT_2ADDR:
30         case OP_ADD_FLOAT:
31             op = kThumb2Vadds;
32             break;
33         case OP_SUB_FLOAT_2ADDR:
34         case OP_SUB_FLOAT:
35             op = kThumb2Vsubs;
36             break;
37         case OP_DIV_FLOAT_2ADDR:
38         case OP_DIV_FLOAT:
39             op = kThumb2Vdivs;
40             break;
41         case OP_MUL_FLOAT_2ADDR:
42         case OP_MUL_FLOAT:
43             op = kThumb2Vmuls;
44             break;
45         case OP_REM_FLOAT_2ADDR:
46         case OP_REM_FLOAT:
47         case OP_NEG_FLOAT: {
48             return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1,
49                                               rlSrc2);
50         }
51         default:
52             return true;
53     }
54     rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
55     rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
56     rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
57     newLIR3(cUnit, op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
58     storeValue(cUnit, rlDest, rlResult);
59     return false;
60 }
61 
genArithOpDouble(CompilationUnit * cUnit,MIR * mir,RegLocation rlDest,RegLocation rlSrc1,RegLocation rlSrc2)62 static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
63                              RegLocation rlDest, RegLocation rlSrc1,
64                              RegLocation rlSrc2)
65 {
66     int op = kThumbBkpt;
67     RegLocation rlResult;
68 
69     switch (mir->dalvikInsn.opCode) {
70         case OP_ADD_DOUBLE_2ADDR:
71         case OP_ADD_DOUBLE:
72             op = kThumb2Vaddd;
73             break;
74         case OP_SUB_DOUBLE_2ADDR:
75         case OP_SUB_DOUBLE:
76             op = kThumb2Vsubd;
77             break;
78         case OP_DIV_DOUBLE_2ADDR:
79         case OP_DIV_DOUBLE:
80             op = kThumb2Vdivd;
81             break;
82         case OP_MUL_DOUBLE_2ADDR:
83         case OP_MUL_DOUBLE:
84             op = kThumb2Vmuld;
85             break;
86         case OP_REM_DOUBLE_2ADDR:
87         case OP_REM_DOUBLE:
88         case OP_NEG_DOUBLE: {
89             return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
90                                                rlSrc2);
91         }
92         default:
93             return true;
94     }
95 
96     rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
97     assert(rlSrc1.wide);
98     rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
99     assert(rlSrc2.wide);
100     rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
101     assert(rlDest.wide);
102     assert(rlResult.wide);
103     newLIR3(cUnit, op, S2D(rlResult.lowReg, rlResult.highReg),
104             S2D(rlSrc1.lowReg, rlSrc1.highReg),
105             S2D(rlSrc2.lowReg, rlSrc2.highReg));
106     storeValueWide(cUnit, rlDest, rlResult);
107     return false;
108 }
109 
genConversion(CompilationUnit * cUnit,MIR * mir)110 static bool genConversion(CompilationUnit *cUnit, MIR *mir)
111 {
112     OpCode opCode = mir->dalvikInsn.opCode;
113     int op = kThumbBkpt;
114     bool longSrc = false;
115     bool longDest = false;
116     int srcReg;
117     RegLocation rlSrc;
118     RegLocation rlDest;
119     RegLocation rlResult;
120 
121     switch (opCode) {
122         case OP_INT_TO_FLOAT:
123             longSrc = false;
124             longDest = false;
125             op = kThumb2VcvtIF;
126             break;
127         case OP_FLOAT_TO_INT:
128             longSrc = false;
129             longDest = false;
130             op = kThumb2VcvtFI;
131             break;
132         case OP_DOUBLE_TO_FLOAT:
133             longSrc = true;
134             longDest = false;
135             op = kThumb2VcvtDF;
136             break;
137         case OP_FLOAT_TO_DOUBLE:
138             longSrc = false;
139             longDest = true;
140             op = kThumb2VcvtFd;
141             break;
142         case OP_INT_TO_DOUBLE:
143             longSrc = false;
144             longDest = true;
145             op = kThumb2VcvtID;
146             break;
147         case OP_DOUBLE_TO_INT:
148             longSrc = true;
149             longDest = false;
150             op = kThumb2VcvtDI;
151             break;
152         case OP_LONG_TO_DOUBLE:
153         case OP_FLOAT_TO_LONG:
154         case OP_LONG_TO_FLOAT:
155         case OP_DOUBLE_TO_LONG:
156             return genConversionPortable(cUnit, mir);
157         default:
158             return true;
159     }
160     if (longSrc) {
161         rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
162         rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
163         srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
164     } else {
165         rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
166         rlSrc = loadValue(cUnit, rlSrc, kFPReg);
167         srcReg = rlSrc.lowReg;
168     }
169     if (longDest) {
170         rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
171         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
172         newLIR2(cUnit, op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
173         storeValueWide(cUnit, rlDest, rlResult);
174     } else {
175         rlDest = dvmCompilerGetDest(cUnit, mir, 0);
176         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
177         newLIR2(cUnit, op, rlResult.lowReg, srcReg);
178         storeValue(cUnit, rlDest, rlResult);
179     }
180     return false;
181 }
182 
genInlineSqrt(CompilationUnit * cUnit,MIR * mir)183 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
184 {
185     ArmLIR *branch;
186     RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
187     RegLocation rlDest = inlinedTargetWide(cUnit, mir, true);
188     rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
189     RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
190     newLIR2(cUnit, kThumb2Vsqrtd, S2D(rlResult.lowReg, rlResult.highReg),
191             S2D(rlSrc.lowReg, rlSrc.highReg));
192     newLIR2(cUnit, kThumb2Vcmpd, S2D(rlResult.lowReg, rlResult.highReg),
193             S2D(rlResult.lowReg, rlResult.highReg));
194     newLIR0(cUnit, kThumb2Fmstat);
195     branch = newLIR2(cUnit, kThumbBCond, 0, kArmCondEq);
196     dvmCompilerClobberCallRegs(cUnit);
197     LOAD_FUNC_ADDR(cUnit, r2, (int)sqrt);
198     newLIR3(cUnit, kThumb2Fmrrd, r0, r1, S2D(rlSrc.lowReg, rlSrc.highReg));
199     newLIR1(cUnit, kThumbBlxR, r2);
200     newLIR3(cUnit, kThumb2Fmdrr, S2D(rlResult.lowReg, rlResult.highReg),
201             r0, r1);
202     ArmLIR *label = newLIR0(cUnit, kArmPseudoTargetLabel);
203     label->defMask = ENCODE_ALL;
204     branch->generic.target = (LIR *)label;
205     storeValueWide(cUnit, rlDest, rlResult);
206     return true;
207 }
208 
genCmpFP(CompilationUnit * cUnit,MIR * mir,RegLocation rlDest,RegLocation rlSrc1,RegLocation rlSrc2)209 static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
210                      RegLocation rlSrc1, RegLocation rlSrc2)
211 {
212     bool isDouble;
213     int defaultResult;
214     RegLocation rlResult;
215 
216     switch(mir->dalvikInsn.opCode) {
217         case OP_CMPL_FLOAT:
218             isDouble = false;
219             defaultResult = -1;
220             break;
221         case OP_CMPG_FLOAT:
222             isDouble = false;
223             defaultResult = 1;
224             break;
225         case OP_CMPL_DOUBLE:
226             isDouble = true;
227             defaultResult = -1;
228             break;
229         case OP_CMPG_DOUBLE:
230             isDouble = true;
231             defaultResult = 1;
232             break;
233         default:
234             return true;
235     }
236     if (isDouble) {
237         rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
238         rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
239         dvmCompilerClobberSReg(cUnit, rlDest.sRegLow);
240         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
241         loadConstant(cUnit, rlResult.lowReg, defaultResult);
242         newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
243                 S2D(rlSrc2.lowReg, rlSrc2.highReg));
244     } else {
245         rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
246         rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
247         dvmCompilerClobberSReg(cUnit, rlDest.sRegLow);
248         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
249         loadConstant(cUnit, rlResult.lowReg, defaultResult);
250         newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
251     }
252     assert(!FPREG(rlResult.lowReg));
253     newLIR0(cUnit, kThumb2Fmstat);
254     genIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
255     newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
256             modifiedImmediate(-defaultResult)); // Must not alter ccodes
257     genIT(cUnit, kArmCondEq, "");
258     loadConstant(cUnit, rlResult.lowReg, 0);
259     storeValue(cUnit, rlDest, rlResult);
260     return false;
261 }
262