blob: a7faa1d39442dbc1866e84ca407971bccec01f0d [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
buzbeeb046e162012-10-30 15:48:42 -070019/* This file contains codegen for the MIPS32 ISA. */
buzbeee3acd072012-02-25 17:03:10 -080020
buzbee5de34942012-03-01 14:51:57 -080021void genBarrier(CompilationUnit *cUnit);
buzbee31a4a6f2012-02-28 15:36:15 -080022void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
buzbee5de34942012-03-01 14:51:57 -080023LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
buzbee31a4a6f2012-02-28 15:36:15 -080024 int rDest);
buzbee5de34942012-03-01 14:51:57 -080025LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -080026 int displacement, int rSrc);
buzbee5de34942012-03-01 14:51:57 -080027LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
buzbeee3acd072012-02-25 17:03:10 -080028
29#ifdef __mips_hard_float
buzbee5de34942012-03-01 14:51:57 -080030LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -080031{
Bill Buzbeea114add2012-05-03 15:00:40 -070032 int opcode;
33 /* must be both DOUBLE or both not DOUBLE */
buzbeef0504cd2012-11-13 16:31:10 -080034 DCHECK_EQ(MIPS_DOUBLEREG(rDest),MIPS_DOUBLEREG(rSrc));
35 if (MIPS_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070036 opcode = kMipsFmovd;
37 } else {
buzbeef0504cd2012-11-13 16:31:10 -080038 if (MIPS_SINGLEREG(rDest)) {
39 if (MIPS_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070040 opcode = kMipsFmovs;
41 } else {
42 /* note the operands are swapped for the mtc1 instr */
43 int tOpnd = rSrc;
44 rSrc = rDest;
45 rDest = tOpnd;
46 opcode = kMipsMtc1;
47 }
buzbeee3acd072012-02-25 17:03:10 -080048 } else {
buzbeef0504cd2012-11-13 16:31:10 -080049 DCHECK(MIPS_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -070050 opcode = kMipsMfc1;
buzbeee3acd072012-02-25 17:03:10 -080051 }
Bill Buzbeea114add2012-05-03 15:00:40 -070052 }
53 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rSrc, rDest);
54 if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
55 res->flags.isNop = true;
56 }
57 return res;
buzbeee3acd072012-02-25 17:03:10 -080058}
59#endif
60
61/*
62 * Load a immediate using a shortcut if possible; otherwise
63 * grab from the per-translation literal pool. If target is
64 * a high register, build constant into a low register and copy.
65 *
66 * No additional register clobbering operation performed. Use this version when
67 * 1) rDest is freshly returned from oatAllocTemp or
68 * 2) The codegen is under fixed register usage
69 */
Bill Buzbeea114add2012-05-03 15:00:40 -070070LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, int value)
buzbeee3acd072012-02-25 17:03:10 -080071{
Bill Buzbeea114add2012-05-03 15:00:40 -070072 LIR *res;
buzbeee3acd072012-02-25 17:03:10 -080073
74#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -070075 int rDestSave = rDest;
buzbeef0504cd2012-11-13 16:31:10 -080076 int isFpReg = MIPS_FPREG(rDest);
Bill Buzbeea114add2012-05-03 15:00:40 -070077 if (isFpReg) {
buzbeef0504cd2012-11-13 16:31:10 -080078 DCHECK(MIPS_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -070079 rDest = oatAllocTemp(cUnit);
80 }
buzbeee3acd072012-02-25 17:03:10 -080081#endif
82
Bill Buzbeea114add2012-05-03 15:00:40 -070083 /* See if the value can be constructed cheaply */
84 if (value == 0) {
85 res = newLIR2(cUnit, kMipsMove, rDest, r_ZERO);
86 } else if ((value > 0) && (value <= 65535)) {
87 res = newLIR3(cUnit, kMipsOri, rDest, r_ZERO, value);
88 } else if ((value < 0) && (value >= -32768)) {
89 res = newLIR3(cUnit, kMipsAddiu, rDest, r_ZERO, value);
90 } else {
91 res = newLIR2(cUnit, kMipsLui, rDest, value>>16);
92 if (value & 0xffff)
93 newLIR3(cUnit, kMipsOri, rDest, rDest, value);
94 }
buzbeee3acd072012-02-25 17:03:10 -080095
96#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -070097 if (isFpReg) {
98 newLIR2(cUnit, kMipsMtc1, rDest, rDestSave);
99 oatFreeTemp(cUnit, rDest);
100 }
buzbeee3acd072012-02-25 17:03:10 -0800101#endif
102
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 return res;
buzbeee3acd072012-02-25 17:03:10 -0800104}
105
Ian Rogers680b1bd2012-03-07 20:18:49 -0800106LIR *opBranchUnconditional(CompilationUnit *cUnit, OpKind op)
buzbeee3acd072012-02-25 17:03:10 -0800107{
Bill Buzbeea114add2012-05-03 15:00:40 -0700108 DCHECK_EQ(op, kOpUncondBr);
109 return newLIR1(cUnit, kMipsB, 0 /* offset to be patched */ );
buzbeee3acd072012-02-25 17:03:10 -0800110}
111
buzbee5de34942012-03-01 14:51:57 -0800112LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
buzbeee3acd072012-02-25 17:03:10 -0800113
buzbee5de34942012-03-01 14:51:57 -0800114LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
buzbeee3acd072012-02-25 17:03:10 -0800115{
Bill Buzbeea114add2012-05-03 15:00:40 -0700116 MipsOpCode opcode = kMipsNop;
117 switch (op) {
118 case kOpBlx:
119 opcode = kMipsJalr;
120 break;
121 case kOpBx:
122 return newLIR1(cUnit, kMipsJr, rDestSrc);
123 break;
124 default:
125 LOG(FATAL) << "Bad case in opReg";
126 }
127 return newLIR2(cUnit, opcode, r_RA, rDestSrc);
buzbeee3acd072012-02-25 17:03:10 -0800128}
129
buzbee5de34942012-03-01 14:51:57 -0800130LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 int rSrc1, int value);
buzbee5de34942012-03-01 14:51:57 -0800132LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 int value)
buzbeee3acd072012-02-25 17:03:10 -0800134{
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 LIR *res;
136 bool neg = (value < 0);
137 int absValue = (neg) ? -value : value;
138 bool shortForm = (absValue & 0xff) == absValue;
139 MipsOpCode opcode = kMipsNop;
140 switch (op) {
141 case kOpAdd:
142 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
143 break;
144 case kOpSub:
145 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
146 break;
147 default:
148 LOG(FATAL) << "Bad case in opRegImm";
149 break;
150 }
151 if (shortForm)
152 res = newLIR2(cUnit, opcode, rDestSrc1, absValue);
153 else {
154 int rScratch = oatAllocTemp(cUnit);
155 res = loadConstant(cUnit, rScratch, value);
156 if (op == kOpCmp)
157 newLIR2(cUnit, opcode, rDestSrc1, rScratch);
158 else
159 newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rScratch);
160 }
161 return res;
buzbeee3acd072012-02-25 17:03:10 -0800162}
163
buzbee5de34942012-03-01 14:51:57 -0800164LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 int rSrc1, int rSrc2)
buzbeee3acd072012-02-25 17:03:10 -0800166{
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 MipsOpCode opcode = kMipsNop;
168 switch (op) {
169 case kOpAdd:
170 opcode = kMipsAddu;
171 break;
172 case kOpSub:
173 opcode = kMipsSubu;
174 break;
175 case kOpAnd:
176 opcode = kMipsAnd;
177 break;
178 case kOpMul:
179 opcode = kMipsMul;
180 break;
181 case kOpOr:
182 opcode = kMipsOr;
183 break;
184 case kOpXor:
185 opcode = kMipsXor;
186 break;
187 case kOpLsl:
188 opcode = kMipsSllv;
189 break;
190 case kOpLsr:
191 opcode = kMipsSrlv;
192 break;
193 case kOpAsr:
194 opcode = kMipsSrav;
195 break;
196 case kOpAdc:
197 case kOpSbc:
198 LOG(FATAL) << "No carry bit on MIPS";
199 break;
200 default:
201 LOG(FATAL) << "bad case in opRegRegReg";
202 break;
203 }
204 return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800205}
206
buzbee5de34942012-03-01 14:51:57 -0800207LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 int rSrc1, int value)
buzbeee3acd072012-02-25 17:03:10 -0800209{
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 LIR *res;
211 MipsOpCode opcode = kMipsNop;
212 bool shortForm = true;
buzbeee3acd072012-02-25 17:03:10 -0800213
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 switch (op) {
215 case kOpAdd:
216 if (IS_SIMM16(value)) {
217 opcode = kMipsAddiu;
218 }
219 else {
220 shortForm = false;
221 opcode = kMipsAddu;
222 }
223 break;
224 case kOpSub:
225 if (IS_SIMM16((-value))) {
226 value = -value;
227 opcode = kMipsAddiu;
228 }
229 else {
230 shortForm = false;
231 opcode = kMipsSubu;
232 }
233 break;
234 case kOpLsl:
235 DCHECK(value >= 0 && value <= 31);
236 opcode = kMipsSll;
237 break;
238 case kOpLsr:
239 DCHECK(value >= 0 && value <= 31);
240 opcode = kMipsSrl;
241 break;
242 case kOpAsr:
243 DCHECK(value >= 0 && value <= 31);
244 opcode = kMipsSra;
245 break;
246 case kOpAnd:
247 if (IS_UIMM16((value))) {
248 opcode = kMipsAndi;
249 }
250 else {
251 shortForm = false;
252 opcode = kMipsAnd;
253 }
254 break;
255 case kOpOr:
256 if (IS_UIMM16((value))) {
257 opcode = kMipsOri;
258 }
259 else {
260 shortForm = false;
261 opcode = kMipsOr;
262 }
263 break;
264 case kOpXor:
265 if (IS_UIMM16((value))) {
266 opcode = kMipsXori;
267 }
268 else {
269 shortForm = false;
270 opcode = kMipsXor;
271 }
272 break;
273 case kOpMul:
274 shortForm = false;
275 opcode = kMipsMul;
276 break;
277 default:
278 LOG(FATAL) << "Bad case in opRegRegImm";
279 break;
280 }
buzbeee3acd072012-02-25 17:03:10 -0800281
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 if (shortForm)
283 res = newLIR3(cUnit, opcode, rDest, rSrc1, value);
284 else {
285 if (rDest != rSrc1) {
286 res = loadConstant(cUnit, rDest, value);
287 newLIR3(cUnit, opcode, rDest, rSrc1, rDest);
288 } else {
289 int rScratch = oatAllocTemp(cUnit);
290 res = loadConstant(cUnit, rScratch, value);
291 newLIR3(cUnit, opcode, rDest, rSrc1, rScratch);
buzbeee3acd072012-02-25 17:03:10 -0800292 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 }
294 return res;
buzbeee3acd072012-02-25 17:03:10 -0800295}
296
Bill Buzbeea114add2012-05-03 15:00:40 -0700297LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbeee3acd072012-02-25 17:03:10 -0800298{
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 MipsOpCode opcode = kMipsNop;
300 LIR *res;
301 switch (op) {
302 case kOpMov:
303 opcode = kMipsMove;
304 break;
305 case kOpMvn:
306 return newLIR3(cUnit, kMipsNor, rDestSrc1, rSrc2, r_ZERO);
307 case kOpNeg:
308 return newLIR3(cUnit, kMipsSubu, rDestSrc1, r_ZERO, rSrc2);
309 case kOpAdd:
310 case kOpAnd:
311 case kOpMul:
312 case kOpOr:
313 case kOpSub:
314 case kOpXor:
315 return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
316 case kOp2Byte:
buzbeee3acd072012-02-25 17:03:10 -0800317#if __mips_isa_rev>=2
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 res = newLIR2(cUnit, kMipsSeb, rDestSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800319#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700320 res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 24);
321 opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 24);
buzbeee3acd072012-02-25 17:03:10 -0800322#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700323 return res;
324 case kOp2Short:
buzbeee3acd072012-02-25 17:03:10 -0800325#if __mips_isa_rev>=2
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 res = newLIR2(cUnit, kMipsSeh, rDestSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800327#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 16);
329 opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 16);
buzbeee3acd072012-02-25 17:03:10 -0800330#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 return res;
332 case kOp2Char:
333 return newLIR3(cUnit, kMipsAndi, rDestSrc1, rSrc2, 0xFFFF);
334 default:
335 LOG(FATAL) << "Bad case in opRegReg";
336 break;
337 }
338 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
buzbeee3acd072012-02-25 17:03:10 -0800339}
340
buzbee5de34942012-03-01 14:51:57 -0800341LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 int rDestHi, int valLo, int valHi)
buzbeee3acd072012-02-25 17:03:10 -0800343{
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 LIR *res;
345 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
346 loadConstantNoClobber(cUnit, rDestHi, valHi);
347 return res;
buzbeee3acd072012-02-25 17:03:10 -0800348}
349
350/* Load value from base + scaled index. */
buzbee5de34942012-03-01 14:51:57 -0800351LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 int rIndex, int rDest, int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800353{
Bill Buzbeea114add2012-05-03 15:00:40 -0700354 LIR *first = NULL;
355 LIR *res;
356 MipsOpCode opcode = kMipsNop;
357 int tReg = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800358
359#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800360 if (MIPS_FPREG(rDest)) {
361 DCHECK(MIPS_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700362 DCHECK((size == kWord) || (size == kSingle));
363 size = kSingle;
364 } else {
365 if (size == kSingle)
366 size = kWord;
367 }
buzbeee3acd072012-02-25 17:03:10 -0800368#endif
369
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 if (!scale) {
371 first = newLIR3(cUnit, kMipsAddu, tReg , rBase, rIndex);
372 } else {
373 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
374 newLIR3(cUnit, kMipsAddu, tReg , rBase, tReg);
375 }
buzbeee3acd072012-02-25 17:03:10 -0800376
Bill Buzbeea114add2012-05-03 15:00:40 -0700377 switch (size) {
buzbeee3acd072012-02-25 17:03:10 -0800378#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 case kSingle:
380 opcode = kMipsFlwc1;
381 break;
buzbeee3acd072012-02-25 17:03:10 -0800382#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 case kWord:
384 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 }
buzbeee3acd072012-02-25 17:03:10 -0800401
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 res = newLIR3(cUnit, opcode, rDest, 0, tReg);
403 oatFreeTemp(cUnit, tReg);
404 return (first) ? first : res;
buzbeee3acd072012-02-25 17:03:10 -0800405}
406
407/* store value base base + scaled index. */
buzbee5de34942012-03-01 14:51:57 -0800408LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 int rIndex, int rSrc, int scale, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800410{
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 LIR *first = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 MipsOpCode opcode = kMipsNop;
413 int rNewIndex = rIndex;
414 int tReg = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800415
416#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800417 if (MIPS_FPREG(rSrc)) {
418 DCHECK(MIPS_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 DCHECK((size == kWord) || (size == kSingle));
420 size = kSingle;
421 } else {
422 if (size == kSingle)
423 size = kWord;
424 }
buzbeee3acd072012-02-25 17:03:10 -0800425#endif
426
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 if (!scale) {
428 first = newLIR3(cUnit, kMipsAddu, tReg , rBase, rIndex);
429 } else {
430 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
431 newLIR3(cUnit, kMipsAddu, tReg , rBase, tReg);
432 }
buzbeee3acd072012-02-25 17:03:10 -0800433
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 switch (size) {
buzbeee3acd072012-02-25 17:03:10 -0800435#ifdef __mips_hard_float
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 case kSingle:
437 opcode = kMipsFswc1;
438 break;
buzbeee3acd072012-02-25 17:03:10 -0800439#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 case kWord:
441 opcode = kMipsSw;
442 break;
443 case kUnsignedHalf:
444 case kSignedHalf:
445 opcode = kMipsSh;
446 break;
447 case kUnsignedByte:
448 case kSignedByte:
449 opcode = kMipsSb;
450 break;
451 default:
452 LOG(FATAL) << "Bad case in storeBaseIndexed";
453 }
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700454 newLIR3(cUnit, opcode, rSrc, 0, tReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 oatFreeTemp(cUnit, rNewIndex);
456 return first;
buzbeee3acd072012-02-25 17:03:10 -0800457}
458
buzbee5de34942012-03-01 14:51:57 -0800459LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee3acd072012-02-25 17:03:10 -0800460{
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 int i;
462 int loadCnt = 0;
463 LIR *res = NULL ;
464 genBarrier(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800465
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 for (i = 0; i < 8; i++, rMask >>= 1) {
467 if (rMask & 0x1) { /* map r0 to MIPS r_A0 */
468 newLIR3(cUnit, kMipsLw, i+r_A0, loadCnt*4, rBase);
469 loadCnt++;
buzbeee3acd072012-02-25 17:03:10 -0800470 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 }
buzbeee3acd072012-02-25 17:03:10 -0800472
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 if (loadCnt) {/* increment after */
474 newLIR3(cUnit, kMipsAddiu, rBase, rBase, loadCnt*4);
475 }
buzbeee3acd072012-02-25 17:03:10 -0800476
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 genBarrier(cUnit);
478 return res; /* NULL always returned which should be ok since no callers use it */
buzbeee3acd072012-02-25 17:03:10 -0800479}
480
buzbee5de34942012-03-01 14:51:57 -0800481LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee3acd072012-02-25 17:03:10 -0800482{
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 int i;
484 int storeCnt = 0;
485 LIR *res = NULL ;
486 genBarrier(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800487
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 for (i = 0; i < 8; i++, rMask >>= 1) {
489 if (rMask & 0x1) { /* map r0 to MIPS r_A0 */
490 newLIR3(cUnit, kMipsSw, i+r_A0, storeCnt*4, rBase);
491 storeCnt++;
buzbeee3acd072012-02-25 17:03:10 -0800492 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 }
buzbeee3acd072012-02-25 17:03:10 -0800494
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 if (storeCnt) { /* increment after */
496 newLIR3(cUnit, kMipsAddiu, rBase, rBase, storeCnt*4);
497 }
buzbeee3acd072012-02-25 17:03:10 -0800498
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 genBarrier(cUnit);
500 return res; /* NULL always returned which should be ok since no callers use it */
buzbeee3acd072012-02-25 17:03:10 -0800501}
502
buzbee408ad162012-06-06 16:45:18 -0700503LIR *loadBaseDispBody(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 int displacement, int rDest, int rDestHi,
505 OpSize size, int sReg)
buzbeee3acd072012-02-25 17:03:10 -0800506/*
507 * Load value from base + displacement. Optionally perform null check
508 * on base (which must have an associated sReg and MIR). If not
509 * performing null check, incoming MIR can be null. IMPORTANT: this
510 * code must not allocate any new temps. If a new register is needed
511 * and base and dest are the same, spill some other register to
512 * rlp and then restore.
513 */
514{
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 LIR *res;
516 LIR *load = NULL;
517 LIR *load2 = NULL;
518 MipsOpCode opcode = kMipsNop;
519 bool shortForm = IS_SIMM16(displacement);
520 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800521
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 switch (size) {
523 case kLong:
524 case kDouble:
525 pair = true;
526 opcode = kMipsLw;
buzbeee3acd072012-02-25 17:03:10 -0800527#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800528 if (MIPS_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700529 opcode = kMipsFlwc1;
buzbeef0504cd2012-11-13 16:31:10 -0800530 if (MIPS_DOUBLEREG(rDest)) {
531 rDest = rDest - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800532 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800533 DCHECK(MIPS_FPREG(rDestHi));
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 DCHECK(rDest == (rDestHi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800535 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 rDestHi = rDest + 1;
537 }
538#endif
539 shortForm = IS_SIMM16_2WORD(displacement);
540 DCHECK_EQ((displacement & 0x3), 0);
541 break;
542 case kWord:
543 case kSingle:
544 opcode = kMipsLw;
545#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800546 if (MIPS_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 opcode = kMipsFlwc1;
buzbeef0504cd2012-11-13 16:31:10 -0800548 DCHECK(MIPS_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 }
550#endif
551 DCHECK_EQ((displacement & 0x3), 0);
552 break;
553 case kUnsignedHalf:
554 opcode = kMipsLhu;
555 DCHECK_EQ((displacement & 0x1), 0);
556 break;
557 case kSignedHalf:
558 opcode = kMipsLh;
559 DCHECK_EQ((displacement & 0x1), 0);
560 break;
561 case kUnsignedByte:
562 opcode = kMipsLbu;
563 break;
564 case kSignedByte:
565 opcode = kMipsLb;
566 break;
567 default:
568 LOG(FATAL) << "Bad case in loadBaseIndexedBody";
569 }
570
571 if (shortForm) {
572 if (!pair) {
573 load = res = newLIR3(cUnit, opcode, rDest, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800574 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 load = res = newLIR3(cUnit, opcode, rDest,
576 displacement + LOWORD_OFFSET, rBase);
577 load2 = newLIR3(cUnit, opcode, rDestHi,
578 displacement + HIWORD_OFFSET, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800579 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 } else {
581 if (pair) {
582 int rTmp = oatAllocFreeTemp(cUnit);
583 res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
584 load = newLIR3(cUnit, opcode, rDest, LOWORD_OFFSET, rTmp);
585 load2 = newLIR3(cUnit, opcode, rDestHi, HIWORD_OFFSET, rTmp);
586 oatFreeTemp(cUnit, rTmp);
587 } else {
588 int rTmp = (rBase == rDest) ? oatAllocFreeTemp(cUnit) : rDest;
jeffhaofa147e22012-10-12 17:03:32 -0700589 res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
590 load = newLIR3(cUnit, opcode, rDest, 0, rTmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 if (rTmp != rDest)
592 oatFreeTemp(cUnit, rTmp);
593 }
594 }
buzbeee3acd072012-02-25 17:03:10 -0800595
buzbeef0504cd2012-11-13 16:31:10 -0800596 if (rBase == rMIPS_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 annotateDalvikRegAccess(load,
598 (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
599 true /* isLoad */, pair /* is64bit */);
600 if (pair) {
601 annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
602 true /* isLoad */, pair /* is64bit */);
buzbeee3acd072012-02-25 17:03:10 -0800603 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 }
605 return load;
buzbeee3acd072012-02-25 17:03:10 -0800606}
607
buzbee408ad162012-06-06 16:45:18 -0700608LIR *loadBaseDisp(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 int displacement, int rDest, OpSize size, int sReg)
buzbeee3acd072012-02-25 17:03:10 -0800610{
buzbee408ad162012-06-06 16:45:18 -0700611 return loadBaseDispBody(cUnit, rBase, displacement, rDest, -1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 size, sReg);
buzbeee3acd072012-02-25 17:03:10 -0800613}
614
buzbee408ad162012-06-06 16:45:18 -0700615LIR *loadBaseDispWide(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 int displacement, int rDestLo, int rDestHi, int sReg)
buzbeee3acd072012-02-25 17:03:10 -0800617{
buzbee408ad162012-06-06 16:45:18 -0700618 return loadBaseDispBody(cUnit, rBase, displacement, rDestLo, rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700619 kLong, sReg);
buzbeee3acd072012-02-25 17:03:10 -0800620}
621
buzbee5de34942012-03-01 14:51:57 -0800622LIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 int displacement, int rSrc, int rSrcHi, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800624{
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 LIR *res;
626 LIR *store = NULL;
627 LIR *store2 = NULL;
628 MipsOpCode opcode = kMipsNop;
629 bool shortForm = IS_SIMM16(displacement);
630 bool pair = false;
buzbeee3acd072012-02-25 17:03:10 -0800631
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 switch (size) {
633 case kLong:
634 case kDouble:
635 pair = true;
636 opcode = kMipsSw;
buzbeee3acd072012-02-25 17:03:10 -0800637#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800638 if (MIPS_FPREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 opcode = kMipsFswc1;
buzbeef0504cd2012-11-13 16:31:10 -0800640 if (MIPS_DOUBLEREG(rSrc)) {
641 rSrc = rSrc - MIPS_FP_DOUBLE;
buzbeee3acd072012-02-25 17:03:10 -0800642 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800643 DCHECK(MIPS_FPREG(rSrcHi));
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 DCHECK_EQ(rSrc, (rSrcHi - 1));
buzbeee3acd072012-02-25 17:03:10 -0800645 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700646 rSrcHi = rSrc + 1;
647 }
648#endif
649 shortForm = IS_SIMM16_2WORD(displacement);
650 DCHECK_EQ((displacement & 0x3), 0);
651 break;
652 case kWord:
653 case kSingle:
654 opcode = kMipsSw;
655#ifdef __mips_hard_float
buzbeef0504cd2012-11-13 16:31:10 -0800656 if (MIPS_FPREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 opcode = kMipsFswc1;
buzbeef0504cd2012-11-13 16:31:10 -0800658 DCHECK(MIPS_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 }
660#endif
661 DCHECK_EQ((displacement & 0x3), 0);
662 break;
663 case kUnsignedHalf:
664 case kSignedHalf:
665 opcode = kMipsSh;
666 DCHECK_EQ((displacement & 0x1), 0);
667 break;
668 case kUnsignedByte:
669 case kSignedByte:
670 opcode = kMipsSb;
671 break;
672 default:
673 LOG(FATAL) << "Bad case in storeBaseIndexedBody";
674 }
675
676 if (shortForm) {
677 if (!pair) {
678 store = res = newLIR3(cUnit, opcode, rSrc, displacement, rBase);
buzbeee3acd072012-02-25 17:03:10 -0800679 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700680 store = res = newLIR3(cUnit, opcode, rSrc, displacement + LOWORD_OFFSET,
681 rBase);
682 store2 = newLIR3(cUnit, opcode, rSrcHi, displacement + HIWORD_OFFSET,
683 rBase);
buzbeee3acd072012-02-25 17:03:10 -0800684 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700685 } else {
686 int rScratch = oatAllocTemp(cUnit);
687 res = opRegRegImm(cUnit, kOpAdd, rScratch, rBase, displacement);
688 if (!pair) {
689 store = newLIR3(cUnit, opcode, rSrc, 0, rScratch);
690 } else {
691 store = newLIR3(cUnit, opcode, rSrc, LOWORD_OFFSET, rScratch);
692 store2 = newLIR3(cUnit, opcode, rSrcHi, HIWORD_OFFSET, rScratch);
buzbeee3acd072012-02-25 17:03:10 -0800693 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 oatFreeTemp(cUnit, rScratch);
695 }
buzbeee3acd072012-02-25 17:03:10 -0800696
buzbeef0504cd2012-11-13 16:31:10 -0800697 if (rBase == rMIPS_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 annotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0))
699 >> 2, false /* isLoad */, pair /* is64bit */);
700 if (pair) {
701 annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
702 false /* isLoad */, pair /* is64bit */);
703 }
704 }
705
706 return res;
buzbeee3acd072012-02-25 17:03:10 -0800707}
708
buzbee5de34942012-03-01 14:51:57 -0800709LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -0800711{
Bill Buzbeea114add2012-05-03 15:00:40 -0700712 return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
buzbeee3acd072012-02-25 17:03:10 -0800713}
714
buzbee5de34942012-03-01 14:51:57 -0800715LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700716 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -0800717{
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
buzbeee3acd072012-02-25 17:03:10 -0800719}
720
buzbee31a4a6f2012-02-28 15:36:15 -0800721void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
buzbeee3acd072012-02-25 17:03:10 -0800722{
Bill Buzbeea114add2012-05-03 15:00:40 -0700723 loadWordDisp(cUnit, base, LOWORD_OFFSET , lowReg);
724 loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg);
buzbeee3acd072012-02-25 17:03:10 -0800725}
726
buzbeeb046e162012-10-30 15:48:42 -0700727LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
728{
729 LOG(FATAL) << "Unexpected use of opThreadMem for MIPS";
730 return NULL;
731}
732
733LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
734{
735 LOG(FATAL) << "Unexpected use of opMem for MIPS";
736 return NULL;
737}
738
739LIR* storeBaseIndexedDisp(CompilationUnit *cUnit,
740 int rBase, int rIndex, int scale, int displacement,
741 int rSrc, int rSrcHi,
742 OpSize size, int sReg)
743{
744 LOG(FATAL) << "Unexpected use of storeBaseIndexedDisp for MIPS";
745 return NULL;
746}
747
748LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
749 int offset)
750{
751 LOG(FATAL) << "Unexpected use of opRegMem for MIPS";
752 return NULL;
753}
754
755LIR* loadBaseIndexedDisp(CompilationUnit *cUnit,
756 int rBase, int rIndex, int scale, int displacement,
757 int rDest, int rDestHi,
758 OpSize size, int sReg)
759{
760 LOG(FATAL) << "Unexpected use of loadBaseIndexedDisp for MIPS";
761 return NULL;
762}
763
764LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
765{
766 LOG(FATAL) << "Unexpected use of opCondBranch for MIPS";
767 return NULL;
768}
769
buzbeee3acd072012-02-25 17:03:10 -0800770} // namespace art