blob: 5ee5de451e701b2e1fe3e77df8ef5262d9d130ca [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"
18
buzbeee3acd072012-02-25 17:03:10 -080019namespace art {
20
buzbee408ad162012-06-06 16:45:18 -070021bool genArithOpFloat(CompilationUnit *cUnit, Instruction::Code opcode, RegLocation rlDest,
buzbee5de34942012-03-01 14:51:57 -080022 RegLocation rlSrc1, RegLocation rlSrc2)
buzbeee3acd072012-02-25 17:03:10 -080023{
24#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -070025 int op = kMipsNop;
26 RegLocation rlResult;
buzbeee3acd072012-02-25 17:03:10 -080027
Bill Buzbeea114add2012-05-03 15:00:40 -070028 /*
29 * Don't attempt to optimize register usage since these opcodes call out to
30 * the handlers.
31 */
buzbee408ad162012-06-06 16:45:18 -070032 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070033 case Instruction::ADD_FLOAT_2ADDR:
34 case Instruction::ADD_FLOAT:
35 op = kMipsFadds;
36 break;
37 case Instruction::SUB_FLOAT_2ADDR:
38 case Instruction::SUB_FLOAT:
39 op = kMipsFsubs;
40 break;
41 case Instruction::DIV_FLOAT_2ADDR:
42 case Instruction::DIV_FLOAT:
43 op = kMipsFdivs;
44 break;
45 case Instruction::MUL_FLOAT_2ADDR:
46 case Instruction::MUL_FLOAT:
47 op = kMipsFmuls;
48 break;
49 case Instruction::REM_FLOAT_2ADDR:
50 case Instruction::REM_FLOAT:
51 case Instruction::NEG_FLOAT: {
buzbee408ad162012-06-06 16:45:18 -070052 return genArithOpFloatPortable(cUnit, opcode, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -080053 }
Bill Buzbeea114add2012-05-03 15:00:40 -070054 default:
55 return true;
56 }
57 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
58 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
59 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
60 newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg,
61 rlSrc2.lowReg);
62 storeValue(cUnit, rlDest, rlResult);
buzbeee3acd072012-02-25 17:03:10 -080063
Bill Buzbeea114add2012-05-03 15:00:40 -070064 return false;
buzbeee3acd072012-02-25 17:03:10 -080065#else
buzbee408ad162012-06-06 16:45:18 -070066 return genArithOpFloatPortable(cUnit, opcode, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -080067#endif
68}
69
buzbeeeaf09bc2012-11-15 14:51:41 -080070bool genArithOpDouble(CompilationUnit *cUnit, Instruction::Code opcode,
71 RegLocation rlDest, RegLocation rlSrc1, RegLocation rlSrc2)
buzbeee3acd072012-02-25 17:03:10 -080072{
73#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -070074 int op = kMipsNop;
75 RegLocation rlResult;
buzbeee3acd072012-02-25 17:03:10 -080076
buzbee408ad162012-06-06 16:45:18 -070077 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -070078 case Instruction::ADD_DOUBLE_2ADDR:
79 case Instruction::ADD_DOUBLE:
80 op = kMipsFaddd;
81 break;
82 case Instruction::SUB_DOUBLE_2ADDR:
83 case Instruction::SUB_DOUBLE:
84 op = kMipsFsubd;
85 break;
86 case Instruction::DIV_DOUBLE_2ADDR:
87 case Instruction::DIV_DOUBLE:
88 op = kMipsFdivd;
89 break;
90 case Instruction::MUL_DOUBLE_2ADDR:
91 case Instruction::MUL_DOUBLE:
92 op = kMipsFmuld;
93 break;
94 case Instruction::REM_DOUBLE_2ADDR:
95 case Instruction::REM_DOUBLE:
96 case Instruction::NEG_DOUBLE: {
buzbee408ad162012-06-06 16:45:18 -070097 return genArithOpDoublePortable(cUnit, opcode, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -080098 }
Bill Buzbeea114add2012-05-03 15:00:40 -070099 default:
100 return true;
101 }
102 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
103 DCHECK(rlSrc1.wide);
104 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
105 DCHECK(rlSrc2.wide);
106 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
107 DCHECK(rlDest.wide);
108 DCHECK(rlResult.wide);
buzbeef0504cd2012-11-13 16:31:10 -0800109 newLIR3(cUnit, (MipsOpCode)op, s2d(rlResult.lowReg, rlResult.highReg),
110 s2d(rlSrc1.lowReg, rlSrc1.highReg),
111 s2d(rlSrc2.lowReg, rlSrc2.highReg));
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 storeValueWide(cUnit, rlDest, rlResult);
113 return false;
buzbeee3acd072012-02-25 17:03:10 -0800114#else
buzbee408ad162012-06-06 16:45:18 -0700115 return genArithOpDoublePortable(cUnit, opcode, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800116#endif
117}
118
buzbeeeaf09bc2012-11-15 14:51:41 -0800119bool genConversion(CompilationUnit *cUnit, Instruction::Code opcode, RegLocation rlDest,
120 RegLocation rlSrc)
buzbeee3acd072012-02-25 17:03:10 -0800121{
buzbee5de34942012-03-01 14:51:57 -0800122#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -0700123 int op = kMipsNop;
124 int srcReg;
125 RegLocation rlResult;
126 switch (opcode) {
127 case Instruction::INT_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 op = kMipsFcvtsw;
129 break;
130 case Instruction::DOUBLE_TO_FLOAT:
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 op = kMipsFcvtsd;
132 break;
133 case Instruction::FLOAT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 op = kMipsFcvtds;
135 break;
136 case Instruction::INT_TO_DOUBLE:
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 op = kMipsFcvtdw;
138 break;
139 case Instruction::FLOAT_TO_INT:
140 case Instruction::DOUBLE_TO_INT:
141 case Instruction::LONG_TO_DOUBLE:
142 case Instruction::FLOAT_TO_LONG:
143 case Instruction::LONG_TO_FLOAT:
144 case Instruction::DOUBLE_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700145 return genConversionPortable(cUnit, opcode, rlDest, rlSrc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 default:
147 return true;
148 }
buzbee408ad162012-06-06 16:45:18 -0700149 if (rlSrc.wide) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
buzbeef0504cd2012-11-13 16:31:10 -0800151 srcReg = s2d(rlSrc.lowReg, rlSrc.highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
154 srcReg = rlSrc.lowReg;
155 }
buzbee408ad162012-06-06 16:45:18 -0700156 if (rlDest.wide) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700157 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
buzbeef0504cd2012-11-13 16:31:10 -0800158 newLIR2(cUnit, (MipsOpCode)op, s2d(rlResult.lowReg, rlResult.highReg),
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 srcReg);
160 storeValueWide(cUnit, rlDest, rlResult);
161 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
163 newLIR2(cUnit, (MipsOpCode)op, rlResult.lowReg, srcReg);
164 storeValue(cUnit, rlDest, rlResult);
165 }
166 return false;
buzbeee3acd072012-02-25 17:03:10 -0800167#else
buzbee408ad162012-06-06 16:45:18 -0700168 return genConversionPortable(cUnit, opcode, rlDest, rlSrc);
buzbeee3acd072012-02-25 17:03:10 -0800169#endif
170}
171
buzbeeeaf09bc2012-11-15 14:51:41 -0800172bool genCmpFP(CompilationUnit *cUnit, Instruction::Code opcode, RegLocation rlDest,
173 RegLocation rlSrc1, RegLocation rlSrc2)
buzbeee3acd072012-02-25 17:03:10 -0800174{
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 bool wide = true;
176 int offset;
buzbeee3acd072012-02-25 17:03:10 -0800177
buzbee408ad162012-06-06 16:45:18 -0700178 switch (opcode) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 case Instruction::CMPL_FLOAT:
180 offset = ENTRYPOINT_OFFSET(pCmplFloat);
181 wide = false;
182 break;
183 case Instruction::CMPG_FLOAT:
184 offset = ENTRYPOINT_OFFSET(pCmpgFloat);
185 wide = false;
186 break;
187 case Instruction::CMPL_DOUBLE:
188 offset = ENTRYPOINT_OFFSET(pCmplDouble);
189 break;
190 case Instruction::CMPG_DOUBLE:
191 offset = ENTRYPOINT_OFFSET(pCmpgDouble);
192 break;
193 default:
194 return true;
195 }
196 oatFlushAllRegs(cUnit);
197 oatLockCallTemps(cUnit);
198 if (wide) {
buzbeef0504cd2012-11-13 16:31:10 -0800199 loadValueDirectWideFixed(cUnit, rlSrc1, rMIPS_FARG0, rMIPS_FARG1);
200 loadValueDirectWideFixed(cUnit, rlSrc2, rMIPS_FARG2, rMIPS_FARG3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800202 loadValueDirectFixed(cUnit, rlSrc1, rMIPS_FARG0);
203 loadValueDirectFixed(cUnit, rlSrc2, rMIPS_FARG2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 }
205 int rTgt = loadHelper(cUnit, offset);
buzbee8320f382012-09-11 16:29:42 -0700206 // NOTE: not a safepoint
Bill Buzbeea114add2012-05-03 15:00:40 -0700207 opReg(cUnit, kOpBlx, rTgt);
208 RegLocation rlResult = oatGetReturn(cUnit, false);
209 storeValue(cUnit, rlDest, rlResult);
210 return false;
buzbeee3acd072012-02-25 17:03:10 -0800211}
212
jeffhao4b771a02012-07-25 15:07:21 -0700213void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
214 bool gtBias, bool isDouble)
215{
216 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
217}
218
buzbeeefc63692012-11-14 16:31:52 -0800219void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
220{
221 RegLocation rlResult;
222 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
223 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
224 opRegRegImm(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, 0x80000000);
225 storeValue(cUnit, rlDest, rlResult);
226}
227
228void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
229{
230 RegLocation rlResult;
231 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
232 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
233 opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg, 0x80000000);
234 opRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
235 storeValueWide(cUnit, rlDest, rlResult);
236}
237
238bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin)
239{
240 // TODO: need Mips implementation
241 return false;
242}
243
buzbeee3acd072012-02-25 17:03:10 -0800244} // namespace art