fp_arm.cc revision a5954be0aac5edd892fb31a209960543d00e4500
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"
19641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "compiler/codegen/codegen_util.h"
20641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "compiler/codegen/ralloc_util.h"
211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
2211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2311d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
24a5954be0aac5edd892fb31a209960543d00e4500buzbeevoid ArmCodegen::GenArithOpFloat(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
2502031b185b4653e6c72e21f7a51238b903f6d638buzbee                                 RegLocation rl_src1, RegLocation rl_src2)
2667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
27a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
28fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
2967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
30a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Don't attempt to optimize register usage since these opcodes call out to
32a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * the handlers.
33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
34408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_FLOAT_2ADDR:
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::ADD_FLOAT:
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vadds;
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_FLOAT_2ADDR:
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::SUB_FLOAT:
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vsubs;
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_FLOAT_2ADDR:
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DIV_FLOAT:
45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vdivs;
46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_FLOAT_2ADDR:
48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::MUL_FLOAT:
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2Vmuls;
50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
51a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_FLOAT_2ADDR:
52a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::REM_FLOAT:
53a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      FlushAllRegs(cu);   // Send everything to home location
54a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false);
55a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      rl_result = GetReturn(cu, true);
56a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      StoreValue(cu, rl_dest, rl_result);
57a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
58a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_FLOAT:
59a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      GenNegFloat(cu, rl_dest, rl_src1);
60a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
61a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
62a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
63a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
64fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src1 = LoadValue(cu, rl_src1, kFPReg);
65fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src2 = LoadValue(cu, rl_src2, kFPReg);
66fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
67fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR3(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
68fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  StoreValue(cu, rl_dest, rl_result);
6967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
7067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
71a5954be0aac5edd892fb31a209960543d00e4500buzbeevoid ArmCodegen::GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode,
7202031b185b4653e6c72e21f7a51238b903f6d638buzbee                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
7367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
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:
96a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      FlushAllRegs(cu);   // Send everything to home location
97a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false);
98a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      rl_result = GetReturnWide(cu, true);
99a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      StoreValueWide(cu, rl_dest, rl_result);
100a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
101a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    case Instruction::NEG_DOUBLE:
102a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      GenNegDouble(cu, rl_dest, rl_src1);
103a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
105a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
106a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
108fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src1 = LoadValueWide(cu, rl_src1, kFPReg);
109fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src1.wide);
110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src2 = LoadValueWide(cu, rl_src2, kFPReg);
111fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_src2.wide);
112fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
113fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_dest.wide);
114fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(rl_result.wide);
115fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR3(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
116fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src2.low_reg, rl_src2.high_reg));
117fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  StoreValueWide(cu, rl_dest, rl_result);
11867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
11967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
120a5954be0aac5edd892fb31a209960543d00e4500buzbeevoid ArmCodegen::GenConversion(CompilationUnit* cu, Instruction::Code opcode,
12102031b185b4653e6c72e21f7a51238b903f6d638buzbee                               RegLocation rl_dest, RegLocation rl_src)
12267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
123a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int op = kThumbBkpt;
124fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int src_reg;
125fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
12667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (opcode) {
128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_FLOAT:
129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtIF;
130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_INT:
132a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFI;
133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_FLOAT:
135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDF;
136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_DOUBLE:
138a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtFd;
139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
140a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::INT_TO_DOUBLE:
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtID;
142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_INT:
144a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      op = kThumb2VcvtDI;
145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
146a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::LONG_TO_DOUBLE:
147a5954be0aac5edd892fb31a209960543d00e4500buzbee      GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
148a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::FLOAT_TO_LONG:
150a5954be0aac5edd892fb31a209960543d00e4500buzbee      GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
151a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::LONG_TO_FLOAT:
153a5954be0aac5edd892fb31a209960543d00e4500buzbee      GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
154a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
155a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::DOUBLE_TO_LONG:
156a5954be0aac5edd892fb31a209960543d00e4500buzbee      GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
157a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
159a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
160a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
161fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_src.wide) {
162fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src = LoadValueWide(cu, rl_src, kFPReg);
163fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
164a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
165fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src = LoadValue(cu, rl_src, kFPReg);
166fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    src_reg = rl_src.low_reg;
167a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
168fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_dest.wide) {
169fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
170fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
171fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    StoreValueWide(cu, rl_dest, rl_result);
172a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
173fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
174fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, op, rl_result.low_reg, src_reg);
175fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    StoreValue(cu, rl_dest, rl_result);
176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
17767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
17867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
17902031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid ArmCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias,
18002031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     bool is_double)
18184fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee{
182fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* label_list = cu->block_label_list;
183fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* target = &label_list[bb->taken->id];
184fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1;
185fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2;
186fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src1 = GetSrcWide(cu, mir, 0);
188fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src2 = GetSrcWide(cu, mir, 2);
189fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src1 = LoadValueWide(cu, rl_src1, kFPReg);
190fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src2 = LoadValueWide(cu, rl_src2, kFPReg);
191fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg),
192fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
193a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
194fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src1 = GetSrc(cu, mir, 0);
195fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src2 = GetSrc(cu, mir, 1);
196fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src1 = LoadValue(cu, rl_src1, kFPReg);
197fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src2 = LoadValue(cu, rl_src2, kFPReg);
198fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg);
199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
200fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR0(cu, kThumb2Fmstat);
201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch(ccode) {
203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondEq:
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondNe:
205a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
206a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLt:
207fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
208a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondMi;
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
211a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondLe:
212fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondLs;
214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGt:
217fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondHi;
219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
220a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kCondGe:
222fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (gt_bias) {
223a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        ccode = kCondCs;
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
225a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
226a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
227cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
228a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
229fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  OpCondBranch(cu, ccode, target);
23084fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee}
23184fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
23284fd693103dddd50b6a18522bfb5eaab0e51b6ecbuzbee
233a5954be0aac5edd892fb31a209960543d00e4500buzbeevoid ArmCodegen::GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
23402031b185b4653e6c72e21f7a51238b903f6d638buzbee                          RegLocation rl_src1, RegLocation rl_src2)
23567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
236a5954be0aac5edd892fb31a209960543d00e4500buzbee  bool is_double = false;
237a5954be0aac5edd892fb31a209960543d00e4500buzbee  int default_result = -1;
238fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
23967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
240408ad16bf7c460bf34ca55ff6351b79841a6fcd5buzbee  switch (opcode) {
241a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_FLOAT:
242fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
243fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_FLOAT:
246fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = false;
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPL_DOUBLE:
250fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
251fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = -1;
252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
253a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case Instruction::CMPG_DOUBLE:
254fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      is_double = true;
255fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default_result = 1;
256a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
257a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
258a5954be0aac5edd892fb31a209960543d00e4500buzbee      LOG(FATAL) << "Unexpected opcode: " << opcode;
259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
260fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_double) {
261fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src1 = LoadValueWide(cu, rl_src1, kFPReg);
262fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src2 = LoadValueWide(cu, rl_src2, kFPReg);
263078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc()
264fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    ClobberSReg(cu, rl_dest.s_reg_low);
265fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
266fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LoadConstant(cu, rl_result.low_reg, default_result);
267fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg),
268fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            S2d(rl_src2.low_reg, rl_src2.high_reg));
269a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
270fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src1 = LoadValue(cu, rl_src1, kFPReg);
271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_src2 = LoadValue(cu, rl_src2, kFPReg);
272078fa459fee2d5f26a94fbbe5b8f4feeafb4afb2buzbee    // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc()
273fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    ClobberSReg(cu, rl_dest.s_reg_low);
274fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
275fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LoadConstant(cu, rl_result.low_reg, default_result);
276fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg);
277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
278fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(!ARM_FPREG(rl_result.low_reg));
279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR0(cu, kThumb2Fmstat);
28067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
28102031b185b4653e6c72e21f7a51238b903f6d638buzbee  OpIT(cu, (default_result == -1) ? kCondGt : kCondMi, "");
282fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR2(cu, kThumb2MovImmShift, rl_result.low_reg,
283fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          ModifiedImmediate(-default_result)); // Must not alter ccodes
284fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GenBarrier(cu);
28567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
28602031b185b4653e6c72e21f7a51238b903f6d638buzbee  OpIT(cu, kCondEq, "");
287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LoadConstant(cu, rl_result.low_reg, 0);
288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GenBarrier(cu);
28967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
290fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  StoreValue(cu, rl_dest, rl_result);
29167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
29211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
29302031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid ArmCodegen::GenNegFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
295fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
296fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src = LoadValue(cu, rl_src, kFPReg);
297fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
298fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR2(cu, kThumb2Vnegs, rl_result.low_reg, rl_src.low_reg);
299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  StoreValue(cu, rl_dest, rl_result);
300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
30202031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid ArmCodegen::GenNegDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result;
305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src = LoadValueWide(cu, rl_src, kFPReg);
306fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
307fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR2(cu, kThumb2Vnegd, S2d(rl_result.low_reg, rl_result.high_reg),
308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src.low_reg, rl_src.high_reg));
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  StoreValueWide(cu, rl_dest, rl_result);
310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
31202031b185b4653e6c72e21f7a51238b903f6d638buzbeebool ArmCodegen::GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) {
313fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(cu->instruction_set, kThumb2);
314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR *branch;
315fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src = info->args[0];
316fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_dest = InlineTargetWide(cu, info);  // double place for result
317fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src = LoadValueWide(cu, rl_src, kFPReg);
318fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
319fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR2(cu, kThumb2Vsqrtd, S2d(rl_result.low_reg, rl_result.high_reg),
320fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_src.low_reg, rl_src.high_reg));
321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR2(cu, kThumb2Vcmpd, S2d(rl_result.low_reg, rl_result.high_reg),
322fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          S2d(rl_result.low_reg, rl_result.high_reg));
323fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR0(cu, kThumb2Fmstat);
324fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  branch = NewLIR2(cu, kThumbBCond, 0, kArmCondEq);
325fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  ClobberCalleeSave(cu);
326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LockCallTemps(cu);  // Using fixed registers
327fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pSqrt));
328fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR3(cu, kThumb2Fmrrd, r0, r1, S2d(rl_src.low_reg, rl_src.high_reg));
329fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR1(cu, kThumbBlxR, r_tgt);
330fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NewLIR3(cu, kThumb2Fmdrr, S2d(rl_result.low_reg, rl_result.high_reg), r0, r1);
331fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  branch->target = NewLIR0(cu, kPseudoTargetLabel);
332fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  StoreValueWide(cu, rl_dest, rl_result);
333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
33711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
338