fp_arm.cc revision 7934ac288acfb2552bb0b06ec1f61e5820d924a4
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
521fd3346740dfb7f47be9922312b68a4227fada96buzbee      CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false);
531fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturn(true);
541fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
55a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
56a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_FLOAT:
571fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegFloat(rl_dest, rl_src1);
58a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
59a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
60a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
61a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
621fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kFPReg);
631fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kFPReg);
641fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
651fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
661fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
6767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
6867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
691fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithOpDouble(Instruction::Code opcode,
702ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
71a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
72fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
7367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
74408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
75a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_DOUBLE_2ADDR:
76a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_DOUBLE:
77a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vaddd;
78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_DOUBLE_2ADDR:
80a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_DOUBLE:
81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vsubd;
82a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
83a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_DOUBLE_2ADDR:
84a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_DOUBLE:
85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vdivd;
86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
87a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_DOUBLE_2ADDR:
88a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_DOUBLE:
89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vmuld;
90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
91a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_DOUBLE_2ADDR:
92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_DOUBLE:
931fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();   // Send everything to home location
941fd3346740dfb7f47be9922312b68a4227fada96buzbee      CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false);
951fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturnWide(true);
961fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
97a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
98a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_DOUBLE:
991fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenNegDouble(rl_dest, rl_src1);
100a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
101a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
102a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
103a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1051fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kFPReg);
106fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src1.wide);
1071fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kFPReg);
108fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src2.wide);
1091fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_dest.wide);
111fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_result.wide);
1121fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
113fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src2.low_reg, rl_src2.high_reg));
1141fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
11567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
11667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1171fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenConversion(Instruction::Code opcode,
1182ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               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:
137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtID;
138a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_INT:
140a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDI;
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::LONG_TO_DOUBLE:
1431fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenConversionCall(ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
144a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_LONG:
1461fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenConversionCall(ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
147a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
148a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::LONG_TO_FLOAT:
1491fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenConversionCall(ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
150a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
151a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_LONG:
1521fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenConversionCall(ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
153a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
154a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
155a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
157fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
1581fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValueWide(rl_src, kFPReg);
159fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
160a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1611fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, kFPReg);
162fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = rl_src.low_reg;
163a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
164fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
1651fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
1661fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
1671fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
168a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
1701fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(op, rl_result.low_reg, src_reg);
1711fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
172a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
17367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
17467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1751fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
1762ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_double) {
1771fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* target = &block_label_list_[bb->taken->id];
178fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
179fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
180fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
1811fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrcWide(mir, 0);
1821fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrcWide(mir, 2);
1831fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
1841fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
1851fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg),
186fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
187a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1881fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrc(mir, 0);
1891fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrc(mir, 1);
1901fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
1911fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
1921fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg);
193a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
1941fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
196df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondEq:
198a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondNe:
199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
200a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLt:
201fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondMi;
203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
205a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLe:
206fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondLs;
208a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGt:
211fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondHi;
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGe:
216fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondCs;
218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
220a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
221cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2231fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, target);
22484fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee}
22584fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
22684fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
2271fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
2282ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_src1, RegLocation rl_src2) {
229a5954be0aac5edd892fb31a209960543d00e4500buzbee  bool is_double = false;
230a5954be0aac5edd892fb31a209960543d00e4500buzbee  int default_result = -1;
231fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
23267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
233408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_FLOAT:
235fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
236fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_FLOAT:
239fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
240fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
241a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_DOUBLE:
243fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
244fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_DOUBLE:
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
248fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
251a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
253fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
2541fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
2551fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
256078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
2571fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
2581fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2591fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadConstant(rl_result.low_reg, default_result);
2601fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg),
261fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
2641fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
265078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
2661fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
2671fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2681fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadConstant(rl_result.low_reg, default_result);
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg);
270a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(!ARM_FPREG(rl_result.low_reg));
2721fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
27367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2741fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT((default_result == -1) ? kCondGt : kCondMi, "");
2751fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2MovImmShift, rl_result.low_reg,
2767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          ModifiedImmediate(-default_result));  // Must not alter ccodes
2771fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
27867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2791fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT(kCondEq, "");
2801fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(rl_result.low_reg, 0);
2811fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
28267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2831fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
28467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
28511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
2862ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
2881fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kFPReg);
2891fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
2901fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vnegs, rl_result.low_reg, rl_src.low_reg);
2911fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2942ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
295fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
2961fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
2971fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
2981fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vnegd, S2d(rl_result.low_reg, rl_result.high_reg),
299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src.low_reg, rl_src.high_reg));
3001fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3031fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) {
3041fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR *branch;
306fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src = info->args[0];
3071fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTargetWide(info);  // double place for result
3081fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
3091fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
3101fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vsqrtd, S2d(rl_result.low_reg, rl_result.high_reg),
311fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src.low_reg, rl_src.high_reg));
3121fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vcmpd, S2d(rl_result.low_reg, rl_result.high_reg),
313fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_result.low_reg, rl_result.high_reg));
3141fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
3151fd3346740dfb7f47be9922312b68a4227fada96buzbee  branch = NewLIR2(kThumbBCond, 0, kArmCondEq);
3161fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberCalleeSave();
3171fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockCallTemps();  // Using fixed registers
3181fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pSqrt));
3191fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2Fmrrd, r0, r1, S2d(rl_src.low_reg, rl_src.high_reg));
3201fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR1(kThumbBlxR, r_tgt);
3211fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2Fmdrr, S2d(rl_result.low_reg, rl_result.high_reg), r0, r1);
3221fd3346740dfb7f47be9922312b68a4227fada96buzbee  branch->target = NewLIR0(kPseudoTargetLabel);
3231fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
32811d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
329