blob: f5a030b1e0eff3ddb2dc339e21a2a19a50c8d2c0 [file] [log] [blame]
buzbeee88dfbf2012-03-05 11:19:57 -08001/*
2 * Copyright (C) 2012 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
17namespace art {
18
Bill Buzbeea114add2012-05-03 15:00:40 -070019static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
20 RegLocation rlDest, RegLocation rlSrc1,
21 RegLocation rlSrc2) {
Ian Rogersb5d09b22012-03-06 22:14:17 -080022 X86OpCode op = kX86Nop;
23 RegLocation rlResult;
buzbeee88dfbf2012-03-05 11:19:57 -080024
Ian Rogersb5d09b22012-03-06 22:14:17 -080025 /*
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 = kX86AddssRR;
33 break;
34 case Instruction::SUB_FLOAT_2ADDR:
35 case Instruction::SUB_FLOAT:
36 op = kX86SubssRR;
37 break;
38 case Instruction::DIV_FLOAT_2ADDR:
39 case Instruction::DIV_FLOAT:
40 op = kX86DivssRR;
41 break;
42 case Instruction::MUL_FLOAT_2ADDR:
43 case Instruction::MUL_FLOAT:
44 op = kX86MulssRR;
45 break;
46 case Instruction::NEG_FLOAT:
47 UNIMPLEMENTED(WARNING) << "inline fneg"; // pxor xmm, [0x80000000]
48 // fall-through
49 case Instruction::REM_FLOAT_2ADDR:
50 case Instruction::REM_FLOAT: {
51 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee88dfbf2012-03-05 11:19:57 -080052 }
Ian Rogersb5d09b22012-03-06 22:14:17 -080053 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 int rDest = rlResult.lowReg;
60 int rSrc1 = rlSrc1.lowReg;
61 int rSrc2 = rlSrc2.lowReg;
62 // TODO: at least CHECK_NE(rDest, rSrc2);
63 opRegCopy(cUnit, rDest, rSrc1);
64 newLIR2(cUnit, op, rDest, rSrc2);
65 storeValue(cUnit, rlDest, rlResult);
buzbeee88dfbf2012-03-05 11:19:57 -080066
Ian Rogersb5d09b22012-03-06 22:14:17 -080067 return false;
buzbeee88dfbf2012-03-05 11:19:57 -080068}
69
70static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
71 RegLocation rlDest, RegLocation rlSrc1,
Ian Rogersb5d09b22012-03-06 22:14:17 -080072 RegLocation rlSrc2) {
73 X86OpCode op = kX86Nop;
74 RegLocation rlResult;
buzbeee88dfbf2012-03-05 11:19:57 -080075
Ian Rogersb5d09b22012-03-06 22:14:17 -080076 switch (mir->dalvikInsn.opcode) {
77 case Instruction::ADD_DOUBLE_2ADDR:
78 case Instruction::ADD_DOUBLE:
79 op = kX86AddsdRR;
80 break;
81 case Instruction::SUB_DOUBLE_2ADDR:
82 case Instruction::SUB_DOUBLE:
83 op = kX86SubsdRR;
84 break;
85 case Instruction::DIV_DOUBLE_2ADDR:
86 case Instruction::DIV_DOUBLE:
87 op = kX86DivsdRR;
88 break;
89 case Instruction::MUL_DOUBLE_2ADDR:
90 case Instruction::MUL_DOUBLE:
91 op = kX86MulsdRR;
92 break;
93 case Instruction::NEG_DOUBLE:
94 case Instruction::REM_DOUBLE_2ADDR:
95 case Instruction::REM_DOUBLE: {
96 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee88dfbf2012-03-05 11:19:57 -080097 }
Ian Rogersb5d09b22012-03-06 22:14:17 -080098 default:
99 return true;
100 }
101 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
102 DCHECK(rlSrc1.wide);
103 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
104 DCHECK(rlSrc2.wide);
105 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
106 DCHECK(rlDest.wide);
107 DCHECK(rlResult.wide);
108 int rDest = S2D(rlResult.lowReg, rlResult.highReg);
109 int rSrc1 = S2D(rlSrc1.lowReg, rlSrc1.highReg);
110 int rSrc2 = S2D(rlSrc2.lowReg, rlSrc2.highReg);
111 // TODO: at least CHECK_NE(rDest, rSrc2);
112 opRegCopy(cUnit, rDest, rSrc1);
113 newLIR2(cUnit, op, rDest, rSrc2);
114 storeValueWide(cUnit, rlDest, rlResult);
115 return false;
buzbeee88dfbf2012-03-05 11:19:57 -0800116}
117
Ian Rogersb5d09b22012-03-06 22:14:17 -0800118static bool genConversion(CompilationUnit *cUnit, MIR *mir) {
119 Instruction::Code opcode = mir->dalvikInsn.opcode;
120 bool longSrc = false;
121 bool longDest = false;
122 RegLocation rlSrc;
123 RegLocation rlDest;
124 X86OpCode op = kX86Nop;
125 int srcReg;
126 RegLocation rlResult;
127 switch (opcode) {
128 case Instruction::INT_TO_FLOAT:
129 longSrc = false;
130 longDest = false;
131 op = kX86Cvtsi2ssRR;
132 break;
133 case Instruction::DOUBLE_TO_FLOAT:
134 longSrc = true;
135 longDest = false;
136 op = kX86Cvtsd2ssRR;
137 break;
138 case Instruction::FLOAT_TO_DOUBLE:
139 longSrc = false;
140 longDest = true;
141 op = kX86Cvtss2sdRR;
142 break;
143 case Instruction::INT_TO_DOUBLE:
144 longSrc = false;
145 longDest = true;
146 op = kX86Cvtsi2sdRR;
147 break;
148 case Instruction::FLOAT_TO_INT:
149 case Instruction::DOUBLE_TO_INT:
150 // These are easy to implement inline except when the src is > MAX_INT/LONG the result
151 // needs to be changed from 0x80000000 to 0x7FFFFFF (requires an in memory float/double
152 // literal constant to compare against).
Elliott Hughes225ae522012-04-16 20:21:45 -0700153 UNIMPLEMENTED(WARNING) << "inline [df]2i " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800154 case Instruction::LONG_TO_DOUBLE:
155 case Instruction::FLOAT_TO_LONG:
156 case Instruction::LONG_TO_FLOAT:
157 case Instruction::DOUBLE_TO_LONG:
158 return genConversionPortable(cUnit, mir);
159 default:
160 return true;
161 }
162 if (longSrc) {
163 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
164 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
165 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
166 } else {
167 rlSrc = oatGetSrc(cUnit, mir, 0);
168 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
169 srcReg = rlSrc.lowReg;
170 }
171 if (longDest) {
172 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
173 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
174 newLIR2(cUnit, op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
175 storeValueWide(cUnit, rlDest, rlResult);
176 } else {
177 rlDest = oatGetDest(cUnit, mir, 0);
178 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
179 newLIR2(cUnit, op, rlResult.lowReg, srcReg);
180 storeValue(cUnit, rlDest, rlResult);
181 }
182 return false;
buzbeee88dfbf2012-03-05 11:19:57 -0800183}
184
185static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800186 RegLocation rlSrc1, RegLocation rlSrc2) {
187 Instruction::Code code = mir->dalvikInsn.opcode;
188 bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT);
189 bool unorderedGt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT);
190 int srcReg1;
191 int srcReg2;
192 if (single) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800193 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
194 srcReg1 = rlSrc1.lowReg;
jeffhao644d5312012-05-03 19:04:49 -0700195 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
196 srcReg2 = rlSrc2.lowReg;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800197 } else {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800198 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
199 srcReg1 = S2D(rlSrc1.lowReg, rlSrc1.highReg);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800200 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
201 srcReg2 = S2D(rlSrc2.lowReg, rlSrc2.highReg);
202 }
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700203 RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
204 loadConstantNoClobber(cUnit, rlResult.lowReg, unorderedGt ? 1 : 0);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800205 if (single) {
206 newLIR2(cUnit, kX86UcomissRR, srcReg1, srcReg2);
207 } else {
208 newLIR2(cUnit, kX86UcomisdRR, srcReg1, srcReg2);
209 }
210 LIR* branch = NULL;
211 if (unorderedGt) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700212 branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800213 }
214 newLIR2(cUnit, kX86Set8R, rlResult.lowReg, kX86CondA /* above - unsigned > */);
215 newLIR2(cUnit, kX86Sbb32RI, rlResult.lowReg, 0);
216 if (unorderedGt) {
217 branch->target = newLIR0(cUnit, kPseudoTargetLabel);
218 }
jeffhao644d5312012-05-03 19:04:49 -0700219 storeValue(cUnit, rlDest, rlResult);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800220 return false;
buzbeee88dfbf2012-03-05 11:19:57 -0800221}
222
223} // namespace art