blob: 71220c0be75145164fee9e3cec3ab317679687c6 [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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
17namespace art {
18
19/*
20 * This file contains codegen for the MIPS32 ISA and is intended to be
21 * includes by:
22 *
23 * Codegen-$(TARGET_ARCH_VARIANT).c
24 *
25 */
26
27static int coreRegs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3,
28 r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7,
29 r_S0, r_S1, r_S2, r_S3, r_S4, r_S5, r_S6, r_S7, r_T8,
30 r_T9, r_K0, r_K1, r_GP, r_SP, r_FP, r_RA};
31static int reservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP};
32static int coreTemps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
33 r_T3, r_T4, r_T5, r_T6, r_T7, r_T8, r_T9};
34#ifdef __mips_hard_float
35static int fpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
36 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
37static int fpTemps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
38 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
39#endif
40
buzbee5de34942012-03-01 14:51:57 -080041void genBarrier(CompilationUnit *cUnit);
42LIR* genCompareBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
43 int src2);
44LIR* opCompareBranch(CompilationUnit* cUnit, MipsOpCode opc, int src1,
45 int src2);
buzbee31a4a6f2012-02-28 15:36:15 -080046void storePair(CompilationUnit *cUnit, int base, int lowReg,
47 int highReg);
48void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
buzbee5de34942012-03-01 14:51:57 -080049LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
buzbee31a4a6f2012-02-28 15:36:15 -080050 int rDest);
buzbee5de34942012-03-01 14:51:57 -080051LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -080052 int displacement, int rSrc);
buzbee5de34942012-03-01 14:51:57 -080053LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
buzbeee3acd072012-02-25 17:03:10 -080054
55#ifdef __mips_hard_float
buzbee5de34942012-03-01 14:51:57 -080056LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -080057{
buzbee5de34942012-03-01 14:51:57 -080058 LIR* res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -080059 res->operands[0] = rDest;
60 res->operands[1] = rSrc;
61 if (rDest == rSrc) {
62 res->flags.isNop = true;
63 } else {
64 /* must be both DOUBLE or both not DOUBLE */
65 DCHECK_EQ(DOUBLEREG(rDest),DOUBLEREG(rSrc));
66 if (DOUBLEREG(rDest)) {
67 res->opcode = kMipsFmovd;
68 } else {
69 if (SINGLEREG(rDest)) {
70 if (SINGLEREG(rSrc)) {
71 res->opcode = kMipsFmovs;
72 } else {
73 /* note the operands are swapped for the mtc1 instr */
74 res->opcode = kMipsMtc1;
75 res->operands[0] = rSrc;
76 res->operands[1] = rDest;
77 }
78 } else {
79 DCHECK(SINGLEREG(rSrc));
80 res->opcode = kMipsMfc1;
81 }
82 }
83 }
84 setupResourceMasks(res);
85 return res;
86}
87#endif
88
89/*
90 * Load a immediate using a shortcut if possible; otherwise
91 * grab from the per-translation literal pool. If target is
92 * a high register, build constant into a low register and copy.
93 *
94 * No additional register clobbering operation performed. Use this version when
95 * 1) rDest is freshly returned from oatAllocTemp or
96 * 2) The codegen is under fixed register usage
97 */
buzbee5de34942012-03-01 14:51:57 -080098LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
buzbee31a4a6f2012-02-28 15:36:15 -080099 int value)
buzbeee3acd072012-02-25 17:03:10 -0800100{
buzbee5de34942012-03-01 14:51:57 -0800101 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800102
103#ifdef __mips_hard_float
104 int rDestSave = rDest;
105 int isFpReg = FPREG(rDest);
106 if (isFpReg) {
107 DCHECK(SINGLEREG(rDest));
108 rDest = oatAllocTemp(cUnit);
109 }
110#endif
111
112 /* See if the value can be constructed cheaply */
113 if (value == 0) {
114 res = newLIR2(cUnit, kMipsMove, rDest, r_ZERO);
115 } else if ((value > 0) && (value <= 65535)) {
116 res = newLIR3(cUnit, kMipsOri, rDest, r_ZERO, value);
117 } else if ((value < 0) && (value >= -32768)) {
118 res = newLIR3(cUnit, kMipsAddiu, rDest, r_ZERO, value);
119 } else {
120 res = newLIR2(cUnit, kMipsLui, rDest, value>>16);
121 if (value & 0xffff)
122 newLIR3(cUnit, kMipsOri, rDest, rDest, value);
123 }
124
125#ifdef __mips_hard_float
126 if (isFpReg) {
127 newLIR2(cUnit, kMipsMtc1, rDest, rDestSave);
128 oatFreeTemp(cUnit, rDest);
129 }
130#endif
131
132 return res;
133}
134
buzbee5de34942012-03-01 14:51:57 -0800135LIR *opNone(CompilationUnit *cUnit, OpKind op)
buzbeee3acd072012-02-25 17:03:10 -0800136{
buzbee5de34942012-03-01 14:51:57 -0800137 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800138 MipsOpCode opcode = kMipsNop;
139 switch (op) {
140 case kOpUncondBr:
141 opcode = kMipsB;
142 break;
143 default:
144 LOG(FATAL) << "Bad case in opNone";
145 }
146 res = newLIR0(cUnit, opcode);
147 return res;
148}
149
buzbee31a4a6f2012-02-28 15:36:15 -0800150
buzbee5de34942012-03-01 14:51:57 -0800151LIR *opCmpBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
buzbee31a4a6f2012-02-28 15:36:15 -0800152 int rs, int rt)
153{
154 UNIMPLEMENTED(FATAL);
155 return 0;
156}
buzbee5de34942012-03-01 14:51:57 -0800157LIR *opCmpImmBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
buzbee31a4a6f2012-02-28 15:36:15 -0800158 int rs, int immVal)
159{
160 UNIMPLEMENTED(FATAL);
161 return 0;
162}
buzbee5de34942012-03-01 14:51:57 -0800163LIR *opCmpImmBranch(CompilationUnit *cUnit, MipsOpCode cc,
buzbee31a4a6f2012-02-28 15:36:15 -0800164 int rs, int immVal)
165{
166 UNIMPLEMENTED(FATAL);
167 return 0;
168}
169
buzbee5de34942012-03-01 14:51:57 -0800170LIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)
buzbeee3acd072012-02-25 17:03:10 -0800171{
buzbee5de34942012-03-01 14:51:57 -0800172 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800173 if (rt < 0) {
174 DCHECK(opc >= kMipsBeqz && opc <= kMipsBnez);
175 res = newLIR1(cUnit, opc, rs);
176 } else {
177 DCHECK(opc == kMipsBeq || opc == kMipsBne);
178 res = newLIR2(cUnit, opc, rs, rt);
179 }
180 return res;
181}
182
buzbee5de34942012-03-01 14:51:57 -0800183LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
buzbeee3acd072012-02-25 17:03:10 -0800184
buzbee5de34942012-03-01 14:51:57 -0800185LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
buzbeee3acd072012-02-25 17:03:10 -0800186{
187 MipsOpCode opcode = kMipsNop;
188 switch (op) {
189 case kOpBlx:
190 opcode = kMipsJalr;
191 break;
192 default:
193 LOG(FATAL) << "Bad case in opReg";
194 }
195 return newLIR2(cUnit, opcode, r_RA, rDestSrc);
196}
197
buzbee5de34942012-03-01 14:51:57 -0800198LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
buzbee31a4a6f2012-02-28 15:36:15 -0800199 int rSrc1, int value);
buzbee5de34942012-03-01 14:51:57 -0800200LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
buzbeee3acd072012-02-25 17:03:10 -0800201 int value)
202{
buzbee5de34942012-03-01 14:51:57 -0800203 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800204 bool neg = (value < 0);
205 int absValue = (neg) ? -value : value;
206 bool shortForm = (absValue & 0xff) == absValue;
207 MipsOpCode opcode = kMipsNop;
208 switch (op) {
209 case kOpAdd:
210 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
211 break;
212 case kOpSub:
213 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
214 break;
215 default:
216 LOG(FATAL) << "Bad case in opRegImm";
217 break;
218 }
219 if (shortForm)
220 res = newLIR2(cUnit, opcode, rDestSrc1, absValue);
221 else {
222 int rScratch = oatAllocTemp(cUnit);
223 res = loadConstant(cUnit, rScratch, value);
224 if (op == kOpCmp)
225 newLIR2(cUnit, opcode, rDestSrc1, rScratch);
226 else
227 newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rScratch);
228 }
229 return res;
230}
231
buzbee5de34942012-03-01 14:51:57 -0800232LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
buzbeee3acd072012-02-25 17:03:10 -0800233 int rSrc1, int rSrc2)
234{
235 MipsOpCode opcode = kMipsNop;
236 switch (op) {
237 case kOpAdd:
238 opcode = kMipsAddu;
239 break;
240 case kOpSub:
241 opcode = kMipsSubu;
242 break;
243 case kOpAnd:
244 opcode = kMipsAnd;
245 break;
246 case kOpMul:
247 opcode = kMipsMul;
248 break;
249 case kOpOr:
250 opcode = kMipsOr;
251 break;
252 case kOpXor:
253 opcode = kMipsXor;
254 break;
255 case kOpLsl:
256 opcode = kMipsSllv;
257 break;
258 case kOpLsr:
259 opcode = kMipsSrlv;
260 break;
261 case kOpAsr:
262 opcode = kMipsSrav;
263 break;
264 default:
265 LOG(FATAL) << "bad case in opRegRegReg";
266 break;
267 }
268 return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
269}
270
buzbee5de34942012-03-01 14:51:57 -0800271LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
buzbeee3acd072012-02-25 17:03:10 -0800272 int rSrc1, int value)
273{
buzbee5de34942012-03-01 14:51:57 -0800274 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800275 MipsOpCode opcode = kMipsNop;
276 bool shortForm = true;
277
278 switch(op) {
279 case kOpAdd:
280 if (IS_SIMM16(value)) {
281 opcode = kMipsAddiu;
282 }
283 else {
284 shortForm = false;
285 opcode = kMipsAddu;
286 }
287 break;
288 case kOpSub:
289 if (IS_SIMM16((-value))) {
290 value = -value;
291 opcode = kMipsAddiu;
292 }
293 else {
294 shortForm = false;
295 opcode = kMipsSubu;
296 }
297 break;
298 case kOpLsl:
299 DCHECK(value >= 0 && value <= 31);
300 opcode = kMipsSll;
301 break;
302 case kOpLsr:
303 DCHECK(value >= 0 && value <= 31);
304 opcode = kMipsSrl;
305 break;
306 case kOpAsr:
307 DCHECK(value >= 0 && value <= 31);
308 opcode = kMipsSra;
309 break;
310 case kOpAnd:
311 if (IS_UIMM16((value))) {
312 opcode = kMipsAndi;
313 }
314 else {
315 shortForm = false;
316 opcode = kMipsAnd;
317 }
318 break;
319 case kOpOr:
320 if (IS_UIMM16((value))) {
321 opcode = kMipsOri;
322 }
323 else {
324 shortForm = false;
325 opcode = kMipsOr;
326 }
327 break;
328 case kOpXor:
329 if (IS_UIMM16((value))) {
330 opcode = kMipsXori;
331 }
332 else {
333 shortForm = false;
334 opcode = kMipsXor;
335 }
336 break;
337 case kOpMul:
338 shortForm = false;
339 opcode = kMipsMul;
340 break;
341 default:
342 LOG(FATAL) << "Bad case in opRegRegImm";
343 break;
344 }
345
346 if (shortForm)
347 res = newLIR3(cUnit, opcode, rDest, rSrc1, value);
348 else {
349 if (rDest != rSrc1) {
350 res = loadConstant(cUnit, rDest, value);
351 newLIR3(cUnit, opcode, rDest, rSrc1, rDest);
352 } else {
353 int rScratch = oatAllocTemp(cUnit);
354 res = loadConstant(cUnit, rScratch, value);
355 newLIR3(cUnit, opcode, rDest, rSrc1, rScratch);
356 }
357 }
358 return res;
359}
360
buzbee5de34942012-03-01 14:51:57 -0800361LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
buzbeee3acd072012-02-25 17:03:10 -0800362 int rSrc2)
363{
364 MipsOpCode opcode = kMipsNop;
buzbee5de34942012-03-01 14:51:57 -0800365 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800366 switch (op) {
367 case kOpMov:
368 opcode = kMipsMove;
369 break;
370 case kOpMvn:
371 return newLIR3(cUnit, kMipsNor, rDestSrc1, rSrc2, r_ZERO);
372 case kOpNeg:
373 return newLIR3(cUnit, kMipsSubu, rDestSrc1, r_ZERO, rSrc2);
374 case kOpAdd:
375 case kOpAnd:
376 case kOpMul:
377 case kOpOr:
378 case kOpSub:
379 case kOpXor:
380 return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
381 case kOp2Byte:
382#if __mips_isa_rev>=2
383 res = newLIR2(cUnit, kMipsSeb, rDestSrc1, rSrc2);
384#else
385 res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 24);
386 opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 24);
387#endif
388 return res;
389 case kOp2Short:
390#if __mips_isa_rev>=2
391 res = newLIR2(cUnit, kMipsSeh, rDestSrc1, rSrc2);
392#else
393 res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 16);
394 opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 16);
395#endif
396 return res;
397 case kOp2Char:
398 return newLIR3(cUnit, kMipsAndi, rDestSrc1, rSrc2, 0xFFFF);
399 default:
400 LOG(FATAL) << "Bad case in opRegReg";
401 break;
402 }
403 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
404}
405
buzbee5de34942012-03-01 14:51:57 -0800406LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
buzbeee3acd072012-02-25 17:03:10 -0800407 int rDestHi, int valLo, int valHi)
408{
buzbee5de34942012-03-01 14:51:57 -0800409 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800410 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
411 loadConstantNoClobber(cUnit, rDestHi, valHi);
412 return res;
413}
414
415/* Load value from base + scaled index. */
buzbee5de34942012-03-01 14:51:57 -0800416LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
buzbeee3acd072012-02-25 17:03:10 -0800417 int rIndex, int rDest, int scale, OpSize size)
418{
buzbee5de34942012-03-01 14:51:57 -0800419 LIR *first = NULL;
420 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800421 MipsOpCode opcode = kMipsNop;
422 int tReg = oatAllocTemp(cUnit);
423
424#ifdef __mips_hard_float
425 if (FPREG(rDest)) {
426 DCHECK(SINGLEREG(rDest));
427 DCHECK((size == kWord) || (size == kSingle));
428 size = kSingle;
429 } else {
430 if (size == kSingle)
431 size = kWord;
432 }
433#endif
434
435 if (!scale) {
436 first = newLIR3(cUnit, kMipsAddu, tReg , rBase, rIndex);
437 } else {
438 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
439 newLIR3(cUnit, kMipsAddu, tReg , rBase, tReg);
440 }
441
442 switch (size) {
443#ifdef __mips_hard_float
444 case kSingle:
445 opcode = kMipsFlwc1;
446 break;
447#endif
448 case kWord:
449 opcode = kMipsLw;
450 break;
451 case kUnsignedHalf:
452 opcode = kMipsLhu;
453 break;
454 case kSignedHalf:
455 opcode = kMipsLh;
456 break;
457 case kUnsignedByte:
458 opcode = kMipsLbu;
459 break;
460 case kSignedByte:
461 opcode = kMipsLb;
462 break;
463 default:
464 LOG(FATAL) << "Bad case in loadBaseIndexed";
465 }
466
467 res = newLIR3(cUnit, opcode, rDest, 0, tReg);
468 oatFreeTemp(cUnit, tReg);
469 return (first) ? first : res;
470}
471
472/* store value base base + scaled index. */
buzbee5de34942012-03-01 14:51:57 -0800473LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
buzbeee3acd072012-02-25 17:03:10 -0800474 int rIndex, int rSrc, int scale, OpSize size)
475{
buzbee5de34942012-03-01 14:51:57 -0800476 LIR *first = NULL;
477 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -0800478 MipsOpCode opcode = kMipsNop;
479 int rNewIndex = rIndex;
480 int tReg = oatAllocTemp(cUnit);
481
482#ifdef __mips_hard_float
483 if (FPREG(rSrc)) {
484 DCHECK(SINGLEREG(rSrc));
485 DCHECK((size == kWord) || (size == kSingle));
486 size = kSingle;
487 } else {
488 if (size == kSingle)
489 size = kWord;
490 }
491#endif
492
493 if (!scale) {
494 first = newLIR3(cUnit, kMipsAddu, tReg , rBase, rIndex);
495 } else {
496 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
497 newLIR3(cUnit, kMipsAddu, tReg , rBase, tReg);
498 }
499
500 switch (size) {
501#ifdef __mips_hard_float
502 case kSingle:
503 opcode = kMipsFswc1;
504 break;
505#endif
506 case kWord:
507 opcode = kMipsSw;
508 break;
509 case kUnsignedHalf:
510 case kSignedHalf:
511 opcode = kMipsSh;
512 break;
513 case kUnsignedByte:
514 case kSignedByte:
515 opcode = kMipsSb;
516 break;
517 default:
518 LOG(FATAL) << "Bad case in storeBaseIndexed";
519 }
520 res = newLIR3(cUnit, opcode, rSrc, 0, tReg);
521 oatFreeTemp(cUnit, rNewIndex);
522 return first;
523}
524
buzbee5de34942012-03-01 14:51:57 -0800525LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee3acd072012-02-25 17:03:10 -0800526{
527 int i;
528 int loadCnt = 0;
buzbee5de34942012-03-01 14:51:57 -0800529 LIR *res = NULL ;
buzbeee3acd072012-02-25 17:03:10 -0800530 genBarrier(cUnit);
531
532 for (i = 0; i < 8; i++, rMask >>= 1) {
533 if (rMask & 0x1) { /* map r0 to MIPS r_A0 */
534 newLIR3(cUnit, kMipsLw, i+r_A0, loadCnt*4, rBase);
535 loadCnt++;
536 }
537 }
538
539 if (loadCnt) {/* increment after */
540 newLIR3(cUnit, kMipsAddiu, rBase, rBase, loadCnt*4);
541 }
542
543 genBarrier(cUnit);
544 return res; /* NULL always returned which should be ok since no callers use it */
545}
546
buzbee5de34942012-03-01 14:51:57 -0800547LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee3acd072012-02-25 17:03:10 -0800548{
549 int i;
550 int storeCnt = 0;
buzbee5de34942012-03-01 14:51:57 -0800551 LIR *res = NULL ;
buzbeee3acd072012-02-25 17:03:10 -0800552 genBarrier(cUnit);
553
554 for (i = 0; i < 8; i++, rMask >>= 1) {
555 if (rMask & 0x1) { /* map r0 to MIPS r_A0 */
556 newLIR3(cUnit, kMipsSw, i+r_A0, storeCnt*4, rBase);
557 storeCnt++;
558 }
559 }
560
561 if (storeCnt) { /* increment after */
562 newLIR3(cUnit, kMipsAddiu, rBase, rBase, storeCnt*4);
563 }
564
565 genBarrier(cUnit);
566 return res; /* NULL always returned which should be ok since no callers use it */
567}
568
buzbee5de34942012-03-01 14:51:57 -0800569LIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
buzbeee3acd072012-02-25 17:03:10 -0800570 int displacement, int rDest, int rDestHi,
571 OpSize size, int sReg)
572/*
573 * Load value from base + displacement. Optionally perform null check
574 * on base (which must have an associated sReg and MIR). If not
575 * performing null check, incoming MIR can be null. IMPORTANT: this
576 * code must not allocate any new temps. If a new register is needed
577 * and base and dest are the same, spill some other register to
578 * rlp and then restore.
579 */
580{
buzbee5de34942012-03-01 14:51:57 -0800581 LIR *res;
582 LIR *load = NULL;
583 LIR *load2 = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800584 MipsOpCode opcode = kMipsNop;
585 bool shortForm = IS_SIMM16(displacement);
586 bool pair = false;
587
588 switch (size) {
589 case kLong:
590 case kDouble:
591 pair = true;
592 opcode = kMipsLw;
593#ifdef __mips_hard_float
594 if (FPREG(rDest)) {
595 opcode = kMipsFlwc1;
596 if (DOUBLEREG(rDest)) {
597 rDest = rDest - FP_DOUBLE;
598 } else {
599 DCHECK(FPREG(rDestHi));
600 DCHECK(rDest == (rDestHi - 1));
601 }
602 rDestHi = rDest + 1;
603 }
604#endif
605 shortForm = IS_SIMM16_2WORD(displacement);
606 DCHECK_EQ((displacement & 0x3), 0);
607 break;
608 case kWord:
609 case kSingle:
610 opcode = kMipsLw;
611#ifdef __mips_hard_float
612 if (FPREG(rDest)) {
613 opcode = kMipsFlwc1;
614 DCHECK(SINGLEREG(rDest));
615 }
616#endif
617 DCHECK_EQ((displacement & 0x3), 0);
618 break;
619 case kUnsignedHalf:
620 opcode = kMipsLhu;
621 DCHECK_EQ((displacement & 0x1), 0);
622 break;
623 case kSignedHalf:
624 opcode = kMipsLh;
625 DCHECK_EQ((displacement & 0x1), 0);
626 break;
627 case kUnsignedByte:
628 opcode = kMipsLbu;
629 break;
630 case kSignedByte:
631 opcode = kMipsLb;
632 break;
633 default:
634 LOG(FATAL) << "Bad case in loadBaseIndexedBody";
635 }
636
637 if (shortForm) {
638 if (!pair) {
639 load = res = newLIR3(cUnit, opcode, rDest, displacement, rBase);
640 } else {
641 load = res = newLIR3(cUnit, opcode, rDest, displacement + LOWORD_OFFSET, rBase);
642 load2 = newLIR3(cUnit, opcode, rDestHi, displacement + HIWORD_OFFSET, rBase);
643 }
644 } else {
645 if (pair) {
646 int rTmp = oatAllocFreeTemp(cUnit);
647 res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
648 load = newLIR3(cUnit, opcode, rDest, LOWORD_OFFSET, rTmp);
649 load2 = newLIR3(cUnit, opcode, rDestHi, HIWORD_OFFSET, rTmp);
650 oatFreeTemp(cUnit, rTmp);
651 } else {
652 int rTmp = (rBase == rDest) ? oatAllocFreeTemp(cUnit)
653 : rDest;
654 res = loadConstant(cUnit, rTmp, displacement);
655 load = newLIR3(cUnit, opcode, rDest, rBase, rTmp);
656 if (rTmp != rDest)
657 oatFreeTemp(cUnit, rTmp);
658 }
659 }
660
661 UNIMPLEMENTED(FATAL) << "Needs art conversion";
662#if 0
663 if (rBase == rFP) {
664 if (load != NULL)
665 annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
666 true /* isLoad */);
667 if (load2 != NULL)
668 annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
669 true /* isLoad */);
670 }
671#endif
672 return load;
673}
674
buzbee5de34942012-03-01 14:51:57 -0800675LIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
buzbeee3acd072012-02-25 17:03:10 -0800676 int displacement, int rDest, OpSize size,
677 int sReg)
678{
679 return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
680 size, sReg);
681}
682
buzbee5de34942012-03-01 14:51:57 -0800683LIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800684 int displacement, int rDestLo, int rDestHi,
buzbeee3acd072012-02-25 17:03:10 -0800685 int sReg)
686{
687 return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
688 kLong, sReg);
689}
690
buzbee5de34942012-03-01 14:51:57 -0800691LIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
buzbeee3acd072012-02-25 17:03:10 -0800692 int displacement, int rSrc, int rSrcHi,
693 OpSize size)
694{
buzbee5de34942012-03-01 14:51:57 -0800695 LIR *res;
696 LIR *store = NULL;
697 LIR *store2 = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800698 MipsOpCode opcode = kMipsNop;
699 bool shortForm = IS_SIMM16(displacement);
700 bool pair = false;
701
702 switch (size) {
703 case kLong:
704 case kDouble:
705 pair = true;
706 opcode = kMipsSw;
707#ifdef __mips_hard_float
708 if (FPREG(rSrc)) {
709 opcode = kMipsFswc1;
710 if (DOUBLEREG(rSrc)) {
711 rSrc = rSrc - FP_DOUBLE;
712 } else {
713 DCHECK(FPREG(rSrcHi));
714 DCHECK_EQ(rSrc, (rSrcHi - 1));
715 }
716 rSrcHi = rSrc + 1;
717 }
718#endif
719 shortForm = IS_SIMM16_2WORD(displacement);
720 DCHECK_EQ((displacement & 0x3), 0);
721 break;
722 case kWord:
723 case kSingle:
724 opcode = kMipsSw;
725#ifdef __mips_hard_float
726 if (FPREG(rSrc)) {
727 opcode = kMipsFswc1;
728 DCHECK(SINGLEREG(rSrc));
729 }
730#endif
731 DCHECK_EQ((displacement & 0x3), 0);
732 break;
733 case kUnsignedHalf:
734 case kSignedHalf:
735 opcode = kMipsSh;
736 DCHECK_EQ((displacement & 0x1), 0);
737 break;
738 case kUnsignedByte:
739 case kSignedByte:
740 opcode = kMipsSb;
741 break;
742 default:
743 LOG(FATAL) << "Bad case in storeBaseIndexedBody";
744 }
745
746 if (shortForm) {
747 if (!pair) {
748 store = res = newLIR3(cUnit, opcode, rSrc, displacement, rBase);
749 } else {
750 store = res = newLIR3(cUnit, opcode, rSrc, displacement + LOWORD_OFFSET, rBase);
751 store2 = newLIR3(cUnit, opcode, rSrcHi, displacement + HIWORD_OFFSET, rBase);
752 }
753 } else {
754 int rScratch = oatAllocTemp(cUnit);
755 res = opRegRegImm(cUnit, kOpAdd, rScratch, rBase, displacement);
756 if (!pair) {
757 store = newLIR3(cUnit, opcode, rSrc, 0, rScratch);
758 } else {
759 store = newLIR3(cUnit, opcode, rSrc, LOWORD_OFFSET, rScratch);
760 store2 = newLIR3(cUnit, opcode, rSrcHi, HIWORD_OFFSET, rScratch);
761 }
762 oatFreeTemp(cUnit, rScratch);
763 }
764
765 UNIMPLEMENTED(FATAL) << "Needs art conversion";
766#if 0
767 if (rBase == rFP) {
768 if (store != NULL)
769 annotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
770 false /* isLoad */);
771 if (store2 != NULL)
772 annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
773 false /* isLoad */);
774 }
775#endif
776
777 return res;
778}
779
buzbee5de34942012-03-01 14:51:57 -0800780LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800781 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800782{
783 return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
784}
785
buzbee5de34942012-03-01 14:51:57 -0800786LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800787 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -0800788{
789 return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
790}
791
buzbee31a4a6f2012-02-28 15:36:15 -0800792void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
buzbeee3acd072012-02-25 17:03:10 -0800793{
794 loadWordDisp(cUnit, base, LOWORD_OFFSET , lowReg);
795 loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg);
796}
797
buzbee5de34942012-03-01 14:51:57 -0800798LIR *genRegImmCheck(CompilationUnit *cUnit,
buzbee31a4a6f2012-02-28 15:36:15 -0800799 MipsConditionCode cond, int reg,
800 int checkValue, int dOffset,
buzbee5de34942012-03-01 14:51:57 -0800801 LIR *pcrLabel)
buzbeee3acd072012-02-25 17:03:10 -0800802{
buzbee5de34942012-03-01 14:51:57 -0800803 LIR *branch = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800804
805 if (checkValue == 0) {
806 MipsOpCode opc = kMipsNop;
807 if (cond == kMipsCondEq) {
808 opc = kMipsBeqz;
809 } else if (cond == kMipsCondNe) {
810 opc = kMipsBnez;
811 } else if (cond == kMipsCondLt || cond == kMipsCondMi) {
812 opc = kMipsBltz;
813 } else if (cond == kMipsCondLe) {
814 opc = kMipsBlez;
815 } else if (cond == kMipsCondGt) {
816 opc = kMipsBgtz;
817 } else if (cond == kMipsCondGe) {
818 opc = kMipsBgez;
819 } else {
820 LOG(FATAL) << "Bad case in genRegImmCheck";
821 }
822 branch = opCompareBranch(cUnit, opc, reg, -1);
823 } else if (IS_SIMM16(checkValue)) {
824 if (cond == kMipsCondLt) {
825 int tReg = oatAllocTemp(cUnit);
826 newLIR3(cUnit, kMipsSlti, tReg, reg, checkValue);
827 branch = opCompareBranch(cUnit, kMipsBne, tReg, r_ZERO);
828 oatFreeTemp(cUnit, tReg);
829 } else {
830 LOG(FATAL) << "Bad case in genRegImmCheck";
831 }
832 } else {
833 LOG(FATAL) << "Bad case in genRegImmCheck";
834 }
835
836 UNIMPLEMENTED(FATAL) << "Needs art conversion";
837 return NULL;
838#if 0
839 if (cUnit->jitMode == kJitMethod) {
840 BasicBlock *bb = cUnit->curBlock;
841 if (bb->taken) {
buzbee5de34942012-03-01 14:51:57 -0800842 LIR *exceptionLabel = (LIR *) cUnit->blockLabelList;
buzbeee3acd072012-02-25 17:03:10 -0800843 exceptionLabel += bb->taken->id;
buzbee5de34942012-03-01 14:51:57 -0800844 branch->target = (LIR *) exceptionLabel;
buzbeee3acd072012-02-25 17:03:10 -0800845 return exceptionLabel;
846 } else {
847 LOG(FATAL) << "Catch blocks not handled yet";
848 return NULL;
849 }
850 } else {
851 return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
852 }
853#endif
854}
855
856} // namespace art