blob: d28abbf5a4024c74f4368260711efe586f541b0a [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"
19#include "mips_lir.h"
20
21namespace art {
22
23/* This file contains codegen for the MIPS32 ISA. */
buzbee2700f7e2014-03-07 09:46:20 -080024LIR* MipsMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070025 int opcode;
26 /* must be both DOUBLE or both not DOUBLE */
buzbee091cc402014-03-31 10:14:40 -070027 DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
28 if (r_dest.IsDouble()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070029 opcode = kMipsFmovd;
30 } else {
buzbee091cc402014-03-31 10:14:40 -070031 if (r_dest.IsSingle()) {
32 if (r_src.IsSingle()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070033 opcode = kMipsFmovs;
34 } else {
35 /* note the operands are swapped for the mtc1 instr */
buzbee2700f7e2014-03-07 09:46:20 -080036 RegStorage t_opnd = r_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -070037 r_src = r_dest;
38 r_dest = t_opnd;
39 opcode = kMipsMtc1;
40 }
41 } else {
buzbee091cc402014-03-31 10:14:40 -070042 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070043 opcode = kMipsMfc1;
44 }
45 }
buzbee2700f7e2014-03-07 09:46:20 -080046 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -070047 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
48 res->flags.is_nop = true;
49 }
50 return res;
51}
52
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070053bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070054 return ((value == 0) || IsUint(16, value) || ((value < 0) && (value >= -32768)));
55}
56
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070057bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070058 return false; // TUNING
59}
60
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070061bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070062 return false; // TUNING
63}
64
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070065bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -070066 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070067}
68
69/*
70 * Load a immediate using a shortcut if possible; otherwise
71 * grab from the per-translation literal pool. If target is
72 * a high register, build constant into a low register and copy.
73 *
74 * No additional register clobbering operation performed. Use this version when
75 * 1) r_dest is freshly returned from AllocTemp or
76 * 2) The codegen is under fixed register usage
77 */
buzbee2700f7e2014-03-07 09:46:20 -080078LIR* MipsMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070079 LIR *res;
80
buzbee2700f7e2014-03-07 09:46:20 -080081 RegStorage r_dest_save = r_dest;
buzbee091cc402014-03-31 10:14:40 -070082 int is_fp_reg = r_dest.IsFloat();
Brian Carlstrom7940e442013-07-12 13:46:57 -070083 if (is_fp_reg) {
buzbee091cc402014-03-31 10:14:40 -070084 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -070085 r_dest = AllocTemp();
86 }
87
88 /* See if the value can be constructed cheaply */
89 if (value == 0) {
buzbee2700f7e2014-03-07 09:46:20 -080090 res = NewLIR2(kMipsMove, r_dest.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 } else if ((value > 0) && (value <= 65535)) {
buzbee2700f7e2014-03-07 09:46:20 -080092 res = NewLIR3(kMipsOri, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070093 } else if ((value < 0) && (value >= -32768)) {
buzbee2700f7e2014-03-07 09:46:20 -080094 res = NewLIR3(kMipsAddiu, r_dest.GetReg(), rZERO, value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070095 } else {
buzbee2700f7e2014-03-07 09:46:20 -080096 res = NewLIR2(kMipsLui, r_dest.GetReg(), value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -070097 if (value & 0xffff)
buzbee2700f7e2014-03-07 09:46:20 -080098 NewLIR3(kMipsOri, r_dest.GetReg(), r_dest.GetReg(), value);
Brian Carlstrom7940e442013-07-12 13:46:57 -070099 }
100
101 if (is_fp_reg) {
buzbee2700f7e2014-03-07 09:46:20 -0800102 NewLIR2(kMipsMtc1, r_dest.GetReg(), r_dest_save.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103 FreeTemp(r_dest);
104 }
105
106 return res;
107}
108
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700109LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700110 LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700111 res->target = target;
112 return res;
113}
114
buzbee2700f7e2014-03-07 09:46:20 -0800115LIR* MipsMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700116 MipsOpCode opcode = kMipsNop;
117 switch (op) {
118 case kOpBlx:
119 opcode = kMipsJalr;
120 break;
121 case kOpBx:
buzbee2700f7e2014-03-07 09:46:20 -0800122 return NewLIR1(kMipsJr, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700123 break;
124 default:
125 LOG(FATAL) << "Bad case in OpReg";
126 }
buzbee2700f7e2014-03-07 09:46:20 -0800127 return NewLIR2(opcode, rRA, r_dest_src.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128}
129
buzbee2700f7e2014-03-07 09:46:20 -0800130LIR* MipsMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700131 LIR *res;
132 bool neg = (value < 0);
133 int abs_value = (neg) ? -value : value;
134 bool short_form = (abs_value & 0xff) == abs_value;
135 MipsOpCode opcode = kMipsNop;
136 switch (op) {
137 case kOpAdd:
138 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
139 break;
140 case kOpSub:
141 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
142 break;
143 default:
144 LOG(FATAL) << "Bad case in OpRegImm";
145 break;
146 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700147 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800148 res = NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700149 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800150 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151 res = LoadConstant(r_scratch, value);
152 if (op == kOpCmp)
buzbee2700f7e2014-03-07 09:46:20 -0800153 NewLIR2(opcode, r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700154 else
buzbee2700f7e2014-03-07 09:46:20 -0800155 NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700156 }
157 return res;
158}
159
buzbee2700f7e2014-03-07 09:46:20 -0800160LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700161 MipsOpCode opcode = kMipsNop;
162 switch (op) {
163 case kOpAdd:
164 opcode = kMipsAddu;
165 break;
166 case kOpSub:
167 opcode = kMipsSubu;
168 break;
169 case kOpAnd:
170 opcode = kMipsAnd;
171 break;
172 case kOpMul:
173 opcode = kMipsMul;
174 break;
175 case kOpOr:
176 opcode = kMipsOr;
177 break;
178 case kOpXor:
179 opcode = kMipsXor;
180 break;
181 case kOpLsl:
182 opcode = kMipsSllv;
183 break;
184 case kOpLsr:
185 opcode = kMipsSrlv;
186 break;
187 case kOpAsr:
188 opcode = kMipsSrav;
189 break;
190 case kOpAdc:
191 case kOpSbc:
192 LOG(FATAL) << "No carry bit on MIPS";
193 break;
194 default:
195 LOG(FATAL) << "bad case in OpRegRegReg";
196 break;
197 }
buzbee2700f7e2014-03-07 09:46:20 -0800198 return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700199}
200
buzbee2700f7e2014-03-07 09:46:20 -0800201LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700202 LIR *res;
203 MipsOpCode opcode = kMipsNop;
204 bool short_form = true;
205
206 switch (op) {
207 case kOpAdd:
208 if (IS_SIMM16(value)) {
209 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700210 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700211 short_form = false;
212 opcode = kMipsAddu;
213 }
214 break;
215 case kOpSub:
216 if (IS_SIMM16((-value))) {
217 value = -value;
218 opcode = kMipsAddiu;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700219 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700220 short_form = false;
221 opcode = kMipsSubu;
222 }
223 break;
224 case kOpLsl:
225 DCHECK(value >= 0 && value <= 31);
226 opcode = kMipsSll;
227 break;
228 case kOpLsr:
229 DCHECK(value >= 0 && value <= 31);
230 opcode = kMipsSrl;
231 break;
232 case kOpAsr:
233 DCHECK(value >= 0 && value <= 31);
234 opcode = kMipsSra;
235 break;
236 case kOpAnd:
237 if (IS_UIMM16((value))) {
238 opcode = kMipsAndi;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700239 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 short_form = false;
241 opcode = kMipsAnd;
242 }
243 break;
244 case kOpOr:
245 if (IS_UIMM16((value))) {
246 opcode = kMipsOri;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700247 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 short_form = false;
249 opcode = kMipsOr;
250 }
251 break;
252 case kOpXor:
253 if (IS_UIMM16((value))) {
254 opcode = kMipsXori;
Brian Carlstromf69863b2013-07-17 21:53:13 -0700255 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700256 short_form = false;
257 opcode = kMipsXor;
258 }
259 break;
260 case kOpMul:
261 short_form = false;
262 opcode = kMipsMul;
263 break;
264 default:
265 LOG(FATAL) << "Bad case in OpRegRegImm";
266 break;
267 }
268
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700269 if (short_form) {
buzbee2700f7e2014-03-07 09:46:20 -0800270 res = NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700271 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700272 if (r_dest != r_src1) {
273 res = LoadConstant(r_dest, value);
buzbee2700f7e2014-03-07 09:46:20 -0800274 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_dest.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800276 RegStorage r_scratch = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700277 res = LoadConstant(r_scratch, value);
buzbee2700f7e2014-03-07 09:46:20 -0800278 NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700279 }
280 }
281 return res;
282}
283
buzbee2700f7e2014-03-07 09:46:20 -0800284LIR* MipsMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700285 MipsOpCode opcode = kMipsNop;
286 LIR *res;
287 switch (op) {
288 case kOpMov:
289 opcode = kMipsMove;
290 break;
291 case kOpMvn:
buzbee2700f7e2014-03-07 09:46:20 -0800292 return NewLIR3(kMipsNor, r_dest_src1.GetReg(), r_src2.GetReg(), rZERO);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700293 case kOpNeg:
buzbee2700f7e2014-03-07 09:46:20 -0800294 return NewLIR3(kMipsSubu, r_dest_src1.GetReg(), rZERO, r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700295 case kOpAdd:
296 case kOpAnd:
297 case kOpMul:
298 case kOpOr:
299 case kOpSub:
300 case kOpXor:
301 return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2);
302 case kOp2Byte:
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700303#if __mips_isa_rev >= 2
buzbee2700f7e2014-03-07 09:46:20 -0800304 res = NewLIR2(kMipsSeb, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305#else
306 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24);
307 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24);
308#endif
309 return res;
310 case kOp2Short:
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700311#if __mips_isa_rev >= 2
buzbee2700f7e2014-03-07 09:46:20 -0800312 res = NewLIR2(kMipsSeh, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313#else
314 res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16);
315 OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16);
316#endif
317 return res;
318 case kOp2Char:
buzbee2700f7e2014-03-07 09:46:20 -0800319 return NewLIR3(kMipsAndi, r_dest_src1.GetReg(), r_src2.GetReg(), 0xFFFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700320 default:
321 LOG(FATAL) << "Bad case in OpRegReg";
322 break;
323 }
buzbee2700f7e2014-03-07 09:46:20 -0800324 return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700325}
326
buzbee2700f7e2014-03-07 09:46:20 -0800327LIR* MipsMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
328 MoveType move_type) {
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800329 UNIMPLEMENTED(FATAL);
330 return nullptr;
331}
332
buzbee2700f7e2014-03-07 09:46:20 -0800333LIR* MipsMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800334 UNIMPLEMENTED(FATAL);
335 return nullptr;
336}
337
buzbee2700f7e2014-03-07 09:46:20 -0800338LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800339 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
340 return NULL;
341}
342
buzbee2700f7e2014-03-07 09:46:20 -0800343LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700344 LIR *res;
Douglas Leung2db3e262014-06-25 16:02:55 -0700345 if (!r_dest.IsPair()) {
346 // Form 64-bit pair
347 r_dest = Solo64ToPair64(r_dest);
348 }
buzbee2700f7e2014-03-07 09:46:20 -0800349 res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value));
350 LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700351 return res;
352}
353
354/* Load value from base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800355LIR* MipsMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700356 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700357 LIR *first = NULL;
358 LIR *res;
359 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800360 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700361
buzbee091cc402014-03-31 10:14:40 -0700362 if (r_dest.IsFloat()) {
363 DCHECK(r_dest.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700364 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700365 size = kSingle;
366 } else {
367 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700368 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700369 }
370
371 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800372 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700373 } else {
374 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800375 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700376 }
377
378 switch (size) {
379 case kSingle:
380 opcode = kMipsFlwc1;
381 break;
buzbee695d13a2014-04-19 13:32:20 -0700382 case k32:
383 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700384 opcode = kMipsLw;
385 break;
386 case kUnsignedHalf:
387 opcode = kMipsLhu;
388 break;
389 case kSignedHalf:
390 opcode = kMipsLh;
391 break;
392 case kUnsignedByte:
393 opcode = kMipsLbu;
394 break;
395 case kSignedByte:
396 opcode = kMipsLb;
397 break;
398 default:
399 LOG(FATAL) << "Bad case in LoadBaseIndexed";
400 }
401
buzbee2700f7e2014-03-07 09:46:20 -0800402 res = NewLIR3(opcode, r_dest.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700403 FreeTemp(t_reg);
404 return (first) ? first : res;
405}
406
407/* store value base base + scaled index. */
buzbee2700f7e2014-03-07 09:46:20 -0800408LIR* MipsMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700409 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700410 LIR *first = NULL;
411 MipsOpCode opcode = kMipsNop;
buzbee2700f7e2014-03-07 09:46:20 -0800412 RegStorage t_reg = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700413
buzbee091cc402014-03-31 10:14:40 -0700414 if (r_src.IsFloat()) {
415 DCHECK(r_src.IsSingle());
buzbeefd698e62014-04-27 19:33:22 -0700416 DCHECK((size == k32) || (size == kSingle) || (size == kReference));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700417 size = kSingle;
418 } else {
419 if (size == kSingle)
buzbee695d13a2014-04-19 13:32:20 -0700420 size = k32;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700421 }
422
423 if (!scale) {
buzbee2700f7e2014-03-07 09:46:20 -0800424 first = NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), r_index.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700425 } else {
426 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
buzbee2700f7e2014-03-07 09:46:20 -0800427 NewLIR3(kMipsAddu, t_reg.GetReg() , r_base.GetReg(), t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700428 }
429
430 switch (size) {
431 case kSingle:
432 opcode = kMipsFswc1;
433 break;
buzbee695d13a2014-04-19 13:32:20 -0700434 case k32:
435 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700436 opcode = kMipsSw;
437 break;
438 case kUnsignedHalf:
439 case kSignedHalf:
440 opcode = kMipsSh;
441 break;
442 case kUnsignedByte:
443 case kSignedByte:
444 opcode = kMipsSb;
445 break;
446 default:
447 LOG(FATAL) << "Bad case in StoreBaseIndexed";
448 }
buzbee2700f7e2014-03-07 09:46:20 -0800449 NewLIR3(opcode, r_src.GetReg(), 0, t_reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700450 return first;
451}
452
buzbee2700f7e2014-03-07 09:46:20 -0800453// FIXME: don't split r_dest into 2 containers.
454LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
Douglas Leung2db3e262014-06-25 16:02:55 -0700455 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700456/*
457 * Load value from base + displacement. Optionally perform null check
458 * on base (which must have an associated s_reg and MIR). If not
459 * performing null check, incoming MIR can be null. IMPORTANT: this
460 * code must not allocate any new temps. If a new register is needed
461 * and base and dest are the same, spill some other register to
462 * rlp and then restore.
463 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700464 LIR *res;
465 LIR *load = NULL;
466 LIR *load2 = NULL;
467 MipsOpCode opcode = kMipsNop;
468 bool short_form = IS_SIMM16(displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700469 bool pair = r_dest.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700470
471 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700472 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700473 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700474 if (!pair) {
475 // Form 64-bit pair
476 r_dest = Solo64ToPair64(r_dest);
477 pair = 1;
478 }
buzbee091cc402014-03-31 10:14:40 -0700479 if (r_dest.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700480 DCHECK_EQ(r_dest.GetLowReg(), r_dest.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700481 opcode = kMipsFlwc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700482 } else {
483 opcode = kMipsLw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700484 }
485 short_form = IS_SIMM16_2WORD(displacement);
486 DCHECK_EQ((displacement & 0x3), 0);
487 break;
buzbee695d13a2014-04-19 13:32:20 -0700488 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700489 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700490 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700491 opcode = kMipsLw;
buzbee091cc402014-03-31 10:14:40 -0700492 if (r_dest.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700493 opcode = kMipsFlwc1;
buzbee091cc402014-03-31 10:14:40 -0700494 DCHECK(r_dest.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700495 }
496 DCHECK_EQ((displacement & 0x3), 0);
497 break;
498 case kUnsignedHalf:
499 opcode = kMipsLhu;
500 DCHECK_EQ((displacement & 0x1), 0);
501 break;
502 case kSignedHalf:
503 opcode = kMipsLh;
504 DCHECK_EQ((displacement & 0x1), 0);
505 break;
506 case kUnsignedByte:
507 opcode = kMipsLbu;
508 break;
509 case kSignedByte:
510 opcode = kMipsLb;
511 break;
512 default:
513 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
514 }
515
516 if (short_form) {
517 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800518 load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700519 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700520 load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
521 load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700522 }
523 } else {
524 if (pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800525 RegStorage r_tmp = AllocTemp();
526 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
Douglas Leung2db3e262014-06-25 16:02:55 -0700527 load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg());
528 load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700529 FreeTemp(r_tmp);
530 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800531 RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest;
532 res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement);
533 load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700534 if (r_tmp != r_dest)
535 FreeTemp(r_tmp);
536 }
537 }
538
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100539 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
540 DCHECK(r_base == rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700541 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
542 true /* is_load */, pair /* is64bit */);
543 if (pair) {
544 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
545 true /* is_load */, pair /* is64bit */);
546 }
547 }
548 return load;
549}
550
Andreas Gampede686762014-06-24 18:42:06 +0000551LIR* MipsMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000552 OpSize size, VolatileKind is_volatile) {
553 if (is_volatile == kVolatile) {
554 DCHECK(size != k64 && size != kDouble);
555 }
556
buzbee695d13a2014-04-19 13:32:20 -0700557 // TODO: base this on target.
558 if (size == kWord) {
559 size = k32;
560 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000561 LIR* load;
Douglas Leung2db3e262014-06-25 16:02:55 -0700562 load = LoadBaseDispBody(r_base, displacement, r_dest, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000563
564 if (UNLIKELY(is_volatile == kVolatile)) {
565 // Without context sensitive analysis, we must issue the most conservative barriers.
566 // In this case, either a load or store may follow so we issue both barriers.
567 GenMemBarrier(kLoadLoad);
568 GenMemBarrier(kLoadStore);
569 }
570
571 return load;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700572}
573
Vladimir Marko455759b2014-05-06 20:49:36 +0100574// FIXME: don't split r_dest into 2 containers.
buzbee2700f7e2014-03-07 09:46:20 -0800575LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement,
Douglas Leung2db3e262014-06-25 16:02:55 -0700576 RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700577 LIR *res;
578 LIR *store = NULL;
579 LIR *store2 = NULL;
580 MipsOpCode opcode = kMipsNop;
581 bool short_form = IS_SIMM16(displacement);
buzbee091cc402014-03-31 10:14:40 -0700582 bool pair = r_src.IsPair();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700583
584 switch (size) {
buzbee695d13a2014-04-19 13:32:20 -0700585 case k64:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700586 case kDouble:
Douglas Leung2db3e262014-06-25 16:02:55 -0700587 if (!pair) {
588 // Form 64-bit pair
589 r_src = Solo64ToPair64(r_src);
590 pair = 1;
591 }
buzbee091cc402014-03-31 10:14:40 -0700592 if (r_src.IsFloat()) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700593 DCHECK_EQ(r_src.GetLowReg(), r_src.GetHighReg() - 1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700594 opcode = kMipsFswc1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700595 } else {
596 opcode = kMipsSw;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700597 }
598 short_form = IS_SIMM16_2WORD(displacement);
599 DCHECK_EQ((displacement & 0x3), 0);
600 break;
buzbee695d13a2014-04-19 13:32:20 -0700601 case k32:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700602 case kSingle:
buzbee695d13a2014-04-19 13:32:20 -0700603 case kReference:
Brian Carlstrom7940e442013-07-12 13:46:57 -0700604 opcode = kMipsSw;
buzbee091cc402014-03-31 10:14:40 -0700605 if (r_src.IsFloat()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700606 opcode = kMipsFswc1;
buzbee091cc402014-03-31 10:14:40 -0700607 DCHECK(r_src.IsSingle());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700608 }
609 DCHECK_EQ((displacement & 0x3), 0);
610 break;
611 case kUnsignedHalf:
612 case kSignedHalf:
613 opcode = kMipsSh;
614 DCHECK_EQ((displacement & 0x1), 0);
615 break;
616 case kUnsignedByte:
617 case kSignedByte:
618 opcode = kMipsSb;
619 break;
620 default:
buzbee2700f7e2014-03-07 09:46:20 -0800621 LOG(FATAL) << "Bad case in StoreBaseDispBody";
Brian Carlstrom7940e442013-07-12 13:46:57 -0700622 }
623
624 if (short_form) {
625 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800626 store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700627 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700628 store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg());
629 store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700630 }
631 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800632 RegStorage r_scratch = AllocTemp();
633 res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700634 if (!pair) {
buzbee2700f7e2014-03-07 09:46:20 -0800635 store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700636 } else {
Douglas Leung2db3e262014-06-25 16:02:55 -0700637 store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg());
638 store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700639 }
640 FreeTemp(r_scratch);
641 }
642
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100643 if (mem_ref_type_ == ResourceMask::kDalvikReg) {
644 DCHECK(r_base == rs_rMIPS_SP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700645 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
646 false /* is_load */, pair /* is64bit */);
647 if (pair) {
648 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
649 false /* is_load */, pair /* is64bit */);
650 }
651 }
652
653 return res;
654}
655
Andreas Gampede686762014-06-24 18:42:06 +0000656LIR* MipsMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
Andreas Gampe3c12c512014-06-24 18:46:29 +0000657 OpSize size, VolatileKind is_volatile) {
658 if (is_volatile == kVolatile) {
659 DCHECK(size != k64 && size != kDouble);
660 // There might have been a store before this volatile one so insert StoreStore barrier.
661 GenMemBarrier(kStoreStore);
662 }
663
buzbee695d13a2014-04-19 13:32:20 -0700664 // TODO: base this on target.
665 if (size == kWord) {
666 size = k32;
667 }
Andreas Gampe3c12c512014-06-24 18:46:29 +0000668 LIR* store;
Douglas Leung2db3e262014-06-25 16:02:55 -0700669 store = StoreBaseDispBody(r_base, displacement, r_src, size);
Andreas Gampe3c12c512014-06-24 18:46:29 +0000670
671 if (UNLIKELY(is_volatile == kVolatile)) {
672 // A load might follow the volatile store so insert a StoreLoad barrier.
673 GenMemBarrier(kStoreLoad);
674 }
675
676 return store;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700677}
678
Ian Rogersdd7624d2014-03-14 17:43:00 -0700679LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset<4> thread_offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700680 LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
681 return NULL;
682}
683
Andreas Gampe2f244e92014-05-08 03:35:25 -0700684LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset<8> thread_offset) {
685 UNIMPLEMENTED(FATAL) << "Should not be called.";
686 return nullptr;
687}
688
buzbee2700f7e2014-03-07 09:46:20 -0800689LIR* MipsMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700690 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
691 return NULL;
692}
693
buzbee2700f7e2014-03-07 09:46:20 -0800694LIR* MipsMir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
Vladimir Marko3bf7c602014-05-07 14:55:43 +0100695 int displacement, RegStorage r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700696 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
697 return NULL;
698}
699
buzbee2700f7e2014-03-07 09:46:20 -0800700LIR* MipsMir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700701 LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
702 return NULL;
703}
704
buzbee2700f7e2014-03-07 09:46:20 -0800705LIR* MipsMir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
Vladimir Marko3bf7c602014-05-07 14:55:43 +0100706 int displacement, RegStorage r_dest, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700707 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
708 return NULL;
709}
710
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700711LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700712 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
713 return NULL;
714}
715
716} // namespace art