blob: efc4f80fcf52a2fb889aa5902711c0f6127cb6c2 [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;
52 case Instruction::REM_FLOAT_2ADDR:
53 case Instruction::REM_FLOAT:
54 case Instruction::NEG_FLOAT: {
buzbeefa57c472012-11-21 12:06:18 -080055 return GenArithOpFloatPortable(cu, opcode, rl_dest, rl_src1, rl_src2);
buzbeee3acd072012-02-25 17:03:10 -080056 }
Bill Buzbeea114add2012-05-03 15:00:40 -070057 default:
58 return true;
59 }
buzbeefa57c472012-11-21 12:06:18 -080060 rl_src1 = LoadValue(cu, rl_src1, kFPReg);
61 rl_src2 = LoadValue(cu, rl_src2, kFPReg);
62 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
63 NewLIR3(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
64 StoreValue(cu, rl_dest, rl_result);
buzbeee3acd072012-02-25 17:03:10 -080065
Bill Buzbeea114add2012-05-03 15:00:40 -070066 return false;
buzbeee3acd072012-02-25 17:03:10 -080067}
68
buzbee02031b12012-11-23 09:41:35 -080069bool MipsCodegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode,
70 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -080071{
Bill Buzbeea114add2012-05-03 15:00:40 -070072 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -080073 RegLocation rl_result;
buzbeee3acd072012-02-25 17:03:10 -080074
buzbee408ad162012-06-06 16:45:18 -070075 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070076 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 case Instruction::NEG_DOUBLE: {
buzbeefa57c472012-11-21 12:06:18 -080095 return GenArithOpDoublePortable(cu, opcode, rl_dest, rl_src1, rl_src2);
buzbeee3acd072012-02-25 17:03:10 -080096 }
Bill Buzbeea114add2012-05-03 15:00:40 -070097 default:
98 return true;
99 }
buzbeefa57c472012-11-21 12:06:18 -0800100 rl_src1 = LoadValueWide(cu, rl_src1, kFPReg);
101 DCHECK(rl_src1.wide);
102 rl_src2 = LoadValueWide(cu, rl_src2, kFPReg);
103 DCHECK(rl_src2.wide);
104 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
105 DCHECK(rl_dest.wide);
106 DCHECK(rl_result.wide);
107 NewLIR3(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
108 S2d(rl_src2.low_reg, rl_src2.high_reg));
109 StoreValueWide(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 return false;
buzbeee3acd072012-02-25 17:03:10 -0800111}
112
buzbee02031b12012-11-23 09:41:35 -0800113bool MipsCodegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest,
114 RegLocation rl_src)
buzbeee3acd072012-02-25 17:03:10 -0800115{
Bill Buzbeea114add2012-05-03 15:00:40 -0700116 int op = kMipsNop;
buzbeefa57c472012-11-21 12:06:18 -0800117 int src_reg;
118 RegLocation rl_result;
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 switch (opcode) {
120 case Instruction::INT_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 op = kMipsFcvtsw;
122 break;
123 case Instruction::DOUBLE_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 op = kMipsFcvtsd;
125 break;
126 case Instruction::FLOAT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 op = kMipsFcvtds;
128 break;
129 case Instruction::INT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 op = kMipsFcvtdw;
131 break;
132 case Instruction::FLOAT_TO_INT:
133 case Instruction::DOUBLE_TO_INT:
134 case Instruction::LONG_TO_DOUBLE:
135 case Instruction::FLOAT_TO_LONG:
136 case Instruction::LONG_TO_FLOAT:
137 case Instruction::DOUBLE_TO_LONG:
buzbeefa57c472012-11-21 12:06:18 -0800138 return GenConversionPortable(cu, opcode, rl_dest, rl_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 default:
140 return true;
141 }
buzbeefa57c472012-11-21 12:06:18 -0800142 if (rl_src.wide) {
143 rl_src = LoadValueWide(cu, rl_src, kFPReg);
144 src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 } else {
buzbeefa57c472012-11-21 12:06:18 -0800146 rl_src = LoadValue(cu, rl_src, kFPReg);
147 src_reg = rl_src.low_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 }
buzbeefa57c472012-11-21 12:06:18 -0800149 if (rl_dest.wide) {
150 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
151 NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
152 StoreValueWide(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 } else {
buzbeefa57c472012-11-21 12:06:18 -0800154 rl_result = EvalLoc(cu, rl_dest, kFPReg, true);
155 NewLIR2(cu, op, rl_result.low_reg, src_reg);
156 StoreValue(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700157 }
158 return false;
buzbeee3acd072012-02-25 17:03:10 -0800159}
160
buzbee02031b12012-11-23 09:41:35 -0800161bool MipsCodegen::GenCmpFP(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest,
162 RegLocation rl_src1, RegLocation rl_src2)
buzbeee3acd072012-02-25 17:03:10 -0800163{
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 bool wide = true;
165 int offset;
buzbeee3acd072012-02-25 17:03:10 -0800166
buzbee408ad162012-06-06 16:45:18 -0700167 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700168 case Instruction::CMPL_FLOAT:
169 offset = ENTRYPOINT_OFFSET(pCmplFloat);
170 wide = false;
171 break;
172 case Instruction::CMPG_FLOAT:
173 offset = ENTRYPOINT_OFFSET(pCmpgFloat);
174 wide = false;
175 break;
176 case Instruction::CMPL_DOUBLE:
177 offset = ENTRYPOINT_OFFSET(pCmplDouble);
178 break;
179 case Instruction::CMPG_DOUBLE:
180 offset = ENTRYPOINT_OFFSET(pCmpgDouble);
181 break;
182 default:
183 return true;
184 }
buzbeefa57c472012-11-21 12:06:18 -0800185 FlushAllRegs(cu);
186 LockCallTemps(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 if (wide) {
buzbeefa57c472012-11-21 12:06:18 -0800188 LoadValueDirectWideFixed(cu, rl_src1, rMIPS_FARG0, rMIPS_FARG1);
189 LoadValueDirectWideFixed(cu, rl_src2, rMIPS_FARG2, rMIPS_FARG3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 } else {
buzbeefa57c472012-11-21 12:06:18 -0800191 LoadValueDirectFixed(cu, rl_src1, rMIPS_FARG0);
192 LoadValueDirectFixed(cu, rl_src2, rMIPS_FARG2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 }
buzbeefa57c472012-11-21 12:06:18 -0800194 int r_tgt = LoadHelper(cu, offset);
buzbee8320f382012-09-11 16:29:42 -0700195 // NOTE: not a safepoint
buzbeefa57c472012-11-21 12:06:18 -0800196 OpReg(cu, kOpBlx, r_tgt);
197 RegLocation rl_result = GetReturn(cu, false);
198 StoreValue(cu, rl_dest, rl_result);
Bill Buzbeea114add2012-05-03 15:00:40 -0700199 return false;
buzbeee3acd072012-02-25 17:03:10 -0800200}
201
buzbee02031b12012-11-23 09:41:35 -0800202void MipsCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir,
buzbeefa57c472012-11-21 12:06:18 -0800203 bool gt_bias, bool is_double)
jeffhao4b771a02012-07-25 15:07:21 -0700204{
205 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
206}
207
buzbee02031b12012-11-23 09:41:35 -0800208void MipsCodegen::GenNegFloat(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800209{
buzbeefa57c472012-11-21 12:06:18 -0800210 RegLocation rl_result;
211 rl_src = LoadValue(cu, rl_src, kCoreReg);
212 rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
213 OpRegRegImm(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000);
214 StoreValue(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800215}
216
buzbee02031b12012-11-23 09:41:35 -0800217void MipsCodegen::GenNegDouble(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800218{
buzbeefa57c472012-11-21 12:06:18 -0800219 RegLocation rl_result;
220 rl_src = LoadValueWide(cu, rl_src, kCoreReg);
221 rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
222 OpRegRegImm(cu, kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000);
223 OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg);
224 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800225}
226
buzbee02031b12012-11-23 09:41:35 -0800227bool MipsCodegen::GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min)
buzbeeefc63692012-11-14 16:31:52 -0800228{
229 // TODO: need Mips implementation
230 return false;
231}
232
buzbeee3acd072012-02-25 17:03:10 -0800233} // namespace art