fp_mips.cc revision 984305917bf57b3f8d92965e4715a0370cc5bcfb
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "codegen_mips.h"
18#include "dex/quick/mir_to_lir-inl.h"
19#include "entrypoints/quick/quick_entrypoints.h"
20#include "mips_lir.h"
21
22namespace art {
23
24void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode,
25                                  RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
26  int op = kMipsNop;
27  RegLocation rl_result;
28
29  /*
30   * Don't attempt to optimize register usage since these opcodes call out to
31   * the handlers.
32   */
33  switch (opcode) {
34    case Instruction::ADD_FLOAT_2ADDR:
35    case Instruction::ADD_FLOAT:
36      op = kMipsFadds;
37      break;
38    case Instruction::SUB_FLOAT_2ADDR:
39    case Instruction::SUB_FLOAT:
40      op = kMipsFsubs;
41      break;
42    case Instruction::DIV_FLOAT_2ADDR:
43    case Instruction::DIV_FLOAT:
44      op = kMipsFdivs;
45      break;
46    case Instruction::MUL_FLOAT_2ADDR:
47    case Instruction::MUL_FLOAT:
48      op = kMipsFmuls;
49      break;
50    case Instruction::REM_FLOAT_2ADDR:
51    case Instruction::REM_FLOAT:
52      FlushAllRegs();   // Send everything to home location
53      CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
54      rl_result = GetReturn(kFPReg);
55      StoreValue(rl_dest, rl_result);
56      return;
57    case Instruction::NEG_FLOAT:
58      GenNegFloat(rl_dest, rl_src1);
59      return;
60    default:
61      LOG(FATAL) << "Unexpected opcode: " << opcode;
62  }
63  rl_src1 = LoadValue(rl_src1, kFPReg);
64  rl_src2 = LoadValue(rl_src2, kFPReg);
65  rl_result = EvalLoc(rl_dest, kFPReg, true);
66  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
67  StoreValue(rl_dest, rl_result);
68}
69
70void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode,
71                                   RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
72  int op = kMipsNop;
73  RegLocation rl_result;
74
75  switch (opcode) {
76    case Instruction::ADD_DOUBLE_2ADDR:
77    case Instruction::ADD_DOUBLE:
78      op = kMipsFaddd;
79      break;
80    case Instruction::SUB_DOUBLE_2ADDR:
81    case Instruction::SUB_DOUBLE:
82      op = kMipsFsubd;
83      break;
84    case Instruction::DIV_DOUBLE_2ADDR:
85    case Instruction::DIV_DOUBLE:
86      op = kMipsFdivd;
87      break;
88    case Instruction::MUL_DOUBLE_2ADDR:
89    case Instruction::MUL_DOUBLE:
90      op = kMipsFmuld;
91      break;
92    case Instruction::REM_DOUBLE_2ADDR:
93    case Instruction::REM_DOUBLE:
94      FlushAllRegs();   // Send everything to home location
95      CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
96      rl_result = GetReturnWide(kFPReg);
97      StoreValueWide(rl_dest, rl_result);
98      return;
99    case Instruction::NEG_DOUBLE:
100      GenNegDouble(rl_dest, rl_src1);
101      return;
102    default:
103      LOG(FATAL) << "Unpexpected opcode: " << opcode;
104  }
105  rl_src1 = LoadValueWide(rl_src1, kFPReg);
106  DCHECK(rl_src1.wide);
107  rl_src2 = LoadValueWide(rl_src2, kFPReg);
108  DCHECK(rl_src2.wide);
109  rl_result = EvalLoc(rl_dest, kFPReg, true);
110  DCHECK(rl_dest.wide);
111  DCHECK(rl_result.wide);
112  NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
113  StoreValueWide(rl_dest, rl_result);
114}
115
116void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
117                                RegLocation rl_src) {
118  int op = kMipsNop;
119  RegLocation rl_result;
120  switch (opcode) {
121    case Instruction::INT_TO_FLOAT:
122      op = kMipsFcvtsw;
123      break;
124    case Instruction::DOUBLE_TO_FLOAT:
125      op = kMipsFcvtsd;
126      break;
127    case Instruction::FLOAT_TO_DOUBLE:
128      op = kMipsFcvtds;
129      break;
130    case Instruction::INT_TO_DOUBLE:
131      op = kMipsFcvtdw;
132      break;
133    case Instruction::FLOAT_TO_INT:
134      GenConversionCall(kQuickF2iz, rl_dest, rl_src);
135      return;
136    case Instruction::DOUBLE_TO_INT:
137      GenConversionCall(kQuickD2iz, rl_dest, rl_src);
138      return;
139    case Instruction::LONG_TO_DOUBLE:
140      GenConversionCall(kQuickL2d, rl_dest, rl_src);
141      return;
142    case Instruction::FLOAT_TO_LONG:
143      GenConversionCall(kQuickF2l, rl_dest, rl_src);
144      return;
145    case Instruction::LONG_TO_FLOAT:
146      GenConversionCall(kQuickL2f, rl_dest, rl_src);
147      return;
148    case Instruction::DOUBLE_TO_LONG:
149      GenConversionCall(kQuickD2l, rl_dest, rl_src);
150      return;
151    default:
152      LOG(FATAL) << "Unexpected opcode: " << opcode;
153  }
154  if (rl_src.wide) {
155    rl_src = LoadValueWide(rl_src, kFPReg);
156  } else {
157    rl_src = LoadValue(rl_src, kFPReg);
158  }
159  rl_result = EvalLoc(rl_dest, kFPReg, true);
160  NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
161  if (rl_dest.wide) {
162    StoreValueWide(rl_dest, rl_result);
163  } else {
164    StoreValue(rl_dest, rl_result);
165  }
166}
167
168void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
169                           RegLocation rl_src1, RegLocation rl_src2) {
170  bool wide = true;
171  QuickEntrypointEnum target;
172
173  switch (opcode) {
174    case Instruction::CMPL_FLOAT:
175      target = kQuickCmplFloat;
176      wide = false;
177      break;
178    case Instruction::CMPG_FLOAT:
179      target = kQuickCmpgFloat;
180      wide = false;
181      break;
182    case Instruction::CMPL_DOUBLE:
183      target = kQuickCmplDouble;
184      break;
185    case Instruction::CMPG_DOUBLE:
186      target = kQuickCmpgDouble;
187      break;
188    default:
189      LOG(FATAL) << "Unexpected opcode: " << opcode;
190      target = kQuickCmplFloat;
191  }
192  FlushAllRegs();
193  LockCallTemps();
194  if (wide) {
195    RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
196    RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
197    LoadValueDirectWideFixed(rl_src1, r_tmp1);
198    LoadValueDirectWideFixed(rl_src2, r_tmp2);
199  } else {
200    LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
201    LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
202  }
203  RegStorage r_tgt = LoadHelper(target);
204  // NOTE: not a safepoint
205  OpReg(kOpBlx, r_tgt);
206  RegLocation rl_result = GetReturn(kCoreReg);
207  StoreValue(rl_dest, rl_result);
208}
209
210void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir,
211                                bool gt_bias, bool is_double) {
212  UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
213}
214
215void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
216  RegLocation rl_result;
217  rl_src = LoadValue(rl_src, kCoreReg);
218  rl_result = EvalLoc(rl_dest, kCoreReg, true);
219  OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
220  StoreValue(rl_dest, rl_result);
221}
222
223void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
224  RegLocation rl_result;
225  rl_src = LoadValueWide(rl_src, kCoreReg);
226  rl_result = EvalLoc(rl_dest, kCoreReg, true);
227  OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
228  OpRegCopy(rl_result.reg, rl_src.reg);
229  StoreValueWide(rl_dest, rl_result);
230}
231
232bool MipsMir2Lir::GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) {
233  // TODO: need Mips implementation
234  return false;
235}
236
237}  // namespace art
238