blob: d8ca0a1b597cbbb2dc44f6238ce07923740e3c44 [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
17namespace art {
18
buzbee5de34942012-03-01 14:51:57 -080019bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
20 RegLocation rlSrc1, RegLocation rlSrc2)
buzbeee3acd072012-02-25 17:03:10 -080021{
22#ifdef __mips_hard_float
23 int op = kMipsNop;
24 RegLocation rlResult;
25
26 /*
27 * Don't attempt to optimize register usage since these opcodes call out to
28 * the handlers.
29 */
30 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -080031 case Instruction::ADD_FLOAT_2ADDR:
32 case Instruction::ADD_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080033 op = kMipsFadds;
34 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080035 case Instruction::SUB_FLOAT_2ADDR:
36 case Instruction::SUB_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080037 op = kMipsFsubs;
38 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080039 case Instruction::DIV_FLOAT_2ADDR:
40 case Instruction::DIV_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080041 op = kMipsFdivs;
42 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080043 case Instruction::MUL_FLOAT_2ADDR:
44 case Instruction::MUL_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -080045 op = kMipsFmuls;
46 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080047 case Instruction::REM_FLOAT_2ADDR:
48 case Instruction::REM_FLOAT:
49 case Instruction::NEG_FLOAT: {
buzbeee3acd072012-02-25 17:03:10 -080050 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
51 }
52 default:
53 return true;
54 }
55 rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
56 rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
57 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
buzbee5de34942012-03-01 14:51:57 -080058 newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg,
59 rlSrc2.lowReg);
buzbeee3acd072012-02-25 17:03:10 -080060 storeValue(cUnit, rlDest, rlResult);
61
62 return false;
63#else
Bill Buzbee11f9d212012-03-03 20:03:18 -080064 return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -080065#endif
66}
67
68static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
69 RegLocation rlDest, RegLocation rlSrc1,
70 RegLocation rlSrc2)
71{
72#ifdef __mips_hard_float
73 int op = kMipsNop;
74 RegLocation rlResult;
75
76 switch (mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -080077 case Instruction::ADD_DOUBLE_2ADDR:
78 case Instruction::ADD_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080079 op = kMipsFaddd;
80 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080081 case Instruction::SUB_DOUBLE_2ADDR:
82 case Instruction::SUB_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080083 op = kMipsFsubd;
84 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080085 case Instruction::DIV_DOUBLE_2ADDR:
86 case Instruction::DIV_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080087 op = kMipsFdivd;
88 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080089 case Instruction::MUL_DOUBLE_2ADDR:
90 case Instruction::MUL_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -080091 op = kMipsFmuld;
92 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -080093 case Instruction::REM_DOUBLE_2ADDR:
94 case Instruction::REM_DOUBLE:
95 case Instruction::NEG_DOUBLE: {
buzbeee3acd072012-02-25 17:03:10 -080096 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
97 }
98 default:
99 return true;
100 }
101 rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
102 DCHECK(rlSrc1.wide);
103 rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
104 DCHECK(rlSrc2.wide);
105 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
106 DCHECK(rlDest.wide);
107 DCHECK(rlResult.wide);
108 newLIR3(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg),
109 S2D(rlSrc1.lowReg, rlSrc1.highReg),
110 S2D(rlSrc2.lowReg, rlSrc2.highReg));
111 storeValueWide(cUnit, rlDest, rlResult);
112 return false;
113#else
Bill Buzbee11f9d212012-03-03 20:03:18 -0800114 return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800115#endif
116}
117
118static bool genConversion(CompilationUnit *cUnit, MIR *mir)
119{
buzbee5de34942012-03-01 14:51:57 -0800120#ifdef __mips_hard_float
Elliott Hughesadb8c672012-03-06 16:49:32 -0800121 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800122 bool longSrc = false;
123 bool longDest = false;
124 RegLocation rlSrc;
125 RegLocation rlDest;
buzbeee3acd072012-02-25 17:03:10 -0800126 int op = kMipsNop;
127 int srcReg;
128 RegLocation rlResult;
buzbeee3acd072012-02-25 17:03:10 -0800129 switch (opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800130 case Instruction::INT_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800131 longSrc = false;
132 longDest = false;
133 op = kMipsFcvtsw;
134 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800135 case Instruction::DOUBLE_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800136 longSrc = true;
137 longDest = false;
138 op = kMipsFcvtsd;
139 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800140 case Instruction::FLOAT_TO_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800141 longSrc = false;
142 longDest = true;
143 op = kMipsFcvtds;
144 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800145 case Instruction::INT_TO_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800146 longSrc = false;
147 longDest = true;
148 op = kMipsFcvtdw;
149 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800150 case Instruction::FLOAT_TO_INT:
151 case Instruction::DOUBLE_TO_INT:
152 case Instruction::LONG_TO_DOUBLE:
153 case Instruction::FLOAT_TO_LONG:
154 case Instruction::LONG_TO_FLOAT:
155 case Instruction::DOUBLE_TO_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800156 return genConversionPortable(cUnit, mir);
157 default:
158 return true;
159 }
160 if (longSrc) {
161 rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
162 rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
163 srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
164 } else {
165 rlSrc = oatGetSrc(cUnit, mir, 0);
166 rlSrc = loadValue(cUnit, rlSrc, kFPReg);
167 srcReg = rlSrc.lowReg;
168 }
169 if (longDest) {
170 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
171 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
172 newLIR2(cUnit, (MipsOpCode)op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
173 storeValueWide(cUnit, rlDest, rlResult);
174 } else {
175 rlDest = oatGetDest(cUnit, mir, 0);
176 rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
177 newLIR2(cUnit, (MipsOpCode)op, rlResult.lowReg, srcReg);
178 storeValue(cUnit, rlDest, rlResult);
179 }
180 return false;
181#else
Bill Buzbee11f9d212012-03-03 20:03:18 -0800182 return genConversionPortable(cUnit, mir);
buzbeee3acd072012-02-25 17:03:10 -0800183#endif
184}
185
186static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
187 RegLocation rlSrc1, RegLocation rlSrc2)
188{
buzbeee3acd072012-02-25 17:03:10 -0800189 bool wide = true;
Bill Buzbee11f9d212012-03-03 20:03:18 -0800190 int offset;
buzbeee3acd072012-02-25 17:03:10 -0800191
192 switch(mir->dalvikInsn.opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800193 case Instruction::CMPL_FLOAT:
Bill Buzbee11f9d212012-03-03 20:03:18 -0800194 offset = OFFSETOF_MEMBER(Thread, pCmplFloat);
buzbeee3acd072012-02-25 17:03:10 -0800195 wide = false;
196 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800197 case Instruction::CMPG_FLOAT:
Bill Buzbee11f9d212012-03-03 20:03:18 -0800198 offset = OFFSETOF_MEMBER(Thread, pCmpgFloat);
buzbeee3acd072012-02-25 17:03:10 -0800199 wide = false;
200 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800201 case Instruction::CMPL_DOUBLE:
Bill Buzbee11f9d212012-03-03 20:03:18 -0800202 offset = OFFSETOF_MEMBER(Thread, pCmplDouble);
buzbeee3acd072012-02-25 17:03:10 -0800203 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800204 case Instruction::CMPG_DOUBLE:
Bill Buzbee11f9d212012-03-03 20:03:18 -0800205 offset = OFFSETOF_MEMBER(Thread, pCmpgDouble);
buzbeee3acd072012-02-25 17:03:10 -0800206 break;
207 default:
208 return true;
209 }
Bill Buzbee11f9d212012-03-03 20:03:18 -0800210 oatFlushAllRegs(cUnit);
211 oatLockCallTemps(cUnit);
212 if (wide) {
213 loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
214 loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
215 } else {
216 loadValueDirectFixed(cUnit, rlSrc1, rARG0);
217 loadValueDirectFixed(cUnit, rlSrc2, rARG1);
218 }
219 int rTgt = loadHelper(cUnit, offset);
220 opReg(cUnit, kOpBlx, rTgt);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700221 RegLocation rlResult = oatGetReturn(cUnit, false);
buzbeee3acd072012-02-25 17:03:10 -0800222 storeValue(cUnit, rlDest, rlResult);
223 return false;
buzbeee3acd072012-02-25 17:03:10 -0800224}
225
226} // namespace art