blob: ec6edabdbd4c5f0a5d20611d50bac749029ab217 [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
19#include "arch/mips/instruction_set_features_mips.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080020#include "base/logging.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "dex/quick/mir_to_lir-inl.h"
buzbeeb5860fb2014-06-21 15:31:01 -070022#include "dex/reg_storage_eq.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080023#include "driver/compiler_driver.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070024#include "mips_lir.h"
25
26namespace art {
27
28/* This file contains codegen for the MIPS32 ISA. */
buzbee2700f7e2014-03-07 09:46:20 -080029LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070030 int opcode;
31 /* must be both DOUBLE or both not DOUBLE */
buzbee091cc402014-03-31 10:14:40 -070032 DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
33 if (r_dest.IsDouble()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070034 opcode = kMipsFmovd;
35 } else {
buzbee091cc402014-03-31 10:14:40 -070036 if (r_dest.IsSingle()) {
37 if (r_src.IsSingle()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070038 opcode = kMipsFmovs;
39 } else {
40 /* note the operands are swapped for the mtc1 instr */
buzbee2700f7e2014-03-07 09:46:20 -080041 RegStorage t_opnd = r_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -070042 r_src = r_dest;
43 r_dest = t_opnd;
44 opcode = kMipsMtc1;
45 }
46 } else {
buzbee091cc402014-03-31 10:14:40 -070047 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 opcode = kMipsMfc1;
49 }
50 }
buzbee2700f7e2014-03-07 09:46:20 -080051 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070052 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
53 res->flags.is_nop = true;
54 }
55 return res;
56}
57
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070058bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) {
Andreas Gampeab1eb0d2015-02-13 19:23:55 -080059 // For encodings, see LoadConstantNoClobber below.
60 return ((value == 0) || IsUint<16>(value) || IsInt<16>(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -070061}
62
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070063bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070064 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070065 return false; // TUNING
66}
67
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070068bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070069 UNUSED(value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070070 return false; // TUNING
71}
72
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070073bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070074 UNUSED(value);
Brian Carlstrom7934ac22013-07-26 10:54:15 -070075 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070076}
77
78/*
79 * Load a immediate using a shortcut if possible; otherwise
80 * grab from the per-translation literal pool. If target is
81 * a high register, build constant into a low register and copy.
82 *
83 * No additional register clobbering operation performed. Use this version when
84 * 1) r_dest is freshly returned from AllocTemp or
85 * 2) The codegen is under fixed register usage
86 */
buzbee2700f7e2014-03-07 09:46:20 -080087LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070088 LIR *res;
89
buzbee2700f7e2014-03-07 09:46:20 -080090 RegStorage r_dest_save = r_dest;
buzbee091cc402014-03-31 10:14:40 -070091 int is_fp_reg = r_dest.IsFloat();
Brian Carlstrom7940e442013-07-12 13:46:57 -070092 if (is_fp_reg) {
buzbee091cc402014-03-31 10:14:40 -070093 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070094 r_dest = AllocTemp();
95 }
96
97 /* See if the value can be constructed cheaply */
98 if (value == 0) {
buzbee2700f7e2014-03-07 09:46:20 -080099 res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
Andreas Gampeab1eb0d2015-02-13 19:23:55 -0800100 } else if (IsUint<16>(value)) {
101 // Use OR with (unsigned) immediate to encode 16b unsigned int.
buzbee2700f7e2014-03-07 09:46:20 -0800102 res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
Andreas Gampeab1eb0d2015-02-13 19:23:55 -0800103 } else if (IsInt<16>(value)) {
104 // Use ADD with (signed) immediate to encode 16b signed int.
buzbee2700f7e2014-03-07 09:46:20 -0800105 res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700106 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800107 res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700108 if (value & 0xffff)
buzbee2700f7e2014-03-07 09:46:20 -0800109 NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700110 }
111
112 if (is_fp_reg) {
buzbee2700f7e2014-03-07 09:46:20 -0800113 NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700114 FreeTemp(r_dest);
115 }
116
117 return res;
118}
119
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700120LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700121 LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700122 res->target = target;
123 return res;
124}
125
buzbee2700f7e2014-03-07 09:46:20 -0800126LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700127 MipsOpCode opcode = kMipsNop;
128 switch (op) {
129 case kOpBlx:
130 opcode = kMipsJalr;
131 break;
132 case kOpBx:
Andreas Gampe8d365912015-01-13 11:32:32 -0800133 return NewLIR2(kMipsJalr, rZERO, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134 break;
135 default:
136 LOG(FATAL) << "Bad case in OpReg";
137 }
buzbee2700f7e2014-03-07 09:46:20 -0800138 return NewLIR2(opcode, rRA, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139}
140
buzbee2700f7e2014-03-07 09:46:20 -0800141LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700142 LIR *res;
143 bool neg = (value < 0);
144 int abs_value = (neg) ? -value : value;
145 bool short_form = (abs_value & 0xff) == abs_value;
146 MipsOpCode opcode = kMipsNop;
147 switch (op) {
148 case kOpAdd:
149 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
150 break;
151 case kOpSub:
152 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
153 break;
154 default:
155 LOG(FATAL) << "Bad case in OpRegImm";
156 break;
157 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700158 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800159 res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700160 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800161 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 res = LoadConstant(r_scratch, value);
163 if (op == kOpCmp)
buzbee2700f7e2014-03-07 09:46:20 -0800164 NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165 else
buzbee2700f7e2014-03-07 09:46:20 -0800166 NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 }
168 return res;
169}
170
buzbee2700f7e2014-03-07 09:46:20 -0800171LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172 MipsOpCode opcode = kMipsNop;
173 switch (op) {
174 case kOpAdd:
175 opcode = kMipsAddu;
176 break;
177 case kOpSub:
178 opcode = kMipsSubu;
179 break;
180 case kOpAnd:
181 opcode = kMipsAnd;
182 break;
183 case kOpMul:
184 opcode = kMipsMul;
185 break;
186 case kOpOr:
187 opcode = kMipsOr;
188 break;
189 case kOpXor:
190 opcode = kMipsXor;
191 break;
192 case kOpLsl:
193 opcode = kMipsSllv;
194 break;
195 case kOpLsr:
196 opcode = kMipsSrlv;
197 break;
198 case kOpAsr:
199 opcode = kMipsSrav;
200 break;
201 case kOpAdc:
202 case kOpSbc:
203 LOG(FATAL) << "No carry bit on MIPS";
204 break;
205 default:
206 LOG(FATAL) << "bad case in OpRegRegReg";
207 break;
208 }
buzbee2700f7e2014-03-07 09:46:20 -0800209 return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700210}
211
buzbee2700f7e2014-03-07 09:46:20 -0800212LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700213 LIR *res;
214 MipsOpCode opcode = kMipsNop;
215 bool short_form = true;
216
217 switch (op) {
218 case kOpAdd:
219 if (IS_SIMM16(value)) {
220 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700221 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 short_form = false;
223 opcode = kMipsAddu;
224 }
225 break;
226 case kOpSub:
227 if (IS_SIMM16((-value))) {
228 value = -value;
229 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700230 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231 short_form = false;
232 opcode = kMipsSubu;
233 }
234 break;
235 case kOpLsl:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800236 DCHECK(value >= 0 && value <= 31);
237 opcode = kMipsSll;
238 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 case kOpLsr:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800240 DCHECK(value >= 0 && value <= 31);
241 opcode = kMipsSrl;
242 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700243 case kOpAsr:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800244 DCHECK(value >= 0 && value <= 31);
245 opcode = kMipsSra;
246 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 case kOpAnd:
248 if (IS_UIMM16((value))) {
249 opcode = kMipsAndi;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700250 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700251 short_form = false;
252 opcode = kMipsAnd;
253 }
254 break;
255 case kOpOr:
256 if (IS_UIMM16((value))) {
257 opcode = kMipsOri;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700258 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700259 short_form = false;
260 opcode = kMipsOr;
261 }
262 break;
263 case kOpXor:
264 if (IS_UIMM16((value))) {
265 opcode = kMipsXori;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700266 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700267 short_form = false;
268 opcode = kMipsXor;
269 }
270 break;
271 case kOpMul:
272 short_form = false;
273 opcode = kMipsMul;
274 break;
275 default:
276 LOG(FATAL) << "Bad case in OpRegRegImm";
277 break;
278 }
279
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700280 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800281 res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700282 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 if (r_dest != r_src1) {
284 res = LoadConstant(r_dest, value);
buzbee2700f7e2014-03-07 09:46:20 -0800285 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700286 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800287 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700288 res = LoadConstant(r_scratch, value);
buzbee2700f7e2014-03-07 09:46:20 -0800289 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700290 }
291 }
292 return res;
293}
294
buzbee2700f7e2014-03-07 09:46:20 -0800295LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700296 MipsOpCode opcode = kMipsNop;
297 LIR *res;
298 switch (op) {
299 case kOpMov:
300 opcode = kMipsMove;
301 break;
302 case kOpMvn:
buzbee2700f7e2014-03-07 09:46:20 -0800303 return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700304 case kOpNeg:
buzbee2700f7e2014-03-07 09:46:20 -0800305 return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700306 case kOpAdd:
307 case kOpAnd:
308 case kOpMul:
309 case kOpOr:
310 case kOpSub:
311 case kOpXor:
312 return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
313 case kOp2Byte:
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800314 if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
Ian Rogersd582fa42014-11-05 23:46:43 -0800315 ->IsMipsIsaRevGreaterThanEqual2()) {
316 res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
317 } else {
318 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
319 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
320 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700321 return res;
322 case kOp2Short:
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800323 if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()
Ian Rogersd582fa42014-11-05 23:46:43 -0800324 ->IsMipsIsaRevGreaterThanEqual2()) {
325 res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
326 } else {
327 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
328 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
329 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700330 return res;
331 case kOp2Char:
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800332 return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700333 default:
334 LOG(FATAL) << "Bad case in OpRegReg";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700335 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700336 }
buzbee2700f7e2014-03-07 09:46:20 -0800337 return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700338}
339
buzbee2700f7e2014-03-07 09:46:20 -0800340LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
341 MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700342 UNUSED(r_dest, r_base, offset, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800343 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700344 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800345}
346
buzbee2700f7e2014-03-07 09:46:20 -0800347LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700348 UNUSED(r_base, offset, r_src, move_type);
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800349 UNIMPLEMENTED(FATAL);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700350 UNREACHABLE();
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800351}
352
buzbee2700f7e2014-03-07 09:46:20 -0800353LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700354 UNUSED(op, cc, r_dest, r_src);
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800355 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700356 UNREACHABLE();
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800357}
358
buzbee2700f7e2014-03-07 09:46:20 -0800359LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700360 LIR *res;
Douglas Leung2db3e262014-06-25 16:02:55 -0700361 if (!r_dest.IsPair()) {
362 // Form 64-bit pair
363 r_dest = Solo64ToPair64(r_dest);
364 }
buzbee2700f7e2014-03-07 09:46:20 -0800365 res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
366 LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700367 return res;
368}
369
370/* Load value from base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800371LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700372 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700373 LIR *first = NULL;
374 LIR *res;
375 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800376 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700377
buzbee091cc402014-03-31 10:14:40 -0700378 if (r_dest.IsFloat()) {
379 DCHECK(r_dest.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700380 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700381 size = kSingle;
382 } else {
383 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700384 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700385 }
386
387 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800388 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700389 } else {
390 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800391 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700392 }
393
394 switch (size) {
395 case kSingle:
396 opcode = kMipsFlwc1;
397 break;
buzbee695d13a2014-04-19 13:32:20 -0700398 case k32:
399 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700400 opcode = kMipsLw;
401 break;
402 case kUnsignedHalf:
403 opcode = kMipsLhu;
404 break;
405 case kSignedHalf:
406 opcode = kMipsLh;
407 break;
408 case kUnsignedByte:
409 opcode = kMipsLbu;
410 break;
411 case kSignedByte:
412 opcode = kMipsLb;
413 break;
414 default:
415 LOG(FATAL) << "Bad case in LoadBaseIndexed";
416 }
417
buzbee2700f7e2014-03-07 09:46:20 -0800418 res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700419 FreeTemp(t_reg);
420 return (first) ? first : res;
421}
422
423/* store value base base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800424LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700425 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426 LIR *first = NULL;
427 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800428 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700429
buzbee091cc402014-03-31 10:14:40 -0700430 if (r_src.IsFloat()) {
431 DCHECK(r_src.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700432 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700433 size = kSingle;
434 } else {
435 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700436 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700437 }
438
439 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800440 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441 } else {
442 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800443 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700444 }
445
446 switch (size) {
447 case kSingle:
448 opcode = kMipsFswc1;
449 break;
buzbee695d13a2014-04-19 13:32:20 -0700450 case k32:
451 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700452 opcode = kMipsSw;
453 break;
454 case kUnsignedHalf:
455 case kSignedHalf:
456 opcode = kMipsSh;
457 break;
458 case kUnsignedByte:
459 case kSignedByte:
460 opcode = kMipsSb;
461 break;
462 default:
463 LOG(FATAL) << "Bad case in StoreBaseIndexed";
464 }
buzbee2700f7e2014-03-07 09:46:20 -0800465 NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700466 return first;
467}
468
buzbee2700f7e2014-03-07 09:46:20 -0800469// FIXME: don't split r_dest into 2 containers.
470LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
Douglas Leung2db3e262014-06-25 16:02:55 -0700471 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700472/*
473 * Load value from base + displacement. Optionally perform null check
474 * on base (which must have an associated s_reg and MIR). If not
475 * performing null check, incoming MIR can be null. IMPORTANT: this
476 * code must not allocate any new temps. If a new register is needed
477 * and base and dest are the same, spill some other register to
478 * rlp and then restore.
479 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700480 LIR *res;
481 LIR *load = NULL;
482 LIR *load2 = NULL;
483 MipsOpCode opcode = kMipsNop;
484 bool short_form = IS_SIMM16(displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700485 bool pair = r_dest.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486
487 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700488 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700489 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700490 if (!pair) {
491 // Form 64-bit pair
492 r_dest = Solo64ToPair64(r_dest);
493 pair = 1;
494 }
buzbee091cc402014-03-31 10:14:40 -0700495 if (r_dest.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700496 DCHECK_EQ(r_dest.GetLowReg(), r_dest.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700497 opcode = kMipsFlwc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700498 } else {
499 opcode = kMipsLw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700500 }
501 short_form = IS_SIMM16_2WORD(displacement);
502 DCHECK_EQ((displacement & 0x3), 0);
503 break;
buzbee695d13a2014-04-19 13:32:20 -0700504 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700505 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700506 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700507 opcode = kMipsLw;
buzbee091cc402014-03-31 10:14:40 -0700508 if (r_dest.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700509 opcode = kMipsFlwc1;
buzbee091cc402014-03-31 10:14:40 -0700510 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700511 }
512 DCHECK_EQ((displacement & 0x3), 0);
513 break;
514 case kUnsignedHalf:
515 opcode = kMipsLhu;
516 DCHECK_EQ((displacement & 0x1), 0);
517 break;
518 case kSignedHalf:
519 opcode = kMipsLh;
520 DCHECK_EQ((displacement & 0x1), 0);
521 break;
522 case kUnsignedByte:
523 opcode = kMipsLbu;
524 break;
525 case kSignedByte:
526 opcode = kMipsLb;
527 break;
528 default:
529 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
530 }
531
532 if (short_form) {
533 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800534 load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700536 load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
537 load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700538 }
539 } else {
540 if (pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800541 RegStorage r_tmp = AllocTemp();
542 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700543 load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg());
544 load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700545 FreeTemp(r_tmp);
546 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800547 RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
548 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
549 load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700550 if (r_tmp != r_dest)
551 FreeTemp(r_tmp);
552 }
553 }
554
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100555 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800556 DCHECK_EQ(r_base, rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700557 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
558 true /* is_load */, pair /* is64bit */);
559 if (pair) {
560 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
561 true /* is_load */, pair /* is64bit */);
562 }
563 }
564 return load;
565}
566
Andreas Gampede686762014-06-24 18:42:06 +0000567LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000568 OpSize size, VolatileKind is_volatile) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700569 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
570 // Do atomic 64-bit load.
571 return GenAtomic64Load(r_base, displacement, r_dest);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000572 }
573
buzbee695d13a2014-04-19 13:32:20 -0700574 // TODO: base this on target.
575 if (size == kWord) {
576 size = k32;
577 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000578 LIR* load;
Douglas Leung2db3e262014-06-25 16:02:55 -0700579 load = LoadBaseDispBody(r_base, displacement, r_dest, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000580
581 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700582 GenMemBarrier(kLoadAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000583 }
584
585 return load;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700586}
587
Vladimir Marko455759b2014-05-06 20:49:36 +0100588// FIXME: don't split r_dest into 2 containers.
buzbee2700f7e2014-03-07 09:46:20 -0800589LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
Douglas Leung2db3e262014-06-25 16:02:55 -0700590 RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700591 LIR *res;
592 LIR *store = NULL;
593 LIR *store2 = NULL;
594 MipsOpCode opcode = kMipsNop;
595 bool short_form = IS_SIMM16(displacement);
buzbee091cc402014-03-31 10:14:40 -0700596 bool pair = r_src.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700597
598 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700599 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700600 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700601 if (!pair) {
602 // Form 64-bit pair
603 r_src = Solo64ToPair64(r_src);
604 pair = 1;
605 }
buzbee091cc402014-03-31 10:14:40 -0700606 if (r_src.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700607 DCHECK_EQ(r_src.GetLowReg(), r_src.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700608 opcode = kMipsFswc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700609 } else {
610 opcode = kMipsSw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700611 }
612 short_form = IS_SIMM16_2WORD(displacement);
613 DCHECK_EQ((displacement & 0x3), 0);
614 break;
buzbee695d13a2014-04-19 13:32:20 -0700615 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700616 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700617 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700618 opcode = kMipsSw;
buzbee091cc402014-03-31 10:14:40 -0700619 if (r_src.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700620 opcode = kMipsFswc1;
buzbee091cc402014-03-31 10:14:40 -0700621 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700622 }
623 DCHECK_EQ((displacement & 0x3), 0);
624 break;
625 case kUnsignedHalf:
626 case kSignedHalf:
627 opcode = kMipsSh;
628 DCHECK_EQ((displacement & 0x1), 0);
629 break;
630 case kUnsignedByte:
631 case kSignedByte:
632 opcode = kMipsSb;
633 break;
634 default:
buzbee2700f7e2014-03-07 09:46:20 -0800635 LOG(FATAL) << "Bad case in StoreBaseDispBody";
Brian Carlstrom7940e442013-07-12 13:46:57 -0700636 }
637
638 if (short_form) {
639 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800640 store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700641 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700642 store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
643 store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700644 }
645 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800646 RegStorage r_scratch = AllocTemp();
647 res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700648 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800649 store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700650 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700651 store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg());
652 store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700653 }
654 FreeTemp(r_scratch);
655 }
656
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100657 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
Ian Rogersb28c1c02014-11-08 11:21:21 -0800658 DCHECK_EQ(r_base, rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700659 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
660 false /* is_load */, pair /* is64bit */);
661 if (pair) {
662 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
663 false /* is_load */, pair /* is64bit */);
664 }
665 }
666
667 return res;
668}
669
Andreas Gampede686762014-06-24 18:42:06 +0000670LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000671 OpSize size, VolatileKind is_volatile) {
672 if (is_volatile == kVolatile) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700673 // Ensure that prior accesses become visible to other threads first.
674 GenMemBarrier(kAnyStore);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000675 }
676
Andreas Gampe3c12c512014-06-24 18:46:29 +0000677 LIR* store;
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700678 if (UNLIKELY(is_volatile == kVolatile && (size == k64 || size == kDouble))) {
679 // Do atomic 64-bit load.
680 store = GenAtomic64Store(r_base, displacement, r_src);
681 } else {
682 // TODO: base this on target.
683 if (size == kWord) {
684 size = k32;
685 }
686 store = StoreBaseDispBody(r_base, displacement, r_src, size);
687 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000688
689 if (UNLIKELY(is_volatile == kVolatile)) {
Hans Boehm48f5c472014-06-27 14:50:10 -0700690 // Preserve order with respect to any subsequent volatile loads.
691 // We need StoreLoad, but that generally requires the most expensive barrier.
692 GenMemBarrier(kAnyAny);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000693 }
694
695 return store;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700696}
697
buzbee2700f7e2014-03-07 09:46:20 -0800698LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700699 UNUSED(op, r_base, disp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700700 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700701 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700702}
703
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700704LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700705 UNUSED(cc, target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700706 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700707 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700708}
709
Andreas Gampe98430592014-07-27 19:44:50 -0700710LIR* MipsMir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700711 UNUSED(trampoline); // The address of the trampoline is already loaded into r_tgt.
Andreas Gampe98430592014-07-27 19:44:50 -0700712 return OpReg(op, r_tgt);
713}
714
Brian Carlstrom7940e442013-07-12 13:46:57 -0700715} // namespace art