blob: e7b106e87a7652744c1f171a9d0fc3ac46142895 [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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
buzbee02031b12012-11-23 09:41:35 -080017#include "codegen_mips.h"
Brian Carlstrom641ce032013-01-31 15:21:37 -080018#include "compiler/codegen/codegen_util.h"
19#include "compiler/codegen/ralloc_util.h"
20#include "mips_lir.h"
21#include "oat/runtime/oat_support_entrypoints.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070022
buzbeee3acd072012-02-25 17:03:10 -080023namespace art {
24
buzbee02031b12012-11-23 09:41:35 -080025bool MipsCodegen::GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode,
26 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -080027{
Bill Buzbeea114add2012-05-03 15:00:40 -070028 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -080029 RegLocation rl_result;
buzbeee3acd072012-02-25 17:03:10 -080030
Bill Buzbeea114add2012-05-03 15:00:40 -070031 /*
32 * Don't attempt to optimize register usage since these opcodes call out to
33 * the handlers.
34 */
buzbee408ad162012-06-06 16:45:18 -070035 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070036 case Instruction::ADD_FLOAT_2ADDR:
37 case Instruction::ADD_FLOAT:
38 op = kMipsFadds;
39 break;
40 case Instruction::SUB_FLOAT_2ADDR:
41 case Instruction::SUB_FLOAT:
42 op = kMipsFsubs;
43 break;
44 case Instruction::DIV_FLOAT_2ADDR:
45 case Instruction::DIV_FLOAT:
46 op = kMipsFdivs;
47 break;
48 case Instruction::MUL_FLOAT_2ADDR:
49 case Instruction::MUL_FLOAT:
50 op = kMipsFmuls;
51 break;
Ian Rogersa6f3aaf2013-01-16 15:17:58 -080052 case Instruction::REM_FLOAT_2ADDR:
53 case Instruction::REM_FLOAT:
buzbeea3a82b22012-11-27 16:09:55 -080054 FlushAllRegs(cu); // Send everything to home location
55 CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false);
56 rl_result = GetReturn(cu, true);
57 StoreValue(cu, rl_dest, rl_result);
58 return false;
59 case Instruction::NEG_FLOAT:
60 GenNegFloat(cu, rl_dest, rl_src1);
61 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -070062 default:
63 return true;
64 }
buzbeefa57c472012-11-21 12:06:18 -080065 rl_src1 = LoadValue(cu, rl_src1, kFPReg);
66 rl_src2 = LoadValue(cu, rl_src2, kFPReg);
67 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
68 NewLIR3(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
69 StoreValue(cu, rl_dest, rl_result);
buzbeee3acd072012-02-25 17:03:10 -080070
Bill Buzbeea114add2012-05-03 15:00:40 -070071 return false;
buzbeee3acd072012-02-25 17:03:10 -080072}
73
buzbee02031b12012-11-23 09:41:35 -080074bool MipsCodegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode,
75 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -080076{
Bill Buzbeea114add2012-05-03 15:00:40 -070077 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -080078 RegLocation rl_result;
buzbeee3acd072012-02-25 17:03:10 -080079
buzbee408ad162012-06-06 16:45:18 -070080 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070081 case Instruction::ADD_DOUBLE_2ADDR:
82 case Instruction::ADD_DOUBLE:
83 op = kMipsFaddd;
84 break;
85 case Instruction::SUB_DOUBLE_2ADDR:
86 case Instruction::SUB_DOUBLE:
87 op = kMipsFsubd;
88 break;
89 case Instruction::DIV_DOUBLE_2ADDR:
90 case Instruction::DIV_DOUBLE:
91 op = kMipsFdivd;
92 break;
93 case Instruction::MUL_DOUBLE_2ADDR:
94 case Instruction::MUL_DOUBLE:
95 op = kMipsFmuld;
96 break;
97 case Instruction::REM_DOUBLE_2ADDR:
98 case Instruction::REM_DOUBLE:
buzbeea3a82b22012-11-27 16:09:55 -080099 FlushAllRegs(cu); // Send everything to home location
100 CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false);
101 rl_result = GetReturnWide(cu, true);
102 StoreValueWide(cu, rl_dest, rl_result);
103 return false;
104 case Instruction::NEG_DOUBLE:
105 GenNegDouble(cu, rl_dest, rl_src1);
106 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 default:
108 return true;
109 }
buzbeefa57c472012-11-21 12:06:18 -0800110 rl_src1 = LoadValueWide(cu, rl_src1, kFPReg);
111 DCHECK(rl_src1.wide);
112 rl_src2 = LoadValueWide(cu, rl_src2, kFPReg);
113 DCHECK(rl_src2.wide);
114 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
115 DCHECK(rl_dest.wide);
116 DCHECK(rl_result.wide);
117 NewLIR3(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
118 S2d(rl_src2.low_reg, rl_src2.high_reg));
119 StoreValueWide(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 return false;
buzbeee3acd072012-02-25 17:03:10 -0800121}
122
buzbee02031b12012-11-23 09:41:35 -0800123bool MipsCodegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest,
124 RegLocation rl_src)
buzbeee3acd072012-02-25 17:03:10 -0800125{
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800127 int src_reg;
128 RegLocation rl_result;
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 switch (opcode) {
130 case Instruction::INT_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 op = kMipsFcvtsw;
132 break;
133 case Instruction::DOUBLE_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 op = kMipsFcvtsd;
135 break;
136 case Instruction::FLOAT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 op = kMipsFcvtds;
138 break;
139 case Instruction::INT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 op = kMipsFcvtdw;
141 break;
142 case Instruction::FLOAT_TO_INT:
buzbeea3a82b22012-11-27 16:09:55 -0800143 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2iz), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700144 case Instruction::DOUBLE_TO_INT:
buzbeea3a82b22012-11-27 16:09:55 -0800145 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2iz), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 case Instruction::LONG_TO_DOUBLE:
buzbeea3a82b22012-11-27 16:09:55 -0800147 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 case Instruction::FLOAT_TO_LONG:
buzbeea3a82b22012-11-27 16:09:55 -0800149 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 case Instruction::LONG_TO_FLOAT:
buzbeea3a82b22012-11-27 16:09:55 -0800151 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 case Instruction::DOUBLE_TO_LONG:
buzbeea3a82b22012-11-27 16:09:55 -0800153 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 default:
155 return true;
156 }
buzbeefa57c472012-11-21 12:06:18 -0800157 if (rl_src.wide) {
158 rl_src = LoadValueWide(cu, rl_src, kFPReg);
159 src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 } else {
buzbeefa57c472012-11-21 12:06:18 -0800161 rl_src = LoadValue(cu, rl_src, kFPReg);
162 src_reg = rl_src.low_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700163 }
buzbeefa57c472012-11-21 12:06:18 -0800164 if (rl_dest.wide) {
165 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
166 NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
167 StoreValueWide(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700168 } else {
buzbeefa57c472012-11-21 12:06:18 -0800169 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
170 NewLIR2(cu, op, rl_result.low_reg, src_reg);
171 StoreValue(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 }
173 return false;
buzbeee3acd072012-02-25 17:03:10 -0800174}
175
buzbee02031b12012-11-23 09:41:35 -0800176bool MipsCodegen::GenCmpFP(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest,
177 RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -0800178{
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 bool wide = true;
180 int offset;
buzbeee3acd072012-02-25 17:03:10 -0800181
buzbee408ad162012-06-06 16:45:18 -0700182 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 case Instruction::CMPL_FLOAT:
184 offset = ENTRYPOINT_OFFSET(pCmplFloat);
185 wide = false;
186 break;
187 case Instruction::CMPG_FLOAT:
188 offset = ENTRYPOINT_OFFSET(pCmpgFloat);
189 wide = false;
190 break;
191 case Instruction::CMPL_DOUBLE:
192 offset = ENTRYPOINT_OFFSET(pCmplDouble);
193 break;
194 case Instruction::CMPG_DOUBLE:
195 offset = ENTRYPOINT_OFFSET(pCmpgDouble);
196 break;
197 default:
198 return true;
199 }
buzbeefa57c472012-11-21 12:06:18 -0800200 FlushAllRegs(cu);
201 LockCallTemps(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 if (wide) {
buzbeefa57c472012-11-21 12:06:18 -0800203 LoadValueDirectWideFixed(cu, rl_src1, rMIPS_FARG0, rMIPS_FARG1);
204 LoadValueDirectWideFixed(cu, rl_src2, rMIPS_FARG2, rMIPS_FARG3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 } else {
buzbeefa57c472012-11-21 12:06:18 -0800206 LoadValueDirectFixed(cu, rl_src1, rMIPS_FARG0);
207 LoadValueDirectFixed(cu, rl_src2, rMIPS_FARG2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 }
buzbeefa57c472012-11-21 12:06:18 -0800209 int r_tgt = LoadHelper(cu, offset);
buzbee8320f382012-09-11 16:29:42 -0700210 // NOTE: not a safepoint
buzbeefa57c472012-11-21 12:06:18 -0800211 OpReg(cu, kOpBlx, r_tgt);
212 RegLocation rl_result = GetReturn(cu, false);
213 StoreValue(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 return false;
buzbeee3acd072012-02-25 17:03:10 -0800215}
216
buzbee02031b12012-11-23 09:41:35 -0800217void MipsCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir,
buzbeefa57c472012-11-21 12:06:18 -0800218 bool gt_bias, bool is_double)
jeffhao4b771a02012-07-25 15:07:21 -0700219{
220 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
221}
222
buzbee02031b12012-11-23 09:41:35 -0800223void MipsCodegen::GenNegFloat(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800224{
buzbeefa57c472012-11-21 12:06:18 -0800225 RegLocation rl_result;
226 rl_src = LoadValue(cu, rl_src, kCoreReg);
227 rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
228 OpRegRegImm(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000);
229 StoreValue(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800230}
231
buzbee02031b12012-11-23 09:41:35 -0800232void MipsCodegen::GenNegDouble(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800233{
buzbeefa57c472012-11-21 12:06:18 -0800234 RegLocation rl_result;
235 rl_src = LoadValueWide(cu, rl_src, kCoreReg);
236 rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
237 OpRegRegImm(cu, kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000);
238 OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg);
239 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800240}
241
buzbee02031b12012-11-23 09:41:35 -0800242bool MipsCodegen::GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min)
buzbeeefc63692012-11-14 16:31:52 -0800243{
244 // TODO: need Mips implementation
245 return false;
246}
247
buzbeee3acd072012-02-25 17:03:10 -0800248} // namespace art