blob: 494e09f42b794a0a18994a9b8ba50b4f401a84c4 [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
buzbeeed3e9302011-09-23 17:34:19 -070019STATIC bool genArithOpFloat(CompilationUnit* cUnit, MIR* mir,
buzbee67bf8852011-08-17 17:51:35 -070020 RegLocation rlDest, RegLocation rlSrc1,
21 RegLocation rlSrc2)
22{
23 int op = kThumbBkpt;
24 RegLocation rlResult;
25
26 /*
27 * Don't attempt to optimize register usage since these opcodes call out to
28 * the handlers.
29 */
30 switch (mir->dalvikInsn.opcode) {
31 case OP_ADD_FLOAT_2ADDR:
32 case OP_ADD_FLOAT:
33 op = kThumb2Vadds;
34 break;
35 case OP_SUB_FLOAT_2ADDR:
36 case OP_SUB_FLOAT:
37 op = kThumb2Vsubs;
38 break;
39 case OP_DIV_FLOAT_2ADDR:
40 case OP_DIV_FLOAT:
41 op = kThumb2Vdivs;
42 break;
43 case OP_MUL_FLOAT_2ADDR:
44 case OP_MUL_FLOAT:
45 op = kThumb2Vmuls;
46 break;
47 case OP_REM_FLOAT_2ADDR:
48 case OP_REM_FLOAT:
49 case OP_NEG_FLOAT: {
50 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1,
51 rlSrc2);
52 }
53 default:
54 return true;
55 }
56 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
57 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
58 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
59 newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg,
60 rlSrc2.lowReg);
61 storeValue(cUnit, rlDest, rlResult);
62 return false;
63}
64
buzbeeed3e9302011-09-23 17:34:19 -070065STATIC bool genArithOpDouble(CompilationUnit* cUnit, MIR* mir,
buzbee67bf8852011-08-17 17:51:35 -070066 RegLocation rlDest, RegLocation rlSrc1,
67 RegLocation rlSrc2)
68{
69 int op = kThumbBkpt;
70 RegLocation rlResult;
71
72 switch (mir->dalvikInsn.opcode) {
73 case OP_ADD_DOUBLE_2ADDR:
74 case OP_ADD_DOUBLE:
75 op = kThumb2Vaddd;
76 break;
77 case OP_SUB_DOUBLE_2ADDR:
78 case OP_SUB_DOUBLE:
79 op = kThumb2Vsubd;
80 break;
81 case OP_DIV_DOUBLE_2ADDR:
82 case OP_DIV_DOUBLE:
83 op = kThumb2Vdivd;
84 break;
85 case OP_MUL_DOUBLE_2ADDR:
86 case OP_MUL_DOUBLE:
87 op = kThumb2Vmuld;
88 break;
89 case OP_REM_DOUBLE_2ADDR:
90 case OP_REM_DOUBLE:
91 case OP_NEG_DOUBLE: {
92 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
93 rlSrc2);
94 }
95 default:
96 return true;
97 }
98
99 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
buzbeeed3e9302011-09-23 17:34:19 -0700100 DCHECK(rlSrc1.wide);
buzbee67bf8852011-08-17 17:51:35 -0700101 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
buzbeeed3e9302011-09-23 17:34:19 -0700102 DCHECK(rlSrc2.wide);
buzbee67bf8852011-08-17 17:51:35 -0700103 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
buzbeeed3e9302011-09-23 17:34:19 -0700104 DCHECK(rlDest.wide);
105 DCHECK(rlResult.wide);
buzbee67bf8852011-08-17 17:51:35 -0700106 newLIR3(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
107 S2D(rlSrc1.lowReg, rlSrc1.highReg),
108 S2D(rlSrc2.lowReg, rlSrc2.highReg));
109 storeValueWide(cUnit, rlDest, rlResult);
110 return false;
111}
112
buzbeeed3e9302011-09-23 17:34:19 -0700113STATIC bool genConversion(CompilationUnit* cUnit, MIR* mir)
buzbee67bf8852011-08-17 17:51:35 -0700114{
115 Opcode opcode = mir->dalvikInsn.opcode;
116 int op = kThumbBkpt;
117 bool longSrc = false;
118 bool longDest = false;
119 int srcReg;
120 RegLocation rlSrc;
121 RegLocation rlDest;
122 RegLocation rlResult;
123
124 switch (opcode) {
125 case OP_INT_TO_FLOAT:
126 longSrc = false;
127 longDest = false;
128 op = kThumb2VcvtIF;
129 break;
130 case OP_FLOAT_TO_INT:
131 longSrc = false;
132 longDest = false;
133 op = kThumb2VcvtFI;
134 break;
135 case OP_DOUBLE_TO_FLOAT:
136 longSrc = true;
137 longDest = false;
138 op = kThumb2VcvtDF;
139 break;
140 case OP_FLOAT_TO_DOUBLE:
141 longSrc = false;
142 longDest = true;
143 op = kThumb2VcvtFd;
144 break;
145 case OP_INT_TO_DOUBLE:
146 longSrc = false;
147 longDest = true;
148 op = kThumb2VcvtID;
149 break;
150 case OP_DOUBLE_TO_INT:
151 longSrc = true;
152 longDest = false;
153 op = kThumb2VcvtDI;
154 break;
155 case OP_LONG_TO_DOUBLE:
156 case OP_FLOAT_TO_LONG:
157 case OP_LONG_TO_FLOAT:
158 case OP_DOUBLE_TO_LONG:
159 return genConversionPortable(cUnit, mir);
160 default:
161 return true;
162 }
163 if (longSrc) {
164 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
165 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
166 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
167 } else {
168 rlSrc = oatGetSrc(cUnit, mir, 0);
169 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
170 srcReg = rlSrc.lowReg;
171 }
172 if (longDest) {
173 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
174 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
175 newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
176 srcReg);
177 storeValueWide(cUnit, rlDest, rlResult);
178 } else {
179 rlDest = oatGetDest(cUnit, mir, 0);
180 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
181 newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
182 storeValue(cUnit, rlDest, rlResult);
183 }
184 return false;
185}
186
buzbeeed3e9302011-09-23 17:34:19 -0700187STATIC bool genCmpFP(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
buzbee67bf8852011-08-17 17:51:35 -0700188 RegLocation rlSrc1, RegLocation rlSrc2)
189{
190 bool isDouble;
191 int defaultResult;
192 RegLocation rlResult;
193
194 switch(mir->dalvikInsn.opcode) {
195 case OP_CMPL_FLOAT:
196 isDouble = false;
197 defaultResult = -1;
198 break;
199 case OP_CMPG_FLOAT:
200 isDouble = false;
201 defaultResult = 1;
202 break;
203 case OP_CMPL_DOUBLE:
204 isDouble = true;
205 defaultResult = -1;
206 break;
207 case OP_CMPG_DOUBLE:
208 isDouble = true;
209 defaultResult = 1;
210 break;
211 default:
212 return true;
213 }
214 if (isDouble) {
215 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
216 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
217 oatClobberSReg(cUnit, rlDest.sRegLow);
218 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
219 loadConstant(cUnit, rlResult.lowReg, defaultResult);
220 newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
221 S2D(rlSrc2.lowReg, rlSrc2.highReg));
222 } else {
223 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
224 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
225 oatClobberSReg(cUnit, rlDest.sRegLow);
226 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
227 loadConstant(cUnit, rlResult.lowReg, defaultResult);
228 newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
229 }
buzbeeed3e9302011-09-23 17:34:19 -0700230 DCHECK(!FPREG(rlResult.lowReg));
buzbee67bf8852011-08-17 17:51:35 -0700231 newLIR0(cUnit, kThumb2Fmstat);
232
233 genIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
234 newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
235 modifiedImmediate(-defaultResult)); // Must not alter ccodes
236 genBarrier(cUnit);
237
238 genIT(cUnit, kArmCondEq, "");
239 loadConstant(cUnit, rlResult.lowReg, 0);
240 genBarrier(cUnit);
241
242 storeValue(cUnit, rlDest, rlResult);
243 return false;
244}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800245
246} // namespace art