blob: e718c5cfd479961451ddee5bfaa9a81c636e3295 [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
Ian Rogers57b86d42012-03-27 16:05:41 -070017#include "oat/runtime/oat_support_entrypoints.h"
buzbee1bc37c62012-11-20 13:35:41 -080018#include "mips_lir.h"
buzbee02031b12012-11-23 09:41:35 -080019#include "codegen_mips.h"
buzbee1bc37c62012-11-20 13:35:41 -080020#include "../codegen_util.h"
21#include "../ralloc_util.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;
buzbeea3a82b22012-11-27 16:09:55 -080052 FlushAllRegs(cu); // Send everything to home location
53 CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false);
54 rl_result = GetReturn(cu, true);
55 StoreValue(cu, rl_dest, rl_result);
56 return false;
57 case Instruction::NEG_FLOAT:
58 GenNegFloat(cu, rl_dest, rl_src1);
59 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -070060 default:
61 return true;
62 }
buzbeefa57c472012-11-21 12:06:18 -080063 rl_src1 = LoadValue(cu, rl_src1, kFPReg);
64 rl_src2 = LoadValue(cu, rl_src2, kFPReg);
65 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
66 NewLIR3(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
67 StoreValue(cu, rl_dest, rl_result);
buzbeee3acd072012-02-25 17:03:10 -080068
Bill Buzbeea114add2012-05-03 15:00:40 -070069 return false;
buzbeee3acd072012-02-25 17:03:10 -080070}
71
buzbee02031b12012-11-23 09:41:35 -080072bool MipsCodegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode,
73 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -080074{
Bill Buzbeea114add2012-05-03 15:00:40 -070075 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -080076 RegLocation rl_result;
buzbeee3acd072012-02-25 17:03:10 -080077
buzbee408ad162012-06-06 16:45:18 -070078 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070079 case Instruction::ADD_DOUBLE_2ADDR:
80 case Instruction::ADD_DOUBLE:
81 op = kMipsFaddd;
82 break;
83 case Instruction::SUB_DOUBLE_2ADDR:
84 case Instruction::SUB_DOUBLE:
85 op = kMipsFsubd;
86 break;
87 case Instruction::DIV_DOUBLE_2ADDR:
88 case Instruction::DIV_DOUBLE:
89 op = kMipsFdivd;
90 break;
91 case Instruction::MUL_DOUBLE_2ADDR:
92 case Instruction::MUL_DOUBLE:
93 op = kMipsFmuld;
94 break;
95 case Instruction::REM_DOUBLE_2ADDR:
96 case Instruction::REM_DOUBLE:
buzbeea3a82b22012-11-27 16:09:55 -080097 FlushAllRegs(cu); // Send everything to home location
98 CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false);
99 rl_result = GetReturnWide(cu, true);
100 StoreValueWide(cu, rl_dest, rl_result);
101 return false;
102 case Instruction::NEG_DOUBLE:
103 GenNegDouble(cu, rl_dest, rl_src1);
104 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 default:
106 return true;
107 }
buzbeefa57c472012-11-21 12:06:18 -0800108 rl_src1 = LoadValueWide(cu, rl_src1, kFPReg);
109 DCHECK(rl_src1.wide);
110 rl_src2 = LoadValueWide(cu, rl_src2, kFPReg);
111 DCHECK(rl_src2.wide);
112 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
113 DCHECK(rl_dest.wide);
114 DCHECK(rl_result.wide);
115 NewLIR3(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
116 S2d(rl_src2.low_reg, rl_src2.high_reg));
117 StoreValueWide(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 return false;
buzbeee3acd072012-02-25 17:03:10 -0800119}
120
buzbee02031b12012-11-23 09:41:35 -0800121bool MipsCodegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest,
122 RegLocation rl_src)
buzbeee3acd072012-02-25 17:03:10 -0800123{
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800125 int src_reg;
126 RegLocation rl_result;
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 switch (opcode) {
128 case Instruction::INT_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 op = kMipsFcvtsw;
130 break;
131 case Instruction::DOUBLE_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 op = kMipsFcvtsd;
133 break;
134 case Instruction::FLOAT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 op = kMipsFcvtds;
136 break;
137 case Instruction::INT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700138 op = kMipsFcvtdw;
139 break;
140 case Instruction::FLOAT_TO_INT:
buzbeea3a82b22012-11-27 16:09:55 -0800141 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2iz), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 case Instruction::DOUBLE_TO_INT:
buzbeea3a82b22012-11-27 16:09:55 -0800143 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2iz), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700144 case Instruction::LONG_TO_DOUBLE:
buzbeea3a82b22012-11-27 16:09:55 -0800145 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 case Instruction::FLOAT_TO_LONG:
buzbeea3a82b22012-11-27 16:09:55 -0800147 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 case Instruction::LONG_TO_FLOAT:
buzbeea3a82b22012-11-27 16:09:55 -0800149 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 case Instruction::DOUBLE_TO_LONG:
buzbeea3a82b22012-11-27 16:09:55 -0800151 return GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 default:
153 return true;
154 }
buzbeefa57c472012-11-21 12:06:18 -0800155 if (rl_src.wide) {
156 rl_src = LoadValueWide(cu, rl_src, kFPReg);
157 src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 } else {
buzbeefa57c472012-11-21 12:06:18 -0800159 rl_src = LoadValue(cu, rl_src, kFPReg);
160 src_reg = rl_src.low_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 }
buzbeefa57c472012-11-21 12:06:18 -0800162 if (rl_dest.wide) {
163 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
164 NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
165 StoreValueWide(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 } else {
buzbeefa57c472012-11-21 12:06:18 -0800167 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
168 NewLIR2(cu, op, rl_result.low_reg, src_reg);
169 StoreValue(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 }
171 return false;
buzbeee3acd072012-02-25 17:03:10 -0800172}
173
buzbee02031b12012-11-23 09:41:35 -0800174bool MipsCodegen::GenCmpFP(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest,
175 RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -0800176{
Bill Buzbeea114add2012-05-03 15:00:40 -0700177 bool wide = true;
178 int offset;
buzbeee3acd072012-02-25 17:03:10 -0800179
buzbee408ad162012-06-06 16:45:18 -0700180 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 case Instruction::CMPL_FLOAT:
182 offset = ENTRYPOINT_OFFSET(pCmplFloat);
183 wide = false;
184 break;
185 case Instruction::CMPG_FLOAT:
186 offset = ENTRYPOINT_OFFSET(pCmpgFloat);
187 wide = false;
188 break;
189 case Instruction::CMPL_DOUBLE:
190 offset = ENTRYPOINT_OFFSET(pCmplDouble);
191 break;
192 case Instruction::CMPG_DOUBLE:
193 offset = ENTRYPOINT_OFFSET(pCmpgDouble);
194 break;
195 default:
196 return true;
197 }
buzbeefa57c472012-11-21 12:06:18 -0800198 FlushAllRegs(cu);
199 LockCallTemps(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 if (wide) {
buzbeefa57c472012-11-21 12:06:18 -0800201 LoadValueDirectWideFixed(cu, rl_src1, rMIPS_FARG0, rMIPS_FARG1);
202 LoadValueDirectWideFixed(cu, rl_src2, rMIPS_FARG2, rMIPS_FARG3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 } else {
buzbeefa57c472012-11-21 12:06:18 -0800204 LoadValueDirectFixed(cu, rl_src1, rMIPS_FARG0);
205 LoadValueDirectFixed(cu, rl_src2, rMIPS_FARG2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700206 }
buzbeefa57c472012-11-21 12:06:18 -0800207 int r_tgt = LoadHelper(cu, offset);
buzbee8320f382012-09-11 16:29:42 -0700208 // NOTE: not a safepoint
buzbeefa57c472012-11-21 12:06:18 -0800209 OpReg(cu, kOpBlx, r_tgt);
210 RegLocation rl_result = GetReturn(cu, false);
211 StoreValue(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 return false;
buzbeee3acd072012-02-25 17:03:10 -0800213}
214
buzbee02031b12012-11-23 09:41:35 -0800215void MipsCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir,
buzbeefa57c472012-11-21 12:06:18 -0800216 bool gt_bias, bool is_double)
jeffhao4b771a02012-07-25 15:07:21 -0700217{
218 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
219}
220
buzbee02031b12012-11-23 09:41:35 -0800221void MipsCodegen::GenNegFloat(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800222{
buzbeefa57c472012-11-21 12:06:18 -0800223 RegLocation rl_result;
224 rl_src = LoadValue(cu, rl_src, kCoreReg);
225 rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
226 OpRegRegImm(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000);
227 StoreValue(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800228}
229
buzbee02031b12012-11-23 09:41:35 -0800230void MipsCodegen::GenNegDouble(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800231{
buzbeefa57c472012-11-21 12:06:18 -0800232 RegLocation rl_result;
233 rl_src = LoadValueWide(cu, rl_src, kCoreReg);
234 rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
235 OpRegRegImm(cu, kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000);
236 OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg);
237 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800238}
239
buzbee02031b12012-11-23 09:41:35 -0800240bool MipsCodegen::GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min)
buzbeeefc63692012-11-14 16:31:52 -0800241{
242 // TODO: need Mips implementation
243 return false;
244}
245
buzbeee3acd072012-02-25 17:03:10 -0800246} // namespace art