167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Copyright (C) 2011 The Android Open Source Project
367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Licensed under the Apache License, Version 2.0 (the "License");
567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * you may not use this file except in compliance with the License.
667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * You may obtain a copy of the License at
767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *      http://www.apache.org/licenses/LICENSE-2.0
967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
1067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Unless required by applicable law or agreed to in writing, software
1167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * distributed under the License is distributed on an "AS IS" BASIS,
1267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * See the License for the specific language governing permissions and
1467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * limitations under the License.
1567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
1667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1702031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h"
180b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe
190b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "arm_lir.h"
200b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h"
210b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "dex/mir_graph.h"
227940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
231bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
2411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
261fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
272ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 RegLocation rl_src1, RegLocation rl_src2) {
28a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
29fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
32a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Don't attempt to optimize register usage since these opcodes call out to
33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * the handlers.
34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
35408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_FLOAT_2ADDR:
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_FLOAT:
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vadds;
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_FLOAT_2ADDR:
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_FLOAT:
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vsubs;
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_FLOAT_2ADDR:
45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_FLOAT:
46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vdivs;
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_FLOAT_2ADDR:
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_FLOAT:
50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vmuls;
51a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
52a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_FLOAT_2ADDR:
53a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_FLOAT:
541fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
55984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe      CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
56a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee      rl_result = GetReturn(kFPReg);
571fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
58a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
59a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_FLOAT:
601fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegFloat(rl_dest, rl_src1);
61a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
62a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
63a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
64a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
651fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kFPReg);
661fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kFPReg);
671fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
6800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
691fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
7067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
7167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
721fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpDouble(Instruction::Code opcode,
732ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
74a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
75fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
7667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
77408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_DOUBLE_2ADDR:
79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_DOUBLE:
80a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vaddd;
81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
82a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_DOUBLE_2ADDR:
83a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_DOUBLE:
84a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vsubd;
85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_DOUBLE_2ADDR:
87a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_DOUBLE:
88a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vdivd;
89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_DOUBLE_2ADDR:
91a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_DOUBLE:
92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vmuld;
93a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
94a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_DOUBLE_2ADDR:
95a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_DOUBLE:
961fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
97984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe      CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
98a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee      rl_result = GetReturnWide(kFPReg);
991fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
100a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
101a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_DOUBLE:
1021fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegDouble(rl_dest, rl_src1);
103a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
105a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
106a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1081fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kFPReg);
109fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src1.wide);
1101fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kFPReg);
111fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src2.wide);
1121fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
113fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_dest.wide);
114fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_result.wide);
115091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
1161fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
11767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
11867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
119675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jianvoid ArmMir2Lir::GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1,
120675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian                                            int32_t constant) {
121675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  RegLocation rl_result;
122675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  RegStorage r_tmp = AllocTempSingle();
123675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  LoadConstantNoClobber(r_tmp, constant);
124675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  rl_src1 = LoadValue(rl_src1, kFPReg);
125675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  rl_result = EvalLoc(rl_dest, kFPReg, true);
126675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  NewLIR3(kThumb2Vmuls, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), r_tmp.GetReg());
127675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  StoreValue(rl_dest, rl_result);
128675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian}
129675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian
130675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jianvoid ArmMir2Lir::GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1,
131675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian                                             int64_t constant) {
132675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  RegLocation rl_result;
133675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  RegStorage r_tmp = AllocTempDouble();
134675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  DCHECK(r_tmp.IsDouble());
135675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  LoadConstantWide(r_tmp, constant);
136675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  rl_src1 = LoadValueWide(rl_src1, kFPReg);
137675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  DCHECK(rl_src1.wide);
138675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  rl_result = EvalLocWide(rl_dest, kFPReg, true);
139675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  DCHECK(rl_dest.wide);
140675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  DCHECK(rl_result.wide);
141675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  NewLIR3(kThumb2Vmuld, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), r_tmp.GetReg());
142675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian  StoreValueWide(rl_dest, rl_result);
143675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian}
144675e09b2753c2fcd521bd8f0230a0abf06e9b0e9Ningsheng Jian
145091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid ArmMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) {
146a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
147fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg;
148fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
14967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (opcode) {
151a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_FLOAT:
152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtIF;
153a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
154a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_INT:
155a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFI;
156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
157a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_FLOAT:
158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDF;
159a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
160a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_DOUBLE:
161a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFd;
162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
163a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_DOUBLE:
164e19649a91702234f9aa9941d76da447a1e0dcc2aZheng Xu      op = kThumb2VcvtF64S32;
165a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
166a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_INT:
167a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDI;
168a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
169ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers    case Instruction::LONG_TO_DOUBLE: {
170ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      rl_src = LoadValueWide(rl_src, kFPReg);
17185089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegisterInfo* info = GetRegInfo(rl_src.reg);
17285089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg();
17385089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_low.Valid());
17485089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg();
17585089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_high.Valid());
176ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      rl_result = EvalLoc(rl_dest, kFPReg, true);
1772700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage tmp1 = AllocTempDouble();
1782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage tmp2 = AllocTempDouble();
179ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers
180091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64S32, tmp1.GetReg(), src_high.GetReg());
181091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64U32, rl_result.reg.GetReg(), src_low.GetReg());
1822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstantWide(tmp2, 0x41f0000000000000LL);
183091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR3(kThumb2VmlaF64, rl_result.reg.GetReg(), tmp1.GetReg(), tmp2.GetReg());
184ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      FreeTemp(tmp1);
185ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      FreeTemp(tmp2);
186ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      StoreValueWide(rl_dest, rl_result);
187a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
188ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers    }
189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_LONG:
190fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko      CheckEntrypointTypes<kQuickF2l, int64_t, float>();  // int64_t -> kCoreReg
191fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko      GenConversionCall(kQuickF2l, rl_dest, rl_src, kCoreReg);
192a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
193f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu    case Instruction::LONG_TO_FLOAT: {
194f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      rl_src = LoadValueWide(rl_src, kFPReg);
19585089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegisterInfo* info = GetRegInfo(rl_src.reg);
19685089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg();
19785089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_low.Valid());
19885089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg();
19985089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_high.Valid());
200f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      rl_result = EvalLoc(rl_dest, kFPReg, true);
201f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Allocate temp registers.
2022700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage high_val = AllocTempDouble();
2032700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage low_val = AllocTempDouble();
2042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage const_val = AllocTempDouble();
205f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Long to double.
206091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64S32, high_val.GetReg(), src_high.GetReg());
207091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64U32, low_val.GetReg(), src_low.GetReg());
2082700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstantWide(const_val, INT64_C(0x41f0000000000000));
209091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR3(kThumb2VmlaF64, low_val.GetReg(), high_val.GetReg(), const_val.GetReg());
210f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Double to float.
211091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtDF, rl_result.reg.GetReg(), low_val.GetReg());
212f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Free temp registers.
213f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      FreeTemp(high_val);
214f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      FreeTemp(low_val);
215f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      FreeTemp(const_val);
216f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Store result.
217f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      StoreValue(rl_dest, rl_result);
218a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
219f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu    }
220a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_LONG:
221fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko      CheckEntrypointTypes<kQuickD2l, int64_t, double>();  // int64_t -> kCoreReg
222fac10700fd99516e8a14f751fe35553021ce6982Vladimir Marko      GenConversionCall(kQuickD2l, rl_dest, rl_src, kCoreReg);
223a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
225a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
226a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
227fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
2281fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValueWide(rl_src, kFPReg);
229091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    src_reg = rl_src.reg.GetReg();
230a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2311fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, kFPReg);
23200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    src_reg = rl_src.reg.GetReg();
233a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
234fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
2351fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
236091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(op, rl_result.reg.GetReg(), src_reg);
2371fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2391fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
24000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(op, rl_result.reg.GetReg(), src_reg);
2411fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
24367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
24467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2451fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
2462ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_double) {
2470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* target = &block_label_list_[bb->taken];
248fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
249fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
250fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
2511fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrcWide(mir, 0);
2521fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrcWide(mir, 2);
2531fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
2541fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
255091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
256a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2571fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrc(mir, 0);
2581fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrc(mir, 1);
2591fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
2601fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
26100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
264a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko  ConditionCode ccode = mir->meta.ccode;
265df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondEq:
267a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondNe:
268a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
269a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLt:
270fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondMi;
272a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLe:
275fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
276a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondLs;
277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
279a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGt:
280fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondHi;
282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
283a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
284a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGe:
285fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
28658af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko        ccode = kCondUge;
287a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
288a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
289a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
290cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
291a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2921fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, target);
29384fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee}
29484fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
29584fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
2961fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
2972ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_src1, RegLocation rl_src2) {
298a5954be0aac5edd892fb31a209960543d00e4500buzbee  bool is_double = false;
299a5954be0aac5edd892fb31a209960543d00e4500buzbee  int default_result = -1;
300fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
30167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
302408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
303a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_FLOAT:
304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
306a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
307a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_FLOAT:
308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_DOUBLE:
312fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
313fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
314a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
315a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_DOUBLE:
316fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
317fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
318a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
319a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
320a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
322fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
3231fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
3241fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
325078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
3261fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
3271fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
3282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadConstant(rl_result.reg, default_result);
329091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
330a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
3311fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
3321fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
333078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
3341fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
3351fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
3362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadConstant(rl_result.reg, default_result);
33700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
338a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
339091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(!rl_result.reg.IsFloat());
3401fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
34167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3423da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  LIR* it = OpIT((default_result == -1) ? kCondGt : kCondMi, "");
34300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR2(kThumb2MovI8M, rl_result.reg.GetReg(),
3447934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          ModifiedImmediate(-default_result));  // Must not alter ccodes
3453da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  OpEndIT(it);
34667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3473da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  it = OpIT(kCondEq, "");
3482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadConstant(rl_result.reg, 0);
3493da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  OpEndIT(it);
35067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3511fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
35267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
35311d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
3542ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
355fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3561fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kFPReg);
3571fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
35800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR2(kThumb2Vnegs, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3591fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
363fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3641fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
3651fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
366091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(kThumb2Vnegd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3671fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
368efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3705030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markostatic RegisterClass RegClassForAbsFP(RegLocation rl_src, RegLocation rl_dest) {
3715030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // If src is in a core reg or, unlikely, dest has been promoted to a core reg, use core reg.
3725030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if ((rl_src.location == kLocPhysReg && !rl_src.reg.IsFloat()) ||
3735030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko      (rl_dest.location == kLocPhysReg && !rl_dest.reg.IsFloat())) {
3745030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return kCoreReg;
3755030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3765030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // If src is in an fp reg or dest has been promoted to an fp reg, use fp reg.
3775030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (rl_src.location == kLocPhysReg || rl_dest.location == kLocPhysReg) {
3785030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return kFPReg;
3795030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3805030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // With both src and dest in the stack frame we have to perform load+abs+store. Whether this
3815030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // is faster using a core reg or fp reg depends on the particular CPU. Without further
3825030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // investigation and testing we prefer core register. (If the result is subsequently used in
3835030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // another fp operation, the dalvik reg will probably get promoted and that should be handled
3845030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // by the cases above.)
3855030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  return kCoreReg;
3865030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko}
3875030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko
3885030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markobool ArmMir2Lir::GenInlinedAbsFloat(CallInfo* info) {
3895030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (info->result.location == kLocInvalid) {
3905030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return true;  // Result is unused: inlining successful, no code generated.
3915030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3925030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_dest = info->result;
3935030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_src = UpdateLoc(info->args[0]);
3945030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest);
3955030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  rl_src = LoadValue(rl_src, reg_class);
3965030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
3975030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (reg_class == kFPReg) {
3985030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    NewLIR2(kThumb2Vabss, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3995030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  } else {
4005030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff);
4015030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
4025030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  StoreValue(rl_dest, rl_result);
4035030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  return true;
4045030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko}
4055030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko
4065030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markobool ArmMir2Lir::GenInlinedAbsDouble(CallInfo* info) {
4075030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (info->result.location == kLocInvalid) {
4085030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return true;  // Result is unused: inlining successful, no code generated.
4095030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
4105030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_dest = info->result;
4115030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_src = UpdateLocWide(info->args[0]);
4125030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest);
4135030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  rl_src = LoadValueWide(rl_src, reg_class);
4145030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
4155030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (reg_class == kFPReg) {
4165030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    NewLIR2(kThumb2Vabsd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
417a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko  } else if (rl_result.reg.GetLow().GetReg() != rl_src.reg.GetHigh().GetReg()) {
418a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    // No inconvenient overlap.
419a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetLow());
420a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x7fffffff);
4215030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  } else {
422a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    // Inconvenient overlap, use a temp register to preserve the high word of the source.
423a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    RegStorage rs_tmp = AllocTemp();
424a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    OpRegCopy(rs_tmp, rl_src.reg.GetHigh());
425a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetLow());
426a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rs_tmp, 0x7fffffff);
427a5f90b6f0f5b33487e71eaeb05508555f17dcf30Vladimir Marko    FreeTemp(rs_tmp);
4285030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
4295030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  StoreValueWide(rl_dest, rl_result);
4305030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  return true;
4315030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko}
4325030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko
4331fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) {
4341fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
435fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src = info->args[0];
4361fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTargetWide(info);  // double place for result
4371fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
4381fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
439091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(kThumb2Vsqrtd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
4401fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
441efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
442efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
444efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
44511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
446