blob: 948ded61a8ed5b2d52aa3c78709bd8659a22c445 [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
buzbee5de34942012-03-01 14:51:57 -080021bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
22 RegLocation rlSrc1, RegLocation rlSrc2)
buzbeee3acd072012-02-25 17:03:10 -080023{
24#ifdef __mips_hard_float
25 int op = kMipsNop;
26 RegLocation rlResult;
27
28 /*
29 * Don't attempt to optimize register usage since these opcodes call out to
30 * the handlers.
31 */
32 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -080033 case Instruction::ADD_FLOAT_2ADDR:
34 case Instruction::ADD_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080035 op = kMipsFadds;
36 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080037 case Instruction::SUB_FLOAT_2ADDR:
38 case Instruction::SUB_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080039 op = kMipsFsubs;
40 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080041 case Instruction::DIV_FLOAT_2ADDR:
42 case Instruction::DIV_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080043 op = kMipsFdivs;
44 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080045 case Instruction::MUL_FLOAT_2ADDR:
46 case Instruction::MUL_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080047 op = kMipsFmuls;
48 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080049 case Instruction::REM_FLOAT_2ADDR:
50 case Instruction::REM_FLOAT:
51 case Instruction::NEG_FLOAT: {
buzbeee3acd072012-02-25 17:03:10 -080052 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
53 }
54 default:
55 return true;
56 }
57 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
58 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
59 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
buzbee5de34942012-03-01 14:51:57 -080060 newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg,
61 rlSrc2.lowReg);
buzbeee3acd072012-02-25 17:03:10 -080062 storeValue(cUnit, rlDest, rlResult);
63
64 return false;
65#else
Bill Buzbee11f9d212012-03-03 20:03:18 -080066 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -080067#endif
68}
69
70static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
71 RegLocation rlDest, RegLocation rlSrc1,
72 RegLocation rlSrc2)
73{
74#ifdef __mips_hard_float
75 int op = kMipsNop;
76 RegLocation rlResult;
77
78 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -080079 case Instruction::ADD_DOUBLE_2ADDR:
80 case Instruction::ADD_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080081 op = kMipsFaddd;
82 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080083 case Instruction::SUB_DOUBLE_2ADDR:
84 case Instruction::SUB_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080085 op = kMipsFsubd;
86 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080087 case Instruction::DIV_DOUBLE_2ADDR:
88 case Instruction::DIV_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080089 op = kMipsFdivd;
90 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080091 case Instruction::MUL_DOUBLE_2ADDR:
92 case Instruction::MUL_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080093 op = kMipsFmuld;
94 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080095 case Instruction::REM_DOUBLE_2ADDR:
96 case Instruction::REM_DOUBLE:
97 case Instruction::NEG_DOUBLE: {
buzbeee3acd072012-02-25 17:03:10 -080098 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
99 }
100 default:
101 return true;
102 }
103 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
104 DCHECK(rlSrc1.wide);
105 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
106 DCHECK(rlSrc2.wide);
107 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
108 DCHECK(rlDest.wide);
109 DCHECK(rlResult.wide);
110 newLIR3(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg),
111 S2D(rlSrc1.lowReg, rlSrc1.highReg),
112 S2D(rlSrc2.lowReg, rlSrc2.highReg));
113 storeValueWide(cUnit, rlDest, rlResult);
114 return false;
115#else
Bill Buzbee11f9d212012-03-03 20:03:18 -0800116 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800117#endif
118}
119
120static bool genConversion(CompilationUnit *cUnit, MIR *mir)
121{
buzbee5de34942012-03-01 14:51:57 -0800122#ifdef __mips_hard_float
Elliott Hughesadb8c672012-03-06 16:49:32 -0800123 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800124 bool longSrc = false;
125 bool longDest = false;
126 RegLocation rlSrc;
127 RegLocation rlDest;
buzbeee3acd072012-02-25 17:03:10 -0800128 int op = kMipsNop;
129 int srcReg;
130 RegLocation rlResult;
buzbeee3acd072012-02-25 17:03:10 -0800131 switch (opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800132 case Instruction::INT_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800133 longSrc = false;
134 longDest = false;
135 op = kMipsFcvtsw;
136 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800137 case Instruction::DOUBLE_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800138 longSrc = true;
139 longDest = false;
140 op = kMipsFcvtsd;
141 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800142 case Instruction::FLOAT_TO_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800143 longSrc = false;
144 longDest = true;
145 op = kMipsFcvtds;
146 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800147 case Instruction::INT_TO_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800148 longSrc = false;
149 longDest = true;
150 op = kMipsFcvtdw;
151 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800152 case Instruction::FLOAT_TO_INT:
153 case Instruction::DOUBLE_TO_INT:
154 case Instruction::LONG_TO_DOUBLE:
155 case Instruction::FLOAT_TO_LONG:
156 case Instruction::LONG_TO_FLOAT:
157 case Instruction::DOUBLE_TO_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800158 return genConversionPortable(cUnit, mir);
159 default:
160 return true;
161 }
162 if (longSrc) {
163 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
164 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
165 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
166 } else {
167 rlSrc = oatGetSrc(cUnit, mir, 0);
168 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
169 srcReg = rlSrc.lowReg;
170 }
171 if (longDest) {
172 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
173 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
174 newLIR2(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
175 storeValueWide(cUnit, rlDest, rlResult);
176 } else {
177 rlDest = oatGetDest(cUnit, mir, 0);
178 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
179 newLIR2(cUnit, (MipsOpCode)op, rlResult.lowReg, srcReg);
180 storeValue(cUnit, rlDest, rlResult);
181 }
182 return false;
183#else
Bill Buzbee11f9d212012-03-03 20:03:18 -0800184 return genConversionPortable(cUnit, mir);
buzbeee3acd072012-02-25 17:03:10 -0800185#endif
186}
187
188static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
189 RegLocation rlSrc1, RegLocation rlSrc2)
190{
buzbeee3acd072012-02-25 17:03:10 -0800191 bool wide = true;
Bill Buzbee11f9d212012-03-03 20:03:18 -0800192 int offset;
buzbeee3acd072012-02-25 17:03:10 -0800193
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700194 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800195 case Instruction::CMPL_FLOAT:
Ian Rogers57b86d42012-03-27 16:05:41 -0700196 offset = ENTRYPOINT_OFFSET(pCmplFloat);
buzbeee3acd072012-02-25 17:03:10 -0800197 wide = false;
198 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800199 case Instruction::CMPG_FLOAT:
Ian Rogers57b86d42012-03-27 16:05:41 -0700200 offset = ENTRYPOINT_OFFSET(pCmpgFloat);
buzbeee3acd072012-02-25 17:03:10 -0800201 wide = false;
202 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800203 case Instruction::CMPL_DOUBLE:
Ian Rogers57b86d42012-03-27 16:05:41 -0700204 offset = ENTRYPOINT_OFFSET(pCmplDouble);
buzbeee3acd072012-02-25 17:03:10 -0800205 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800206 case Instruction::CMPG_DOUBLE:
Ian Rogers57b86d42012-03-27 16:05:41 -0700207 offset = ENTRYPOINT_OFFSET(pCmpgDouble);
buzbeee3acd072012-02-25 17:03:10 -0800208 break;
209 default:
210 return true;
211 }
Bill Buzbee11f9d212012-03-03 20:03:18 -0800212 oatFlushAllRegs(cUnit);
213 oatLockCallTemps(cUnit);
214 if (wide) {
215 loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
216 loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
217 } else {
218 loadValueDirectFixed(cUnit, rlSrc1, rARG0);
219 loadValueDirectFixed(cUnit, rlSrc2, rARG1);
220 }
221 int rTgt = loadHelper(cUnit, offset);
222 opReg(cUnit, kOpBlx, rTgt);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700223 RegLocation rlResult = oatGetReturn(cUnit, false);
buzbeee3acd072012-02-25 17:03:10 -0800224 storeValue(cUnit, rlDest, rlResult);
225 return false;
buzbeee3acd072012-02-25 17:03:10 -0800226}
227
228} // namespace art