blob: 9bfcd555557e8ed98245e3ce27d3028bce2ef381 [file] [log] [blame]
Ben Cheng5d90c202009-11-22 23:31:11 -08001/*
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
17/*
18 * This file is included by Codegen-armv5te-vfp.c, and implements architecture
19 * variant-specific code.
20 */
21
buzbee10a548d2010-08-13 17:52:46 -070022/*
23 * Take the address of a Dalvik register and store it into rDest.
24 * Clobber any live values associated either with the Dalvik value
25 * or the target register and lock the target fixed register.
26 */
27static void loadValueAddressDirect(CompilationUnit *cUnit, RegLocation rlSrc,
28 int rDest)
Ben Cheng5d90c202009-11-22 23:31:11 -080029{
Bill Buzbeec6f10662010-02-09 11:16:15 -080030 rlSrc = rlSrc.wide ? dvmCompilerUpdateLocWide(cUnit, rlSrc) :
31 dvmCompilerUpdateLoc(cUnit, rlSrc);
Ben Cheng5d90c202009-11-22 23:31:11 -080032 if (rlSrc.location == kLocPhysReg) {
33 if (rlSrc.wide) {
buzbeef6789272010-09-24 15:37:12 -070034 dvmCompilerFlushRegWide(cUnit, rlSrc.lowReg, rlSrc.highReg);
Ben Cheng5d90c202009-11-22 23:31:11 -080035 } else {
buzbeef6789272010-09-24 15:37:12 -070036 dvmCompilerFlushReg(cUnit, rlSrc.lowReg);
Ben Cheng5d90c202009-11-22 23:31:11 -080037 }
38 }
buzbee10a548d2010-08-13 17:52:46 -070039 dvmCompilerClobber(cUnit, rDest);
40 dvmCompilerLockTemp(cUnit, rDest);
Ben Cheng5d90c202009-11-22 23:31:11 -080041 opRegRegImm(cUnit, kOpAdd, rDest, rFP,
Bill Buzbeec6f10662010-02-09 11:16:15 -080042 dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2);
Ben Cheng5d90c202009-11-22 23:31:11 -080043}
44
45static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
46{
Bill Buzbeec6f10662010-02-09 11:16:15 -080047 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Ben Cheng5d90c202009-11-22 23:31:11 -080048 RegLocation rlResult = LOC_C_RETURN_WIDE;
49 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
buzbee10a548d2010-08-13 17:52:46 -070050 loadValueAddressDirect(cUnit, rlSrc, r2);
Ben Cheng5d90c202009-11-22 23:31:11 -080051 genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
52 storeValueWide(cUnit, rlDest, rlResult);
53 return false;
54}
55
56/*
57 * TUNING: On some implementations, it is quicker to pass addresses
58 * to the handlers rather than load the operands into core registers
59 * and then move the values to FP regs in the handlers. Other implementations
60 * may prefer passing data in registers (and the latter approach would
61 * yeild cleaner register handling - avoiding the requirement that operands
62 * be flushed to memory prior to the call).
63 */
64static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
65 RegLocation rlDest, RegLocation rlSrc1,
66 RegLocation rlSrc2)
67{
Dan Bornstein9a1f8162010-12-01 17:02:26 -080068 TemplateOpcode opcode;
Ben Cheng5d90c202009-11-22 23:31:11 -080069
70 /*
71 * Don't attempt to optimize register usage since these opcodes call out to
72 * the handlers.
73 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -080074 switch (mir->dalvikInsn.opcode) {
Ben Cheng5d90c202009-11-22 23:31:11 -080075 case OP_ADD_FLOAT_2ADDR:
76 case OP_ADD_FLOAT:
Dan Bornstein9a1f8162010-12-01 17:02:26 -080077 opcode = TEMPLATE_ADD_FLOAT_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -080078 break;
79 case OP_SUB_FLOAT_2ADDR:
80 case OP_SUB_FLOAT:
Dan Bornstein9a1f8162010-12-01 17:02:26 -080081 opcode = TEMPLATE_SUB_FLOAT_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -080082 break;
83 case OP_DIV_FLOAT_2ADDR:
84 case OP_DIV_FLOAT:
Dan Bornstein9a1f8162010-12-01 17:02:26 -080085 opcode = TEMPLATE_DIV_FLOAT_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -080086 break;
87 case OP_MUL_FLOAT_2ADDR:
88 case OP_MUL_FLOAT:
Dan Bornstein9a1f8162010-12-01 17:02:26 -080089 opcode = TEMPLATE_MUL_FLOAT_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -080090 break;
91 case OP_REM_FLOAT_2ADDR:
92 case OP_REM_FLOAT:
93 case OP_NEG_FLOAT: {
94 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
95 }
96 default:
97 return true;
98 }
buzbee10a548d2010-08-13 17:52:46 -070099 loadValueAddressDirect(cUnit, rlDest, r0);
100 loadValueAddressDirect(cUnit, rlSrc1, r1);
101 loadValueAddressDirect(cUnit, rlSrc2, r2);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800102 genDispatchToHandler(cUnit, opcode);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800103 rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
Ben Cheng5d90c202009-11-22 23:31:11 -0800104 if (rlDest.location == kLocPhysReg) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800105 dvmCompilerClobber(cUnit, rlDest.lowReg);
Ben Cheng5d90c202009-11-22 23:31:11 -0800106 }
107 return false;
108}
109
110static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
111 RegLocation rlDest, RegLocation rlSrc1,
112 RegLocation rlSrc2)
113{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800114 TemplateOpcode opcode;
Ben Cheng5d90c202009-11-22 23:31:11 -0800115
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800116 switch (mir->dalvikInsn.opcode) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800117 case OP_ADD_DOUBLE_2ADDR:
118 case OP_ADD_DOUBLE:
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800119 opcode = TEMPLATE_ADD_DOUBLE_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -0800120 break;
121 case OP_SUB_DOUBLE_2ADDR:
122 case OP_SUB_DOUBLE:
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800123 opcode = TEMPLATE_SUB_DOUBLE_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -0800124 break;
125 case OP_DIV_DOUBLE_2ADDR:
126 case OP_DIV_DOUBLE:
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800127 opcode = TEMPLATE_DIV_DOUBLE_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -0800128 break;
129 case OP_MUL_DOUBLE_2ADDR:
130 case OP_MUL_DOUBLE:
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800131 opcode = TEMPLATE_MUL_DOUBLE_VFP;
Ben Cheng5d90c202009-11-22 23:31:11 -0800132 break;
133 case OP_REM_DOUBLE_2ADDR:
134 case OP_REM_DOUBLE:
135 case OP_NEG_DOUBLE: {
136 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
137 rlSrc2);
138 }
139 default:
140 return true;
141 }
buzbee10a548d2010-08-13 17:52:46 -0700142 loadValueAddressDirect(cUnit, rlDest, r0);
143 loadValueAddressDirect(cUnit, rlSrc1, r1);
144 loadValueAddressDirect(cUnit, rlSrc2, r2);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800145 genDispatchToHandler(cUnit, opcode);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800146 rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
Ben Cheng5d90c202009-11-22 23:31:11 -0800147 if (rlDest.location == kLocPhysReg) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800148 dvmCompilerClobber(cUnit, rlDest.lowReg);
149 dvmCompilerClobber(cUnit, rlDest.highReg);
Ben Cheng5d90c202009-11-22 23:31:11 -0800150 }
151 return false;
152}
153
154static bool genConversion(CompilationUnit *cUnit, MIR *mir)
155{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800156 Opcode opcode = mir->dalvikInsn.opcode;
Ben Cheng5d90c202009-11-22 23:31:11 -0800157 bool longSrc = false;
158 bool longDest = false;
159 RegLocation rlSrc;
160 RegLocation rlDest;
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800161 TemplateOpcode template;
162 switch (opcode) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800163 case OP_INT_TO_FLOAT:
164 longSrc = false;
165 longDest = false;
166 template = TEMPLATE_INT_TO_FLOAT_VFP;
167 break;
168 case OP_FLOAT_TO_INT:
169 longSrc = false;
170 longDest = false;
171 template = TEMPLATE_FLOAT_TO_INT_VFP;
172 break;
173 case OP_DOUBLE_TO_FLOAT:
174 longSrc = true;
175 longDest = false;
176 template = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
177 break;
178 case OP_FLOAT_TO_DOUBLE:
179 longSrc = false;
180 longDest = true;
181 template = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
182 break;
183 case OP_INT_TO_DOUBLE:
184 longSrc = false;
185 longDest = true;
186 template = TEMPLATE_INT_TO_DOUBLE_VFP;
187 break;
188 case OP_DOUBLE_TO_INT:
189 longSrc = true;
190 longDest = false;
191 template = TEMPLATE_DOUBLE_TO_INT_VFP;
192 break;
193 case OP_LONG_TO_DOUBLE:
194 case OP_FLOAT_TO_LONG:
195 case OP_LONG_TO_FLOAT:
196 case OP_DOUBLE_TO_LONG:
197 return genConversionPortable(cUnit, mir);
198 default:
199 return true;
200 }
201
202 if (longSrc) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800203 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Ben Cheng5d90c202009-11-22 23:31:11 -0800204 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800205 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Ben Cheng5d90c202009-11-22 23:31:11 -0800206 }
207
208 if (longDest) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800209 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Ben Cheng5d90c202009-11-22 23:31:11 -0800210 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800211 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Ben Cheng5d90c202009-11-22 23:31:11 -0800212 }
buzbee10a548d2010-08-13 17:52:46 -0700213 loadValueAddressDirect(cUnit, rlDest, r0);
214 loadValueAddressDirect(cUnit, rlSrc, r1);
Ben Cheng5d90c202009-11-22 23:31:11 -0800215 genDispatchToHandler(cUnit, template);
216 if (rlDest.wide) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800217 rlDest = dvmCompilerUpdateLocWide(cUnit, rlDest);
218 dvmCompilerClobber(cUnit, rlDest.highReg);
Ben Cheng5d90c202009-11-22 23:31:11 -0800219 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800220 rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
Ben Cheng5d90c202009-11-22 23:31:11 -0800221 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800222 dvmCompilerClobber(cUnit, rlDest.lowReg);
Ben Cheng5d90c202009-11-22 23:31:11 -0800223 return false;
224}
225
226static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800227 RegLocation rlSrc1, RegLocation rlSrc2)
Ben Cheng5d90c202009-11-22 23:31:11 -0800228{
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800229 TemplateOpcode template;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800230 RegLocation rlResult = dvmCompilerGetReturn(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -0800231 bool wide = true;
232
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800233 switch(mir->dalvikInsn.opcode) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800234 case OP_CMPL_FLOAT:
235 template = TEMPLATE_CMPL_FLOAT_VFP;
236 wide = false;
237 break;
238 case OP_CMPG_FLOAT:
239 template = TEMPLATE_CMPG_FLOAT_VFP;
240 wide = false;
241 break;
242 case OP_CMPL_DOUBLE:
243 template = TEMPLATE_CMPL_DOUBLE_VFP;
244 break;
245 case OP_CMPG_DOUBLE:
246 template = TEMPLATE_CMPG_DOUBLE_VFP;
247 break;
248 default:
249 return true;
250 }
buzbee10a548d2010-08-13 17:52:46 -0700251 loadValueAddressDirect(cUnit, rlSrc1, r0);
252 loadValueAddressDirect(cUnit, rlSrc2, r1);
Ben Cheng5d90c202009-11-22 23:31:11 -0800253 genDispatchToHandler(cUnit, template);
254 storeValue(cUnit, rlDest, rlResult);
255 return false;
256}