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