blob: c91664055cdfd3c5e7f42589b22691ea14aef778 [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
19bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
Ian Rogersb5d09b22012-03-06 22:14:17 -080020 RegLocation rlSrc1, RegLocation rlSrc2) {
21 X86OpCode op = kX86Nop;
22 RegLocation rlResult;
buzbeee88dfbf2012-03-05 11:19:57 -080023
Ian Rogersb5d09b22012-03-06 22:14:17 -080024 /*
25 * Don't attempt to optimize register usage since these opcodes call out to
26 * the handlers.
27 */
28 switch (mir->dalvikInsn.opcode) {
29 case Instruction::ADD_FLOAT_2ADDR:
30 case Instruction::ADD_FLOAT:
31 op = kX86AddssRR;
32 break;
33 case Instruction::SUB_FLOAT_2ADDR:
34 case Instruction::SUB_FLOAT:
35 op = kX86SubssRR;
36 break;
37 case Instruction::DIV_FLOAT_2ADDR:
38 case Instruction::DIV_FLOAT:
39 op = kX86DivssRR;
40 break;
41 case Instruction::MUL_FLOAT_2ADDR:
42 case Instruction::MUL_FLOAT:
43 op = kX86MulssRR;
44 break;
45 case Instruction::NEG_FLOAT:
46 UNIMPLEMENTED(WARNING) << "inline fneg"; // pxor xmm, [0x80000000]
47 // fall-through
48 case Instruction::REM_FLOAT_2ADDR:
49 case Instruction::REM_FLOAT: {
50 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee88dfbf2012-03-05 11:19:57 -080051 }
Ian Rogersb5d09b22012-03-06 22:14:17 -080052 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 int rDest = rlResult.lowReg;
59 int rSrc1 = rlSrc1.lowReg;
60 int rSrc2 = rlSrc2.lowReg;
61 // TODO: at least CHECK_NE(rDest, rSrc2);
62 opRegCopy(cUnit, rDest, rSrc1);
63 newLIR2(cUnit, op, rDest, rSrc2);
64 storeValue(cUnit, rlDest, rlResult);
buzbeee88dfbf2012-03-05 11:19:57 -080065
Ian Rogersb5d09b22012-03-06 22:14:17 -080066 return false;
buzbeee88dfbf2012-03-05 11:19:57 -080067}
68
69static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
70 RegLocation rlDest, RegLocation rlSrc1,
Ian Rogersb5d09b22012-03-06 22:14:17 -080071 RegLocation rlSrc2) {
72 X86OpCode op = kX86Nop;
73 RegLocation rlResult;
buzbeee88dfbf2012-03-05 11:19:57 -080074
Ian Rogersb5d09b22012-03-06 22:14:17 -080075 switch (mir->dalvikInsn.opcode) {
76 case Instruction::ADD_DOUBLE_2ADDR:
77 case Instruction::ADD_DOUBLE:
78 op = kX86AddsdRR;
79 break;
80 case Instruction::SUB_DOUBLE_2ADDR:
81 case Instruction::SUB_DOUBLE:
82 op = kX86SubsdRR;
83 break;
84 case Instruction::DIV_DOUBLE_2ADDR:
85 case Instruction::DIV_DOUBLE:
86 op = kX86DivsdRR;
87 break;
88 case Instruction::MUL_DOUBLE_2ADDR:
89 case Instruction::MUL_DOUBLE:
90 op = kX86MulsdRR;
91 break;
92 case Instruction::NEG_DOUBLE:
93 case Instruction::REM_DOUBLE_2ADDR:
94 case Instruction::REM_DOUBLE: {
95 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee88dfbf2012-03-05 11:19:57 -080096 }
Ian Rogersb5d09b22012-03-06 22:14:17 -080097 default:
98 return true;
99 }
100 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
101 DCHECK(rlSrc1.wide);
102 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
103 DCHECK(rlSrc2.wide);
104 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
105 DCHECK(rlDest.wide);
106 DCHECK(rlResult.wide);
107 int rDest = S2D(rlResult.lowReg, rlResult.highReg);
108 int rSrc1 = S2D(rlSrc1.lowReg, rlSrc1.highReg);
109 int rSrc2 = S2D(rlSrc2.lowReg, rlSrc2.highReg);
110 // TODO: at least CHECK_NE(rDest, rSrc2);
111 opRegCopy(cUnit, rDest, rSrc1);
112 newLIR2(cUnit, op, rDest, rSrc2);
113 storeValueWide(cUnit, rlDest, rlResult);
114 return false;
buzbeee88dfbf2012-03-05 11:19:57 -0800115}
116
Ian Rogersb5d09b22012-03-06 22:14:17 -0800117static bool genConversion(CompilationUnit *cUnit, MIR *mir) {
118 Instruction::Code opcode = mir->dalvikInsn.opcode;
119 bool longSrc = false;
120 bool longDest = false;
121 RegLocation rlSrc;
122 RegLocation rlDest;
123 X86OpCode op = kX86Nop;
124 int srcReg;
125 RegLocation rlResult;
126 switch (opcode) {
127 case Instruction::INT_TO_FLOAT:
128 longSrc = false;
129 longDest = false;
130 op = kX86Cvtsi2ssRR;
131 break;
132 case Instruction::DOUBLE_TO_FLOAT:
133 longSrc = true;
134 longDest = false;
135 op = kX86Cvtsd2ssRR;
136 break;
137 case Instruction::FLOAT_TO_DOUBLE:
138 longSrc = false;
139 longDest = true;
140 op = kX86Cvtss2sdRR;
141 break;
142 case Instruction::INT_TO_DOUBLE:
143 longSrc = false;
144 longDest = true;
145 op = kX86Cvtsi2sdRR;
146 break;
147 case Instruction::FLOAT_TO_INT:
148 case Instruction::DOUBLE_TO_INT:
149 // These are easy to implement inline except when the src is > MAX_INT/LONG the result
150 // needs to be changed from 0x80000000 to 0x7FFFFFF (requires an in memory float/double
151 // literal constant to compare against).
152 UNIMPLEMENTED(WARNING) << "inline [df]2i";
153 case Instruction::LONG_TO_DOUBLE:
154 case Instruction::FLOAT_TO_LONG:
155 case Instruction::LONG_TO_FLOAT:
156 case Instruction::DOUBLE_TO_LONG:
157 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, op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
174 storeValueWide(cUnit, rlDest, rlResult);
175 } else {
176 rlDest = oatGetDest(cUnit, mir, 0);
177 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
178 newLIR2(cUnit, op, rlResult.lowReg, srcReg);
179 storeValue(cUnit, rlDest, rlResult);
180 }
181 return false;
buzbeee88dfbf2012-03-05 11:19:57 -0800182}
183
184static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800185 RegLocation rlSrc1, RegLocation rlSrc2) {
186 Instruction::Code code = mir->dalvikInsn.opcode;
187 bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT);
188 bool unorderedGt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT);
189 int srcReg1;
190 int srcReg2;
191 if (single) {
192 rlSrc1 = oatGetSrc(cUnit, mir, 0);
193 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
194 srcReg1 = rlSrc1.lowReg;
195 rlSrc2 = oatGetSrc(cUnit, mir, 0);
196 rlSrc2 = loadValue(cUnit, rlSrc1, kFPReg);
197 srcReg2 = rlSrc1.lowReg;
198 } else {
199 rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
200 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
201 srcReg1 = S2D(rlSrc1.lowReg, rlSrc1.highReg);
202 rlSrc2 = oatGetSrcWide(cUnit, mir, 0, 1);
203 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
204 srcReg2 = S2D(rlSrc2.lowReg, rlSrc2.highReg);
205 }
206 rlDest = oatGetDest(cUnit, mir, 0);
207 RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
208 opRegImm(cUnit, kOpMov, rlResult.lowReg, unorderedGt ? 1 : 0);
209 if (single) {
210 newLIR2(cUnit, kX86UcomissRR, srcReg1, srcReg2);
211 } else {
212 newLIR2(cUnit, kX86UcomisdRR, srcReg1, srcReg2);
213 }
214 LIR* branch = NULL;
215 if (unorderedGt) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700216 branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800217 }
218 newLIR2(cUnit, kX86Set8R, rlResult.lowReg, kX86CondA /* above - unsigned > */);
219 newLIR2(cUnit, kX86Sbb32RI, rlResult.lowReg, 0);
220 if (unorderedGt) {
221 branch->target = newLIR0(cUnit, kPseudoTargetLabel);
222 }
223 return false;
buzbeee88dfbf2012-03-05 11:19:57 -0800224}
225
226} // namespace art