blob: 7a018c5f6c2cb31f3dd2a722f723d170a61a02c5 [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
buzbee1bc37c62012-11-20 13:35:41 -080017#include "mips_lir.h"
18#include "../codegen_util.h"
19#include "../ralloc_util.h"
20
buzbeee3acd072012-02-25 17:03:10 -080021namespace art {
22
buzbeeb046e162012-10-30 15:48:42 -070023/* This file contains codegen for the MIPS32 ISA. */
buzbeee3acd072012-02-25 17:03:10 -080024
buzbee5de34942012-03-01 14:51:57 -080025void genBarrier(CompilationUnit *cUnit);
buzbee31a4a6f2012-02-28 15:36:15 -080026void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
buzbee5de34942012-03-01 14:51:57 -080027LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
buzbee31a4a6f2012-02-28 15:36:15 -080028 int rDest);
buzbee5de34942012-03-01 14:51:57 -080029LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -080030 int displacement, int rSrc);
buzbee5de34942012-03-01 14:51:57 -080031LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
buzbeee3acd072012-02-25 17:03:10 -080032
33#ifdef __mips_hard_float
buzbee5de34942012-03-01 14:51:57 -080034LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -080035{
Bill Buzbeea114add2012-05-03 15:00:40 -070036 int opcode;
37 /* must be both DOUBLE or both not DOUBLE */
buzbeef0504cd2012-11-13 16:31:10 -080038 DCHECK_EQ(MIPS_DOUBLEREG(rDest),MIPS_DOUBLEREG(rSrc));
39 if (MIPS_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070040 opcode = kMipsFmovd;
41 } else {
buzbeef0504cd2012-11-13 16:31:10 -080042 if (MIPS_SINGLEREG(rDest)) {
43 if (MIPS_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070044 opcode = kMipsFmovs;
45 } else {
46 /* note the operands are swapped for the mtc1 instr */
47 int tOpnd = rSrc;
48 rSrc = rDest;
49 rDest = tOpnd;
50 opcode = kMipsMtc1;
51 }
buzbeee3acd072012-02-25 17:03:10 -080052 } else {
buzbeef0504cd2012-11-13 16:31:10 -080053 DCHECK(MIPS_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -070054 opcode = kMipsMfc1;
buzbeee3acd072012-02-25 17:03:10 -080055 }
Bill Buzbeea114add2012-05-03 15:00:40 -070056 }
57 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rSrc, rDest);
58 if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
59 res->flags.isNop = true;
60 }
61 return res;
buzbeee3acd072012-02-25 17:03:10 -080062}
63#endif
64
65/*
66 * Load a immediate using a shortcut if possible; otherwise
67 * grab from the per-translation literal pool. If target is
68 * a high register, build constant into a low register and copy.
69 *
70 * No additional register clobbering operation performed. Use this version when
71 * 1) rDest is freshly returned from oatAllocTemp or
72 * 2) The codegen is under fixed register usage
73 */
Bill Buzbeea114add2012-05-03 15:00:40 -070074LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, int value)
buzbeee3acd072012-02-25 17:03:10 -080075{
Bill Buzbeea114add2012-05-03 15:00:40 -070076 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -080077
78#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -070079 int rDestSave = rDest;
buzbeef0504cd2012-11-13 16:31:10 -080080 int isFpReg = MIPS_FPREG(rDest);
Bill Buzbeea114add2012-05-03 15:00:40 -070081 if (isFpReg) {
buzbeef0504cd2012-11-13 16:31:10 -080082 DCHECK(MIPS_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -070083 rDest = oatAllocTemp(cUnit);
84 }
buzbeee3acd072012-02-25 17:03:10 -080085#endif
86
Bill Buzbeea114add2012-05-03 15:00:40 -070087 /* See if the value can be constructed cheaply */
88 if (value == 0) {
89 res = newLIR2(cUnit, kMipsMove, rDest, r_ZERO);
90 } else if ((value > 0) && (value <= 65535)) {
91 res = newLIR3(cUnit, kMipsOri, rDest, r_ZERO, value);
92 } else if ((value < 0) && (value >= -32768)) {
93 res = newLIR3(cUnit, kMipsAddiu, rDest, r_ZERO, value);
94 } else {
95 res = newLIR2(cUnit, kMipsLui, rDest, value>>16);
96 if (value & 0xffff)
97 newLIR3(cUnit, kMipsOri, rDest, rDest, value);
98 }
buzbeee3acd072012-02-25 17:03:10 -080099
100#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -0700101 if (isFpReg) {
102 newLIR2(cUnit, kMipsMtc1, rDest, rDestSave);
103 oatFreeTemp(cUnit, rDest);
104 }
buzbeee3acd072012-02-25 17:03:10 -0800105#endif
106
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 return res;
buzbeee3acd072012-02-25 17:03:10 -0800108}
109
Ian Rogers680b1bd2012-03-07 20:18:49 -0800110LIR *opBranchUnconditional(CompilationUnit *cUnit, OpKind op)
buzbeee3acd072012-02-25 17:03:10 -0800111{
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 DCHECK_EQ(op, kOpUncondBr);
113 return newLIR1(cUnit, kMipsB, 0 /* offset to be patched */ );
buzbeee3acd072012-02-25 17:03:10 -0800114}
115
buzbee5de34942012-03-01 14:51:57 -0800116LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
buzbeee3acd072012-02-25 17:03:10 -0800117
buzbee5de34942012-03-01 14:51:57 -0800118LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
buzbeee3acd072012-02-25 17:03:10 -0800119{
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 MipsOpCode opcode = kMipsNop;
121 switch (op) {
122 case kOpBlx:
123 opcode = kMipsJalr;
124 break;
125 case kOpBx:
126 return newLIR1(cUnit, kMipsJr, rDestSrc);
127 break;
128 default:
129 LOG(FATAL) << "Bad case in opReg";
130 }
131 return newLIR2(cUnit, opcode, r_RA, rDestSrc);
buzbeee3acd072012-02-25 17:03:10 -0800132}
133
buzbee5de34942012-03-01 14:51:57 -0800134LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 int rSrc1, int value);
buzbee5de34942012-03-01 14:51:57 -0800136LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 int value)
buzbeee3acd072012-02-25 17:03:10 -0800138{
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 LIR *res;
140 bool neg = (value < 0);
141 int absValue = (neg) ? -value : value;
142 bool shortForm = (absValue & 0xff) == absValue;
143 MipsOpCode opcode = kMipsNop;
144 switch (op) {
145 case kOpAdd:
146 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
147 break;
148 case kOpSub:
149 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
150 break;
151 default:
152 LOG(FATAL) << "Bad case in opRegImm";
153 break;
154 }
155 if (shortForm)
156 res = newLIR2(cUnit, opcode, rDestSrc1, absValue);
157 else {
158 int rScratch = oatAllocTemp(cUnit);
159 res = loadConstant(cUnit, rScratch, value);
160 if (op == kOpCmp)
161 newLIR2(cUnit, opcode, rDestSrc1, rScratch);
162 else
163 newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rScratch);
164 }
165 return res;
buzbeee3acd072012-02-25 17:03:10 -0800166}
167
buzbee5de34942012-03-01 14:51:57 -0800168LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700169 int rSrc1, int rSrc2)
buzbeee3acd072012-02-25 17:03:10 -0800170{
Bill Buzbeea114add2012-05-03 15:00:40 -0700171 MipsOpCode opcode = kMipsNop;
172 switch (op) {
173 case kOpAdd:
174 opcode = kMipsAddu;
175 break;
176 case kOpSub:
177 opcode = kMipsSubu;
178 break;
179 case kOpAnd:
180 opcode = kMipsAnd;
181 break;
182 case kOpMul:
183 opcode = kMipsMul;
184 break;
185 case kOpOr:
186 opcode = kMipsOr;
187 break;
188 case kOpXor:
189 opcode = kMipsXor;
190 break;
191 case kOpLsl:
192 opcode = kMipsSllv;
193 break;
194 case kOpLsr:
195 opcode = kMipsSrlv;
196 break;
197 case kOpAsr:
198 opcode = kMipsSrav;
199 break;
200 case kOpAdc:
201 case kOpSbc:
202 LOG(FATAL) << "No carry bit on MIPS";
203 break;
204 default:
205 LOG(FATAL) << "bad case in opRegRegReg";
206 break;
207 }
208 return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800209}
210
buzbee5de34942012-03-01 14:51:57 -0800211LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 int rSrc1, int value)
buzbeee3acd072012-02-25 17:03:10 -0800213{
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 LIR *res;
215 MipsOpCode opcode = kMipsNop;
216 bool shortForm = true;
buzbeee3acd072012-02-25 17:03:10 -0800217
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 switch (op) {
219 case kOpAdd:
220 if (IS_SIMM16(value)) {
221 opcode = kMipsAddiu;
222 }
223 else {
224 shortForm = false;
225 opcode = kMipsAddu;
226 }
227 break;
228 case kOpSub:
229 if (IS_SIMM16((-value))) {
230 value = -value;
231 opcode = kMipsAddiu;
232 }
233 else {
234 shortForm = false;
235 opcode = kMipsSubu;
236 }
237 break;
238 case kOpLsl:
239 DCHECK(value >= 0 && value <= 31);
240 opcode = kMipsSll;
241 break;
242 case kOpLsr:
243 DCHECK(value >= 0 && value <= 31);
244 opcode = kMipsSrl;
245 break;
246 case kOpAsr:
247 DCHECK(value >= 0 && value <= 31);
248 opcode = kMipsSra;
249 break;
250 case kOpAnd:
251 if (IS_UIMM16((value))) {
252 opcode = kMipsAndi;
253 }
254 else {
255 shortForm = false;
256 opcode = kMipsAnd;
257 }
258 break;
259 case kOpOr:
260 if (IS_UIMM16((value))) {
261 opcode = kMipsOri;
262 }
263 else {
264 shortForm = false;
265 opcode = kMipsOr;
266 }
267 break;
268 case kOpXor:
269 if (IS_UIMM16((value))) {
270 opcode = kMipsXori;
271 }
272 else {
273 shortForm = false;
274 opcode = kMipsXor;
275 }
276 break;
277 case kOpMul:
278 shortForm = false;
279 opcode = kMipsMul;
280 break;
281 default:
282 LOG(FATAL) << "Bad case in opRegRegImm";
283 break;
284 }
buzbeee3acd072012-02-25 17:03:10 -0800285
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 if (shortForm)
287 res = newLIR3(cUnit, opcode, rDest, rSrc1, value);
288 else {
289 if (rDest != rSrc1) {
290 res = loadConstant(cUnit, rDest, value);
291 newLIR3(cUnit, opcode, rDest, rSrc1, rDest);
292 } else {
293 int rScratch = oatAllocTemp(cUnit);
294 res = loadConstant(cUnit, rScratch, value);
295 newLIR3(cUnit, opcode, rDest, rSrc1, rScratch);
buzbeee3acd072012-02-25 17:03:10 -0800296 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 }
298 return res;
buzbeee3acd072012-02-25 17:03:10 -0800299}
300
Bill Buzbeea114add2012-05-03 15:00:40 -0700301LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbeee3acd072012-02-25 17:03:10 -0800302{
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 MipsOpCode opcode = kMipsNop;
304 LIR *res;
305 switch (op) {
306 case kOpMov:
307 opcode = kMipsMove;
308 break;
309 case kOpMvn:
310 return newLIR3(cUnit, kMipsNor, rDestSrc1, rSrc2, r_ZERO);
311 case kOpNeg:
312 return newLIR3(cUnit, kMipsSubu, rDestSrc1, r_ZERO, rSrc2);
313 case kOpAdd:
314 case kOpAnd:
315 case kOpMul:
316 case kOpOr:
317 case kOpSub:
318 case kOpXor:
319 return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
320 case kOp2Byte:
buzbeee3acd072012-02-25 17:03:10 -0800321#if __mips_isa_rev>=2
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 res = newLIR2(cUnit, kMipsSeb, rDestSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800323#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 24);
325 opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 24);
buzbeee3acd072012-02-25 17:03:10 -0800326#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 return res;
328 case kOp2Short:
buzbeee3acd072012-02-25 17:03:10 -0800329#if __mips_isa_rev>=2
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 res = newLIR2(cUnit, kMipsSeh, rDestSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800331#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 16);
333 opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 16);
buzbeee3acd072012-02-25 17:03:10 -0800334#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 return res;
336 case kOp2Char:
337 return newLIR3(cUnit, kMipsAndi, rDestSrc1, rSrc2, 0xFFFF);
338 default:
339 LOG(FATAL) << "Bad case in opRegReg";
340 break;
341 }
342 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800343}
344
buzbee5de34942012-03-01 14:51:57 -0800345LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
Bill Buzbeea114add2012-05-03 15:00:40 -0700346 int rDestHi, int valLo, int valHi)
buzbeee3acd072012-02-25 17:03:10 -0800347{
Bill Buzbeea114add2012-05-03 15:00:40 -0700348 LIR *res;
349 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
350 loadConstantNoClobber(cUnit, rDestHi, valHi);
351 return res;
buzbeee3acd072012-02-25 17:03:10 -0800352}
353
354/* Load value from base + scaled index. */
buzbee5de34942012-03-01 14:51:57 -0800355LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 int rIndex, int rDest, int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800357{
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 LIR *first = NULL;
359 LIR *res;
360 MipsOpCode opcode = kMipsNop;
361 int tReg = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800362
363#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800364 if (MIPS_FPREG(rDest)) {
365 DCHECK(MIPS_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700366 DCHECK((size == kWord) || (size == kSingle));
367 size = kSingle;
368 } else {
369 if (size == kSingle)
370 size = kWord;
371 }
buzbeee3acd072012-02-25 17:03:10 -0800372#endif
373
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 if (!scale) {
375 first = newLIR3(cUnit, kMipsAddu, tReg , rBase, rIndex);
376 } else {
377 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
378 newLIR3(cUnit, kMipsAddu, tReg , rBase, tReg);
379 }
buzbeee3acd072012-02-25 17:03:10 -0800380
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 switch (size) {
buzbeee3acd072012-02-25 17:03:10 -0800382#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 case kSingle:
384 opcode = kMipsFlwc1;
385 break;
buzbeee3acd072012-02-25 17:03:10 -0800386#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 case kWord:
388 opcode = kMipsLw;
389 break;
390 case kUnsignedHalf:
391 opcode = kMipsLhu;
392 break;
393 case kSignedHalf:
394 opcode = kMipsLh;
395 break;
396 case kUnsignedByte:
397 opcode = kMipsLbu;
398 break;
399 case kSignedByte:
400 opcode = kMipsLb;
401 break;
402 default:
403 LOG(FATAL) << "Bad case in loadBaseIndexed";
404 }
buzbeee3acd072012-02-25 17:03:10 -0800405
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 res = newLIR3(cUnit, opcode, rDest, 0, tReg);
407 oatFreeTemp(cUnit, tReg);
408 return (first) ? first : res;
buzbeee3acd072012-02-25 17:03:10 -0800409}
410
411/* store value base base + scaled index. */
buzbee5de34942012-03-01 14:51:57 -0800412LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 int rIndex, int rSrc, int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800414{
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 LIR *first = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 MipsOpCode opcode = kMipsNop;
417 int rNewIndex = rIndex;
418 int tReg = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800419
420#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800421 if (MIPS_FPREG(rSrc)) {
422 DCHECK(MIPS_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 DCHECK((size == kWord) || (size == kSingle));
424 size = kSingle;
425 } else {
426 if (size == kSingle)
427 size = kWord;
428 }
buzbeee3acd072012-02-25 17:03:10 -0800429#endif
430
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 if (!scale) {
432 first = newLIR3(cUnit, kMipsAddu, tReg , rBase, rIndex);
433 } else {
434 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
435 newLIR3(cUnit, kMipsAddu, tReg , rBase, tReg);
436 }
buzbeee3acd072012-02-25 17:03:10 -0800437
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 switch (size) {
buzbeee3acd072012-02-25 17:03:10 -0800439#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 case kSingle:
441 opcode = kMipsFswc1;
442 break;
buzbeee3acd072012-02-25 17:03:10 -0800443#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 case kWord:
445 opcode = kMipsSw;
446 break;
447 case kUnsignedHalf:
448 case kSignedHalf:
449 opcode = kMipsSh;
450 break;
451 case kUnsignedByte:
452 case kSignedByte:
453 opcode = kMipsSb;
454 break;
455 default:
456 LOG(FATAL) << "Bad case in storeBaseIndexed";
457 }
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700458 newLIR3(cUnit, opcode, rSrc, 0, tReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 oatFreeTemp(cUnit, rNewIndex);
460 return first;
buzbeee3acd072012-02-25 17:03:10 -0800461}
462
buzbee5de34942012-03-01 14:51:57 -0800463LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee3acd072012-02-25 17:03:10 -0800464{
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 int i;
466 int loadCnt = 0;
467 LIR *res = NULL ;
468 genBarrier(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800469
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 for (i = 0; i < 8; i++, rMask >>= 1) {
471 if (rMask & 0x1) { /* map r0 to MIPS r_A0 */
472 newLIR3(cUnit, kMipsLw, i+r_A0, loadCnt*4, rBase);
473 loadCnt++;
buzbeee3acd072012-02-25 17:03:10 -0800474 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700475 }
buzbeee3acd072012-02-25 17:03:10 -0800476
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 if (loadCnt) {/* increment after */
478 newLIR3(cUnit, kMipsAddiu, rBase, rBase, loadCnt*4);
479 }
buzbeee3acd072012-02-25 17:03:10 -0800480
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 genBarrier(cUnit);
482 return res; /* NULL always returned which should be ok since no callers use it */
buzbeee3acd072012-02-25 17:03:10 -0800483}
484
buzbee5de34942012-03-01 14:51:57 -0800485LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee3acd072012-02-25 17:03:10 -0800486{
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 int i;
488 int storeCnt = 0;
489 LIR *res = NULL ;
490 genBarrier(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800491
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 for (i = 0; i < 8; i++, rMask >>= 1) {
493 if (rMask & 0x1) { /* map r0 to MIPS r_A0 */
494 newLIR3(cUnit, kMipsSw, i+r_A0, storeCnt*4, rBase);
495 storeCnt++;
buzbeee3acd072012-02-25 17:03:10 -0800496 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 }
buzbeee3acd072012-02-25 17:03:10 -0800498
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 if (storeCnt) { /* increment after */
500 newLIR3(cUnit, kMipsAddiu, rBase, rBase, storeCnt*4);
501 }
buzbeee3acd072012-02-25 17:03:10 -0800502
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 genBarrier(cUnit);
504 return res; /* NULL always returned which should be ok since no callers use it */
buzbeee3acd072012-02-25 17:03:10 -0800505}
506
buzbee408ad162012-06-06 16:45:18 -0700507LIR *loadBaseDispBody(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 int displacement, int rDest, int rDestHi,
509 OpSize size, int sReg)
buzbeee3acd072012-02-25 17:03:10 -0800510/*
511 * Load value from base + displacement. Optionally perform null check
512 * on base (which must have an associated sReg and MIR). If not
513 * performing null check, incoming MIR can be null. IMPORTANT: this
514 * code must not allocate any new temps. If a new register is needed
515 * and base and dest are the same, spill some other register to
516 * rlp and then restore.
517 */
518{
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 LIR *res;
520 LIR *load = NULL;
521 LIR *load2 = NULL;
522 MipsOpCode opcode = kMipsNop;
523 bool shortForm = IS_SIMM16(displacement);
524 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800525
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 switch (size) {
527 case kLong:
528 case kDouble:
529 pair = true;
530 opcode = kMipsLw;
buzbeee3acd072012-02-25 17:03:10 -0800531#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800532 if (MIPS_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 opcode = kMipsFlwc1;
buzbeef0504cd2012-11-13 16:31:10 -0800534 if (MIPS_DOUBLEREG(rDest)) {
535 rDest = rDest - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800536 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800537 DCHECK(MIPS_FPREG(rDestHi));
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 DCHECK(rDest == (rDestHi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800539 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 rDestHi = rDest + 1;
541 }
542#endif
543 shortForm = IS_SIMM16_2WORD(displacement);
544 DCHECK_EQ((displacement & 0x3), 0);
545 break;
546 case kWord:
547 case kSingle:
548 opcode = kMipsLw;
549#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800550 if (MIPS_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 opcode = kMipsFlwc1;
buzbeef0504cd2012-11-13 16:31:10 -0800552 DCHECK(MIPS_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 }
554#endif
555 DCHECK_EQ((displacement & 0x3), 0);
556 break;
557 case kUnsignedHalf:
558 opcode = kMipsLhu;
559 DCHECK_EQ((displacement & 0x1), 0);
560 break;
561 case kSignedHalf:
562 opcode = kMipsLh;
563 DCHECK_EQ((displacement & 0x1), 0);
564 break;
565 case kUnsignedByte:
566 opcode = kMipsLbu;
567 break;
568 case kSignedByte:
569 opcode = kMipsLb;
570 break;
571 default:
572 LOG(FATAL) << "Bad case in loadBaseIndexedBody";
573 }
574
575 if (shortForm) {
576 if (!pair) {
577 load = res = newLIR3(cUnit, opcode, rDest, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800578 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 load = res = newLIR3(cUnit, opcode, rDest,
580 displacement + LOWORD_OFFSET, rBase);
581 load2 = newLIR3(cUnit, opcode, rDestHi,
582 displacement + HIWORD_OFFSET, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800583 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700584 } else {
585 if (pair) {
586 int rTmp = oatAllocFreeTemp(cUnit);
587 res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
588 load = newLIR3(cUnit, opcode, rDest, LOWORD_OFFSET, rTmp);
589 load2 = newLIR3(cUnit, opcode, rDestHi, HIWORD_OFFSET, rTmp);
590 oatFreeTemp(cUnit, rTmp);
591 } else {
592 int rTmp = (rBase == rDest) ? oatAllocFreeTemp(cUnit) : rDest;
jeffhaofa147e22012-10-12 17:03:32 -0700593 res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
594 load = newLIR3(cUnit, opcode, rDest, 0, rTmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700595 if (rTmp != rDest)
596 oatFreeTemp(cUnit, rTmp);
597 }
598 }
buzbeee3acd072012-02-25 17:03:10 -0800599
buzbeef0504cd2012-11-13 16:31:10 -0800600 if (rBase == rMIPS_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 annotateDalvikRegAccess(load,
602 (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
603 true /* isLoad */, pair /* is64bit */);
604 if (pair) {
605 annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
606 true /* isLoad */, pair /* is64bit */);
buzbeee3acd072012-02-25 17:03:10 -0800607 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700608 }
609 return load;
buzbeee3acd072012-02-25 17:03:10 -0800610}
611
buzbee408ad162012-06-06 16:45:18 -0700612LIR *loadBaseDisp(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 int displacement, int rDest, OpSize size, int sReg)
buzbeee3acd072012-02-25 17:03:10 -0800614{
buzbee408ad162012-06-06 16:45:18 -0700615 return loadBaseDispBody(cUnit, rBase, displacement, rDest, -1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 size, sReg);
buzbeee3acd072012-02-25 17:03:10 -0800617}
618
buzbee408ad162012-06-06 16:45:18 -0700619LIR *loadBaseDispWide(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 int displacement, int rDestLo, int rDestHi, int sReg)
buzbeee3acd072012-02-25 17:03:10 -0800621{
buzbee408ad162012-06-06 16:45:18 -0700622 return loadBaseDispBody(cUnit, rBase, displacement, rDestLo, rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 kLong, sReg);
buzbeee3acd072012-02-25 17:03:10 -0800624}
625
buzbee5de34942012-03-01 14:51:57 -0800626LIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 int displacement, int rSrc, int rSrcHi, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800628{
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 LIR *res;
630 LIR *store = NULL;
631 LIR *store2 = NULL;
632 MipsOpCode opcode = kMipsNop;
633 bool shortForm = IS_SIMM16(displacement);
634 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800635
Bill Buzbeea114add2012-05-03 15:00:40 -0700636 switch (size) {
637 case kLong:
638 case kDouble:
639 pair = true;
640 opcode = kMipsSw;
buzbeee3acd072012-02-25 17:03:10 -0800641#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800642 if (MIPS_FPREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 opcode = kMipsFswc1;
buzbeef0504cd2012-11-13 16:31:10 -0800644 if (MIPS_DOUBLEREG(rSrc)) {
645 rSrc = rSrc - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800646 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800647 DCHECK(MIPS_FPREG(rSrcHi));
Bill Buzbeea114add2012-05-03 15:00:40 -0700648 DCHECK_EQ(rSrc, (rSrcHi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800649 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 rSrcHi = rSrc + 1;
651 }
652#endif
653 shortForm = IS_SIMM16_2WORD(displacement);
654 DCHECK_EQ((displacement & 0x3), 0);
655 break;
656 case kWord:
657 case kSingle:
658 opcode = kMipsSw;
659#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800660 if (MIPS_FPREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 opcode = kMipsFswc1;
buzbeef0504cd2012-11-13 16:31:10 -0800662 DCHECK(MIPS_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 }
664#endif
665 DCHECK_EQ((displacement & 0x3), 0);
666 break;
667 case kUnsignedHalf:
668 case kSignedHalf:
669 opcode = kMipsSh;
670 DCHECK_EQ((displacement & 0x1), 0);
671 break;
672 case kUnsignedByte:
673 case kSignedByte:
674 opcode = kMipsSb;
675 break;
676 default:
677 LOG(FATAL) << "Bad case in storeBaseIndexedBody";
678 }
679
680 if (shortForm) {
681 if (!pair) {
682 store = res = newLIR3(cUnit, opcode, rSrc, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800683 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 store = res = newLIR3(cUnit, opcode, rSrc, displacement + LOWORD_OFFSET,
685 rBase);
686 store2 = newLIR3(cUnit, opcode, rSrcHi, displacement + HIWORD_OFFSET,
687 rBase);
buzbeee3acd072012-02-25 17:03:10 -0800688 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700689 } else {
690 int rScratch = oatAllocTemp(cUnit);
691 res = opRegRegImm(cUnit, kOpAdd, rScratch, rBase, displacement);
692 if (!pair) {
693 store = newLIR3(cUnit, opcode, rSrc, 0, rScratch);
694 } else {
695 store = newLIR3(cUnit, opcode, rSrc, LOWORD_OFFSET, rScratch);
696 store2 = newLIR3(cUnit, opcode, rSrcHi, HIWORD_OFFSET, rScratch);
buzbeee3acd072012-02-25 17:03:10 -0800697 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 oatFreeTemp(cUnit, rScratch);
699 }
buzbeee3acd072012-02-25 17:03:10 -0800700
buzbeef0504cd2012-11-13 16:31:10 -0800701 if (rBase == rMIPS_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 annotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0))
703 >> 2, false /* isLoad */, pair /* is64bit */);
704 if (pair) {
705 annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
706 false /* isLoad */, pair /* is64bit */);
707 }
708 }
709
710 return res;
buzbeee3acd072012-02-25 17:03:10 -0800711}
712
buzbee5de34942012-03-01 14:51:57 -0800713LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700714 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800715{
Bill Buzbeea114add2012-05-03 15:00:40 -0700716 return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
buzbeee3acd072012-02-25 17:03:10 -0800717}
718
buzbee5de34942012-03-01 14:51:57 -0800719LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -0800721{
Bill Buzbeea114add2012-05-03 15:00:40 -0700722 return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
buzbeee3acd072012-02-25 17:03:10 -0800723}
724
buzbee31a4a6f2012-02-28 15:36:15 -0800725void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
buzbeee3acd072012-02-25 17:03:10 -0800726{
Bill Buzbeea114add2012-05-03 15:00:40 -0700727 loadWordDisp(cUnit, base, LOWORD_OFFSET , lowReg);
728 loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg);
buzbeee3acd072012-02-25 17:03:10 -0800729}
730
buzbeeb046e162012-10-30 15:48:42 -0700731LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
732{
733 LOG(FATAL) << "Unexpected use of opThreadMem for MIPS";
734 return NULL;
735}
736
737LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
738{
739 LOG(FATAL) << "Unexpected use of opMem for MIPS";
740 return NULL;
741}
742
743LIR* storeBaseIndexedDisp(CompilationUnit *cUnit,
744 int rBase, int rIndex, int scale, int displacement,
745 int rSrc, int rSrcHi,
746 OpSize size, int sReg)
747{
748 LOG(FATAL) << "Unexpected use of storeBaseIndexedDisp for MIPS";
749 return NULL;
750}
751
752LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
753 int offset)
754{
755 LOG(FATAL) << "Unexpected use of opRegMem for MIPS";
756 return NULL;
757}
758
759LIR* loadBaseIndexedDisp(CompilationUnit *cUnit,
760 int rBase, int rIndex, int scale, int displacement,
761 int rDest, int rDestHi,
762 OpSize size, int sReg)
763{
764 LOG(FATAL) << "Unexpected use of loadBaseIndexedDisp for MIPS";
765 return NULL;
766}
767
768LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
769{
770 LOG(FATAL) << "Unexpected use of opCondBranch for MIPS";
771 return NULL;
772}
773
buzbeee3acd072012-02-25 17:03:10 -0800774} // namespace art