blob: fbce1f5b0b0861d27ea279c0c68dceabc7d14b23 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080017namespace art {
18
buzbee31a4a6f2012-02-28 15:36:15 -080019bool genArithOpFloat(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
20 RegLocation rlSrc1, RegLocation rlSrc2)
buzbee67bf8852011-08-17 17:51:35 -070021{
Bill Buzbeea114add2012-05-03 15:00:40 -070022 int op = kThumbBkpt;
23 RegLocation rlResult;
buzbee67bf8852011-08-17 17:51:35 -070024
Bill Buzbeea114add2012-05-03 15:00:40 -070025 /*
26 * Don't attempt to optimize register usage since these opcodes call out to
27 * the handlers.
28 */
29 switch (mir->dalvikInsn.opcode) {
30 case Instruction::ADD_FLOAT_2ADDR:
31 case Instruction::ADD_FLOAT:
32 op = kThumb2Vadds;
33 break;
34 case Instruction::SUB_FLOAT_2ADDR:
35 case Instruction::SUB_FLOAT:
36 op = kThumb2Vsubs;
37 break;
38 case Instruction::DIV_FLOAT_2ADDR:
39 case Instruction::DIV_FLOAT:
40 op = kThumb2Vdivs;
41 break;
42 case Instruction::MUL_FLOAT_2ADDR:
43 case Instruction::MUL_FLOAT:
44 op = kThumb2Vmuls;
45 break;
46 case Instruction::REM_FLOAT_2ADDR:
47 case Instruction::REM_FLOAT:
48 case Instruction::NEG_FLOAT: {
49 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbee67bf8852011-08-17 17:51:35 -070050 }
Bill Buzbeea114add2012-05-03 15:00:40 -070051 default:
52 return true;
53 }
54 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
55 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
56 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
57 newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
58 storeValue(cUnit, rlDest, rlResult);
59 return false;
buzbee67bf8852011-08-17 17:51:35 -070060}
61
buzbee31a4a6f2012-02-28 15:36:15 -080062bool genArithOpDouble(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
63 RegLocation rlSrc1, RegLocation rlSrc2)
buzbee67bf8852011-08-17 17:51:35 -070064{
Bill Buzbeea114add2012-05-03 15:00:40 -070065 int op = kThumbBkpt;
66 RegLocation rlResult;
buzbee67bf8852011-08-17 17:51:35 -070067
Bill Buzbeea114add2012-05-03 15:00:40 -070068 switch (mir->dalvikInsn.opcode) {
69 case Instruction::ADD_DOUBLE_2ADDR:
70 case Instruction::ADD_DOUBLE:
71 op = kThumb2Vaddd;
72 break;
73 case Instruction::SUB_DOUBLE_2ADDR:
74 case Instruction::SUB_DOUBLE:
75 op = kThumb2Vsubd;
76 break;
77 case Instruction::DIV_DOUBLE_2ADDR:
78 case Instruction::DIV_DOUBLE:
79 op = kThumb2Vdivd;
80 break;
81 case Instruction::MUL_DOUBLE_2ADDR:
82 case Instruction::MUL_DOUBLE:
83 op = kThumb2Vmuld;
84 break;
85 case Instruction::REM_DOUBLE_2ADDR:
86 case Instruction::REM_DOUBLE:
87 case Instruction::NEG_DOUBLE: {
88 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbee67bf8852011-08-17 17:51:35 -070089 }
Bill Buzbeea114add2012-05-03 15:00:40 -070090 default:
91 return true;
92 }
buzbee67bf8852011-08-17 17:51:35 -070093
Bill Buzbeea114add2012-05-03 15:00:40 -070094 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
95 DCHECK(rlSrc1.wide);
96 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
97 DCHECK(rlSrc2.wide);
98 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
99 DCHECK(rlDest.wide);
100 DCHECK(rlResult.wide);
101 newLIR3(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
102 S2D(rlSrc1.lowReg, rlSrc1.highReg),
103 S2D(rlSrc2.lowReg, rlSrc2.highReg));
104 storeValueWide(cUnit, rlDest, rlResult);
105 return false;
buzbee67bf8852011-08-17 17:51:35 -0700106}
107
buzbee31a4a6f2012-02-28 15:36:15 -0800108bool genConversion(CompilationUnit* cUnit, MIR* mir)
buzbee67bf8852011-08-17 17:51:35 -0700109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 Instruction::Code opcode = mir->dalvikInsn.opcode;
111 int op = kThumbBkpt;
112 bool longSrc = false;
113 bool longDest = false;
114 int srcReg;
115 RegLocation rlSrc;
116 RegLocation rlDest;
117 RegLocation rlResult;
buzbee67bf8852011-08-17 17:51:35 -0700118
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 switch (opcode) {
120 case Instruction::INT_TO_FLOAT:
121 longSrc = false;
122 longDest = false;
123 op = kThumb2VcvtIF;
124 break;
125 case Instruction::FLOAT_TO_INT:
126 longSrc = false;
127 longDest = false;
128 op = kThumb2VcvtFI;
129 break;
130 case Instruction::DOUBLE_TO_FLOAT:
131 longSrc = true;
132 longDest = false;
133 op = kThumb2VcvtDF;
134 break;
135 case Instruction::FLOAT_TO_DOUBLE:
136 longSrc = false;
137 longDest = true;
138 op = kThumb2VcvtFd;
139 break;
140 case Instruction::INT_TO_DOUBLE:
141 longSrc = false;
142 longDest = true;
143 op = kThumb2VcvtID;
144 break;
145 case Instruction::DOUBLE_TO_INT:
146 longSrc = true;
147 longDest = false;
148 op = kThumb2VcvtDI;
149 break;
150 case Instruction::LONG_TO_DOUBLE:
151 case Instruction::FLOAT_TO_LONG:
152 case Instruction::LONG_TO_FLOAT:
153 case Instruction::DOUBLE_TO_LONG:
154 return genConversionPortable(cUnit, mir);
155 default:
156 return true;
157 }
158 if (longSrc) {
159 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
160 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
161 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
162 } else {
163 rlSrc = oatGetSrc(cUnit, mir, 0);
164 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
165 srcReg = rlSrc.lowReg;
166 }
167 if (longDest) {
168 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
169 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
170 newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
171 srcReg);
172 storeValueWide(cUnit, rlDest, rlResult);
173 } else {
174 rlDest = oatGetDest(cUnit, mir, 0);
175 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
176 newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
177 storeValue(cUnit, rlDest, rlResult);
178 }
179 return false;
buzbee67bf8852011-08-17 17:51:35 -0700180}
181
buzbee84fd6932012-03-29 16:44:16 -0700182void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
183 bool gtBias, bool isDouble)
184{
Bill Buzbeea114add2012-05-03 15:00:40 -0700185 LIR* labelList = (LIR*)cUnit->blockLabelList;
186 LIR* target = &labelList[bb->taken->id];
187 RegLocation rlSrc1;
188 RegLocation rlSrc2;
189 if (isDouble) {
190 rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
191 rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3);
192 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
193 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
194 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
195 S2D(rlSrc2.lowReg, rlSrc2.highReg));
196 } else {
197 rlSrc1 = oatGetSrc(cUnit, mir, 0);
198 rlSrc2 = oatGetSrc(cUnit, mir, 1);
199 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
200 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
201 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
202 }
203 newLIR0(cUnit, kThumb2Fmstat);
204 ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
205 switch(ccode) {
206 case kCondEq:
207 case kCondNe:
208 break;
209 case kCondLt:
210 if (gtBias) {
211 ccode = kCondMi;
212 }
213 break;
214 case kCondLe:
215 if (gtBias) {
216 ccode = kCondLs;
217 }
218 break;
219 case kCondGt:
220 if (gtBias) {
221 ccode = kCondHi;
222 }
223 break;
224 case kCondGe:
225 if (gtBias) {
226 ccode = kCondCs;
227 }
228 break;
229 default:
230 LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
231 }
232 opCondBranch(cUnit, ccode, target);
buzbee84fd6932012-03-29 16:44:16 -0700233}
234
235
buzbee31a4a6f2012-02-28 15:36:15 -0800236bool genCmpFP(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 RegLocation rlSrc1, RegLocation rlSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700238{
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 bool isDouble;
240 int defaultResult;
241 RegLocation rlResult;
buzbee67bf8852011-08-17 17:51:35 -0700242
Bill Buzbeea114add2012-05-03 15:00:40 -0700243 switch (mir->dalvikInsn.opcode) {
244 case Instruction::CMPL_FLOAT:
245 isDouble = false;
246 defaultResult = -1;
247 break;
248 case Instruction::CMPG_FLOAT:
249 isDouble = false;
250 defaultResult = 1;
251 break;
252 case Instruction::CMPL_DOUBLE:
253 isDouble = true;
254 defaultResult = -1;
255 break;
256 case Instruction::CMPG_DOUBLE:
257 isDouble = true;
258 defaultResult = 1;
259 break;
260 default:
261 return true;
262 }
263 if (isDouble) {
264 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
265 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
266 oatClobberSReg(cUnit, rlDest.sRegLow);
267 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
268 loadConstant(cUnit, rlResult.lowReg, defaultResult);
269 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
270 S2D(rlSrc2.lowReg, rlSrc2.highReg));
271 } else {
272 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
273 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
274 oatClobberSReg(cUnit, rlDest.sRegLow);
275 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
276 loadConstant(cUnit, rlResult.lowReg, defaultResult);
277 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
278 }
279 DCHECK(!FPREG(rlResult.lowReg));
280 newLIR0(cUnit, kThumb2Fmstat);
buzbee67bf8852011-08-17 17:51:35 -0700281
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 opIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
283 newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
284 modifiedImmediate(-defaultResult)); // Must not alter ccodes
285 genBarrier(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700286
Bill Buzbeea114add2012-05-03 15:00:40 -0700287 opIT(cUnit, kArmCondEq, "");
288 loadConstant(cUnit, rlResult.lowReg, 0);
289 genBarrier(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700290
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 storeValue(cUnit, rlDest, rlResult);
292 return false;
buzbee67bf8852011-08-17 17:51:35 -0700293}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800294
295} // namespace art