blob: 495d85e0a479462e3561ca4b244a4022e1ccd19e [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"
Ian Rogersd582fa42014-11-05 23:46:43 -080018
Brian Carlstrom7940e442013-07-12 13:46:57 -070019#include "dex/quick/mir_to_lir-inl.h"
Ian Rogers166db042013-07-26 12:05:57 -070020#include "entrypoints/quick/quick_entrypoints.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "mips_lir.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070022
23namespace art {
24
25void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070026 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070027 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
Andreas Gampe98430592014-07-27 19:44:50 -070054 CallRuntimeHelperRegLocationRegLocation(kQuickFmodf, rl_src1, rl_src2, false);
buzbeea0cd2d72014-06-01 09:33:49 -070055 rl_result = GetReturn(kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070056 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);
Bill Buzbee00e1ec62014-02-27 23:44:13 +000067 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070068 StoreValue(rl_dest, rl_result);
69}
70
71void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070072 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070073 int op = kMipsNop;
74 RegLocation rl_result;
75
76 switch (opcode) {
77 case Instruction::ADD_DOUBLE_2ADDR:
78 case Instruction::ADD_DOUBLE:
79 op = kMipsFaddd;
80 break;
81 case Instruction::SUB_DOUBLE_2ADDR:
82 case Instruction::SUB_DOUBLE:
83 op = kMipsFsubd;
84 break;
85 case Instruction::DIV_DOUBLE_2ADDR:
86 case Instruction::DIV_DOUBLE:
87 op = kMipsFdivd;
88 break;
89 case Instruction::MUL_DOUBLE_2ADDR:
90 case Instruction::MUL_DOUBLE:
91 op = kMipsFmuld;
92 break;
93 case Instruction::REM_DOUBLE_2ADDR:
94 case Instruction::REM_DOUBLE:
95 FlushAllRegs(); // Send everything to home location
Andreas Gampe98430592014-07-27 19:44:50 -070096 CallRuntimeHelperRegLocationRegLocation(kQuickFmod, rl_src1, rl_src2, false);
buzbeea0cd2d72014-06-01 09:33:49 -070097 rl_result = GetReturnWide(kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070098 StoreValueWide(rl_dest, rl_result);
99 return;
100 case Instruction::NEG_DOUBLE:
101 GenNegDouble(rl_dest, rl_src1);
102 return;
103 default:
104 LOG(FATAL) << "Unpexpected opcode: " << opcode;
105 }
106 rl_src1 = LoadValueWide(rl_src1, kFPReg);
107 DCHECK(rl_src1.wide);
108 rl_src2 = LoadValueWide(rl_src2, kFPReg);
109 DCHECK(rl_src2.wide);
110 rl_result = EvalLoc(rl_dest, kFPReg, true);
111 DCHECK(rl_dest.wide);
112 DCHECK(rl_result.wide);
buzbee091cc402014-03-31 10:14:40 -0700113 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700114 StoreValueWide(rl_dest, rl_result);
115}
116
Ningsheng Jian675e09b2014-10-23 13:48:36 +0800117void MipsMir2Lir::GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1,
118 int32_t constant) {
119 // TODO: need mips implementation.
120 UNUSED(rl_dest, rl_src1, constant);
121 LOG(FATAL) << "Unimplemented GenMultiplyByConstantFloat in mips";
122}
123
124void MipsMir2Lir::GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1,
125 int64_t constant) {
126 // TODO: need mips implementation.
127 UNUSED(rl_dest, rl_src1, constant);
128 LOG(FATAL) << "Unimplemented GenMultiplyByConstantDouble in mips";
129}
130
Brian Carlstrom7940e442013-07-12 13:46:57 -0700131void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700132 RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133 int op = kMipsNop;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134 RegLocation rl_result;
135 switch (opcode) {
136 case Instruction::INT_TO_FLOAT:
137 op = kMipsFcvtsw;
138 break;
139 case Instruction::DOUBLE_TO_FLOAT:
140 op = kMipsFcvtsd;
141 break;
142 case Instruction::FLOAT_TO_DOUBLE:
143 op = kMipsFcvtds;
144 break;
145 case Instruction::INT_TO_DOUBLE:
146 op = kMipsFcvtdw;
147 break;
148 case Instruction::FLOAT_TO_INT:
Andreas Gampe98430592014-07-27 19:44:50 -0700149 GenConversionCall(kQuickF2iz, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150 return;
151 case Instruction::DOUBLE_TO_INT:
Andreas Gampe98430592014-07-27 19:44:50 -0700152 GenConversionCall(kQuickD2iz, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700153 return;
154 case Instruction::LONG_TO_DOUBLE:
Andreas Gampe98430592014-07-27 19:44:50 -0700155 GenConversionCall(kQuickL2d, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700156 return;
157 case Instruction::FLOAT_TO_LONG:
Andreas Gampe98430592014-07-27 19:44:50 -0700158 GenConversionCall(kQuickF2l, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159 return;
160 case Instruction::LONG_TO_FLOAT:
Andreas Gampe98430592014-07-27 19:44:50 -0700161 GenConversionCall(kQuickL2f, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 return;
163 case Instruction::DOUBLE_TO_LONG:
Andreas Gampe98430592014-07-27 19:44:50 -0700164 GenConversionCall(kQuickD2l, rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165 return;
166 default:
167 LOG(FATAL) << "Unexpected opcode: " << opcode;
168 }
169 if (rl_src.wide) {
170 rl_src = LoadValueWide(rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700171 } else {
172 rl_src = LoadValue(rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700173 }
buzbee091cc402014-03-31 10:14:40 -0700174 rl_result = EvalLoc(rl_dest, kFPReg, true);
175 NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700176 if (rl_dest.wide) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177 StoreValueWide(rl_dest, rl_result);
178 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700179 StoreValue(rl_dest, rl_result);
180 }
181}
182
183void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700184 RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700185 bool wide = true;
Andreas Gampe98430592014-07-27 19:44:50 -0700186 QuickEntrypointEnum target;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700187
188 switch (opcode) {
189 case Instruction::CMPL_FLOAT:
Andreas Gampe98430592014-07-27 19:44:50 -0700190 target = kQuickCmplFloat;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700191 wide = false;
192 break;
193 case Instruction::CMPG_FLOAT:
Andreas Gampe98430592014-07-27 19:44:50 -0700194 target = kQuickCmpgFloat;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700195 wide = false;
196 break;
197 case Instruction::CMPL_DOUBLE:
Andreas Gampe98430592014-07-27 19:44:50 -0700198 target = kQuickCmplDouble;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700199 break;
200 case Instruction::CMPG_DOUBLE:
Andreas Gampe98430592014-07-27 19:44:50 -0700201 target = kQuickCmpgDouble;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700202 break;
203 default:
204 LOG(FATAL) << "Unexpected opcode: " << opcode;
Andreas Gampe98430592014-07-27 19:44:50 -0700205 target = kQuickCmplFloat;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700206 }
207 FlushAllRegs();
208 LockCallTemps();
209 if (wide) {
buzbee2700f7e2014-03-07 09:46:20 -0800210 RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
211 RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
212 LoadValueDirectWideFixed(rl_src1, r_tmp1);
213 LoadValueDirectWideFixed(rl_src2, r_tmp2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700214 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800215 LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
216 LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 }
Andreas Gampe98430592014-07-27 19:44:50 -0700218 RegStorage r_tgt = LoadHelper(target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700219 // NOTE: not a safepoint
220 OpReg(kOpBlx, r_tgt);
buzbeea0cd2d72014-06-01 09:33:49 -0700221 RegLocation rl_result = GetReturn(kCoreReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 StoreValue(rl_dest, rl_result);
223}
224
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700225void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) {
226 UNUSED(bb, mir, gt_bias, is_double);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
228}
229
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700230void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231 RegLocation rl_result;
232 rl_src = LoadValue(rl_src, kCoreReg);
233 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800234 OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700235 StoreValue(rl_dest, rl_result);
236}
237
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700238void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 RegLocation rl_result;
240 rl_src = LoadValueWide(rl_src, kCoreReg);
241 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800242 OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
243 OpRegCopy(rl_result.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244 StoreValueWide(rl_dest, rl_result);
245}
246
Serban Constantinescu23abec92014-07-02 16:13:38 +0100247bool MipsMir2Lir::GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700248 // TODO: need Mips implementation.
249 UNUSED(info, is_min, is_long);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250 return false;
251}
252
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700253} // namespace art