blob: 0a7aa99c98419cb4354e517567b9f55e569be140 [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"
Ian Rogers166db042013-07-26 12:05:57 -070019#include "entrypoints/quick/quick_entrypoints.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070020#include "mips_lir.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021
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
Andreas Gampe98430592014-07-27 19:44:50 -070053 CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
buzbeea0cd2d72014-06-01 09:33:49 -070054 rl_result = GetReturn(kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070055 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);
Bill Buzbee00e1ec62014-02-27 23:44:13 +000066 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070067 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
Andreas Gampe98430592014-07-27 19:44:50 -070095 CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
buzbeea0cd2d72014-06-01 09:33:49 -070096 rl_result = GetReturnWide(kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070097 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);
buzbee091cc402014-03-31 10:14:40 -0700112 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700113 StoreValueWide(rl_dest, rl_result);
114}
115
Ningsheng Jian675e09b2014-10-23 13:48:36 +0800116void MipsMir2Lir::GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1,
117 int32_t constant) {
118 // TODO: need mips implementation.
119 UNUSED(rl_dest, rl_src1, constant);
120 LOG(FATAL) << "Unimplemented GenMultiplyByConstantFloat in mips";
121}
122
123void MipsMir2Lir::GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1,
124 int64_t constant) {
125 // TODO: need mips implementation.
126 UNUSED(rl_dest, rl_src1, constant);
127 LOG(FATAL) << "Unimplemented GenMultiplyByConstantDouble in mips";
128}
129
Brian Carlstrom7940e442013-07-12 13:46:57 -0700130void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700131 RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132 int op = kMipsNop;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133 RegLocation rl_result;
134 switch (opcode) {
135 case Instruction::INT_TO_FLOAT:
136 op = kMipsFcvtsw;
137 break;
138 case Instruction::DOUBLE_TO_FLOAT:
139 op = kMipsFcvtsd;
140 break;
141 case Instruction::FLOAT_TO_DOUBLE:
142 op = kMipsFcvtds;
143 break;
144 case Instruction::INT_TO_DOUBLE:
145 op = kMipsFcvtdw;
146 break;
147 case Instruction::FLOAT_TO_INT:
Andreas Gampe98430592014-07-27 19:44:50 -0700148 GenConversionCall(kQuickF2iz, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 return;
150 case Instruction::DOUBLE_TO_INT:
Andreas Gampe98430592014-07-27 19:44:50 -0700151 GenConversionCall(kQuickD2iz, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700152 return;
153 case Instruction::LONG_TO_DOUBLE:
Andreas Gampe98430592014-07-27 19:44:50 -0700154 GenConversionCall(kQuickL2d, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700155 return;
156 case Instruction::FLOAT_TO_LONG:
Andreas Gampe98430592014-07-27 19:44:50 -0700157 GenConversionCall(kQuickF2l, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158 return;
159 case Instruction::LONG_TO_FLOAT:
Andreas Gampe98430592014-07-27 19:44:50 -0700160 GenConversionCall(kQuickL2f, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700161 return;
162 case Instruction::DOUBLE_TO_LONG:
Andreas Gampe98430592014-07-27 19:44:50 -0700163 GenConversionCall(kQuickD2l, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 return;
165 default:
166 LOG(FATAL) << "Unexpected opcode: " << opcode;
167 }
168 if (rl_src.wide) {
169 rl_src = LoadValueWide(rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700170 } else {
171 rl_src = LoadValue(rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172 }
buzbee091cc402014-03-31 10:14:40 -0700173 rl_result = EvalLoc(rl_dest, kFPReg, true);
174 NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700175 if (rl_dest.wide) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700176 StoreValueWide(rl_dest, rl_result);
177 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700178 StoreValue(rl_dest, rl_result);
179 }
180}
181
182void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700183 RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184 bool wide = true;
Andreas Gampe98430592014-07-27 19:44:50 -0700185 QuickEntrypointEnum target;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700186
187 switch (opcode) {
188 case Instruction::CMPL_FLOAT:
Andreas Gampe98430592014-07-27 19:44:50 -0700189 target = kQuickCmplFloat;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700190 wide = false;
191 break;
192 case Instruction::CMPG_FLOAT:
Andreas Gampe98430592014-07-27 19:44:50 -0700193 target = kQuickCmpgFloat;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 wide = false;
195 break;
196 case Instruction::CMPL_DOUBLE:
Andreas Gampe98430592014-07-27 19:44:50 -0700197 target = kQuickCmplDouble;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700198 break;
199 case Instruction::CMPG_DOUBLE:
Andreas Gampe98430592014-07-27 19:44:50 -0700200 target = kQuickCmpgDouble;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700201 break;
202 default:
203 LOG(FATAL) << "Unexpected opcode: " << opcode;
Andreas Gampe98430592014-07-27 19:44:50 -0700204 target = kQuickCmplFloat;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205 }
206 FlushAllRegs();
207 LockCallTemps();
208 if (wide) {
buzbee2700f7e2014-03-07 09:46:20 -0800209 RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
210 RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
211 LoadValueDirectWideFixed(rl_src1, r_tmp1);
212 LoadValueDirectWideFixed(rl_src2, r_tmp2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700213 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800214 LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
215 LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700216 }
Andreas Gampe98430592014-07-27 19:44:50 -0700217 RegStorage r_tgt = LoadHelper(target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700218 // NOTE: not a safepoint
219 OpReg(kOpBlx, r_tgt);
buzbeea0cd2d72014-06-01 09:33:49 -0700220 RegLocation rl_result = GetReturn(kCoreReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700221 StoreValue(rl_dest, rl_result);
222}
223
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700224void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) {
225 UNUSED(bb, mir, gt_bias, is_double);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700226 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
227}
228
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700229void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230 RegLocation rl_result;
231 rl_src = LoadValue(rl_src, kCoreReg);
232 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800233 OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 StoreValue(rl_dest, rl_result);
235}
236
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700237void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238 RegLocation rl_result;
239 rl_src = LoadValueWide(rl_src, kCoreReg);
240 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800241 OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
242 OpRegCopy(rl_result.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700243 StoreValueWide(rl_dest, rl_result);
244}
245
Serban Constantinescu23abec92014-07-02 16:13:38 +0100246bool MipsMir2Lir::GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700247 // TODO: need Mips implementation.
248 UNUSED(info, is_min, is_long);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700249 return false;
250}
251
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700252} // namespace art