blob: 1a5c1080ffb8e46efa02330ffe95f20bd50a5f1e [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -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
Brian Carlstrom7940e442013-07-12 13:46:57 -070017#include "codegen_arm.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080018
19#include "arm_lir.h"
20#include "base/logging.h"
21#include "dex/mir_graph.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070022#include "dex/quick/mir_to_lir-inl.h"
23
24namespace art {
25
26void ArmMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070027 RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070028 int op = kThumbBkpt;
29 RegLocation rl_result;
30
31 /*
32 * Don't attempt to optimize register usage since these opcodes call out to
33 * the handlers.
34 */
35 switch (opcode) {
36 case Instruction::ADD_FLOAT_2ADDR:
37 case Instruction::ADD_FLOAT:
38 op = kThumb2Vadds;
39 break;
40 case Instruction::SUB_FLOAT_2ADDR:
41 case Instruction::SUB_FLOAT:
42 op = kThumb2Vsubs;
43 break;
44 case Instruction::DIV_FLOAT_2ADDR:
45 case Instruction::DIV_FLOAT:
46 op = kThumb2Vdivs;
47 break;
48 case Instruction::MUL_FLOAT_2ADDR:
49 case Instruction::MUL_FLOAT:
50 op = kThumb2Vmuls;
51 break;
52 case Instruction::REM_FLOAT_2ADDR:
53 case Instruction::REM_FLOAT:
54 FlushAllRegs(); // Send everything to home location
Andreas Gampe98430592014-07-27 19:44:50 -070055 CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
buzbeea0cd2d72014-06-01 09:33:49 -070056 rl_result = GetReturn(kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070057 StoreValue(rl_dest, rl_result);
58 return;
59 case Instruction::NEG_FLOAT:
60 GenNegFloat(rl_dest, rl_src1);
61 return;
62 default:
63 LOG(FATAL) << "Unexpected opcode: " << opcode;
64 }
65 rl_src1 = LoadValue(rl_src1, kFPReg);
66 rl_src2 = LoadValue(rl_src2, kFPReg);
67 rl_result = EvalLoc(rl_dest, kFPReg, true);
Bill Buzbee00e1ec62014-02-27 23:44:13 +000068 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070069 StoreValue(rl_dest, rl_result);
70}
71
72void ArmMir2Lir::GenArithOpDouble(Instruction::Code opcode,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070073 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070074 int op = kThumbBkpt;
75 RegLocation rl_result;
76
77 switch (opcode) {
78 case Instruction::ADD_DOUBLE_2ADDR:
79 case Instruction::ADD_DOUBLE:
80 op = kThumb2Vaddd;
81 break;
82 case Instruction::SUB_DOUBLE_2ADDR:
83 case Instruction::SUB_DOUBLE:
84 op = kThumb2Vsubd;
85 break;
86 case Instruction::DIV_DOUBLE_2ADDR:
87 case Instruction::DIV_DOUBLE:
88 op = kThumb2Vdivd;
89 break;
90 case Instruction::MUL_DOUBLE_2ADDR:
91 case Instruction::MUL_DOUBLE:
92 op = kThumb2Vmuld;
93 break;
94 case Instruction::REM_DOUBLE_2ADDR:
95 case Instruction::REM_DOUBLE:
96 FlushAllRegs(); // Send everything to home location
Andreas Gampe98430592014-07-27 19:44:50 -070097 CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
buzbeea0cd2d72014-06-01 09:33:49 -070098 rl_result = GetReturnWide(kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070099 StoreValueWide(rl_dest, rl_result);
100 return;
101 case Instruction::NEG_DOUBLE:
102 GenNegDouble(rl_dest, rl_src1);
103 return;
104 default:
105 LOG(FATAL) << "Unexpected opcode: " << opcode;
106 }
107
108 rl_src1 = LoadValueWide(rl_src1, kFPReg);
109 DCHECK(rl_src1.wide);
110 rl_src2 = LoadValueWide(rl_src2, kFPReg);
111 DCHECK(rl_src2.wide);
112 rl_result = EvalLoc(rl_dest, kFPReg, true);
113 DCHECK(rl_dest.wide);
114 DCHECK(rl_result.wide);
buzbee091cc402014-03-31 10:14:40 -0700115 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700116 StoreValueWide(rl_dest, rl_result);
117}
118
Ningsheng Jian675e09b2014-10-23 13:48:36 +0800119void ArmMir2Lir::GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1,
120 int32_t constant) {
121 RegLocation rl_result;
122 RegStorage r_tmp = AllocTempSingle();
123 LoadConstantNoClobber(r_tmp, constant);
124 rl_src1 = LoadValue(rl_src1, kFPReg);
125 rl_result = EvalLoc(rl_dest, kFPReg, true);
126 NewLIR3(kThumb2Vmuls, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), r_tmp.GetReg());
127 StoreValue(rl_dest, rl_result);
128}
129
130void ArmMir2Lir::GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1,
131 int64_t constant) {
132 RegLocation rl_result;
133 RegStorage r_tmp = AllocTempDouble();
134 DCHECK(r_tmp.IsDouble());
135 LoadConstantWide(r_tmp, constant);
136 rl_src1 = LoadValueWide(rl_src1, kFPReg);
137 DCHECK(rl_src1.wide);
138 rl_result = EvalLocWide(rl_dest, kFPReg, true);
139 DCHECK(rl_dest.wide);
140 DCHECK(rl_result.wide);
141 NewLIR3(kThumb2Vmuld, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), r_tmp.GetReg());
142 StoreValueWide(rl_dest, rl_result);
143}
144
buzbee091cc402014-03-31 10:14:40 -0700145void ArmMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700146 int op = kThumbBkpt;
147 int src_reg;
148 RegLocation rl_result;
149
150 switch (opcode) {
151 case Instruction::INT_TO_FLOAT:
152 op = kThumb2VcvtIF;
153 break;
154 case Instruction::FLOAT_TO_INT:
155 op = kThumb2VcvtFI;
156 break;
157 case Instruction::DOUBLE_TO_FLOAT:
158 op = kThumb2VcvtDF;
159 break;
160 case Instruction::FLOAT_TO_DOUBLE:
161 op = kThumb2VcvtFd;
162 break;
163 case Instruction::INT_TO_DOUBLE:
Zheng Xue19649a2014-02-27 13:30:55 +0000164 op = kThumb2VcvtF64S32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165 break;
166 case Instruction::DOUBLE_TO_INT:
167 op = kThumb2VcvtDI;
168 break;
Ian Rogersef6a7762013-12-19 17:58:05 -0800169 case Instruction::LONG_TO_DOUBLE: {
170 rl_src = LoadValueWide(rl_src, kFPReg);
buzbee85089dd2014-05-25 15:10:52 -0700171 RegisterInfo* info = GetRegInfo(rl_src.reg);
172 RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg();
173 DCHECK(src_low.Valid());
174 RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg();
175 DCHECK(src_high.Valid());
Ian Rogersef6a7762013-12-19 17:58:05 -0800176 rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800177 RegStorage tmp1 = AllocTempDouble();
178 RegStorage tmp2 = AllocTempDouble();
Ian Rogersef6a7762013-12-19 17:58:05 -0800179
buzbee091cc402014-03-31 10:14:40 -0700180 NewLIR2(kThumb2VcvtF64S32, tmp1.GetReg(), src_high.GetReg());
181 NewLIR2(kThumb2VcvtF64U32, rl_result.reg.GetReg(), src_low.GetReg());
buzbee2700f7e2014-03-07 09:46:20 -0800182 LoadConstantWide(tmp2, 0x41f0000000000000LL);
buzbee091cc402014-03-31 10:14:40 -0700183 NewLIR3(kThumb2VmlaF64, rl_result.reg.GetReg(), tmp1.GetReg(), tmp2.GetReg());
Ian Rogersef6a7762013-12-19 17:58:05 -0800184 FreeTemp(tmp1);
185 FreeTemp(tmp2);
186 StoreValueWide(rl_dest, rl_result);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700187 return;
Ian Rogersef6a7762013-12-19 17:58:05 -0800188 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700189 case Instruction::FLOAT_TO_LONG:
Vladimir Markofac10702015-04-22 11:51:52 +0100190 CheckEntrypointTypes<kQuickF2l, int64_t, float>(); // int64_t -> kCoreReg
191 GenConversionCall(kQuickF2l, rl_dest, rl_src, kCoreReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700192 return;
Zheng Xuf0e6c9c2014-03-10 10:43:02 +0000193 case Instruction::LONG_TO_FLOAT: {
Roland Levillain5b3ee562015-04-14 16:02:41 +0100194 CheckEntrypointTypes<kQuickL2f, float, int64_t>(); // float -> kFPReg
195 GenConversionCall(kQuickL2f, rl_dest, rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700196 return;
Zheng Xuf0e6c9c2014-03-10 10:43:02 +0000197 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700198 case Instruction::DOUBLE_TO_LONG:
Vladimir Markofac10702015-04-22 11:51:52 +0100199 CheckEntrypointTypes<kQuickD2l, int64_t, double>(); // int64_t -> kCoreReg
200 GenConversionCall(kQuickD2l, rl_dest, rl_src, kCoreReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700201 return;
202 default:
203 LOG(FATAL) << "Unexpected opcode: " << opcode;
204 }
205 if (rl_src.wide) {
206 rl_src = LoadValueWide(rl_src, kFPReg);
buzbee091cc402014-03-31 10:14:40 -0700207 src_reg = rl_src.reg.GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700208 } else {
209 rl_src = LoadValue(rl_src, kFPReg);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000210 src_reg = rl_src.reg.GetReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700211 }
212 if (rl_dest.wide) {
213 rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee091cc402014-03-31 10:14:40 -0700214 NewLIR2(op, rl_result.reg.GetReg(), src_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700215 StoreValueWide(rl_dest, rl_result);
216 } else {
217 rl_result = EvalLoc(rl_dest, kFPReg, true);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000218 NewLIR2(op, rl_result.reg.GetReg(), src_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700219 StoreValue(rl_dest, rl_result);
220 }
221}
222
223void ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700224 bool is_double) {
buzbee0d829482013-10-11 15:24:55 -0700225 LIR* target = &block_label_list_[bb->taken];
Brian Carlstrom7940e442013-07-12 13:46:57 -0700226 RegLocation rl_src1;
227 RegLocation rl_src2;
228 if (is_double) {
229 rl_src1 = mir_graph_->GetSrcWide(mir, 0);
230 rl_src2 = mir_graph_->GetSrcWide(mir, 2);
231 rl_src1 = LoadValueWide(rl_src1, kFPReg);
232 rl_src2 = LoadValueWide(rl_src2, kFPReg);
buzbee091cc402014-03-31 10:14:40 -0700233 NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 } else {
235 rl_src1 = mir_graph_->GetSrc(mir, 0);
236 rl_src2 = mir_graph_->GetSrc(mir, 1);
237 rl_src1 = LoadValue(rl_src1, kFPReg);
238 rl_src2 = LoadValue(rl_src2, kFPReg);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000239 NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 }
241 NewLIR0(kThumb2Fmstat);
Vladimir Markoa8946072014-01-22 10:30:44 +0000242 ConditionCode ccode = mir->meta.ccode;
Brian Carlstromdf629502013-07-17 22:39:56 -0700243 switch (ccode) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244 case kCondEq:
245 case kCondNe:
246 break;
247 case kCondLt:
248 if (gt_bias) {
249 ccode = kCondMi;
250 }
251 break;
252 case kCondLe:
253 if (gt_bias) {
254 ccode = kCondLs;
255 }
256 break;
257 case kCondGt:
258 if (gt_bias) {
259 ccode = kCondHi;
260 }
261 break;
262 case kCondGe:
263 if (gt_bias) {
Vladimir Marko58af1f92013-12-19 13:31:15 +0000264 ccode = kCondUge;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700265 }
266 break;
267 default:
268 LOG(FATAL) << "Unexpected ccode: " << ccode;
269 }
270 OpCondBranch(ccode, target);
271}
272
273
274void ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700275 RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700276 bool is_double = false;
277 int default_result = -1;
278 RegLocation rl_result;
279
280 switch (opcode) {
281 case Instruction::CMPL_FLOAT:
282 is_double = false;
283 default_result = -1;
284 break;
285 case Instruction::CMPG_FLOAT:
286 is_double = false;
287 default_result = 1;
288 break;
289 case Instruction::CMPL_DOUBLE:
290 is_double = true;
291 default_result = -1;
292 break;
293 case Instruction::CMPG_DOUBLE:
294 is_double = true;
295 default_result = 1;
296 break;
297 default:
298 LOG(FATAL) << "Unexpected opcode: " << opcode;
299 }
300 if (is_double) {
301 rl_src1 = LoadValueWide(rl_src1, kFPReg);
302 rl_src2 = LoadValueWide(rl_src2, kFPReg);
303 // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
304 ClobberSReg(rl_dest.s_reg_low);
305 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800306 LoadConstant(rl_result.reg, default_result);
buzbee091cc402014-03-31 10:14:40 -0700307 NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700308 } else {
309 rl_src1 = LoadValue(rl_src1, kFPReg);
310 rl_src2 = LoadValue(rl_src2, kFPReg);
311 // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
312 ClobberSReg(rl_dest.s_reg_low);
313 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800314 LoadConstant(rl_result.reg, default_result);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000315 NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700316 }
buzbee091cc402014-03-31 10:14:40 -0700317 DCHECK(!rl_result.reg.IsFloat());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700318 NewLIR0(kThumb2Fmstat);
319
Dave Allison3da67a52014-04-02 17:03:45 -0700320 LIR* it = OpIT((default_result == -1) ? kCondGt : kCondMi, "");
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000321 NewLIR2(kThumb2MovI8M, rl_result.reg.GetReg(),
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700322 ModifiedImmediate(-default_result)); // Must not alter ccodes
Dave Allison3da67a52014-04-02 17:03:45 -0700323 OpEndIT(it);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700324
Dave Allison3da67a52014-04-02 17:03:45 -0700325 it = OpIT(kCondEq, "");
buzbee2700f7e2014-03-07 09:46:20 -0800326 LoadConstant(rl_result.reg, 0);
Dave Allison3da67a52014-04-02 17:03:45 -0700327 OpEndIT(it);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700328
329 StoreValue(rl_dest, rl_result);
330}
331
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700332void ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700333 RegLocation rl_result;
334 rl_src = LoadValue(rl_src, kFPReg);
335 rl_result = EvalLoc(rl_dest, kFPReg, true);
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000336 NewLIR2(kThumb2Vnegs, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700337 StoreValue(rl_dest, rl_result);
338}
339
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700340void ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700341 RegLocation rl_result;
342 rl_src = LoadValueWide(rl_src, kFPReg);
343 rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee091cc402014-03-31 10:14:40 -0700344 NewLIR2(kThumb2Vnegd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700345 StoreValueWide(rl_dest, rl_result);
346}
347
Vladimir Marko5030d3e2014-07-17 10:43:08 +0100348static RegisterClass RegClassForAbsFP(RegLocation rl_src, RegLocation rl_dest) {
349 // If src is in a core reg or, unlikely, dest has been promoted to a core reg, use core reg.
350 if ((rl_src.location == kLocPhysReg && !rl_src.reg.IsFloat()) ||
351 (rl_dest.location == kLocPhysReg && !rl_dest.reg.IsFloat())) {
352 return kCoreReg;
353 }
354 // If src is in an fp reg or dest has been promoted to an fp reg, use fp reg.
355 if (rl_src.location == kLocPhysReg || rl_dest.location == kLocPhysReg) {
356 return kFPReg;
357 }
358 // With both src and dest in the stack frame we have to perform load+abs+store. Whether this
359 // is faster using a core reg or fp reg depends on the particular CPU. Without further
360 // investigation and testing we prefer core register. (If the result is subsequently used in
361 // another fp operation, the dalvik reg will probably get promoted and that should be handled
362 // by the cases above.)
363 return kCoreReg;
364}
365
366bool ArmMir2Lir::GenInlinedAbsFloat(CallInfo* info) {
367 if (info->result.location == kLocInvalid) {
368 return true; // Result is unused: inlining successful, no code generated.
369 }
370 RegLocation rl_dest = info->result;
371 RegLocation rl_src = UpdateLoc(info->args[0]);
372 RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest);
373 rl_src = LoadValue(rl_src, reg_class);
374 RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
375 if (reg_class == kFPReg) {
376 NewLIR2(kThumb2Vabss, rl_result.reg.GetReg(), rl_src.reg.GetReg());
377 } else {
378 OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff);
379 }
380 StoreValue(rl_dest, rl_result);
381 return true;
382}
383
384bool ArmMir2Lir::GenInlinedAbsDouble(CallInfo* info) {
385 if (info->result.location == kLocInvalid) {
386 return true; // Result is unused: inlining successful, no code generated.
387 }
388 RegLocation rl_dest = info->result;
389 RegLocation rl_src = UpdateLocWide(info->args[0]);
390 RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest);
391 rl_src = LoadValueWide(rl_src, reg_class);
392 RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
393 if (reg_class == kFPReg) {
394 NewLIR2(kThumb2Vabsd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Vladimir Markoa5f90b62014-08-14 15:23:32 +0100395 } else if (rl_result.reg.GetLow().GetReg() != rl_src.reg.GetHigh().GetReg()) {
396 // No inconvenient overlap.
397 OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetLow());
398 OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x7fffffff);
Vladimir Marko5030d3e2014-07-17 10:43:08 +0100399 } else {
Vladimir Markoa5f90b62014-08-14 15:23:32 +0100400 // Inconvenient overlap, use a temp register to preserve the high word of the source.
401 RegStorage rs_tmp = AllocTemp();
402 OpRegCopy(rs_tmp, rl_src.reg.GetHigh());
403 OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetLow());
404 OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rs_tmp, 0x7fffffff);
405 FreeTemp(rs_tmp);
Vladimir Marko5030d3e2014-07-17 10:43:08 +0100406 }
407 StoreValueWide(rl_dest, rl_result);
408 return true;
409}
410
Brian Carlstrom7940e442013-07-12 13:46:57 -0700411bool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) {
412 DCHECK_EQ(cu_->instruction_set, kThumb2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700413 RegLocation rl_src = info->args[0];
414 RegLocation rl_dest = InlineTargetWide(info); // double place for result
415 rl_src = LoadValueWide(rl_src, kFPReg);
416 RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
buzbee091cc402014-03-31 10:14:40 -0700417 NewLIR2(kThumb2Vsqrtd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700418 StoreValueWide(rl_dest, rl_result);
419 return true;
420}
421
422
423} // namespace art