blob: ec4d9db0bb5a103909ee1926b066751b77c5947b [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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
17#include "codegen_x86.h"
18#include "dex/quick/mir_to_lir-inl.h"
19#include "x86_lir.h"
20
21namespace art {
22
23void X86Mir2Lir::GenArithOpFloat(Instruction::Code opcode,
24 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
25 X86OpCode op = kX86Nop;
26 RegLocation rl_result;
27
28 /*
29 * Don't attempt to optimize register usage since these opcodes call out to
30 * the handlers.
31 */
32 switch (opcode) {
33 case Instruction::ADD_FLOAT_2ADDR:
34 case Instruction::ADD_FLOAT:
35 op = kX86AddssRR;
36 break;
37 case Instruction::SUB_FLOAT_2ADDR:
38 case Instruction::SUB_FLOAT:
39 op = kX86SubssRR;
40 break;
41 case Instruction::DIV_FLOAT_2ADDR:
42 case Instruction::DIV_FLOAT:
43 op = kX86DivssRR;
44 break;
45 case Instruction::MUL_FLOAT_2ADDR:
46 case Instruction::MUL_FLOAT:
47 op = kX86MulssRR;
48 break;
49 case Instruction::REM_FLOAT_2ADDR:
50 case Instruction::REM_FLOAT:
51 FlushAllRegs(); // Send everything to home location
Ian Rogers7655f292013-07-29 11:07:13 -070052 CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2,
53 false);
Brian Carlstrom7940e442013-07-12 13:46:57 -070054 rl_result = GetReturn(true);
55 StoreValue(rl_dest, rl_result);
56 return;
57 case Instruction::NEG_FLOAT:
58 GenNegFloat(rl_dest, rl_src1);
59 return;
60 default:
61 LOG(FATAL) << "Unexpected opcode: " << opcode;
62 }
63 rl_src1 = LoadValue(rl_src1, kFPReg);
64 rl_src2 = LoadValue(rl_src2, kFPReg);
65 rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee2700f7e2014-03-07 09:46:20 -080066 RegStorage r_dest = rl_result.reg;
67 RegStorage r_src1 = rl_src1.reg;
68 RegStorage r_src2 = rl_src2.reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070069 if (r_dest == r_src2) {
70 r_src2 = AllocTempFloat();
71 OpRegCopy(r_src2, r_dest);
72 }
73 OpRegCopy(r_dest, r_src1);
buzbee2700f7e2014-03-07 09:46:20 -080074 NewLIR2(op, r_dest.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070075 StoreValue(rl_dest, rl_result);
76}
77
78void X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode,
79 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
80 X86OpCode op = kX86Nop;
81 RegLocation rl_result;
82
83 switch (opcode) {
84 case Instruction::ADD_DOUBLE_2ADDR:
85 case Instruction::ADD_DOUBLE:
86 op = kX86AddsdRR;
87 break;
88 case Instruction::SUB_DOUBLE_2ADDR:
89 case Instruction::SUB_DOUBLE:
90 op = kX86SubsdRR;
91 break;
92 case Instruction::DIV_DOUBLE_2ADDR:
93 case Instruction::DIV_DOUBLE:
94 op = kX86DivsdRR;
95 break;
96 case Instruction::MUL_DOUBLE_2ADDR:
97 case Instruction::MUL_DOUBLE:
98 op = kX86MulsdRR;
99 break;
100 case Instruction::REM_DOUBLE_2ADDR:
101 case Instruction::REM_DOUBLE:
102 FlushAllRegs(); // Send everything to home location
Ian Rogers7655f292013-07-29 11:07:13 -0700103 CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2,
104 false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700105 rl_result = GetReturnWide(true);
106 StoreValueWide(rl_dest, rl_result);
107 return;
108 case Instruction::NEG_DOUBLE:
109 GenNegDouble(rl_dest, rl_src1);
110 return;
111 default:
112 LOG(FATAL) << "Unexpected opcode: " << opcode;
113 }
114 rl_src1 = LoadValueWide(rl_src1, kFPReg);
115 DCHECK(rl_src1.wide);
116 rl_src2 = LoadValueWide(rl_src2, kFPReg);
117 DCHECK(rl_src2.wide);
118 rl_result = EvalLoc(rl_dest, kFPReg, true);
119 DCHECK(rl_dest.wide);
120 DCHECK(rl_result.wide);
buzbee2700f7e2014-03-07 09:46:20 -0800121 // TODO: update with direct 64-bit reg.
122 int r_dest = S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg());
123 int r_src1 = S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg());
124 int r_src2 = S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700125 if (r_dest == r_src2) {
buzbee2700f7e2014-03-07 09:46:20 -0800126 r_src2 = AllocTempDouble().GetLowReg() | X86_FP_DOUBLE;
127 OpRegCopy(RegStorage::Solo64(r_src2), RegStorage::Solo64(r_dest));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128 }
buzbee2700f7e2014-03-07 09:46:20 -0800129 OpRegCopy(RegStorage::Solo64(r_dest), RegStorage::Solo64(r_src1));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700130 NewLIR2(op, r_dest, r_src2);
131 StoreValueWide(rl_dest, rl_result);
132}
133
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800134void X86Mir2Lir::GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double) {
135 // Compute offsets to the source and destination VRs on stack
136 int src_v_reg_offset = SRegOffset(rl_src.s_reg_low);
137 int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low);
138
139 // Update the in-register state of source.
140 rl_src = UpdateLocWide(rl_src);
141
142 // If the source is in physical register, then put it in its location on stack.
143 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800144 RegisterInfo* lo_info = GetRegInfo(rl_src.reg.GetLowReg());
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800145
146 if (lo_info != nullptr && lo_info->is_temp) {
147 // Calling FlushSpecificReg because it will only write back VR if it is dirty.
148 FlushSpecificReg(lo_info);
149 } else {
150 // It must have been register promoted if it is not a temp but is still in physical
151 // register. Since we need it to be in memory to convert, we place it there now.
buzbee2700f7e2014-03-07 09:46:20 -0800152 StoreBaseDispWide(TargetReg(kSp), src_v_reg_offset, rl_src.reg);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800153 }
154 }
155
156 // Push the source virtual register onto the x87 stack.
buzbee2700f7e2014-03-07 09:46:20 -0800157 LIR *fild64 = NewLIR2NoDest(kX86Fild64M, TargetReg(kSp).GetReg(), src_v_reg_offset + LOWORD_OFFSET);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800158 AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2,
159 true /* is_load */, true /* is64bit */);
160
161 // Now pop off x87 stack and store it in the destination VR's stack location.
162 int opcode = is_double ? kX86Fstp64M : kX86Fstp32M;
163 int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset;
buzbee2700f7e2014-03-07 09:46:20 -0800164 LIR *fstp = NewLIR2NoDest(opcode, TargetReg(kSp).GetReg(), displacement);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800165 AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double);
166
167 /*
168 * The result is in a physical register if it was in a temp or was register
169 * promoted. For that reason it is enough to check if it is in physical
170 * register. If it is, then we must do all of the bookkeeping necessary to
171 * invalidate temp (if needed) and load in promoted register (if needed).
172 * If the result's location is in memory, then we do not need to do anything
173 * more since the fstp has already placed the correct value in memory.
174 */
175 RegLocation rl_result = is_double ? UpdateLocWide(rl_dest) : UpdateLoc(rl_dest);
176 if (rl_result.location == kLocPhysReg) {
177 /*
178 * We already know that the result is in a physical register but do not know if it is the
179 * right class. So we call EvalLoc(Wide) first which will ensure that it will get moved to the
180 * correct register class.
181 */
182 if (is_double) {
183 rl_result = EvalLocWide(rl_dest, kFPReg, true);
184
buzbee2700f7e2014-03-07 09:46:20 -0800185 LoadBaseDispWide(TargetReg(kSp), dest_v_reg_offset, rl_result.reg, INVALID_SREG);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800186
Maxim Kazantsev51a80d72014-03-06 11:33:26 +0700187 StoreFinalValueWide(rl_dest, rl_result);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800188 } else {
189 rl_result = EvalLoc(rl_dest, kFPReg, true);
190
buzbee2700f7e2014-03-07 09:46:20 -0800191 LoadWordDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.reg);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800192
Maxim Kazantsev51a80d72014-03-06 11:33:26 +0700193 StoreFinalValue(rl_dest, rl_result);
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800194 }
195 }
196}
197
Brian Carlstrom7940e442013-07-12 13:46:57 -0700198void X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
199 RegLocation rl_src) {
200 RegisterClass rcSrc = kFPReg;
201 X86OpCode op = kX86Nop;
202 int src_reg;
203 RegLocation rl_result;
204 switch (opcode) {
205 case Instruction::INT_TO_FLOAT:
206 rcSrc = kCoreReg;
207 op = kX86Cvtsi2ssRR;
208 break;
209 case Instruction::DOUBLE_TO_FLOAT:
210 rcSrc = kFPReg;
211 op = kX86Cvtsd2ssRR;
212 break;
213 case Instruction::FLOAT_TO_DOUBLE:
214 rcSrc = kFPReg;
215 op = kX86Cvtss2sdRR;
216 break;
217 case Instruction::INT_TO_DOUBLE:
218 rcSrc = kCoreReg;
219 op = kX86Cvtsi2sdRR;
220 break;
221 case Instruction::FLOAT_TO_INT: {
222 rl_src = LoadValue(rl_src, kFPReg);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000223 src_reg = rl_src.reg.GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700224 // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
225 ClobberSReg(rl_dest.s_reg_low);
226 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800227 int temp_reg = AllocTempFloat().GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700228
buzbee2700f7e2014-03-07 09:46:20 -0800229 LoadConstant(rl_result.reg, 0x7fffffff);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000230 NewLIR2(kX86Cvtsi2ssRR, temp_reg, rl_result.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231 NewLIR2(kX86ComissRR, src_reg, temp_reg);
232 LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
233 LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000234 NewLIR2(kX86Cvttss2siRR, rl_result.reg.GetReg(), src_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700235 LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
236 branch_na_n->target = NewLIR0(kPseudoTargetLabel);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000237 NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238 branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
239 branch_normal->target = NewLIR0(kPseudoTargetLabel);
240 StoreValue(rl_dest, rl_result);
241 return;
242 }
243 case Instruction::DOUBLE_TO_INT: {
244 rl_src = LoadValueWide(rl_src, kFPReg);
buzbee2700f7e2014-03-07 09:46:20 -0800245 src_reg = rl_src.reg.GetLowReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700246 // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
247 ClobberSReg(rl_dest.s_reg_low);
248 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800249 int temp_reg = AllocTempDouble().GetLowReg() | X86_FP_DOUBLE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250
buzbee2700f7e2014-03-07 09:46:20 -0800251 LoadConstant(rl_result.reg, 0x7fffffff);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000252 NewLIR2(kX86Cvtsi2sdRR, temp_reg, rl_result.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700253 NewLIR2(kX86ComisdRR, src_reg, temp_reg);
254 LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA);
255 LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000256 NewLIR2(kX86Cvttsd2siRR, rl_result.reg.GetReg(), src_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257 LIR* branch_normal = NewLIR1(kX86Jmp8, 0);
258 branch_na_n->target = NewLIR0(kPseudoTargetLabel);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000259 NewLIR2(kX86Xor32RR, rl_result.reg.GetReg(), rl_result.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700260 branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel);
261 branch_normal->target = NewLIR0(kPseudoTargetLabel);
262 StoreValue(rl_dest, rl_result);
263 return;
264 }
265 case Instruction::LONG_TO_DOUBLE:
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800266 GenLongToFP(rl_dest, rl_src, true /* is_double */);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700267 return;
268 case Instruction::LONG_TO_FLOAT:
Razvan A Lupusoru614c2b42014-01-28 17:05:21 -0800269 GenLongToFP(rl_dest, rl_src, false /* is_double */);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700270 return;
271 case Instruction::FLOAT_TO_LONG:
Ian Rogers7655f292013-07-29 11:07:13 -0700272 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700273 return;
274 case Instruction::DOUBLE_TO_LONG:
Ian Rogers7655f292013-07-29 11:07:13 -0700275 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700276 return;
277 default:
278 LOG(INFO) << "Unexpected opcode: " << opcode;
279 }
280 if (rl_src.wide) {
281 rl_src = LoadValueWide(rl_src, rcSrc);
buzbee2700f7e2014-03-07 09:46:20 -0800282 src_reg = S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 } else {
284 rl_src = LoadValue(rl_src, rcSrc);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000285 src_reg = rl_src.reg.GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700286 }
287 if (rl_dest.wide) {
288 rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800289 NewLIR2(op, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()), src_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700290 StoreValueWide(rl_dest, rl_result);
291 } else {
292 rl_result = EvalLoc(rl_dest, kFPReg, true);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000293 NewLIR2(op, rl_result.reg.GetReg(), src_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700294 StoreValue(rl_dest, rl_result);
295 }
296}
297
298void X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest,
299 RegLocation rl_src1, RegLocation rl_src2) {
300 bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT);
301 bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT);
302 int src_reg1;
303 int src_reg2;
304 if (single) {
305 rl_src1 = LoadValue(rl_src1, kFPReg);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000306 src_reg1 = rl_src1.reg.GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700307 rl_src2 = LoadValue(rl_src2, kFPReg);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000308 src_reg2 = rl_src2.reg.GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700309 } else {
310 rl_src1 = LoadValueWide(rl_src1, kFPReg);
buzbee2700f7e2014-03-07 09:46:20 -0800311 src_reg1 = S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700312 rl_src2 = LoadValueWide(rl_src2, kFPReg);
buzbee2700f7e2014-03-07 09:46:20 -0800313 src_reg2 = S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700314 }
315 // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc()
316 ClobberSReg(rl_dest.s_reg_low);
317 RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800318 LoadConstantNoClobber(rl_result.reg, unordered_gt ? 1 : 0);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700319 if (single) {
320 NewLIR2(kX86UcomissRR, src_reg1, src_reg2);
321 } else {
322 NewLIR2(kX86UcomisdRR, src_reg1, src_reg2);
323 }
324 LIR* branch = NULL;
325 if (unordered_gt) {
326 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
327 }
328 // If the result reg can't be byte accessed, use a jump and move instead of a set.
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000329 if (rl_result.reg.GetReg() >= 4) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700330 LIR* branch2 = NULL;
331 if (unordered_gt) {
332 branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000333 NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x0);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700334 } else {
335 branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000336 NewLIR2(kX86Mov32RI, rl_result.reg.GetReg(), 0x1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700337 }
338 branch2->target = NewLIR0(kPseudoTargetLabel);
339 } else {
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000340 NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondA /* above - unsigned > */);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700341 }
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000342 NewLIR2(kX86Sbb32RI, rl_result.reg.GetReg(), 0);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700343 if (unordered_gt) {
344 branch->target = NewLIR0(kPseudoTargetLabel);
345 }
346 StoreValue(rl_dest, rl_result);
347}
348
349void X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
350 bool is_double) {
buzbee0d829482013-10-11 15:24:55 -0700351 LIR* taken = &block_label_list_[bb->taken];
352 LIR* not_taken = &block_label_list_[bb->fall_through];
Brian Carlstrom7940e442013-07-12 13:46:57 -0700353 LIR* branch = NULL;
354 RegLocation rl_src1;
355 RegLocation rl_src2;
356 if (is_double) {
357 rl_src1 = mir_graph_->GetSrcWide(mir, 0);
358 rl_src2 = mir_graph_->GetSrcWide(mir, 2);
359 rl_src1 = LoadValueWide(rl_src1, kFPReg);
360 rl_src2 = LoadValueWide(rl_src2, kFPReg);
buzbee2700f7e2014-03-07 09:46:20 -0800361 NewLIR2(kX86UcomisdRR, S2d(rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg()),
362 S2d(rl_src2.reg.GetLowReg(), rl_src2.reg.GetHighReg()));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700363 } else {
364 rl_src1 = mir_graph_->GetSrc(mir, 0);
365 rl_src2 = mir_graph_->GetSrc(mir, 1);
366 rl_src1 = LoadValue(rl_src1, kFPReg);
367 rl_src2 = LoadValue(rl_src2, kFPReg);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000368 NewLIR2(kX86UcomissRR, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700369 }
Vladimir Markoa8946072014-01-22 10:30:44 +0000370 ConditionCode ccode = mir->meta.ccode;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700371 switch (ccode) {
372 case kCondEq:
373 if (!gt_bias) {
374 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
375 branch->target = not_taken;
376 }
377 break;
378 case kCondNe:
379 if (!gt_bias) {
380 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
381 branch->target = taken;
382 }
383 break;
384 case kCondLt:
385 if (gt_bias) {
386 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
387 branch->target = not_taken;
388 }
Vladimir Marko58af1f92013-12-19 13:31:15 +0000389 ccode = kCondUlt;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700390 break;
391 case kCondLe:
392 if (gt_bias) {
393 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
394 branch->target = not_taken;
395 }
396 ccode = kCondLs;
397 break;
398 case kCondGt:
399 if (gt_bias) {
400 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
401 branch->target = taken;
402 }
403 ccode = kCondHi;
404 break;
405 case kCondGe:
406 if (gt_bias) {
407 branch = NewLIR2(kX86Jcc8, 0, kX86CondPE);
408 branch->target = taken;
409 }
Vladimir Marko58af1f92013-12-19 13:31:15 +0000410 ccode = kCondUge;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700411 break;
412 default:
413 LOG(FATAL) << "Unexpected ccode: " << ccode;
414 }
415 OpCondBranch(ccode, taken);
416}
417
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700418void X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700419 RegLocation rl_result;
420 rl_src = LoadValue(rl_src, kCoreReg);
421 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800422 OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423 StoreValue(rl_dest, rl_result);
424}
425
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700426void X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700427 RegLocation rl_result;
428 rl_src = LoadValueWide(rl_src, kCoreReg);
429 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800430 OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
431 OpRegCopy(rl_result.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700432 StoreValueWide(rl_dest, rl_result);
433}
434
435bool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) {
Mark Mendellbff1ef02013-12-13 13:47:34 -0800436 RegLocation rl_src = info->args[0];
437 RegLocation rl_dest = InlineTargetWide(info); // double place for result
438 rl_src = LoadValueWide(rl_src, kFPReg);
439 RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800440 NewLIR2(kX86SqrtsdRR, S2d(rl_result.reg.GetLowReg(), rl_result.reg.GetHighReg()),
441 S2d(rl_src.reg.GetLowReg(), rl_src.reg.GetHighReg()));
Mark Mendellbff1ef02013-12-13 13:47:34 -0800442 StoreValueWide(rl_dest, rl_result);
443 return true;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700444}
445
446
447
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700448} // namespace art