blob: 21c971c327787fc65ed41fa0bfa0bc77d3e49f13 [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. */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070024LIR* MipsMir2Lir::OpFpRegCopy(int r_dest, int r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070025 int opcode;
26 /* must be both DOUBLE or both not DOUBLE */
Brian Carlstromb1eba212013-07-17 18:07:19 -070027 DCHECK_EQ(MIPS_DOUBLEREG(r_dest), MIPS_DOUBLEREG(r_src));
Brian Carlstrom7940e442013-07-12 13:46:57 -070028 if (MIPS_DOUBLEREG(r_dest)) {
29 opcode = kMipsFmovd;
30 } else {
31 if (MIPS_SINGLEREG(r_dest)) {
32 if (MIPS_SINGLEREG(r_src)) {
33 opcode = kMipsFmovs;
34 } else {
35 /* note the operands are swapped for the mtc1 instr */
36 int t_opnd = r_src;
37 r_src = r_dest;
38 r_dest = t_opnd;
39 opcode = kMipsMtc1;
40 }
41 } else {
42 DCHECK(MIPS_SINGLEREG(r_src));
43 opcode = kMipsMfc1;
44 }
45 }
46 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src, r_dest);
47 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 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070078LIR* MipsMir2Lir::LoadConstantNoClobber(int r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070079 LIR *res;
80
81 int r_dest_save = r_dest;
82 int is_fp_reg = MIPS_FPREG(r_dest);
83 if (is_fp_reg) {
84 DCHECK(MIPS_SINGLEREG(r_dest));
85 r_dest = AllocTemp();
86 }
87
88 /* See if the value can be constructed cheaply */
89 if (value == 0) {
90 res = NewLIR2(kMipsMove, r_dest, r_ZERO);
91 } else if ((value > 0) && (value <= 65535)) {
92 res = NewLIR3(kMipsOri, r_dest, r_ZERO, value);
93 } else if ((value < 0) && (value >= -32768)) {
94 res = NewLIR3(kMipsAddiu, r_dest, r_ZERO, value);
95 } else {
buzbee0d829482013-10-11 15:24:55 -070096 res = NewLIR2(kMipsLui, r_dest, value >> 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -070097 if (value & 0xffff)
98 NewLIR3(kMipsOri, r_dest, r_dest, value);
99 }
100
101 if (is_fp_reg) {
102 NewLIR2(kMipsMtc1, r_dest, r_dest_save);
103 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
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700115LIR* MipsMir2Lir::OpReg(OpKind op, int 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:
122 return NewLIR1(kMipsJr, r_dest_src);
123 break;
124 default:
125 LOG(FATAL) << "Bad case in OpReg";
126 }
127 return NewLIR2(opcode, r_RA, r_dest_src);
128}
129
130LIR* MipsMir2Lir::OpRegImm(OpKind op, int r_dest_src1,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700131 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) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 res = NewLIR2(opcode, r_dest_src1, abs_value);
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700150 } else {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151 int r_scratch = AllocTemp();
152 res = LoadConstant(r_scratch, value);
153 if (op == kOpCmp)
154 NewLIR2(opcode, r_dest_src1, r_scratch);
155 else
156 NewLIR3(opcode, r_dest_src1, r_dest_src1, r_scratch);
157 }
158 return res;
159}
160
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700161LIR* MipsMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int 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 }
199 return NewLIR3(opcode, r_dest, r_src1, r_src2);
200}
201
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700202LIR* MipsMir2Lir::OpRegRegImm(OpKind op, int r_dest, int 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) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700271 res = NewLIR3(opcode, r_dest, r_src1, 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);
275 NewLIR3(opcode, r_dest, r_src1, r_dest);
276 } else {
277 int r_scratch = AllocTemp();
278 res = LoadConstant(r_scratch, value);
279 NewLIR3(opcode, r_dest, r_src1, r_scratch);
280 }
281 }
282 return res;
283}
284
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700285LIR* MipsMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int 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:
293 return NewLIR3(kMipsNor, r_dest_src1, r_src2, r_ZERO);
294 case kOpNeg:
295 return NewLIR3(kMipsSubu, r_dest_src1, r_ZERO, r_src2);
296 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
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305 res = NewLIR2(kMipsSeb, r_dest_src1, r_src2);
306#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
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313 res = NewLIR2(kMipsSeh, r_dest_src1, r_src2);
314#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:
320 return NewLIR3(kMipsAndi, r_dest_src1, r_src2, 0xFFFF);
321 default:
322 LOG(FATAL) << "Bad case in OpRegReg";
323 break;
324 }
325 return NewLIR2(opcode, r_dest_src1, r_src2);
326}
327
Razvan A Lupusoru2c498d12014-01-29 16:02:57 -0800328LIR* MipsMir2Lir::OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type) {
329 UNIMPLEMENTED(FATAL);
330 return nullptr;
331}
332
333LIR* MipsMir2Lir::OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type) {
334 UNIMPLEMENTED(FATAL);
335 return nullptr;
336}
337
Razvan A Lupusorubd288c22013-12-20 17:27:23 -0800338LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src) {
339 LOG(FATAL) << "Unexpected use of OpCondRegReg for MIPS";
340 return NULL;
341}
342
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700343LIR* MipsMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700344 LIR *res;
345 res = LoadConstantNoClobber(r_dest_lo, Low32Bits(value));
346 LoadConstantNoClobber(r_dest_hi, High32Bits(value));
347 return res;
348}
349
350/* Load value from base + scaled index. */
351LIR* MipsMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700352 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700353 LIR *first = NULL;
354 LIR *res;
355 MipsOpCode opcode = kMipsNop;
356 int t_reg = AllocTemp();
357
358 if (MIPS_FPREG(r_dest)) {
359 DCHECK(MIPS_SINGLEREG(r_dest));
360 DCHECK((size == kWord) || (size == kSingle));
361 size = kSingle;
362 } else {
363 if (size == kSingle)
364 size = kWord;
365 }
366
367 if (!scale) {
368 first = NewLIR3(kMipsAddu, t_reg , rBase, r_index);
369 } else {
370 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
371 NewLIR3(kMipsAddu, t_reg , rBase, t_reg);
372 }
373
374 switch (size) {
375 case kSingle:
376 opcode = kMipsFlwc1;
377 break;
378 case kWord:
379 opcode = kMipsLw;
380 break;
381 case kUnsignedHalf:
382 opcode = kMipsLhu;
383 break;
384 case kSignedHalf:
385 opcode = kMipsLh;
386 break;
387 case kUnsignedByte:
388 opcode = kMipsLbu;
389 break;
390 case kSignedByte:
391 opcode = kMipsLb;
392 break;
393 default:
394 LOG(FATAL) << "Bad case in LoadBaseIndexed";
395 }
396
397 res = NewLIR3(opcode, r_dest, 0, t_reg);
398 FreeTemp(t_reg);
399 return (first) ? first : res;
400}
401
402/* store value base base + scaled index. */
403LIR* MipsMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700404 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700405 LIR *first = NULL;
406 MipsOpCode opcode = kMipsNop;
407 int r_new_index = r_index;
408 int t_reg = AllocTemp();
409
410 if (MIPS_FPREG(r_src)) {
411 DCHECK(MIPS_SINGLEREG(r_src));
412 DCHECK((size == kWord) || (size == kSingle));
413 size = kSingle;
414 } else {
415 if (size == kSingle)
416 size = kWord;
417 }
418
419 if (!scale) {
420 first = NewLIR3(kMipsAddu, t_reg , rBase, r_index);
421 } else {
422 first = OpRegRegImm(kOpLsl, t_reg, r_index, scale);
423 NewLIR3(kMipsAddu, t_reg , rBase, t_reg);
424 }
425
426 switch (size) {
427 case kSingle:
428 opcode = kMipsFswc1;
429 break;
430 case kWord:
431 opcode = kMipsSw;
432 break;
433 case kUnsignedHalf:
434 case kSignedHalf:
435 opcode = kMipsSh;
436 break;
437 case kUnsignedByte:
438 case kSignedByte:
439 opcode = kMipsSb;
440 break;
441 default:
442 LOG(FATAL) << "Bad case in StoreBaseIndexed";
443 }
444 NewLIR3(opcode, r_src, 0, t_reg);
445 FreeTemp(r_new_index);
446 return first;
447}
448
449LIR* MipsMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700450 int r_dest_hi, OpSize size, int s_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700451/*
452 * Load value from base + displacement. Optionally perform null check
453 * on base (which must have an associated s_reg and MIR). If not
454 * performing null check, incoming MIR can be null. IMPORTANT: this
455 * code must not allocate any new temps. If a new register is needed
456 * and base and dest are the same, spill some other register to
457 * rlp and then restore.
458 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 LIR *res;
460 LIR *load = NULL;
461 LIR *load2 = NULL;
462 MipsOpCode opcode = kMipsNop;
463 bool short_form = IS_SIMM16(displacement);
464 bool pair = false;
465
466 switch (size) {
467 case kLong:
468 case kDouble:
469 pair = true;
470 opcode = kMipsLw;
471 if (MIPS_FPREG(r_dest)) {
472 opcode = kMipsFlwc1;
473 if (MIPS_DOUBLEREG(r_dest)) {
474 r_dest = r_dest - MIPS_FP_DOUBLE;
475 } else {
476 DCHECK(MIPS_FPREG(r_dest_hi));
477 DCHECK(r_dest == (r_dest_hi - 1));
478 }
479 r_dest_hi = r_dest + 1;
480 }
481 short_form = IS_SIMM16_2WORD(displacement);
482 DCHECK_EQ((displacement & 0x3), 0);
483 break;
484 case kWord:
485 case kSingle:
486 opcode = kMipsLw;
487 if (MIPS_FPREG(r_dest)) {
488 opcode = kMipsFlwc1;
489 DCHECK(MIPS_SINGLEREG(r_dest));
490 }
491 DCHECK_EQ((displacement & 0x3), 0);
492 break;
493 case kUnsignedHalf:
494 opcode = kMipsLhu;
495 DCHECK_EQ((displacement & 0x1), 0);
496 break;
497 case kSignedHalf:
498 opcode = kMipsLh;
499 DCHECK_EQ((displacement & 0x1), 0);
500 break;
501 case kUnsignedByte:
502 opcode = kMipsLbu;
503 break;
504 case kSignedByte:
505 opcode = kMipsLb;
506 break;
507 default:
508 LOG(FATAL) << "Bad case in LoadBaseIndexedBody";
509 }
510
511 if (short_form) {
512 if (!pair) {
513 load = res = NewLIR3(opcode, r_dest, displacement, rBase);
514 } else {
515 load = res = NewLIR3(opcode, r_dest,
516 displacement + LOWORD_OFFSET, rBase);
517 load2 = NewLIR3(opcode, r_dest_hi,
518 displacement + HIWORD_OFFSET, rBase);
519 }
520 } else {
521 if (pair) {
Vladimir Marko73e08b32013-11-21 10:58:36 +0000522 int r_tmp = AllocTemp();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700523 res = OpRegRegImm(kOpAdd, r_tmp, rBase, displacement);
524 load = NewLIR3(opcode, r_dest, LOWORD_OFFSET, r_tmp);
525 load2 = NewLIR3(opcode, r_dest_hi, HIWORD_OFFSET, r_tmp);
526 FreeTemp(r_tmp);
527 } else {
Vladimir Marko73e08b32013-11-21 10:58:36 +0000528 int r_tmp = (rBase == r_dest) ? AllocTemp() : r_dest;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700529 res = OpRegRegImm(kOpAdd, r_tmp, rBase, displacement);
530 load = NewLIR3(opcode, r_dest, 0, r_tmp);
531 if (r_tmp != r_dest)
532 FreeTemp(r_tmp);
533 }
534 }
535
536 if (rBase == rMIPS_SP) {
537 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
538 true /* is_load */, pair /* is64bit */);
539 if (pair) {
540 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
541 true /* is_load */, pair /* is64bit */);
542 }
543 }
544 return load;
545}
546
547LIR* MipsMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700548 OpSize size, int s_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700549 return LoadBaseDispBody(rBase, displacement, r_dest, -1,
550 size, s_reg);
551}
552
553LIR* MipsMir2Lir::LoadBaseDispWide(int rBase, int displacement,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700554 int r_dest_lo, int r_dest_hi, int s_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700555 return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
556}
557
558LIR* MipsMir2Lir::StoreBaseDispBody(int rBase, int displacement,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700559 int r_src, int r_src_hi, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700560 LIR *res;
561 LIR *store = NULL;
562 LIR *store2 = NULL;
563 MipsOpCode opcode = kMipsNop;
564 bool short_form = IS_SIMM16(displacement);
565 bool pair = false;
566
567 switch (size) {
568 case kLong:
569 case kDouble:
570 pair = true;
571 opcode = kMipsSw;
572 if (MIPS_FPREG(r_src)) {
573 opcode = kMipsFswc1;
574 if (MIPS_DOUBLEREG(r_src)) {
575 r_src = r_src - MIPS_FP_DOUBLE;
576 } else {
577 DCHECK(MIPS_FPREG(r_src_hi));
578 DCHECK_EQ(r_src, (r_src_hi - 1));
579 }
580 r_src_hi = r_src + 1;
581 }
582 short_form = IS_SIMM16_2WORD(displacement);
583 DCHECK_EQ((displacement & 0x3), 0);
584 break;
585 case kWord:
586 case kSingle:
587 opcode = kMipsSw;
588 if (MIPS_FPREG(r_src)) {
589 opcode = kMipsFswc1;
590 DCHECK(MIPS_SINGLEREG(r_src));
591 }
592 DCHECK_EQ((displacement & 0x3), 0);
593 break;
594 case kUnsignedHalf:
595 case kSignedHalf:
596 opcode = kMipsSh;
597 DCHECK_EQ((displacement & 0x1), 0);
598 break;
599 case kUnsignedByte:
600 case kSignedByte:
601 opcode = kMipsSb;
602 break;
603 default:
604 LOG(FATAL) << "Bad case in StoreBaseIndexedBody";
605 }
606
607 if (short_form) {
608 if (!pair) {
609 store = res = NewLIR3(opcode, r_src, displacement, rBase);
610 } else {
611 store = res = NewLIR3(opcode, r_src, displacement + LOWORD_OFFSET,
612 rBase);
613 store2 = NewLIR3(opcode, r_src_hi, displacement + HIWORD_OFFSET,
614 rBase);
615 }
616 } else {
617 int r_scratch = AllocTemp();
618 res = OpRegRegImm(kOpAdd, r_scratch, rBase, displacement);
619 if (!pair) {
620 store = NewLIR3(opcode, r_src, 0, r_scratch);
621 } else {
622 store = NewLIR3(opcode, r_src, LOWORD_OFFSET, r_scratch);
623 store2 = NewLIR3(opcode, r_src_hi, HIWORD_OFFSET, r_scratch);
624 }
625 FreeTemp(r_scratch);
626 }
627
628 if (rBase == rMIPS_SP) {
629 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
630 false /* is_load */, pair /* is64bit */);
631 if (pair) {
632 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
633 false /* is_load */, pair /* is64bit */);
634 }
635 }
636
637 return res;
638}
639
640LIR* MipsMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700641 OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700642 return StoreBaseDispBody(rBase, displacement, r_src, -1, size);
643}
644
645LIR* MipsMir2Lir::StoreBaseDispWide(int rBase, int displacement,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700646 int r_src_lo, int r_src_hi) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700647 return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong);
648}
649
Ian Rogers468532e2013-08-05 10:56:33 -0700650LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700651 LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
652 return NULL;
653}
654
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700655LIR* MipsMir2Lir::OpMem(OpKind op, int rBase, int disp) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700656 LOG(FATAL) << "Unexpected use of OpMem for MIPS";
657 return NULL;
658}
659
Brian Carlstromdf629502013-07-17 22:39:56 -0700660LIR* MipsMir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
661 int r_src, int r_src_hi, OpSize size, int s_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700662 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS";
663 return NULL;
664}
665
666LIR* MipsMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700667 int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700668 LOG(FATAL) << "Unexpected use of OpRegMem for MIPS";
669 return NULL;
670}
671
672LIR* MipsMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700673 int r_dest, int r_dest_hi, OpSize size, int s_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700674 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS";
675 return NULL;
676}
677
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700678LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700679 LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS";
680 return NULL;
681}
682
683} // namespace art