blob: 380c014b6d4997839025117ac58490f9e924f573 [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{
22 int op = kThumbBkpt;
23 RegLocation rlResult;
24
25 /*
26 * Don't attempt to optimize register usage since these opcodes call out to
27 * the handlers.
28 */
29 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -080030 case Instruction::ADD_FLOAT_2ADDR:
31 case Instruction::ADD_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -070032 op = kThumb2Vadds;
33 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080034 case Instruction::SUB_FLOAT_2ADDR:
35 case Instruction::SUB_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -070036 op = kThumb2Vsubs;
37 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080038 case Instruction::DIV_FLOAT_2ADDR:
39 case Instruction::DIV_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -070040 op = kThumb2Vdivs;
41 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080042 case Instruction::MUL_FLOAT_2ADDR:
43 case Instruction::MUL_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -070044 op = kThumb2Vmuls;
45 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080046 case Instruction::REM_FLOAT_2ADDR:
47 case Instruction::REM_FLOAT:
48 case Instruction::NEG_FLOAT: {
buzbee67bf8852011-08-17 17:51:35 -070049 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1,
50 rlSrc2);
51 }
52 default:
53 return true;
54 }
55 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
56 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
57 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
58 newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg,
59 rlSrc2.lowReg);
60 storeValue(cUnit, rlDest, rlResult);
61 return false;
62}
63
buzbee31a4a6f2012-02-28 15:36:15 -080064bool genArithOpDouble(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
65 RegLocation rlSrc1, RegLocation rlSrc2)
buzbee67bf8852011-08-17 17:51:35 -070066{
67 int op = kThumbBkpt;
68 RegLocation rlResult;
69
70 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -080071 case Instruction::ADD_DOUBLE_2ADDR:
72 case Instruction::ADD_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -070073 op = kThumb2Vaddd;
74 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080075 case Instruction::SUB_DOUBLE_2ADDR:
76 case Instruction::SUB_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -070077 op = kThumb2Vsubd;
78 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080079 case Instruction::DIV_DOUBLE_2ADDR:
80 case Instruction::DIV_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -070081 op = kThumb2Vdivd;
82 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080083 case Instruction::MUL_DOUBLE_2ADDR:
84 case Instruction::MUL_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -070085 op = kThumb2Vmuld;
86 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080087 case Instruction::REM_DOUBLE_2ADDR:
88 case Instruction::REM_DOUBLE:
89 case Instruction::NEG_DOUBLE: {
buzbee67bf8852011-08-17 17:51:35 -070090 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
91 rlSrc2);
92 }
93 default:
94 return true;
95 }
96
97 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
buzbeeed3e9302011-09-23 17:34:19 -070098 DCHECK(rlSrc1.wide);
buzbee67bf8852011-08-17 17:51:35 -070099 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
buzbeeed3e9302011-09-23 17:34:19 -0700100 DCHECK(rlSrc2.wide);
buzbee67bf8852011-08-17 17:51:35 -0700101 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
buzbeeed3e9302011-09-23 17:34:19 -0700102 DCHECK(rlDest.wide);
103 DCHECK(rlResult.wide);
buzbee67bf8852011-08-17 17:51:35 -0700104 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
buzbee31a4a6f2012-02-28 15:36:15 -0800111bool genConversion(CompilationUnit* cUnit, MIR* mir)
buzbee67bf8852011-08-17 17:51:35 -0700112{
Elliott Hughesadb8c672012-03-06 16:49:32 -0800113 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee67bf8852011-08-17 17:51:35 -0700114 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) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800123 case Instruction::INT_TO_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -0700124 longSrc = false;
125 longDest = false;
126 op = kThumb2VcvtIF;
127 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800128 case Instruction::FLOAT_TO_INT:
buzbee67bf8852011-08-17 17:51:35 -0700129 longSrc = false;
130 longDest = false;
131 op = kThumb2VcvtFI;
132 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800133 case Instruction::DOUBLE_TO_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -0700134 longSrc = true;
135 longDest = false;
136 op = kThumb2VcvtDF;
137 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800138 case Instruction::FLOAT_TO_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -0700139 longSrc = false;
140 longDest = true;
141 op = kThumb2VcvtFd;
142 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800143 case Instruction::INT_TO_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -0700144 longSrc = false;
145 longDest = true;
146 op = kThumb2VcvtID;
147 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800148 case Instruction::DOUBLE_TO_INT:
buzbee67bf8852011-08-17 17:51:35 -0700149 longSrc = true;
150 longDest = false;
151 op = kThumb2VcvtDI;
152 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800153 case Instruction::LONG_TO_DOUBLE:
154 case Instruction::FLOAT_TO_LONG:
155 case Instruction::LONG_TO_FLOAT:
156 case Instruction::DOUBLE_TO_LONG:
buzbee67bf8852011-08-17 17:51:35 -0700157 return genConversionPortable(cUnit, mir);
158 default:
159 return true;
160 }
161 if (longSrc) {
162 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
163 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
164 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
165 } else {
166 rlSrc = oatGetSrc(cUnit, mir, 0);
167 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
168 srcReg = rlSrc.lowReg;
169 }
170 if (longDest) {
171 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
172 rlResult = oatEvalLoc(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 = oatGetDest(cUnit, mir, 0);
178 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
179 newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
180 storeValue(cUnit, rlDest, rlResult);
181 }
182 return false;
183}
184
buzbee84fd6932012-03-29 16:44:16 -0700185void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
186 bool gtBias, bool isDouble)
187{
188 LIR* labelList = (LIR*)cUnit->blockLabelList;
189 LIR* target = &labelList[bb->taken->id];
190 RegLocation rlSrc1;
191 RegLocation rlSrc2;
192 if (isDouble) {
193 rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
194 rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3);
195 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
196 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
197 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
198 S2D(rlSrc2.lowReg, rlSrc2.highReg));
199 } else {
200 rlSrc1 = oatGetSrc(cUnit, mir, 0);
201 rlSrc2 = oatGetSrc(cUnit, mir, 1);
202 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
203 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
204 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
205 }
206 newLIR0(cUnit, kThumb2Fmstat);
207 ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
208 switch(ccode) {
209 case kCondEq:
210 case kCondNe:
211 break;
212 case kCondLt:
213 if (gtBias) {
214 ccode = kCondMi;
215 }
216 break;
217 case kCondLe:
218 if (gtBias) {
219 ccode = kCondLs;
220 }
221 break;
222 case kCondGt:
223 if (gtBias) {
224 ccode = kCondHi;
225 }
226 break;
227 case kCondGe:
228 if (gtBias) {
229 ccode = kCondCs;
230 }
231 break;
232 default:
233 LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
234 }
235 opCondBranch(cUnit, ccode, target);
236}
237
238
buzbee31a4a6f2012-02-28 15:36:15 -0800239bool genCmpFP(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
240 RegLocation rlSrc1, RegLocation rlSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700241{
242 bool isDouble;
243 int defaultResult;
244 RegLocation rlResult;
245
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700246 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800247 case Instruction::CMPL_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -0700248 isDouble = false;
249 defaultResult = -1;
250 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800251 case Instruction::CMPG_FLOAT:
buzbee67bf8852011-08-17 17:51:35 -0700252 isDouble = false;
253 defaultResult = 1;
254 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800255 case Instruction::CMPL_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -0700256 isDouble = true;
257 defaultResult = -1;
258 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800259 case Instruction::CMPG_DOUBLE:
buzbee67bf8852011-08-17 17:51:35 -0700260 isDouble = true;
261 defaultResult = 1;
262 break;
263 default:
264 return true;
265 }
266 if (isDouble) {
267 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
268 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
269 oatClobberSReg(cUnit, rlDest.sRegLow);
270 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
271 loadConstant(cUnit, rlResult.lowReg, defaultResult);
272 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
273 S2D(rlSrc2.lowReg, rlSrc2.highReg));
274 } else {
275 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
276 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
277 oatClobberSReg(cUnit, rlDest.sRegLow);
278 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
279 loadConstant(cUnit, rlResult.lowReg, defaultResult);
280 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
281 }
buzbeeed3e9302011-09-23 17:34:19 -0700282 DCHECK(!FPREG(rlResult.lowReg));
buzbee67bf8852011-08-17 17:51:35 -0700283 newLIR0(cUnit, kThumb2Fmstat);
284
buzbee82488f52012-03-02 08:20:26 -0800285 opIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
buzbee67bf8852011-08-17 17:51:35 -0700286 newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
287 modifiedImmediate(-defaultResult)); // Must not alter ccodes
288 genBarrier(cUnit);
289
buzbee82488f52012-03-02 08:20:26 -0800290 opIT(cUnit, kArmCondEq, "");
buzbee67bf8852011-08-17 17:51:35 -0700291 loadConstant(cUnit, rlResult.lowReg, 0);
292 genBarrier(cUnit);
293
294 storeValue(cUnit, rlDest, rlResult);
295 return false;
296}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800297
298} // namespace art