blob: 9fffb2fd1dc2e5f0d4377446d7df2728b320458d [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
Ian Rogersdd7624d2014-03-14 17:43:00 -070053 CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmodf), rl_src1, rl_src2,
Ian Rogers7655f292013-07-29 11:07:13 -070054 false);
Brian Carlstrom7940e442013-07-12 13:46:57 -070055 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);
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
Ian Rogersdd7624d2014-03-14 17:43:00 -070096 CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(4, pFmod), rl_src1, rl_src2,
Ian Rogers7655f292013-07-29 11:07:13 -070097 false);
Brian Carlstrom7940e442013-07-12 13:46:57 -070098 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);
buzbee091cc402014-03-31 10:14:40 -0700114 NewLIR3(op, rl_result.reg.GetReg(), rl_src1.reg.GetReg(), rl_src2.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700115 StoreValueWide(rl_dest, rl_result);
116}
117
118void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700119 RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700120 int op = kMipsNop;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700121 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:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700136 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2iz), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137 return;
138 case Instruction::DOUBLE_TO_INT:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700139 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2iz), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140 return;
141 case Instruction::LONG_TO_DOUBLE:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700142 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pL2d), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 return;
144 case Instruction::FLOAT_TO_LONG:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700145 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pF2l), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700146 return;
147 case Instruction::LONG_TO_FLOAT:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700148 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pL2f), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 return;
150 case Instruction::DOUBLE_TO_LONG:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700151 GenConversionCall(QUICK_ENTRYPOINT_OFFSET(4, pD2l), rl_dest, rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700152 return;
153 default:
154 LOG(FATAL) << "Unexpected opcode: " << opcode;
155 }
156 if (rl_src.wide) {
157 rl_src = LoadValueWide(rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158 } else {
159 rl_src = LoadValue(rl_src, kFPReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160 }
buzbee091cc402014-03-31 10:14:40 -0700161 rl_result = EvalLoc(rl_dest, kFPReg, true);
162 NewLIR2(op, rl_result.reg.GetReg(), rl_src.reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 if (rl_dest.wide) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 StoreValueWide(rl_dest, rl_result);
165 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700166 StoreValue(rl_dest, rl_result);
167 }
168}
169
170void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700171 RegLocation rl_src1, RegLocation rl_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172 bool wide = true;
Ian Rogersdd7624d2014-03-14 17:43:00 -0700173 ThreadOffset<4> offset(-1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700174
175 switch (opcode) {
176 case Instruction::CMPL_FLOAT:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700177 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmplFloat);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700178 wide = false;
179 break;
180 case Instruction::CMPG_FLOAT:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700181 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmpgFloat);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700182 wide = false;
183 break;
184 case Instruction::CMPL_DOUBLE:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700185 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmplDouble);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700186 break;
187 case Instruction::CMPG_DOUBLE:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700188 offset = QUICK_ENTRYPOINT_OFFSET(4, pCmpgDouble);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700189 break;
190 default:
191 LOG(FATAL) << "Unexpected opcode: " << opcode;
192 }
193 FlushAllRegs();
194 LockCallTemps();
195 if (wide) {
buzbee2700f7e2014-03-07 09:46:20 -0800196 RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1);
197 RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3);
198 LoadValueDirectWideFixed(rl_src1, r_tmp1);
199 LoadValueDirectWideFixed(rl_src2, r_tmp2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700200 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800201 LoadValueDirectFixed(rl_src1, rs_rMIPS_FARG0);
202 LoadValueDirectFixed(rl_src2, rs_rMIPS_FARG2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700203 }
buzbee2700f7e2014-03-07 09:46:20 -0800204 RegStorage r_tgt = LoadHelper(offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205 // NOTE: not a safepoint
206 OpReg(kOpBlx, r_tgt);
207 RegLocation rl_result = GetReturn(false);
208 StoreValue(rl_dest, rl_result);
209}
210
211void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700212 bool gt_bias, bool is_double) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700213 UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
214}
215
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700216void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 RegLocation rl_result;
218 rl_src = LoadValue(rl_src, kCoreReg);
219 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800220 OpRegRegImm(kOpAdd, rl_result.reg, rl_src.reg, 0x80000000);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700221 StoreValue(rl_dest, rl_result);
222}
223
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700224void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700225 RegLocation rl_result;
226 rl_src = LoadValueWide(rl_src, kCoreReg);
227 rl_result = EvalLoc(rl_dest, kCoreReg, true);
buzbee2700f7e2014-03-07 09:46:20 -0800228 OpRegRegImm(kOpAdd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x80000000);
229 OpRegCopy(rl_result.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230 StoreValueWide(rl_dest, rl_result);
231}
232
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700233bool MipsMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 // TODO: need Mips implementation
235 return false;
236}
237
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700238} // namespace art