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
527655f29fabc0a12765de828914a18314382e5a35Ian Rogers      CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2,
537655f29fabc0a12765de828914a18314382e5a35Ian Rogers                                              false);
541fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturn(true);
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);
661fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
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
957655f29fabc0a12765de828914a18314382e5a35Ian Rogers      CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2,
967655f29fabc0a12765de828914a18314382e5a35Ian Rogers                                              false);
971fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturnWide(true);
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);
1141fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
115fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src2.low_reg, rl_src2.high_reg));
1161fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
11767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
11867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1191fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenConversion(Instruction::Code opcode,
1202ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               RegLocation rl_dest, RegLocation rl_src) {
121a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
122fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg;
123fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
12467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (opcode) {
126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_FLOAT:
127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtIF;
128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_INT:
130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFI;
131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
132a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_FLOAT:
133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDF;
134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_DOUBLE:
136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFd;
137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
138a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_DOUBLE:
139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtID;
140a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_INT:
142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDI;
143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
144a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::LONG_TO_DOUBLE:
1457655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
146a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
147a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_LONG:
1487655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
149a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::LONG_TO_FLOAT:
1517655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
152a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
153a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_LONG:
1547655f29fabc0a12765de828914a18314382e5a35Ian Rogers      GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
155a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
157a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
159fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
1601fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValueWide(rl_src, kFPReg);
161fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1631fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, kFPReg);
164fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = rl_src.low_reg;
165a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
166fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
1671fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
1681fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
170a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1711fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kFPReg, true);
1721fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(op, rl_result.low_reg, src_reg);
1731fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
17567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
17667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1771fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias,
1782ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_double) {
1791fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* target = &block_label_list_[bb->taken->id];
180fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
181fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
182fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
1831fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrcWide(mir, 0);
1841fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrcWide(mir, 2);
1851fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
1861fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
1871fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg),
188fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1901fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = mir_graph_->GetSrc(mir, 0);
1911fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = mir_graph_->GetSrc(mir, 1);
1921fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
1931fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
1941fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg);
195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
1961fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
198df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondEq:
200a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondNe:
201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLt:
203fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondMi;
205a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
206a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLe:
208fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondLs;
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
211a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGt:
213fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondHi;
215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGe:
218fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondCs;
220a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
223cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2251fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, target);
22684fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee}
22784fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
22884fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
2291fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
2302ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_src1, RegLocation rl_src2) {
231a5954be0aac5edd892fb31a209960543d00e4500buzbee  bool is_double = false;
232a5954be0aac5edd892fb31a209960543d00e4500buzbee  int default_result = -1;
233fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
23467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
235408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
236a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_FLOAT:
237fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
238fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_FLOAT:
241fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
242fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_DOUBLE:
245fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
246fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
247a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_DOUBLE:
249fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
250fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
251a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
253a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
254a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
255fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
2561fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kFPReg);
2571fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kFPReg);
258078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
2591fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
2601fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2611fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadConstant(rl_result.low_reg, default_result);
2621fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg),
263fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
2651fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValue(rl_src1, kFPReg);
2661fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValue(rl_src2, kFPReg);
267078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
2681fd3346740dfb7f47be9922312b68a4227fada96buzbee    ClobberSReg(rl_dest.s_reg_low);
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2701fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadConstant(rl_result.low_reg, default_result);
2711fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg);
272a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
273fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(!ARM_FPREG(rl_result.low_reg));
2741fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
27567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2761fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT((default_result == -1) ? kCondGt : kCondMi, "");
2771fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2MovImmShift, rl_result.low_reg,
2787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          ModifiedImmediate(-default_result));  // Must not alter ccodes
2791fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
28067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2811fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT(kCondEq, "");
2821fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(rl_result.low_reg, 0);
2831fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
28467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2851fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
28667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
28711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
2882ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
289fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
2901fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kFPReg);
2911fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
2921fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vnegs, rl_result.low_reg, rl_src.low_reg);
2931fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2962ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
297fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
2981fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
2991fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_result = EvalLoc(rl_dest, kFPReg, true);
3001fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vnegd, S2d(rl_result.low_reg, rl_result.high_reg),
301fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src.low_reg, rl_src.high_reg));
3021fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3051fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) {
3061fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR *branch;
308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src = info->args[0];
3091fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTargetWide(info);  // double place for result
3101fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kFPReg);
3111fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
3121fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vsqrtd, S2d(rl_result.low_reg, rl_result.high_reg),
313fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src.low_reg, rl_src.high_reg));
3141fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2Vcmpd, S2d(rl_result.low_reg, rl_result.high_reg),
315fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_result.low_reg, rl_result.high_reg));
3161fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kThumb2Fmstat);
3171fd3346740dfb7f47be9922312b68a4227fada96buzbee  branch = NewLIR2(kThumbBCond, 0, kArmCondEq);
3181fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberCalleeSave();
3191fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockCallTemps();  // Using fixed registers
3207655f29fabc0a12765de828914a18314382e5a35Ian Rogers  int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pSqrt));
3211fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2Fmrrd, r0, r1, S2d(rl_src.low_reg, rl_src.high_reg));
3221fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR1(kThumbBlxR, r_tgt);
3231fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2Fmdrr, S2d(rl_result.low_reg, rl_result.high_reg), r0, r1);
3241fd3346740dfb7f47be9922312b68a4227fada96buzbee  branch->target = NewLIR0(kPseudoTargetLabel);
3251fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
33011d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
331