blob: b810f980c5b3cd743aa92b2b5adad350279e5616 [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
17/*
18 * This file contains codegen for the Mips ISA and is intended to be
19 * includes by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 */
24
Ian Rogers57b86d42012-03-27 16:05:41 -070025#include "oat/runtime/oat_support_entrypoints.h"
26
buzbeee3acd072012-02-25 17:03:10 -080027namespace art {
28
buzbee16da88c2012-03-20 10:38:17 -070029void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
30 SpecialCaseHandler specialCase)
31{
32 // TODO
33}
34
buzbeee3acd072012-02-25 17:03:10 -080035/*
buzbeec5159d52012-03-03 11:48:39 -080036 * The lack of pc-relative loads on Mips presents somewhat of a challenge
37 * for our PIC switch table strategy. To materialize the current location
38 * we'll do a dummy JAL and reference our tables using r_RA as the
39 * base register. Note that r_RA will be used both as the base to
40 * locate the switch table data and as the reference base for the switch
41 * target offsets stored in the table. We'll use a special pseudo-instruction
42 * to represent the jal and trigger the construction of the
43 * switch table offsets (which will happen after final assembly and all
44 * labels are fixed).
buzbeee3acd072012-02-25 17:03:10 -080045 *
46 * The test loop will look something like:
47 *
buzbeec5159d52012-03-03 11:48:39 -080048 * ori rEnd, r_ZERO, #tableSize ; size in bytes
49 * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA
50 * nop ; opportunistically fill
51 * BaseLabel:
52 * addiu rBase, r_RA, <table> - <BaseLabel> ; table relative to BaseLabel
53 addu rEnd, rEnd, rBase ; end of table
54 * lw rVal, [rSP, vRegOff] ; Test Value
55 * loop:
56 * beq rBase, rEnd, done
57 * lw rKey, 0(rBase)
58 * addu rBase, 8
59 * bne rVal, rKey, loop
60 * lw rDisp, -4(rBase)
61 * addu r_RA, rDisp
62 * jr r_RA
63 * done:
64 *
buzbeee3acd072012-02-25 17:03:10 -080065 */
buzbee5de34942012-03-01 14:51:57 -080066void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
buzbeee3acd072012-02-25 17:03:10 -080067{
buzbeee3acd072012-02-25 17:03:10 -080068 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
69 if (cUnit->printMe) {
70 dumpSparseSwitchTable(table);
71 }
72 // Add the table to the list - we'll process it later
73 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
74 true, kAllocData);
75 tabRec->table = table;
76 tabRec->vaddr = mir->offset;
buzbeec5159d52012-03-03 11:48:39 -080077 int elements = table[1];
78 tabRec->targets = (LIR* *)oatNew(cUnit, elements * sizeof(LIR*), true,
buzbee5de34942012-03-01 14:51:57 -080079 kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -080080 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
81
buzbeec5159d52012-03-03 11:48:39 -080082 // The table is composed of 8-byte key/disp pairs
83 int byteSize = elements * 8;
84
85 int sizeHi = byteSize >> 16;
86 int sizeLo = byteSize & 0xffff;
87
88 int rEnd = oatAllocTemp(cUnit);
89 if (sizeHi) {
90 newLIR2(cUnit, kMipsLui, rEnd, sizeHi);
buzbeee3acd072012-02-25 17:03:10 -080091 }
buzbeec5159d52012-03-03 11:48:39 -080092 // Must prevent code motion for the curr pc pair
93 genBarrier(cUnit); // Scheduling barrier
94 newLIR0(cUnit, kMipsCurrPC); // Really a jal to .+8
95 // Now, fill the branch delay slot
96 if (sizeHi) {
97 newLIR3(cUnit, kMipsOri, rEnd, rEnd, sizeLo);
98 } else {
99 newLIR3(cUnit, kMipsOri, rEnd, r_ZERO, sizeLo);
100 }
101 genBarrier(cUnit); // Scheduling barrier
102
103 // Construct BaseLabel and set up table base register
104 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
105 // Remember base label so offsets can be computed later
106 tabRec->anchor = baseLabel;
107 int rBase = oatAllocTemp(cUnit);
108 newLIR4(cUnit, kMipsDelta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
109 opRegRegReg(cUnit, kOpAdd, rEnd, rEnd, rBase);
110
111 // Grab switch test value
112 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
113
114 // Test loop
115 int rKey = oatAllocTemp(cUnit);
116 LIR* loopLabel = newLIR0(cUnit, kPseudoTargetLabel);
117 LIR* exitBranch = opCmpBranch(cUnit , kCondEq, rBase, rEnd, NULL);
118 loadWordDisp(cUnit, rBase, 0, rKey);
119 opRegImm(cUnit, kOpAdd, rBase, 8);
120 opCmpBranch(cUnit, kCondNe, rlSrc.lowReg, rKey, loopLabel);
121 int rDisp = oatAllocTemp(cUnit);
122 loadWordDisp(cUnit, rBase, -4, rDisp);
123 opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp);
124 opReg(cUnit, kOpBx, r_RA);
125
126 // Loop exit
127 LIR* exitLabel = newLIR0(cUnit, kPseudoTargetLabel);
128 exitBranch->target = exitLabel;
buzbeee3acd072012-02-25 17:03:10 -0800129}
130
buzbeec5159d52012-03-03 11:48:39 -0800131/*
132 * Code pattern will look something like:
133 *
134 * lw rVal
135 * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA
136 * nop ; opportunistically fill
137 * [subiu rVal, bias] ; Remove bias if lowVal != 0
138 * bound check -> done
139 * lw rDisp, [r_RA, rVal]
140 * addu r_RA, rDisp
141 * jr r_RA
142 * done:
143 */
buzbee5de34942012-03-01 14:51:57 -0800144void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
buzbeee3acd072012-02-25 17:03:10 -0800145{
buzbeee3acd072012-02-25 17:03:10 -0800146 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
147 if (cUnit->printMe) {
148 dumpPackedSwitchTable(table);
149 }
150 // Add the table to the list - we'll process it later
151 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
152 true, kAllocData);
153 tabRec->table = table;
154 tabRec->vaddr = mir->offset;
155 int size = table[1];
buzbee5de34942012-03-01 14:51:57 -0800156 tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
buzbeee3acd072012-02-25 17:03:10 -0800157 kAllocLIR);
158 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
159
160 // Get the switch value
161 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
buzbeec5159d52012-03-03 11:48:39 -0800162
163 // Prepare the bias. If too big, handle 1st stage here
buzbeee3acd072012-02-25 17:03:10 -0800164 int lowKey = s4FromSwitchData(&table[2]);
buzbeec5159d52012-03-03 11:48:39 -0800165 bool largeBias = false;
166 int rKey;
buzbeee3acd072012-02-25 17:03:10 -0800167 if (lowKey == 0) {
buzbeec5159d52012-03-03 11:48:39 -0800168 rKey = rlSrc.lowReg;
169 } else if ((lowKey & 0xffff) != lowKey) {
170 rKey = oatAllocTemp(cUnit);
171 loadConstant(cUnit, rKey, lowKey);
172 largeBias = true;
buzbeee3acd072012-02-25 17:03:10 -0800173 } else {
buzbeec5159d52012-03-03 11:48:39 -0800174 rKey = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800175 }
buzbeec5159d52012-03-03 11:48:39 -0800176
177 // Must prevent code motion for the curr pc pair
178 genBarrier(cUnit);
179 newLIR0(cUnit, kMipsCurrPC); // Really a jal to .+8
180 // Now, fill the branch delay slot with bias strip
181 if (lowKey == 0) {
182 newLIR0(cUnit, kMipsNop);
183 } else {
184 if (largeBias) {
185 opRegRegReg(cUnit, kOpSub, rKey, rlSrc.lowReg, rKey);
186 } else {
187 opRegRegImm(cUnit, kOpSub, rKey, rlSrc.lowReg, lowKey);
188 }
189 }
190 genBarrier(cUnit); // Scheduling barrier
191
192 // Construct BaseLabel and set up table base register
193 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
194 // Remember base label so offsets can be computed later
195 tabRec->anchor = baseLabel;
196
buzbeee3acd072012-02-25 17:03:10 -0800197 // Bounds check - if < 0 or >= size continue following switch
buzbeec5159d52012-03-03 11:48:39 -0800198 LIR* branchOver = opCmpImmBranch(cUnit, kCondHi, rKey, size-1, NULL);
199
200 // Materialize the table base pointer
201 int rBase = oatAllocTemp(cUnit);
202 newLIR4(cUnit, kMipsDelta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee3acd072012-02-25 17:03:10 -0800203
204 // Load the displacement from the switch table
buzbeec5159d52012-03-03 11:48:39 -0800205 int rDisp = oatAllocTemp(cUnit);
206 loadBaseIndexed(cUnit, rBase, rKey, rDisp, 2, kWord);
buzbeee3acd072012-02-25 17:03:10 -0800207
buzbeec5159d52012-03-03 11:48:39 -0800208 // Add to r_AP and go
209 opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp);
210 opReg(cUnit, kOpBx, r_RA);
buzbeee3acd072012-02-25 17:03:10 -0800211
212 /* branchOver target here */
buzbee5de34942012-03-01 14:51:57 -0800213 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
buzbee5de34942012-03-01 14:51:57 -0800214 branchOver->target = (LIR*)target;
buzbeee3acd072012-02-25 17:03:10 -0800215}
216
217/*
218 * Array data table format:
219 * ushort ident = 0x0300 magic value
220 * ushort width width of each element in the table
221 * uint size number of elements in the table
222 * ubyte data[size*width] table of data values (may contain a single-byte
223 * padding at the end)
224 *
225 * Total size is 4+(width * size + 1)/2 16-bit code units.
226 */
buzbee5de34942012-03-01 14:51:57 -0800227void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
buzbeee3acd072012-02-25 17:03:10 -0800228{
buzbeee3acd072012-02-25 17:03:10 -0800229 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
230 // Add the table to the list - we'll process it later
231 FillArrayData *tabRec = (FillArrayData *)
232 oatNew(cUnit, sizeof(FillArrayData), true, kAllocData);
233 tabRec->table = table;
234 tabRec->vaddr = mir->offset;
235 u2 width = tabRec->table[1];
236 u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
237 tabRec->size = (size * width) + 8;
238
239 oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
240
241 // Making a call - use explicit registers
242 oatFlushAllRegs(cUnit); /* Everything to home location */
buzbeec5159d52012-03-03 11:48:39 -0800243 oatLockCallTemps(cUnit);
buzbee5de34942012-03-01 14:51:57 -0800244 loadValueDirectFixed(cUnit, rlSrc, rARG0);
buzbeec5159d52012-03-03 11:48:39 -0800245
246 // Must prevent code motion for the curr pc pair
247 genBarrier(cUnit);
248 newLIR0(cUnit, kMipsCurrPC); // Really a jal to .+8
249 // Now, fill the branch delay slot with the helper load
Ian Rogers57b86d42012-03-27 16:05:41 -0700250 int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode));
buzbeec5159d52012-03-03 11:48:39 -0800251 genBarrier(cUnit); // Scheduling barrier
252
253 // Construct BaseLabel and set up table base register
254 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
255
buzbeee3acd072012-02-25 17:03:10 -0800256 // Materialize a pointer to the fill data image
buzbeec5159d52012-03-03 11:48:39 -0800257 newLIR4(cUnit, kMipsDelta, rARG1, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
258
259 // And go...
Ian Rogersab2b55d2012-03-18 00:06:11 -0700260 oatClobberCalleeSave(cUnit);
261 opReg(cUnit, kOpBlx, rTgt); // ( array*, fill_data* )
buzbeee3acd072012-02-25 17:03:10 -0800262}
263
buzbee71ac9942012-03-01 17:23:10 -0800264void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
265{
266 RegLocation rlResult;
267 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
268 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
269 opRegRegImm(cUnit, kOpAdd, rlResult.lowReg,
270 rlSrc.lowReg, 0x80000000);
271 storeValue(cUnit, rlDest, rlResult);
272}
273
274void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
275{
276 RegLocation rlResult;
277 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
278 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
279 opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg,
280 0x80000000);
buzbee82488f52012-03-02 08:20:26 -0800281 opRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
buzbee71ac9942012-03-01 17:23:10 -0800282 storeValueWide(cUnit, rlDest, rlResult);
283}
284
buzbee5de34942012-03-01 14:51:57 -0800285/*
286 * TODO: implement fast path to short-circuit thin-lock case
287 */
288void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
buzbeee3acd072012-02-25 17:03:10 -0800289{
buzbee5de34942012-03-01 14:51:57 -0800290 oatFlushAllRegs(cUnit);
291 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
292 oatLockCallTemps(cUnit); // Prepare for explicit register usage
293 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
294 // Go expensive route - artLockObjectFromCode(self, obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700295 int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pLockObjectFromCode));
Ian Rogersab2b55d2012-03-18 00:06:11 -0700296 oatClobberCalleeSave(cUnit);
297 opReg(cUnit, kOpBlx, rTgt);
buzbeee3acd072012-02-25 17:03:10 -0800298}
299
300/*
buzbee5de34942012-03-01 14:51:57 -0800301 * TODO: implement fast path to short-circuit thin-lock case
buzbeee3acd072012-02-25 17:03:10 -0800302 */
buzbee5de34942012-03-01 14:51:57 -0800303void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
buzbeee3acd072012-02-25 17:03:10 -0800304{
buzbee5de34942012-03-01 14:51:57 -0800305 oatFlushAllRegs(cUnit);
306 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
307 oatLockCallTemps(cUnit); // Prepare for explicit register usage
308 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
309 // Go expensive route - UnlockObjectFromCode(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700310 int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pUnlockObjectFromCode));
Ian Rogersab2b55d2012-03-18 00:06:11 -0700311 oatClobberCalleeSave(cUnit);
312 opReg(cUnit, kOpBlx, rTgt);
buzbee5de34942012-03-01 14:51:57 -0800313}
314
315/*
316 * Compare two 64-bit values
317 * x = y return 0
318 * x < y return -1
319 * x > y return 1
320 *
321 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
322 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
323 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
324 * bnez res, finish
325 * sltu t0, x.lo, y.lo
326 * sgtu r1, x.lo, y.lo
327 * subu res, t0, t1
328 * finish:
329 *
330 */
331void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
332 RegLocation rlSrc1, RegLocation rlSrc2)
333{
334 rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
335 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
336 int t0 = oatAllocTemp(cUnit);
337 int t1 = oatAllocTemp(cUnit);
338 RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
339 newLIR3(cUnit, kMipsSlt, t0, rlSrc1.highReg, rlSrc2.highReg);
340 newLIR3(cUnit, kMipsSlt, t1, rlSrc2.highReg, rlSrc1.highReg);
341 newLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0);
buzbee82488f52012-03-02 08:20:26 -0800342 LIR* branch = opCmpImmBranch(cUnit, kCondNe, rlResult.lowReg, 0, NULL);
buzbee5de34942012-03-01 14:51:57 -0800343 newLIR3(cUnit, kMipsSltu, t0, rlSrc1.lowReg, rlSrc2.lowReg);
344 newLIR3(cUnit, kMipsSltu, t1, rlSrc2.lowReg, rlSrc1.lowReg);
345 newLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0);
346 oatFreeTemp(cUnit, t0);
347 oatFreeTemp(cUnit, t1);
348 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
buzbee5de34942012-03-01 14:51:57 -0800349 branch->target = (LIR*)target;
buzbeee3acd072012-02-25 17:03:10 -0800350 storeValue(cUnit, rlDest, rlResult);
351}
352
buzbee82488f52012-03-02 08:20:26 -0800353LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
354 int src2, LIR* target)
buzbeee3acd072012-02-25 17:03:10 -0800355{
buzbee0398c422012-03-02 15:22:47 -0800356 LIR* branch;
357 MipsOpCode sltOp;
358 MipsOpCode brOp;
359 bool cmpZero = false;
360 bool swapped = false;
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700361 switch (cond) {
buzbee0398c422012-03-02 15:22:47 -0800362 case kCondEq:
363 brOp = kMipsBeq;
364 cmpZero = true;
365 break;
366 case kCondNe:
367 brOp = kMipsBne;
368 cmpZero = true;
369 break;
370 case kCondCc:
371 sltOp = kMipsSltu;
372 brOp = kMipsBnez;
373 break;
374 case kCondCs:
375 sltOp = kMipsSltu;
376 brOp = kMipsBeqz;
377 break;
378 case kCondGe:
379 sltOp = kMipsSlt;
380 brOp = kMipsBeqz;
381 break;
382 case kCondGt:
383 sltOp = kMipsSlt;
384 brOp = kMipsBnez;
385 swapped = true;
386 break;
387 case kCondLe:
388 sltOp = kMipsSlt;
389 brOp = kMipsBeqz;
390 swapped = true;
391 break;
392 case kCondLt:
393 sltOp = kMipsSlt;
394 brOp = kMipsBnez;
395 break;
buzbeec5159d52012-03-03 11:48:39 -0800396 case kCondHi: // Gtu
397 sltOp = kMipsSltu;
398 brOp = kMipsBnez;
399 swapped = true;
400 break;
buzbee0398c422012-03-02 15:22:47 -0800401 default:
buzbeea2ebdd72012-03-04 14:57:06 -0800402 LOG(FATAL) << "No support for ConditionCode: " << (int) cond;
buzbee0398c422012-03-02 15:22:47 -0800403 return NULL;
404 }
405 if (cmpZero) {
406 branch = newLIR2(cUnit, brOp, src1, src2);
buzbee82488f52012-03-02 08:20:26 -0800407 } else {
buzbee82488f52012-03-02 08:20:26 -0800408 int tReg = oatAllocTemp(cUnit);
409 if (swapped) {
410 newLIR3(cUnit, sltOp, tReg, src2, src1);
411 } else {
412 newLIR3(cUnit, sltOp, tReg, src1, src2);
413 }
414 branch = newLIR1(cUnit, brOp, tReg);
buzbee0398c422012-03-02 15:22:47 -0800415 oatFreeTemp(cUnit, tReg);
buzbee5de34942012-03-01 14:51:57 -0800416 }
buzbee0398c422012-03-02 15:22:47 -0800417 branch->target = target;
buzbee82488f52012-03-02 08:20:26 -0800418 return branch;
buzbeee3acd072012-02-25 17:03:10 -0800419}
420
buzbee82488f52012-03-02 08:20:26 -0800421LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
422 int checkValue, LIR* target)
buzbeee3acd072012-02-25 17:03:10 -0800423{
buzbee82488f52012-03-02 08:20:26 -0800424 LIR* branch;
buzbee5de34942012-03-01 14:51:57 -0800425 if (checkValue != 0) {
426 // TUNING: handle s16 & kCondLt/Mi case using slti
427 int tReg = oatAllocTemp(cUnit);
428 loadConstant(cUnit, tReg, checkValue);
buzbee82488f52012-03-02 08:20:26 -0800429 branch = opCmpBranch(cUnit, cond, reg, tReg, target);
430 oatFreeTemp(cUnit, tReg);
431 return branch;
buzbee5de34942012-03-01 14:51:57 -0800432 }
433 MipsOpCode opc;
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700434 switch (cond) {
buzbee5de34942012-03-01 14:51:57 -0800435 case kCondEq: opc = kMipsBeqz; break;
436 case kCondGe: opc = kMipsBgez; break;
437 case kCondGt: opc = kMipsBgtz; break;
438 case kCondLe: opc = kMipsBlez; break;
439 //case KCondMi:
440 case kCondLt: opc = kMipsBltz; break;
441 case kCondNe: opc = kMipsBnez; break;
442 default:
buzbee82488f52012-03-02 08:20:26 -0800443 // Tuning: use slti when applicable
buzbeee3acd072012-02-25 17:03:10 -0800444 int tReg = oatAllocTemp(cUnit);
buzbee5de34942012-03-01 14:51:57 -0800445 loadConstant(cUnit, tReg, checkValue);
buzbee82488f52012-03-02 08:20:26 -0800446 branch = opCmpBranch(cUnit, cond, reg, tReg, target);
447 oatFreeTemp(cUnit, tReg);
448 return branch;
buzbeee3acd072012-02-25 17:03:10 -0800449 }
buzbee82488f52012-03-02 08:20:26 -0800450 branch = newLIR1(cUnit, opc, reg);
451 branch->target = target;
452 return branch;
buzbeee3acd072012-02-25 17:03:10 -0800453}
454
buzbee82488f52012-03-02 08:20:26 -0800455LIR* opRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -0800456{
buzbeee3acd072012-02-25 17:03:10 -0800457#ifdef __mips_hard_float
buzbee5de34942012-03-01 14:51:57 -0800458 if (FPREG(rDest) || FPREG(rSrc))
459 return fpRegCopy(cUnit, rDest, rSrc);
460#endif
buzbeea2ebdd72012-03-04 14:57:06 -0800461 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, kMipsMove,
462 rDest, rSrc);
buzbee239c4e72012-03-16 08:42:29 -0700463 if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
buzbee5de34942012-03-01 14:51:57 -0800464 res->flags.isNop = true;
465 }
466 return res;
467}
468
buzbee82488f52012-03-02 08:20:26 -0800469LIR* opRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbee5de34942012-03-01 14:51:57 -0800470{
buzbee82488f52012-03-02 08:20:26 -0800471 LIR *res = opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbee5de34942012-03-01 14:51:57 -0800472 oatAppendLIR(cUnit, (LIR*)res);
473 return res;
474}
475
buzbee82488f52012-03-02 08:20:26 -0800476void opRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
buzbee5de34942012-03-01 14:51:57 -0800477 int srcLo, int srcHi)
478{
479#ifdef __mips_hard_float
480 bool destFP = FPREG(destLo) && FPREG(destHi);
481 bool srcFP = FPREG(srcLo) && FPREG(srcHi);
482 assert(FPREG(srcLo) == FPREG(srcHi));
483 assert(FPREG(destLo) == FPREG(destHi));
484 if (destFP) {
485 if (srcFP) {
buzbee82488f52012-03-02 08:20:26 -0800486 opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
buzbee5de34942012-03-01 14:51:57 -0800487 } else {
488 /* note the operands are swapped for the mtc1 instr */
489 newLIR2(cUnit, kMipsMtc1, srcLo, destLo);
490 newLIR2(cUnit, kMipsMtc1, srcHi, destHi);
491 }
492 } else {
493 if (srcFP) {
494 newLIR2(cUnit, kMipsMfc1, destLo, srcLo);
495 newLIR2(cUnit, kMipsMfc1, destHi, srcHi);
496 } else {
497 // Handle overlap
498 if (srcHi == destLo) {
buzbee82488f52012-03-02 08:20:26 -0800499 opRegCopy(cUnit, destHi, srcHi);
500 opRegCopy(cUnit, destLo, srcLo);
buzbee5de34942012-03-01 14:51:57 -0800501 } else {
buzbee82488f52012-03-02 08:20:26 -0800502 opRegCopy(cUnit, destLo, srcLo);
503 opRegCopy(cUnit, destHi, srcHi);
buzbee5de34942012-03-01 14:51:57 -0800504 }
505 }
506 }
buzbeee3acd072012-02-25 17:03:10 -0800507#else
buzbee5de34942012-03-01 14:51:57 -0800508 // Handle overlap
509 if (srcHi == destLo) {
buzbee82488f52012-03-02 08:20:26 -0800510 opRegCopy(cUnit, destHi, srcHi);
511 opRegCopy(cUnit, destLo, srcLo);
buzbee5de34942012-03-01 14:51:57 -0800512 } else {
buzbee82488f52012-03-02 08:20:26 -0800513 opRegCopy(cUnit, destLo, srcLo);
514 opRegCopy(cUnit, destHi, srcHi);
buzbee5de34942012-03-01 14:51:57 -0800515 }
buzbeee3acd072012-02-25 17:03:10 -0800516#endif
buzbeee3acd072012-02-25 17:03:10 -0800517}
518
519} // namespace art