blob: 8581d5beb61f012f1d7fc82a02ab1cac90b338c3 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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
17#include "codegen_mips.h"
18#include "dex/quick/mir_to_lir-inl.h"
19#include "mips_lir.h"
20#include "oat/runtime/oat_support_entrypoints.h"
21
22namespace art {
23
24void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode,
25 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
26{
27 int op = kMipsNop;
28 RegLocation rl_result;
29
30 /*
31 * Don't attempt to optimize register usage since these opcodes call out to
32 * the handlers.
33 */
34 switch (opcode) {
35 case Instruction::ADD_FLOAT_2ADDR:
36 case Instruction::ADD_FLOAT:
37 op = kMipsFadds;
38 break;
39 case Instruction::SUB_FLOAT_2ADDR:
40 case Instruction::SUB_FLOAT:
41 op = kMipsFsubs;
42 break;
43 case Instruction::DIV_FLOAT_2ADDR:
44 case Instruction::DIV_FLOAT:
45 op = kMipsFdivs;
46 break;
47 case Instruction::MUL_FLOAT_2ADDR:
48 case Instruction::MUL_FLOAT:
49 op = kMipsFmuls;
50 break;
51 case Instruction::REM_FLOAT_2ADDR:
52 case Instruction::REM_FLOAT:
53 FlushAllRegs(); // Send everything to home location
54 CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false);
55 rl_result = GetReturn(true);
56 StoreValue(rl_dest, rl_result);
57 return;
58 case Instruction::NEG_FLOAT:
59 GenNegFloat(rl_dest, rl_src1);
60 return;
61 default:
62 LOG(FATAL) << "Unexpected opcode: " << opcode;
63 }
64 rl_src1 = LoadValue(rl_src1, kFPReg);
65 rl_src2 = LoadValue(rl_src2, kFPReg);
66 rl_result = EvalLoc(rl_dest, kFPReg, true);
67 NewLIR3(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
68 StoreValue(rl_dest, rl_result);
69}
70
71void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode,
72 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
73{
74 int op = kMipsNop;
75 RegLocation rl_result;
76
77 switch (opcode) {
78 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 FlushAllRegs(); // Send everything to home location
97 CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false);
98 rl_result = GetReturnWide(true);
99 StoreValueWide(rl_dest, rl_result);
100 return;
101 case Instruction::NEG_DOUBLE:
102 GenNegDouble(rl_dest, rl_src1);
103 return;
104 default:
105 LOG(FATAL) << "Unpexpected opcode: " << opcode;
106 }
107 rl_src1 = LoadValueWide(rl_src1, kFPReg);
108 DCHECK(rl_src1.wide);
109 rl_src2 = LoadValueWide(rl_src2, kFPReg);
110 DCHECK(rl_src2.wide);
111 rl_result = EvalLoc(rl_dest, kFPReg, true);
112 DCHECK(rl_dest.wide);
113 DCHECK(rl_result.wide);
114 NewLIR3(op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg),
115 S2d(rl_src2.low_reg, rl_src2.high_reg));
116 StoreValueWide(rl_dest, rl_result);
117}
118
119void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
120 RegLocation rl_src)
121{
122 int op = kMipsNop;
123 int src_reg;
124 RegLocation rl_result;
125 switch (opcode) {
126 case Instruction::INT_TO_FLOAT:
127 op = kMipsFcvtsw;
128 break;
129 case Instruction::DOUBLE_TO_FLOAT:
130 op = kMipsFcvtsd;
131 break;
132 case Instruction::FLOAT_TO_DOUBLE:
133 op = kMipsFcvtds;
134 break;
135 case Instruction::INT_TO_DOUBLE:
136 op = kMipsFcvtdw;
137 break;
138 case Instruction::FLOAT_TO_INT:
139 GenConversionCall(ENTRYPOINT_OFFSET(pF2iz), rl_dest, rl_src);
140 return;
141 case Instruction::DOUBLE_TO_INT:
142 GenConversionCall(ENTRYPOINT_OFFSET(pD2iz), rl_dest, rl_src);
143 return;
144 case Instruction::LONG_TO_DOUBLE:
145 GenConversionCall(ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
146 return;
147 case Instruction::FLOAT_TO_LONG:
148 GenConversionCall(ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
149 return;
150 case Instruction::LONG_TO_FLOAT:
151 GenConversionCall(ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
152 return;
153 case Instruction::DOUBLE_TO_LONG:
154 GenConversionCall(ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src);
155 return;
156 default:
157 LOG(FATAL) << "Unexpected opcode: " << opcode;
158 }
159 if (rl_src.wide) {
160 rl_src = LoadValueWide(rl_src, kFPReg);
161 src_reg = S2d(rl_src.low_reg, rl_src.high_reg);
162 } else {
163 rl_src = LoadValue(rl_src, kFPReg);
164 src_reg = rl_src.low_reg;
165 }
166 if (rl_dest.wide) {
167 rl_result = EvalLoc(rl_dest, kFPReg, true);
168 NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg);
169 StoreValueWide(rl_dest, rl_result);
170 } else {
171 rl_result = EvalLoc(rl_dest, kFPReg, true);
172 NewLIR2(op, rl_result.low_reg, src_reg);
173 StoreValue(rl_dest, rl_result);
174 }
175}
176
177void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
178 RegLocation rl_src1, RegLocation rl_src2)
179{
180 bool wide = true;
181 int offset = -1; // Make gcc happy.
182
183 switch (opcode) {
184 case Instruction::CMPL_FLOAT:
185 offset = ENTRYPOINT_OFFSET(pCmplFloat);
186 wide = false;
187 break;
188 case Instruction::CMPG_FLOAT:
189 offset = ENTRYPOINT_OFFSET(pCmpgFloat);
190 wide = false;
191 break;
192 case Instruction::CMPL_DOUBLE:
193 offset = ENTRYPOINT_OFFSET(pCmplDouble);
194 break;
195 case Instruction::CMPG_DOUBLE:
196 offset = ENTRYPOINT_OFFSET(pCmpgDouble);
197 break;
198 default:
199 LOG(FATAL) << "Unexpected opcode: " << opcode;
200 }
201 FlushAllRegs();
202 LockCallTemps();
203 if (wide) {
204 LoadValueDirectWideFixed(rl_src1, rMIPS_FARG0, rMIPS_FARG1);
205 LoadValueDirectWideFixed(rl_src2, rMIPS_FARG2, rMIPS_FARG3);
206 } else {
207 LoadValueDirectFixed(rl_src1, rMIPS_FARG0);
208 LoadValueDirectFixed(rl_src2, rMIPS_FARG2);
209 }
210 int r_tgt = LoadHelper(offset);
211 // NOTE: not a safepoint
212 OpReg(kOpBlx, r_tgt);
213 RegLocation rl_result = GetReturn(false);
214 StoreValue(rl_dest, rl_result);
215}
216
217void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir,
218 bool gt_bias, bool is_double)
219{
220 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
221}
222
223void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src)
224{
225 RegLocation rl_result;
226 rl_src = LoadValue(rl_src, kCoreReg);
227 rl_result = EvalLoc(rl_dest, kCoreReg, true);
228 OpRegRegImm(kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000);
229 StoreValue(rl_dest, rl_result);
230}
231
232void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src)
233{
234 RegLocation rl_result;
235 rl_src = LoadValueWide(rl_src, kCoreReg);
236 rl_result = EvalLoc(rl_dest, kCoreReg, true);
237 OpRegRegImm(kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000);
238 OpRegCopy(rl_result.low_reg, rl_src.low_reg);
239 StoreValueWide(rl_dest, rl_result);
240}
241
242bool MipsMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min)
243{
244 // TODO: need Mips implementation
245 return false;
246}
247
248} // namespace art