blob: 129a6966259595e40db8dde27c0e8953748a72cc [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"
buzbeeb5860fb2014-06-21 15:31:01 -070019#include "dex/reg_storage_eq.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070020#include "mips_lir.h"
21
22namespace art {
23
24/* This file contains codegen for the MIPS32 ISA. */
buzbee2700f7e2014-03-07 09:46:20 -080025LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070026 int opcode;
27 /* must be both DOUBLE or both not DOUBLE */
buzbee091cc402014-03-31 10:14:40 -070028 DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
29 if (r_dest.IsDouble()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070030 opcode = kMipsFmovd;
31 } else {
buzbee091cc402014-03-31 10:14:40 -070032 if (r_dest.IsSingle()) {
33 if (r_src.IsSingle()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070034 opcode = kMipsFmovs;
35 } else {
36 /* note the operands are swapped for the mtc1 instr */
buzbee2700f7e2014-03-07 09:46:20 -080037 RegStorage t_opnd = r_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -070038 r_src = r_dest;
39 r_dest = t_opnd;
40 opcode = kMipsMtc1;
41 }
42 } else {
buzbee091cc402014-03-31 10:14:40 -070043 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070044 opcode = kMipsMfc1;
45 }
46 }
buzbee2700f7e2014-03-07 09:46:20 -080047 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
49 res->flags.is_nop = true;
50 }
51 return res;
52}
53
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070054bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070055 return ((value == 0) || IsUint(16, value) || ((value < 0) && (value >= -32768)));
56}
57
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070058bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070059 return false; // TUNING
60}
61
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070062bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070063 return false; // TUNING
64}
65
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070066bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -070067 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070068}
69
70/*
71 * Load a immediate using a shortcut if possible; otherwise
72 * grab from the per-translation literal pool. If target is
73 * a high register, build constant into a low register and copy.
74 *
75 * No additional register clobbering operation performed. Use this version when
76 * 1) r_dest is freshly returned from AllocTemp or
77 * 2) The codegen is under fixed register usage
78 */
buzbee2700f7e2014-03-07 09:46:20 -080079LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070080 LIR *res;
81
buzbee2700f7e2014-03-07 09:46:20 -080082 RegStorage r_dest_save = r_dest;
buzbee091cc402014-03-31 10:14:40 -070083 int is_fp_reg = r_dest.IsFloat();
Brian Carlstrom7940e442013-07-12 13:46:57 -070084 if (is_fp_reg) {
buzbee091cc402014-03-31 10:14:40 -070085 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070086 r_dest = AllocTemp();
87 }
88
89 /* See if the value can be constructed cheaply */
90 if (value == 0) {
buzbee2700f7e2014-03-07 09:46:20 -080091 res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -070092 } else if ((value > 0) && (value <= 65535)) {
buzbee2700f7e2014-03-07 09:46:20 -080093 res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070094 } else if ((value < 0) && (value >= -32768)) {
buzbee2700f7e2014-03-07 09:46:20 -080095 res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070096 } else {
buzbee2700f7e2014-03-07 09:46:20 -080097 res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -070098 if (value & 0xffff)
buzbee2700f7e2014-03-07 09:46:20 -080099 NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700100 }
101
102 if (is_fp_reg) {
buzbee2700f7e2014-03-07 09:46:20 -0800103 NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700104 FreeTemp(r_dest);
105 }
106
107 return res;
108}
109
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700110LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700111 LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700112 res->target = target;
113 return res;
114}
115
buzbee2700f7e2014-03-07 09:46:20 -0800116LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700117 MipsOpCode opcode = kMipsNop;
118 switch (op) {
119 case kOpBlx:
120 opcode = kMipsJalr;
121 break;
122 case kOpBx:
buzbee2700f7e2014-03-07 09:46:20 -0800123 return NewLIR1(kMipsJr, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 break;
125 default:
126 LOG(FATAL) << "Bad case in OpReg";
127 }
buzbee2700f7e2014-03-07 09:46:20 -0800128 return NewLIR2(opcode, rRA, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700129}
130
buzbee2700f7e2014-03-07 09:46:20 -0800131LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132 LIR *res;
133 bool neg = (value < 0);
134 int abs_value = (neg) ? -value : value;
135 bool short_form = (abs_value & 0xff) == abs_value;
136 MipsOpCode opcode = kMipsNop;
137 switch (op) {
138 case kOpAdd:
139 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
140 break;
141 case kOpSub:
142 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
143 break;
144 default:
145 LOG(FATAL) << "Bad case in OpRegImm";
146 break;
147 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700148 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800149 res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700150 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800151 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700152 res = LoadConstant(r_scratch, value);
153 if (op == kOpCmp)
buzbee2700f7e2014-03-07 09:46:20 -0800154 NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700155 else
buzbee2700f7e2014-03-07 09:46:20 -0800156 NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 }
158 return res;
159}
160
buzbee2700f7e2014-03-07 09:46:20 -0800161LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 MipsOpCode opcode = kMipsNop;
163 switch (op) {
164 case kOpAdd:
165 opcode = kMipsAddu;
166 break;
167 case kOpSub:
168 opcode = kMipsSubu;
169 break;
170 case kOpAnd:
171 opcode = kMipsAnd;
172 break;
173 case kOpMul:
174 opcode = kMipsMul;
175 break;
176 case kOpOr:
177 opcode = kMipsOr;
178 break;
179 case kOpXor:
180 opcode = kMipsXor;
181 break;
182 case kOpLsl:
183 opcode = kMipsSllv;
184 break;
185 case kOpLsr:
186 opcode = kMipsSrlv;
187 break;
188 case kOpAsr:
189 opcode = kMipsSrav;
190 break;
191 case kOpAdc:
192 case kOpSbc:
193 LOG(FATAL) << "No carry bit on MIPS";
194 break;
195 default:
196 LOG(FATAL) << "bad case in OpRegRegReg";
197 break;
198 }
buzbee2700f7e2014-03-07 09:46:20 -0800199 return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700200}
201
buzbee2700f7e2014-03-07 09:46:20 -0800202LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700203 LIR *res;
204 MipsOpCode opcode = kMipsNop;
205 bool short_form = true;
206
207 switch (op) {
208 case kOpAdd:
209 if (IS_SIMM16(value)) {
210 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700211 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700212 short_form = false;
213 opcode = kMipsAddu;
214 }
215 break;
216 case kOpSub:
217 if (IS_SIMM16((-value))) {
218 value = -value;
219 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700220 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700221 short_form = false;
222 opcode = kMipsSubu;
223 }
224 break;
225 case kOpLsl:
226 DCHECK(value >= 0 && value <= 31);
227 opcode = kMipsSll;
228 break;
229 case kOpLsr:
230 DCHECK(value >= 0 && value <= 31);
231 opcode = kMipsSrl;
232 break;
233 case kOpAsr:
234 DCHECK(value >= 0 && value <= 31);
235 opcode = kMipsSra;
236 break;
237 case kOpAnd:
238 if (IS_UIMM16((value))) {
239 opcode = kMipsAndi;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700240 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700241 short_form = false;
242 opcode = kMipsAnd;
243 }
244 break;
245 case kOpOr:
246 if (IS_UIMM16((value))) {
247 opcode = kMipsOri;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700248 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700249 short_form = false;
250 opcode = kMipsOr;
251 }
252 break;
253 case kOpXor:
254 if (IS_UIMM16((value))) {
255 opcode = kMipsXori;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700256 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257 short_form = false;
258 opcode = kMipsXor;
259 }
260 break;
261 case kOpMul:
262 short_form = false;
263 opcode = kMipsMul;
264 break;
265 default:
266 LOG(FATAL) << "Bad case in OpRegRegImm";
267 break;
268 }
269
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700270 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800271 res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700272 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700273 if (r_dest != r_src1) {
274 res = LoadConstant(r_dest, value);
buzbee2700f7e2014-03-07 09:46:20 -0800275 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700276 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800277 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700278 res = LoadConstant(r_scratch, value);
buzbee2700f7e2014-03-07 09:46:20 -0800279 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700280 }
281 }
282 return res;
283}
284
buzbee2700f7e2014-03-07 09:46:20 -0800285LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700286 MipsOpCode opcode = kMipsNop;
287 LIR *res;
288 switch (op) {
289 case kOpMov:
290 opcode = kMipsMove;
291 break;
292 case kOpMvn:
buzbee2700f7e2014-03-07 09:46:20 -0800293 return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700294 case kOpNeg:
buzbee2700f7e2014-03-07 09:46:20 -0800295 return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700296 case kOpAdd:
297 case kOpAnd:
298 case kOpMul:
299 case kOpOr:
300 case kOpSub:
301 case kOpXor:
302 return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
303 case kOp2Byte:
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700304#if __mips_isa_rev >= 2
buzbee2700f7e2014-03-07 09:46:20 -0800305 res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700306#else
307 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
308 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
309#endif
310 return res;
311 case kOp2Short:
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700312#if __mips_isa_rev >= 2
buzbee2700f7e2014-03-07 09:46:20 -0800313 res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700314#else
315 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
316 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
317#endif
318 return res;
319 case kOp2Char:
buzbee2700f7e2014-03-07 09:46:20 -0800320 return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700321 default:
322 LOG(FATAL) << "Bad case in OpRegReg";
323 break;
324 }
buzbee2700f7e2014-03-07 09:46:20 -0800325 return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700326}
327
buzbee2700f7e2014-03-07 09:46:20 -0800328LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
329 MoveType move_type) {
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800330 UNIMPLEMENTED(FATAL);
331 return nullptr;
332}
333
buzbee2700f7e2014-03-07 09:46:20 -0800334LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800335 UNIMPLEMENTED(FATAL);
336 return nullptr;
337}
338
buzbee2700f7e2014-03-07 09:46:20 -0800339LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800340 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
341 return NULL;
342}
343
buzbee2700f7e2014-03-07 09:46:20 -0800344LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700345 LIR *res;
Douglas Leung2db3e262014-06-25 16:02:55 -0700346 if (!r_dest.IsPair()) {
347 // Form 64-bit pair
348 r_dest = Solo64ToPair64(r_dest);
349 }
buzbee2700f7e2014-03-07 09:46:20 -0800350 res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
351 LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700352 return res;
353}
354
355/* Load value from base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800356LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700357 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700358 LIR *first = NULL;
359 LIR *res;
360 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800361 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700362
buzbee091cc402014-03-31 10:14:40 -0700363 if (r_dest.IsFloat()) {
364 DCHECK(r_dest.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700365 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700366 size = kSingle;
367 } else {
368 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700369 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700370 }
371
372 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800373 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700374 } else {
375 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800376 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700377 }
378
379 switch (size) {
380 case kSingle:
381 opcode = kMipsFlwc1;
382 break;
buzbee695d13a2014-04-19 13:32:20 -0700383 case k32:
384 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700385 opcode = kMipsLw;
386 break;
387 case kUnsignedHalf:
388 opcode = kMipsLhu;
389 break;
390 case kSignedHalf:
391 opcode = kMipsLh;
392 break;
393 case kUnsignedByte:
394 opcode = kMipsLbu;
395 break;
396 case kSignedByte:
397 opcode = kMipsLb;
398 break;
399 default:
400 LOG(FATAL) << "Bad case in LoadBaseIndexed";
401 }
402
buzbee2700f7e2014-03-07 09:46:20 -0800403 res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700404 FreeTemp(t_reg);
405 return (first) ? first : res;
406}
407
408/* store value base base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800409LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700410 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700411 LIR *first = NULL;
412 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800413 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700414
buzbee091cc402014-03-31 10:14:40 -0700415 if (r_src.IsFloat()) {
416 DCHECK(r_src.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700417 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700418 size = kSingle;
419 } else {
420 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700421 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700422 }
423
424 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800425 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426 } else {
427 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800428 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700429 }
430
431 switch (size) {
432 case kSingle:
433 opcode = kMipsFswc1;
434 break;
buzbee695d13a2014-04-19 13:32:20 -0700435 case k32:
436 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700437 opcode = kMipsSw;
438 break;
439 case kUnsignedHalf:
440 case kSignedHalf:
441 opcode = kMipsSh;
442 break;
443 case kUnsignedByte:
444 case kSignedByte:
445 opcode = kMipsSb;
446 break;
447 default:
448 LOG(FATAL) << "Bad case in StoreBaseIndexed";
449 }
buzbee2700f7e2014-03-07 09:46:20 -0800450 NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700451 return first;
452}
453
buzbee2700f7e2014-03-07 09:46:20 -0800454// FIXME: don't split r_dest into 2 containers.
455LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
Douglas Leung2db3e262014-06-25 16:02:55 -0700456 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700457/*
458 * Load value from base + displacement. Optionally perform null check
459 * on base (which must have an associated s_reg and MIR). If not
460 * performing null check, incoming MIR can be null. IMPORTANT: this
461 * code must not allocate any new temps. If a new register is needed
462 * and base and dest are the same, spill some other register to
463 * rlp and then restore.
464 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700465 LIR *res;
466 LIR *load = NULL;
467 LIR *load2 = NULL;
468 MipsOpCode opcode = kMipsNop;
469 bool short_form = IS_SIMM16(displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700470 bool pair = r_dest.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700471
472 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700473 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700474 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700475 if (!pair) {
476 // Form 64-bit pair
477 r_dest = Solo64ToPair64(r_dest);
478 pair = 1;
479 }
buzbee091cc402014-03-31 10:14:40 -0700480 if (r_dest.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700481 DCHECK_EQ(r_dest.GetLowReg(), r_dest.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700482 opcode = kMipsFlwc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700483 } else {
484 opcode = kMipsLw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700485 }
486 short_form = IS_SIMM16_2WORD(displacement);
487 DCHECK_EQ((displacement & 0x3), 0);
488 break;
buzbee695d13a2014-04-19 13:32:20 -0700489 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700490 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700491 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700492 opcode = kMipsLw;
buzbee091cc402014-03-31 10:14:40 -0700493 if (r_dest.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700494 opcode = kMipsFlwc1;
buzbee091cc402014-03-31 10:14:40 -0700495 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700496 }
497 DCHECK_EQ((displacement & 0x3), 0);
498 break;
499 case kUnsignedHalf:
500 opcode = kMipsLhu;
501 DCHECK_EQ((displacement & 0x1), 0);
502 break;
503 case kSignedHalf:
504 opcode = kMipsLh;
505 DCHECK_EQ((displacement & 0x1), 0);
506 break;
507 case kUnsignedByte:
508 opcode = kMipsLbu;
509 break;
510 case kSignedByte:
511 opcode = kMipsLb;
512 break;
513 default:
514 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
515 }
516
517 if (short_form) {
518 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800519 load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700520 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700521 load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
522 load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700523 }
524 } else {
525 if (pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800526 RegStorage r_tmp = AllocTemp();
527 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700528 load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg());
529 load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700530 FreeTemp(r_tmp);
531 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800532 RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
533 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
534 load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 if (r_tmp != r_dest)
536 FreeTemp(r_tmp);
537 }
538 }
539
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100540 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
541 DCHECK(r_base == rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700542 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
543 true /* is_load */, pair /* is64bit */);
544 if (pair) {
545 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
546 true /* is_load */, pair /* is64bit */);
547 }
548 }
549 return load;
550}
551
Andreas Gampede686762014-06-24 18:42:06 +0000552LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000553 OpSize size, VolatileKind is_volatile) {
554 if (is_volatile == kVolatile) {
555 DCHECK(size != k64 && size != kDouble);
556 }
557
buzbee695d13a2014-04-19 13:32:20 -0700558 // TODO: base this on target.
559 if (size == kWord) {
560 size = k32;
561 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000562 LIR* load;
Douglas Leung2db3e262014-06-25 16:02:55 -0700563 load = LoadBaseDispBody(r_base, displacement, r_dest, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000564
565 if (UNLIKELY(is_volatile == kVolatile)) {
566 // Without context sensitive analysis, we must issue the most conservative barriers.
567 // In this case, either a load or store may follow so we issue both barriers.
568 GenMemBarrier(kLoadLoad);
569 GenMemBarrier(kLoadStore);
570 }
571
572 return load;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700573}
574
Vladimir Marko455759b2014-05-06 20:49:36 +0100575// FIXME: don't split r_dest into 2 containers.
buzbee2700f7e2014-03-07 09:46:20 -0800576LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
Douglas Leung2db3e262014-06-25 16:02:55 -0700577 RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700578 LIR *res;
579 LIR *store = NULL;
580 LIR *store2 = NULL;
581 MipsOpCode opcode = kMipsNop;
582 bool short_form = IS_SIMM16(displacement);
buzbee091cc402014-03-31 10:14:40 -0700583 bool pair = r_src.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700584
585 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700586 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700587 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700588 if (!pair) {
589 // Form 64-bit pair
590 r_src = Solo64ToPair64(r_src);
591 pair = 1;
592 }
buzbee091cc402014-03-31 10:14:40 -0700593 if (r_src.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700594 DCHECK_EQ(r_src.GetLowReg(), r_src.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700595 opcode = kMipsFswc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700596 } else {
597 opcode = kMipsSw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700598 }
599 short_form = IS_SIMM16_2WORD(displacement);
600 DCHECK_EQ((displacement & 0x3), 0);
601 break;
buzbee695d13a2014-04-19 13:32:20 -0700602 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700603 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700604 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700605 opcode = kMipsSw;
buzbee091cc402014-03-31 10:14:40 -0700606 if (r_src.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700607 opcode = kMipsFswc1;
buzbee091cc402014-03-31 10:14:40 -0700608 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700609 }
610 DCHECK_EQ((displacement & 0x3), 0);
611 break;
612 case kUnsignedHalf:
613 case kSignedHalf:
614 opcode = kMipsSh;
615 DCHECK_EQ((displacement & 0x1), 0);
616 break;
617 case kUnsignedByte:
618 case kSignedByte:
619 opcode = kMipsSb;
620 break;
621 default:
buzbee2700f7e2014-03-07 09:46:20 -0800622 LOG(FATAL) << "Bad case in StoreBaseDispBody";
Brian Carlstrom7940e442013-07-12 13:46:57 -0700623 }
624
625 if (short_form) {
626 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800627 store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700628 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700629 store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
630 store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700631 }
632 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800633 RegStorage r_scratch = AllocTemp();
634 res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800636 store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700637 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700638 store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg());
639 store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700640 }
641 FreeTemp(r_scratch);
642 }
643
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100644 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
645 DCHECK(r_base == rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
647 false /* is_load */, pair /* is64bit */);
648 if (pair) {
649 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
650 false /* is_load */, pair /* is64bit */);
651 }
652 }
653
654 return res;
655}
656
Andreas Gampede686762014-06-24 18:42:06 +0000657LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000658 OpSize size, VolatileKind is_volatile) {
659 if (is_volatile == kVolatile) {
660 DCHECK(size != k64 && size != kDouble);
661 // There might have been a store before this volatile one so insert StoreStore barrier.
662 GenMemBarrier(kStoreStore);
663 }
664
buzbee695d13a2014-04-19 13:32:20 -0700665 // TODO: base this on target.
666 if (size == kWord) {
667 size = k32;
668 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000669 LIR* store;
Douglas Leung2db3e262014-06-25 16:02:55 -0700670 store = StoreBaseDispBody(r_base, displacement, r_src, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000671
672 if (UNLIKELY(is_volatile == kVolatile)) {
673 // A load might follow the volatile store so insert a StoreLoad barrier.
674 GenMemBarrier(kStoreLoad);
675 }
676
677 return store;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700678}
679
Ian Rogersdd7624d2014-03-14 17:43:00 -0700680LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset<4> thread_offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700681 LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
682 return NULL;
683}
684
Andreas Gampe2f244e92014-05-08 03:35:25 -0700685LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset<8> thread_offset) {
686 UNIMPLEMENTED(FATAL) << "Should not be called.";
687 return nullptr;
688}
689
buzbee2700f7e2014-03-07 09:46:20 -0800690LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700691 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
692 return NULL;
693}
694
buzbee2700f7e2014-03-07 09:46:20 -0800695LIR* MipsMir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
Vladimir Marko3bf7c602014-05-07 14:55:43 +0100696 int displacement, RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700697 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
698 return NULL;
699}
700
buzbee2700f7e2014-03-07 09:46:20 -0800701LIR* MipsMir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700702 LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
703 return NULL;
704}
705
buzbee2700f7e2014-03-07 09:46:20 -0800706LIR* MipsMir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
Vladimir Marko3bf7c602014-05-07 14:55:43 +0100707 int displacement, RegStorage r_dest, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700708 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
709 return NULL;
710}
711
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700712LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700713 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
714 return NULL;
715}
716
717} // namespace art