blob: 29b08ed844ef67f729b8d4b57574139f0f5943d4 [file] [log] [blame]
buzbeeefc63692012-11-14 16:31:52 -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/* This file contains codegen for the Mips ISA */
18
19#include "oat/runtime/oat_support_entrypoints.h"
buzbee1bc37c62012-11-20 13:35:41 -080020#include "mips_lir.h"
21#include "../codegen_util.h"
22#include "../ralloc_util.h"
buzbeeefc63692012-11-14 16:31:52 -080023
24namespace art {
25
26/*
27 * Compare two 64-bit values
28 * x = y return 0
29 * x < y return -1
30 * x > y return 1
31 *
32 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
33 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
34 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
35 * bnez res, finish
36 * sltu t0, x.lo, y.lo
37 * sgtu r1, x.lo, y.lo
38 * subu res, t0, t1
39 * finish:
40 *
41 */
buzbee52a77fc2012-11-20 19:50:46 -080042void GenCmpLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -080043 RegLocation rlSrc1, RegLocation rlSrc2)
44{
buzbee52a77fc2012-11-20 19:50:46 -080045 rlSrc1 = LoadValueWide(cUnit, rlSrc1, kCoreReg);
46 rlSrc2 = LoadValueWide(cUnit, rlSrc2, kCoreReg);
47 int t0 = AllocTemp(cUnit);
48 int t1 = AllocTemp(cUnit);
49 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
50 NewLIR3(cUnit, kMipsSlt, t0, rlSrc1.highReg, rlSrc2.highReg);
51 NewLIR3(cUnit, kMipsSlt, t1, rlSrc2.highReg, rlSrc1.highReg);
52 NewLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0);
53 LIR* branch = OpCmpImmBranch(cUnit, kCondNe, rlResult.lowReg, 0, NULL);
54 NewLIR3(cUnit, kMipsSltu, t0, rlSrc1.lowReg, rlSrc2.lowReg);
55 NewLIR3(cUnit, kMipsSltu, t1, rlSrc2.lowReg, rlSrc1.lowReg);
56 NewLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0);
57 FreeTemp(cUnit, t0);
58 FreeTemp(cUnit, t1);
59 LIR* target = NewLIR0(cUnit, kPseudoTargetLabel);
buzbeecbd6d442012-11-17 14:11:25 -080060 branch->target = target;
buzbee52a77fc2012-11-20 19:50:46 -080061 StoreValue(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -080062}
63
buzbee52a77fc2012-11-20 19:50:46 -080064LIR* OpCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
buzbeeefc63692012-11-14 16:31:52 -080065 int src2, LIR* target)
66{
67 LIR* branch;
68 MipsOpCode sltOp;
69 MipsOpCode brOp;
70 bool cmpZero = false;
71 bool swapped = false;
72 switch (cond) {
73 case kCondEq:
74 brOp = kMipsBeq;
75 cmpZero = true;
76 break;
77 case kCondNe:
78 brOp = kMipsBne;
79 cmpZero = true;
80 break;
81 case kCondCc:
82 sltOp = kMipsSltu;
83 brOp = kMipsBnez;
84 break;
85 case kCondCs:
86 sltOp = kMipsSltu;
87 brOp = kMipsBeqz;
88 break;
89 case kCondGe:
90 sltOp = kMipsSlt;
91 brOp = kMipsBeqz;
92 break;
93 case kCondGt:
94 sltOp = kMipsSlt;
95 brOp = kMipsBnez;
96 swapped = true;
97 break;
98 case kCondLe:
99 sltOp = kMipsSlt;
100 brOp = kMipsBeqz;
101 swapped = true;
102 break;
103 case kCondLt:
104 sltOp = kMipsSlt;
105 brOp = kMipsBnez;
106 break;
107 case kCondHi: // Gtu
108 sltOp = kMipsSltu;
109 brOp = kMipsBnez;
110 swapped = true;
111 break;
112 default:
buzbeecbd6d442012-11-17 14:11:25 -0800113 LOG(FATAL) << "No support for ConditionCode: " << cond;
buzbeeefc63692012-11-14 16:31:52 -0800114 return NULL;
115 }
116 if (cmpZero) {
buzbee52a77fc2012-11-20 19:50:46 -0800117 branch = NewLIR2(cUnit, brOp, src1, src2);
buzbeeefc63692012-11-14 16:31:52 -0800118 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800119 int tReg = AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800120 if (swapped) {
buzbee52a77fc2012-11-20 19:50:46 -0800121 NewLIR3(cUnit, sltOp, tReg, src2, src1);
buzbeeefc63692012-11-14 16:31:52 -0800122 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800123 NewLIR3(cUnit, sltOp, tReg, src1, src2);
buzbeeefc63692012-11-14 16:31:52 -0800124 }
buzbee52a77fc2012-11-20 19:50:46 -0800125 branch = NewLIR1(cUnit, brOp, tReg);
126 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800127 }
128 branch->target = target;
129 return branch;
130}
131
buzbee52a77fc2012-11-20 19:50:46 -0800132LIR* OpCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
buzbeeefc63692012-11-14 16:31:52 -0800133 int checkValue, LIR* target)
134{
135 LIR* branch;
136 if (checkValue != 0) {
137 // TUNING: handle s16 & kCondLt/Mi case using slti
buzbee52a77fc2012-11-20 19:50:46 -0800138 int tReg = AllocTemp(cUnit);
139 LoadConstant(cUnit, tReg, checkValue);
140 branch = OpCmpBranch(cUnit, cond, reg, tReg, target);
141 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800142 return branch;
143 }
144 MipsOpCode opc;
145 switch (cond) {
146 case kCondEq: opc = kMipsBeqz; break;
147 case kCondGe: opc = kMipsBgez; break;
148 case kCondGt: opc = kMipsBgtz; break;
149 case kCondLe: opc = kMipsBlez; break;
150 //case KCondMi:
151 case kCondLt: opc = kMipsBltz; break;
152 case kCondNe: opc = kMipsBnez; break;
153 default:
154 // Tuning: use slti when applicable
buzbee52a77fc2012-11-20 19:50:46 -0800155 int tReg = AllocTemp(cUnit);
156 LoadConstant(cUnit, tReg, checkValue);
157 branch = OpCmpBranch(cUnit, cond, reg, tReg, target);
158 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800159 return branch;
160 }
buzbee52a77fc2012-11-20 19:50:46 -0800161 branch = NewLIR1(cUnit, opc, reg);
buzbeeefc63692012-11-14 16:31:52 -0800162 branch->target = target;
163 return branch;
164}
165
buzbee52a77fc2012-11-20 19:50:46 -0800166LIR* OpRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeeefc63692012-11-14 16:31:52 -0800167{
168#ifdef __mips_hard_float
169 if (MIPS_FPREG(rDest) || MIPS_FPREG(rSrc))
buzbee52a77fc2012-11-20 19:50:46 -0800170 return FpRegCopy(cUnit, rDest, rSrc);
buzbeeefc63692012-11-14 16:31:52 -0800171#endif
buzbee52a77fc2012-11-20 19:50:46 -0800172 LIR* res = RawLIR(cUnit, cUnit->currentDalvikOffset, kMipsMove,
buzbeeefc63692012-11-14 16:31:52 -0800173 rDest, rSrc);
174 if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
175 res->flags.isNop = true;
176 }
177 return res;
178}
179
buzbee52a77fc2012-11-20 19:50:46 -0800180LIR* OpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeeefc63692012-11-14 16:31:52 -0800181{
buzbee52a77fc2012-11-20 19:50:46 -0800182 LIR *res = OpRegCopyNoInsert(cUnit, rDest, rSrc);
183 AppendLIR(cUnit, res);
buzbeeefc63692012-11-14 16:31:52 -0800184 return res;
185}
186
buzbee52a77fc2012-11-20 19:50:46 -0800187void OpRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
buzbeeefc63692012-11-14 16:31:52 -0800188 int srcLo, int srcHi)
189{
190#ifdef __mips_hard_float
191 bool destFP = MIPS_FPREG(destLo) && MIPS_FPREG(destHi);
192 bool srcFP = MIPS_FPREG(srcLo) && MIPS_FPREG(srcHi);
193 assert(MIPS_FPREG(srcLo) == MIPS_FPREG(srcHi));
194 assert(MIPS_FPREG(destLo) == MIPS_FPREG(destHi));
195 if (destFP) {
196 if (srcFP) {
buzbee52a77fc2012-11-20 19:50:46 -0800197 OpRegCopy(cUnit, S2d(destLo, destHi), S2d(srcLo, srcHi));
buzbeeefc63692012-11-14 16:31:52 -0800198 } else {
199 /* note the operands are swapped for the mtc1 instr */
buzbee52a77fc2012-11-20 19:50:46 -0800200 NewLIR2(cUnit, kMipsMtc1, srcLo, destLo);
201 NewLIR2(cUnit, kMipsMtc1, srcHi, destHi);
buzbeeefc63692012-11-14 16:31:52 -0800202 }
203 } else {
204 if (srcFP) {
buzbee52a77fc2012-11-20 19:50:46 -0800205 NewLIR2(cUnit, kMipsMfc1, destLo, srcLo);
206 NewLIR2(cUnit, kMipsMfc1, destHi, srcHi);
buzbeeefc63692012-11-14 16:31:52 -0800207 } else {
208 // Handle overlap
209 if (srcHi == destLo) {
buzbee52a77fc2012-11-20 19:50:46 -0800210 OpRegCopy(cUnit, destHi, srcHi);
211 OpRegCopy(cUnit, destLo, srcLo);
buzbeeefc63692012-11-14 16:31:52 -0800212 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800213 OpRegCopy(cUnit, destLo, srcLo);
214 OpRegCopy(cUnit, destHi, srcHi);
buzbeeefc63692012-11-14 16:31:52 -0800215 }
216 }
217 }
218#else
219 // Handle overlap
220 if (srcHi == destLo) {
buzbee52a77fc2012-11-20 19:50:46 -0800221 OpRegCopy(cUnit, destHi, srcHi);
222 OpRegCopy(cUnit, destLo, srcLo);
buzbeeefc63692012-11-14 16:31:52 -0800223 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800224 OpRegCopy(cUnit, destLo, srcLo);
225 OpRegCopy(cUnit, destHi, srcHi);
buzbeeefc63692012-11-14 16:31:52 -0800226 }
227#endif
228}
229
buzbee52a77fc2012-11-20 19:50:46 -0800230void GenFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeeefc63692012-11-14 16:31:52 -0800231{
232 UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch";
233}
234
buzbee52a77fc2012-11-20 19:50:46 -0800235LIR* GenRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode,
buzbeeefc63692012-11-14 16:31:52 -0800236 int reg1, int base, int offset, ThrowKind kind)
237{
buzbee52a77fc2012-11-20 19:50:46 -0800238 LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
buzbeeefc63692012-11-14 16:31:52 -0800239 return NULL;
240}
241
buzbee52a77fc2012-11-20 19:50:46 -0800242RegLocation GenDivRem(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int reg2, bool isDiv)
buzbeeefc63692012-11-14 16:31:52 -0800243{
buzbee52a77fc2012-11-20 19:50:46 -0800244 NewLIR4(cUnit, kMipsDiv, r_HI, r_LO, reg1, reg2);
245 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800246 if (isDiv) {
buzbee52a77fc2012-11-20 19:50:46 -0800247 NewLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO);
buzbeeefc63692012-11-14 16:31:52 -0800248 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800249 NewLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI);
buzbeeefc63692012-11-14 16:31:52 -0800250 }
251 return rlResult;
252}
253
buzbee52a77fc2012-11-20 19:50:46 -0800254RegLocation GenDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int lit, bool isDiv)
buzbeeefc63692012-11-14 16:31:52 -0800255{
buzbee52a77fc2012-11-20 19:50:46 -0800256 int tReg = AllocTemp(cUnit);
257 NewLIR3(cUnit, kMipsAddiu, tReg, r_ZERO, lit);
258 NewLIR4(cUnit, kMipsDiv, r_HI, r_LO, reg1, tReg);
259 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800260 if (isDiv) {
buzbee52a77fc2012-11-20 19:50:46 -0800261 NewLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO);
buzbeeefc63692012-11-14 16:31:52 -0800262 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800263 NewLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI);
buzbeeefc63692012-11-14 16:31:52 -0800264 }
buzbee52a77fc2012-11-20 19:50:46 -0800265 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800266 return rlResult;
267}
268
buzbee52a77fc2012-11-20 19:50:46 -0800269void OpLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800270{
buzbee52a77fc2012-11-20 19:50:46 -0800271 LOG(FATAL) << "Unexpected use of OpLea for Arm";
buzbeeefc63692012-11-14 16:31:52 -0800272}
273
buzbee52a77fc2012-11-20 19:50:46 -0800274void OpTlsCmp(CompilationUnit* cUnit, int offset, int val)
buzbeeefc63692012-11-14 16:31:52 -0800275{
buzbee52a77fc2012-11-20 19:50:46 -0800276 LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
buzbeeefc63692012-11-14 16:31:52 -0800277}
278
buzbee52a77fc2012-11-20 19:50:46 -0800279bool GenInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) {
buzbeeefc63692012-11-14 16:31:52 -0800280 DCHECK_NE(cUnit->instructionSet, kThumb2);
281 return false;
282}
283
buzbee52a77fc2012-11-20 19:50:46 -0800284bool GenInlinedSqrt(CompilationUnit* cUnit, CallInfo* info) {
buzbeeefc63692012-11-14 16:31:52 -0800285 DCHECK_NE(cUnit->instructionSet, kThumb2);
286 return false;
287}
288
buzbee52a77fc2012-11-20 19:50:46 -0800289LIR* OpPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target) {
290 LOG(FATAL) << "Unexpected use of OpPcRelLoad for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800291 return NULL;
292}
293
buzbee52a77fc2012-11-20 19:50:46 -0800294LIR* OpVldm(CompilationUnit* cUnit, int rBase, int count)
buzbeeefc63692012-11-14 16:31:52 -0800295{
buzbee52a77fc2012-11-20 19:50:46 -0800296 LOG(FATAL) << "Unexpected use of OpVldm for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800297 return NULL;
298}
299
buzbee52a77fc2012-11-20 19:50:46 -0800300LIR* OpVstm(CompilationUnit* cUnit, int rBase, int count)
buzbeeefc63692012-11-14 16:31:52 -0800301{
buzbee52a77fc2012-11-20 19:50:46 -0800302 LOG(FATAL) << "Unexpected use of OpVstm for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800303 return NULL;
304}
305
buzbee52a77fc2012-11-20 19:50:46 -0800306void GenMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc,
buzbeeefc63692012-11-14 16:31:52 -0800307 RegLocation rlResult, int lit,
308 int firstBit, int secondBit)
309{
buzbee52a77fc2012-11-20 19:50:46 -0800310 int tReg = AllocTemp(cUnit);
311 OpRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, secondBit - firstBit);
312 OpRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, tReg);
313 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800314 if (firstBit != 0) {
buzbee52a77fc2012-11-20 19:50:46 -0800315 OpRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
buzbeeefc63692012-11-14 16:31:52 -0800316 }
317}
318
buzbee52a77fc2012-11-20 19:50:46 -0800319void GenDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi)
buzbeeefc63692012-11-14 16:31:52 -0800320{
buzbee52a77fc2012-11-20 19:50:46 -0800321 int tReg = AllocTemp(cUnit);
322 OpRegRegReg(cUnit, kOpOr, tReg, regLo, regHi);
323 GenImmedCheck(cUnit, kCondEq, tReg, 0, kThrowDivZero);
324 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800325}
326
327// Test suspend flag, return target of taken suspend branch
buzbee52a77fc2012-11-20 19:50:46 -0800328LIR* OpTestSuspend(CompilationUnit* cUnit, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800329{
buzbee52a77fc2012-11-20 19:50:46 -0800330 OpRegImm(cUnit, kOpSub, rMIPS_SUSPEND, 1);
331 return OpCmpImmBranch(cUnit, (target == NULL) ? kCondEq : kCondNe, rMIPS_SUSPEND, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800332}
333
334// Decrement register and branch on condition
buzbee52a77fc2012-11-20 19:50:46 -0800335LIR* OpDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800336{
buzbee52a77fc2012-11-20 19:50:46 -0800337 OpRegImm(cUnit, kOpSub, reg, 1);
338 return OpCmpImmBranch(cUnit, cCode, reg, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800339}
340
buzbee52a77fc2012-11-20 19:50:46 -0800341bool SmallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode,
buzbeeefc63692012-11-14 16:31:52 -0800342 RegLocation rlSrc, RegLocation rlDest, int lit)
343{
344 LOG(FATAL) << "Unexpected use of smallLiteralDive in Mips";
345 return false;
346}
347
buzbee52a77fc2012-11-20 19:50:46 -0800348LIR* OpIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide)
buzbeeefc63692012-11-14 16:31:52 -0800349{
buzbee52a77fc2012-11-20 19:50:46 -0800350 LOG(FATAL) << "Unexpected use of OpIT in Mips";
buzbeeefc63692012-11-14 16:31:52 -0800351 return NULL;
352}
353
buzbee52a77fc2012-11-20 19:50:46 -0800354bool GenAddLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800355 RegLocation rlSrc1, RegLocation rlSrc2)
356{
buzbee52a77fc2012-11-20 19:50:46 -0800357 rlSrc1 = LoadValueWide(cUnit, rlSrc1, kCoreReg);
358 rlSrc2 = LoadValueWide(cUnit, rlSrc2, kCoreReg);
359 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800360 /*
361 * [v1 v0] = [a1 a0] + [a3 a2];
362 * addu v0,a2,a0
363 * addu t1,a3,a1
364 * sltu v1,v0,a2
365 * addu v1,v1,t1
366 */
367
buzbee52a77fc2012-11-20 19:50:46 -0800368 OpRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc2.lowReg, rlSrc1.lowReg);
369 int tReg = AllocTemp(cUnit);
370 OpRegRegReg(cUnit, kOpAdd, tReg, rlSrc2.highReg, rlSrc1.highReg);
371 NewLIR3(cUnit, kMipsSltu, rlResult.highReg, rlResult.lowReg, rlSrc2.lowReg);
372 OpRegRegReg(cUnit, kOpAdd, rlResult.highReg, rlResult.highReg, tReg);
373 FreeTemp(cUnit, tReg);
374 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800375 return false;
376}
377
buzbee52a77fc2012-11-20 19:50:46 -0800378bool GenSubLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800379 RegLocation rlSrc1, RegLocation rlSrc2)
380{
buzbee52a77fc2012-11-20 19:50:46 -0800381 rlSrc1 = LoadValueWide(cUnit, rlSrc1, kCoreReg);
382 rlSrc2 = LoadValueWide(cUnit, rlSrc2, kCoreReg);
383 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800384 /*
385 * [v1 v0] = [a1 a0] - [a3 a2];
386 * sltu t1,a0,a2
387 * subu v0,a0,a2
388 * subu v1,a1,a3
389 * subu v1,v1,t1
390 */
391
buzbee52a77fc2012-11-20 19:50:46 -0800392 int tReg = AllocTemp(cUnit);
393 NewLIR3(cUnit, kMipsSltu, tReg, rlSrc1.lowReg, rlSrc2.lowReg);
394 OpRegRegReg(cUnit, kOpSub, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
395 OpRegRegReg(cUnit, kOpSub, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg);
396 OpRegRegReg(cUnit, kOpSub, rlResult.highReg, rlResult.highReg, tReg);
397 FreeTemp(cUnit, tReg);
398 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800399 return false;
400}
401
buzbee52a77fc2012-11-20 19:50:46 -0800402bool GenNegLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800403 RegLocation rlSrc)
404{
buzbee52a77fc2012-11-20 19:50:46 -0800405 rlSrc = LoadValueWide(cUnit, rlSrc, kCoreReg);
406 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800407 /*
408 * [v1 v0] = -[a1 a0]
409 * negu v0,a0
410 * negu v1,a1
411 * sltu t1,r_zero
412 * subu v1,v1,t1
413 */
414
buzbee52a77fc2012-11-20 19:50:46 -0800415 OpRegReg(cUnit, kOpNeg, rlResult.lowReg, rlSrc.lowReg);
416 OpRegReg(cUnit, kOpNeg, rlResult.highReg, rlSrc.highReg);
417 int tReg = AllocTemp(cUnit);
418 NewLIR3(cUnit, kMipsSltu, tReg, r_ZERO, rlResult.lowReg);
419 OpRegRegReg(cUnit, kOpSub, rlResult.highReg, rlResult.highReg, tReg);
420 FreeTemp(cUnit, tReg);
421 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800422 return false;
423}
424
buzbee52a77fc2012-11-20 19:50:46 -0800425bool GenAndLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800426 RegLocation rlSrc1, RegLocation rlSrc2)
427{
buzbee52a77fc2012-11-20 19:50:46 -0800428 LOG(FATAL) << "Unexpected use of GenAndLong for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800429 return false;
430}
431
buzbee52a77fc2012-11-20 19:50:46 -0800432bool GenOrLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800433 RegLocation rlSrc1, RegLocation rlSrc2)
434{
buzbee52a77fc2012-11-20 19:50:46 -0800435 LOG(FATAL) << "Unexpected use of GenOrLong for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800436 return false;
437}
438
buzbee52a77fc2012-11-20 19:50:46 -0800439bool GenXorLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800440 RegLocation rlSrc1, RegLocation rlSrc2)
441{
buzbee52a77fc2012-11-20 19:50:46 -0800442 LOG(FATAL) << "Unexpected use of GenXorLong for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800443 return false;
444}
445
446} // namespace art