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