fp_arm.cc revision 5030d3ee8c6fe10394912ede107cbc8df63b7b16
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
171bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h"
1802031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h"
197940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
2111d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
231fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
242ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 RegLocation rl_src1, RegLocation rl_src2) {
25a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
26fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
2767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
28a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
29a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Don't attempt to optimize register usage since these opcodes call out to
30a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * the handlers.
31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
32408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_FLOAT_2ADDR:
34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_FLOAT:
35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vadds;
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_FLOAT_2ADDR:
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_FLOAT:
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vsubs;
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_FLOAT_2ADDR:
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_FLOAT:
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vdivs;
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_FLOAT_2ADDR:
46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_FLOAT:
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vmuls;
48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_FLOAT_2ADDR:
50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_FLOAT:
511fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
52dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2,
537655f29fabc0a12765de828914a18314382e5a35Ian Rogers                                              false);
54a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee      rl_result = GetReturn(kFPReg);
551fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
56a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
57a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_FLOAT:
581fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegFloat(rl_dest, rl_src1);
59a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
60a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
61a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
62a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
631fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kFPReg);
641fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kFPReg);
651fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
6600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
671fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
6867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
6967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
701fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpDouble(Instruction::Code opcode,
712ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
72a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
73fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
7467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
75408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
76a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_DOUBLE_2ADDR:
77a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_DOUBLE:
78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vaddd;
79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
80a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_DOUBLE_2ADDR:
81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_DOUBLE:
82a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vsubd;
83a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
84a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_DOUBLE_2ADDR:
85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_DOUBLE:
86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vdivd;
87a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
88a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_DOUBLE_2ADDR:
89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_DOUBLE:
90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vmuld;
91a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_DOUBLE_2ADDR:
93a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_DOUBLE:
941fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
95dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2,
967655f29fabc0a12765de828914a18314382e5a35Ian Rogers                                              false);
97a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee      rl_result = GetReturnWide(kFPReg);
981fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
99a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
100a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_DOUBLE:
1011fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegDouble(rl_dest, rl_src1);
102a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
103a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
104a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1071fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kFPReg);
108fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src1.wide);
1091fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kFPReg);
110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src2.wide);
1111fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
112fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_dest.wide);
113fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_result.wide);
114091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
1151fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
11667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
11767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
118091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid ArmMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) {
119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg;
121fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
12267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
123a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (opcode) {
124a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_FLOAT:
125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtIF;
126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_INT:
128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFI;
129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_FLOAT:
131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDF;
132a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_DOUBLE:
134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFd;
135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_DOUBLE:
137e19649a91702234f9aa9941d76da447a1e0dcc2aZheng Xu      op = kThumb2VcvtF64S32;
138a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_INT:
140a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDI;
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
142ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers    case Instruction::LONG_TO_DOUBLE: {
143ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      rl_src = LoadValueWide(rl_src, kFPReg);
14485089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegisterInfo* info = GetRegInfo(rl_src.reg);
14585089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg();
14685089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_low.Valid());
14785089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg();
14885089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_high.Valid());
149ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      rl_result = EvalLoc(rl_dest, kFPReg, true);
1502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage tmp1 = AllocTempDouble();
1512700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage tmp2 = AllocTempDouble();
152ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers
153091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64S32, tmp1.GetReg(), src_high.GetReg());
154091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64U32, rl_result.reg.GetReg(), src_low.GetReg());
1552700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstantWide(tmp2, 0x41f0000000000000LL);
156091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR3(kThumb2VmlaF64, rl_result.reg.GetReg(), tmp1.GetReg(), tmp2.GetReg());
157ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      FreeTemp(tmp1);
158ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      FreeTemp(tmp2);
159ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers      StoreValueWide(rl_dest, rl_result);
160a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
161ef6a776af2b4b8607d5f91add0ed0e8497100e31Ian Rogers    }
162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_LONG:
163dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src);
164a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
165f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu    case Instruction::LONG_TO_FLOAT: {
166f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      rl_src = LoadValueWide(rl_src, kFPReg);
16785089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegisterInfo* info = GetRegInfo(rl_src.reg);
16885089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_low = info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg();
16985089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_low.Valid());
17085089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      RegStorage src_high = info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg();
17185089dd28a39dd20f42ac258398b2a08668f9ef1buzbee      DCHECK(src_high.Valid());
172f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      rl_result = EvalLoc(rl_dest, kFPReg, true);
173f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Allocate temp registers.
1742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage high_val = AllocTempDouble();
1752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage low_val = AllocTempDouble();
1762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage const_val = AllocTempDouble();
177f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Long to double.
178091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64S32, high_val.GetReg(), src_high.GetReg());
179091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtF64U32, low_val.GetReg(), src_low.GetReg());
1802700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstantWide(const_val, INT64_C(0x41f0000000000000));
181091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR3(kThumb2VmlaF64, low_val.GetReg(), high_val.GetReg(), const_val.GetReg());
182f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Double to float.
183091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2VcvtDF, rl_result.reg.GetReg(), low_val.GetReg());
184f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Free temp registers.
185f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      FreeTemp(high_val);
186f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      FreeTemp(low_val);
187f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      FreeTemp(const_val);
188f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      // Store result.
189f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu      StoreValue(rl_dest, rl_result);
190a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
191f0e6c9c7b395f4fce4d00d31cabd362302e1d924Zheng Xu    }
192a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_LONG:
193dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src);
194a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
196a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
198fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
1991fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValueWide(rl_src, kFPReg);
200091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    src_reg = rl_src.reg.GetReg();
201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2021fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, kFPReg);
20300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    src_reg = rl_src.reg.GetReg();
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
205fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
2061fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
207091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(op, rl_result.reg.GetReg(), src_reg);
2081fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2101fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
21100e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(op, rl_result.reg.GetReg(), src_reg);
2121fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
21467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
21567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2161fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
2172ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_double) {
2180d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* target = &block_label_list_[bb->taken];
219fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
221fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
2221fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrcWide(mir, 0);
2231fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrcWide(mir, 2);
2241fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
2251fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
226091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
227a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2281fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrc(mir, 0);
2291fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrc(mir, 1);
2301fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
2311fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
23200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
233a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2341fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
235a894607bca7eb623bc957363e4b36f44cfeea1b6Vladimir Marko  ConditionCode ccode = mir->meta.ccode;
236df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondEq:
238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondNe:
239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLt:
241fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondMi;
243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLe:
246fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
247a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondLs;
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGt:
251fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondHi;
253a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
254a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
255a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGe:
256fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
25758af1f9385742f70aca4fcb5e13aba53b8be2ef4Vladimir Marko        ccode = kCondUge;
258a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
260a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
261cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, target);
26484fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee}
26584fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
26684fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
2671fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
2682ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_src1, RegLocation rl_src2) {
269a5954be0aac5edd892fb31a209960543d00e4500buzbee  bool is_double = false;
270a5954be0aac5edd892fb31a209960543d00e4500buzbee  int default_result = -1;
271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
27267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
273408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_FLOAT:
275fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
276fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_FLOAT:
279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
280fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_DOUBLE:
283fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
284fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
285a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
286a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_DOUBLE:
287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
289a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
290a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
291a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
292a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
293fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
2941fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
2951fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
296078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
2971fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
2981fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2992700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadConstant(rl_result.reg, default_result);
300091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    NewLIR2(kThumb2Vcmpd, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
301a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
3021fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
3031fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
304078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
3051fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
3061fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
3072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadConstant(rl_result.reg, default_result);
30800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    NewLIR2(kThumb2Vcmps, rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
309a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
310091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(!rl_result.reg.IsFloat());
3111fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
31267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3133da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  LIR* it = OpIT((default_result == -1) ? kCondGt : kCondMi, "");
31400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR2(kThumb2MovI8M, rl_result.reg.GetReg(),
3157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          ModifiedImmediate(-default_result));  // Must not alter ccodes
3163da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  OpEndIT(it);
31767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3183da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  it = OpIT(kCondEq, "");
3192700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadConstant(rl_result.reg, 0);
3203da67a558f1fd3d8a157d8044d521753f3f99ac8Dave Allison  OpEndIT(it);
32167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3221fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
32367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
32411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
3252ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3271fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kFPReg);
3281fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
32900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR2(kThumb2Vnegs, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3301fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3332ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
334fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
3351fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
3361fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
337091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(kThumb2Vnegd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3381fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3415030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markostatic RegisterClass RegClassForAbsFP(RegLocation rl_src, RegLocation rl_dest) {
3425030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // If src is in a core reg or, unlikely, dest has been promoted to a core reg, use core reg.
3435030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if ((rl_src.location == kLocPhysReg && !rl_src.reg.IsFloat()) ||
3445030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko      (rl_dest.location == kLocPhysReg && !rl_dest.reg.IsFloat())) {
3455030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return kCoreReg;
3465030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3475030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // If src is in an fp reg or dest has been promoted to an fp reg, use fp reg.
3485030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (rl_src.location == kLocPhysReg || rl_dest.location == kLocPhysReg) {
3495030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return kFPReg;
3505030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3515030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // With both src and dest in the stack frame we have to perform load+abs+store. Whether this
3525030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // is faster using a core reg or fp reg depends on the particular CPU. Without further
3535030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // investigation and testing we prefer core register. (If the result is subsequently used in
3545030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // another fp operation, the dalvik reg will probably get promoted and that should be handled
3555030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  // by the cases above.)
3565030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  return kCoreReg;
3575030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko}
3585030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko
3595030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markobool ArmMir2Lir::GenInlinedAbsFloat(CallInfo* info) {
3605030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (info->result.location == kLocInvalid) {
3615030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return true;  // Result is unused: inlining successful, no code generated.
3625030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3635030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_dest = info->result;
3645030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_src = UpdateLoc(info->args[0]);
3655030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest);
3665030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  rl_src = LoadValue(rl_src, reg_class);
3675030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
3685030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (reg_class == kFPReg) {
3695030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    NewLIR2(kThumb2Vabss, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3705030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  } else {
3715030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff);
3725030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3735030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  StoreValue(rl_dest, rl_result);
3745030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  return true;
3755030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko}
3765030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko
3775030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Markobool ArmMir2Lir::GenInlinedAbsDouble(CallInfo* info) {
3785030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (info->result.location == kLocInvalid) {
3795030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    return true;  // Result is unused: inlining successful, no code generated.
3805030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3815030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_dest = info->result;
3825030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_src = UpdateLocWide(info->args[0]);
3835030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegisterClass reg_class = RegClassForAbsFP(rl_src, rl_dest);
3845030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  rl_src = LoadValueWide(rl_src, reg_class);
3855030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
3865030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  if (reg_class == kFPReg) {
3875030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    NewLIR2(kThumb2Vabsd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
3885030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  } else {
3895030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko    OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff);
3905030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  }
3915030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  StoreValueWide(rl_dest, rl_result);
3925030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko  return true;
3935030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko}
3945030d3ee8c6fe10394912ede107cbc8df63b7b16Vladimir Marko
3951fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) {
3961fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src = info->args[0];
3981fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTargetWide(info);  // double place for result
3991fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
4001fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
401091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR2(kThumb2Vsqrtd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
4021fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
40711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
408