blob: 3ea28c9f4278e8d0ecff89e370d455a52e94300a [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
buzbee408ad162012-06-06 16:45:18 -070019bool genArithOpFloat(CompilationUnit* cUnit, Instruction::Code opcode, RegLocation rlDest,
buzbee31a4a6f2012-02-28 15:36:15 -080020 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 */
buzbee408ad162012-06-06 16:45:18 -070029 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070030 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: {
buzbee408ad162012-06-06 16:45:18 -070049 return genArithOpFloatPortable(cUnit, opcode, 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
buzbee408ad162012-06-06 16:45:18 -070062bool genArithOpDouble(CompilationUnit* cUnit, Instruction::Code opcode,
63 RegLocation rlDest, 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
buzbee408ad162012-06-06 16:45:18 -070068 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070069 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: {
buzbee408ad162012-06-06 16:45:18 -070088 return genArithOpDoublePortable(cUnit, opcode, 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
buzbee408ad162012-06-06 16:45:18 -0700108bool genConversion(CompilationUnit* cUnit, Instruction::Code opcode,
109 RegLocation rlDest, RegLocation rlSrc)
buzbee67bf8852011-08-17 17:51:35 -0700110{
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 int op = kThumbBkpt;
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 int srcReg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 RegLocation rlResult;
buzbee67bf8852011-08-17 17:51:35 -0700114
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 switch (opcode) {
116 case Instruction::INT_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 op = kThumb2VcvtIF;
118 break;
119 case Instruction::FLOAT_TO_INT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 op = kThumb2VcvtFI;
121 break;
122 case Instruction::DOUBLE_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700123 op = kThumb2VcvtDF;
124 break;
125 case Instruction::FLOAT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 op = kThumb2VcvtFd;
127 break;
128 case Instruction::INT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 op = kThumb2VcvtID;
130 break;
131 case Instruction::DOUBLE_TO_INT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 op = kThumb2VcvtDI;
133 break;
134 case Instruction::LONG_TO_DOUBLE:
135 case Instruction::FLOAT_TO_LONG:
136 case Instruction::LONG_TO_FLOAT:
137 case Instruction::DOUBLE_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700138 return genConversionPortable(cUnit, opcode, rlDest, rlSrc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 default:
140 return true;
141 }
buzbee408ad162012-06-06 16:45:18 -0700142 if (rlSrc.wide) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
144 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
145 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
147 srcReg = rlSrc.lowReg;
148 }
buzbee408ad162012-06-06 16:45:18 -0700149 if (rlDest.wide) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
151 newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
152 srcReg);
153 storeValueWide(cUnit, rlDest, rlResult);
154 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
156 newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
157 storeValue(cUnit, rlDest, rlResult);
158 }
159 return false;
buzbee67bf8852011-08-17 17:51:35 -0700160}
161
buzbee84fd6932012-03-29 16:44:16 -0700162void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
163 bool gtBias, bool isDouble)
164{
buzbeea1da8a52012-07-09 14:00:21 -0700165 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 LIR* target = &labelList[bb->taken->id];
167 RegLocation rlSrc1;
168 RegLocation rlSrc2;
169 if (isDouble) {
buzbee15bf9802012-06-12 17:49:27 -0700170 rlSrc1 = oatGetSrcWide(cUnit, mir, 0);
171 rlSrc2 = oatGetSrcWide(cUnit, mir, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
173 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
174 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
175 S2D(rlSrc2.lowReg, rlSrc2.highReg));
176 } else {
177 rlSrc1 = oatGetSrc(cUnit, mir, 0);
178 rlSrc2 = oatGetSrc(cUnit, mir, 1);
179 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
180 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
181 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
182 }
183 newLIR0(cUnit, kThumb2Fmstat);
184 ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
185 switch(ccode) {
186 case kCondEq:
187 case kCondNe:
188 break;
189 case kCondLt:
190 if (gtBias) {
191 ccode = kCondMi;
192 }
193 break;
194 case kCondLe:
195 if (gtBias) {
196 ccode = kCondLs;
197 }
198 break;
199 case kCondGt:
200 if (gtBias) {
201 ccode = kCondHi;
202 }
203 break;
204 case kCondGe:
205 if (gtBias) {
206 ccode = kCondCs;
207 }
208 break;
209 default:
210 LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
211 }
212 opCondBranch(cUnit, ccode, target);
buzbee84fd6932012-03-29 16:44:16 -0700213}
214
215
buzbee408ad162012-06-06 16:45:18 -0700216bool genCmpFP(CompilationUnit* cUnit, Instruction::Code opcode, RegLocation rlDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 RegLocation rlSrc1, RegLocation rlSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700218{
Bill Buzbeea114add2012-05-03 15:00:40 -0700219 bool isDouble;
220 int defaultResult;
221 RegLocation rlResult;
buzbee67bf8852011-08-17 17:51:35 -0700222
buzbee408ad162012-06-06 16:45:18 -0700223 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 case Instruction::CMPL_FLOAT:
225 isDouble = false;
226 defaultResult = -1;
227 break;
228 case Instruction::CMPG_FLOAT:
229 isDouble = false;
230 defaultResult = 1;
231 break;
232 case Instruction::CMPL_DOUBLE:
233 isDouble = true;
234 defaultResult = -1;
235 break;
236 case Instruction::CMPG_DOUBLE:
237 isDouble = true;
238 defaultResult = 1;
239 break;
240 default:
241 return true;
242 }
243 if (isDouble) {
244 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
245 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
246 oatClobberSReg(cUnit, rlDest.sRegLow);
247 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
248 loadConstant(cUnit, rlResult.lowReg, defaultResult);
249 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
250 S2D(rlSrc2.lowReg, rlSrc2.highReg));
251 } else {
252 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
253 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
254 oatClobberSReg(cUnit, rlDest.sRegLow);
255 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
256 loadConstant(cUnit, rlResult.lowReg, defaultResult);
257 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
258 }
259 DCHECK(!FPREG(rlResult.lowReg));
260 newLIR0(cUnit, kThumb2Fmstat);
buzbee67bf8852011-08-17 17:51:35 -0700261
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 opIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
263 newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
264 modifiedImmediate(-defaultResult)); // Must not alter ccodes
265 genBarrier(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700266
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 opIT(cUnit, kArmCondEq, "");
268 loadConstant(cUnit, rlResult.lowReg, 0);
269 genBarrier(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700270
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 storeValue(cUnit, rlDest, rlResult);
272 return false;
buzbee67bf8852011-08-17 17:51:35 -0700273}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800274
275} // namespace art