blob: 273e4bd19ffbf6d5c0467cea8bbd368c5c9bc4f3 [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 */
buzbeefa57c472012-11-21 12:06:18 -080042void GenCmpLong(CompilationUnit* cu, RegLocation rl_dest,
43 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -080044{
buzbeefa57c472012-11-21 12:06:18 -080045 rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
46 rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
47 int t0 = AllocTemp(cu);
48 int t1 = AllocTemp(cu);
49 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
50 NewLIR3(cu, kMipsSlt, t0, rl_src1.high_reg, rl_src2.high_reg);
51 NewLIR3(cu, kMipsSlt, t1, rl_src2.high_reg, rl_src1.high_reg);
52 NewLIR3(cu, kMipsSubu, rl_result.low_reg, t1, t0);
53 LIR* branch = OpCmpImmBranch(cu, kCondNe, rl_result.low_reg, 0, NULL);
54 NewLIR3(cu, kMipsSltu, t0, rl_src1.low_reg, rl_src2.low_reg);
55 NewLIR3(cu, kMipsSltu, t1, rl_src2.low_reg, rl_src1.low_reg);
56 NewLIR3(cu, kMipsSubu, rl_result.low_reg, t1, t0);
57 FreeTemp(cu, t0);
58 FreeTemp(cu, t1);
59 LIR* target = NewLIR0(cu, kPseudoTargetLabel);
buzbeecbd6d442012-11-17 14:11:25 -080060 branch->target = target;
buzbeefa57c472012-11-21 12:06:18 -080061 StoreValue(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -080062}
63
buzbeefa57c472012-11-21 12:06:18 -080064LIR* OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1,
buzbeeefc63692012-11-14 16:31:52 -080065 int src2, LIR* target)
66{
67 LIR* branch;
buzbeefa57c472012-11-21 12:06:18 -080068 MipsOpCode slt_op;
69 MipsOpCode br_op;
70 bool cmp_zero = false;
buzbeeefc63692012-11-14 16:31:52 -080071 bool swapped = false;
72 switch (cond) {
73 case kCondEq:
buzbeefa57c472012-11-21 12:06:18 -080074 br_op = kMipsBeq;
75 cmp_zero = true;
buzbeeefc63692012-11-14 16:31:52 -080076 break;
77 case kCondNe:
buzbeefa57c472012-11-21 12:06:18 -080078 br_op = kMipsBne;
79 cmp_zero = true;
buzbeeefc63692012-11-14 16:31:52 -080080 break;
81 case kCondCc:
buzbeefa57c472012-11-21 12:06:18 -080082 slt_op = kMipsSltu;
83 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -080084 break;
85 case kCondCs:
buzbeefa57c472012-11-21 12:06:18 -080086 slt_op = kMipsSltu;
87 br_op = kMipsBeqz;
buzbeeefc63692012-11-14 16:31:52 -080088 break;
89 case kCondGe:
buzbeefa57c472012-11-21 12:06:18 -080090 slt_op = kMipsSlt;
91 br_op = kMipsBeqz;
buzbeeefc63692012-11-14 16:31:52 -080092 break;
93 case kCondGt:
buzbeefa57c472012-11-21 12:06:18 -080094 slt_op = kMipsSlt;
95 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -080096 swapped = true;
97 break;
98 case kCondLe:
buzbeefa57c472012-11-21 12:06:18 -080099 slt_op = kMipsSlt;
100 br_op = kMipsBeqz;
buzbeeefc63692012-11-14 16:31:52 -0800101 swapped = true;
102 break;
103 case kCondLt:
buzbeefa57c472012-11-21 12:06:18 -0800104 slt_op = kMipsSlt;
105 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -0800106 break;
107 case kCondHi: // Gtu
buzbeefa57c472012-11-21 12:06:18 -0800108 slt_op = kMipsSltu;
109 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -0800110 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 }
buzbeefa57c472012-11-21 12:06:18 -0800116 if (cmp_zero) {
117 branch = NewLIR2(cu, br_op, src1, src2);
buzbeeefc63692012-11-14 16:31:52 -0800118 } else {
buzbeefa57c472012-11-21 12:06:18 -0800119 int t_reg = AllocTemp(cu);
buzbeeefc63692012-11-14 16:31:52 -0800120 if (swapped) {
buzbeefa57c472012-11-21 12:06:18 -0800121 NewLIR3(cu, slt_op, t_reg, src2, src1);
buzbeeefc63692012-11-14 16:31:52 -0800122 } else {
buzbeefa57c472012-11-21 12:06:18 -0800123 NewLIR3(cu, slt_op, t_reg, src1, src2);
buzbeeefc63692012-11-14 16:31:52 -0800124 }
buzbeefa57c472012-11-21 12:06:18 -0800125 branch = NewLIR1(cu, br_op, t_reg);
126 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800127 }
128 branch->target = target;
129 return branch;
130}
131
buzbeefa57c472012-11-21 12:06:18 -0800132LIR* OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg,
133 int check_value, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800134{
135 LIR* branch;
buzbeefa57c472012-11-21 12:06:18 -0800136 if (check_value != 0) {
buzbeeefc63692012-11-14 16:31:52 -0800137 // TUNING: handle s16 & kCondLt/Mi case using slti
buzbeefa57c472012-11-21 12:06:18 -0800138 int t_reg = AllocTemp(cu);
139 LoadConstant(cu, t_reg, check_value);
140 branch = OpCmpBranch(cu, cond, reg, t_reg, target);
141 FreeTemp(cu, t_reg);
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
buzbeefa57c472012-11-21 12:06:18 -0800155 int t_reg = AllocTemp(cu);
156 LoadConstant(cu, t_reg, check_value);
157 branch = OpCmpBranch(cu, cond, reg, t_reg, target);
158 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800159 return branch;
160 }
buzbeefa57c472012-11-21 12:06:18 -0800161 branch = NewLIR1(cu, opc, reg);
buzbeeefc63692012-11-14 16:31:52 -0800162 branch->target = target;
163 return branch;
164}
165
buzbeefa57c472012-11-21 12:06:18 -0800166LIR* OpRegCopyNoInsert(CompilationUnit *cu, int r_dest, int r_src)
buzbeeefc63692012-11-14 16:31:52 -0800167{
168#ifdef __mips_hard_float
buzbeefa57c472012-11-21 12:06:18 -0800169 if (MIPS_FPREG(r_dest) || MIPS_FPREG(r_src))
170 return FpRegCopy(cu, r_dest, r_src);
buzbeeefc63692012-11-14 16:31:52 -0800171#endif
buzbeefa57c472012-11-21 12:06:18 -0800172 LIR* res = RawLIR(cu, cu->current_dalvik_offset, kMipsMove,
173 r_dest, r_src);
174 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
175 res->flags.is_nop = true;
buzbeeefc63692012-11-14 16:31:52 -0800176 }
177 return res;
178}
179
buzbeefa57c472012-11-21 12:06:18 -0800180LIR* OpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
buzbeeefc63692012-11-14 16:31:52 -0800181{
buzbeefa57c472012-11-21 12:06:18 -0800182 LIR *res = OpRegCopyNoInsert(cu, r_dest, r_src);
183 AppendLIR(cu, res);
buzbeeefc63692012-11-14 16:31:52 -0800184 return res;
185}
186
buzbeefa57c472012-11-21 12:06:18 -0800187void OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi,
188 int src_lo, int src_hi)
buzbeeefc63692012-11-14 16:31:52 -0800189{
190#ifdef __mips_hard_float
buzbeefa57c472012-11-21 12:06:18 -0800191 bool dest_fp = MIPS_FPREG(dest_lo) && MIPS_FPREG(dest_hi);
192 bool src_fp = MIPS_FPREG(src_lo) && MIPS_FPREG(src_hi);
193 assert(MIPS_FPREG(src_lo) == MIPS_FPREG(src_hi));
194 assert(MIPS_FPREG(dest_lo) == MIPS_FPREG(dest_hi));
195 if (dest_fp) {
196 if (src_fp) {
197 OpRegCopy(cu, S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
buzbeeefc63692012-11-14 16:31:52 -0800198 } else {
199 /* note the operands are swapped for the mtc1 instr */
buzbeefa57c472012-11-21 12:06:18 -0800200 NewLIR2(cu, kMipsMtc1, src_lo, dest_lo);
201 NewLIR2(cu, kMipsMtc1, src_hi, dest_hi);
buzbeeefc63692012-11-14 16:31:52 -0800202 }
203 } else {
buzbeefa57c472012-11-21 12:06:18 -0800204 if (src_fp) {
205 NewLIR2(cu, kMipsMfc1, dest_lo, src_lo);
206 NewLIR2(cu, kMipsMfc1, dest_hi, src_hi);
buzbeeefc63692012-11-14 16:31:52 -0800207 } else {
208 // Handle overlap
buzbeefa57c472012-11-21 12:06:18 -0800209 if (src_hi == dest_lo) {
210 OpRegCopy(cu, dest_hi, src_hi);
211 OpRegCopy(cu, dest_lo, src_lo);
buzbeeefc63692012-11-14 16:31:52 -0800212 } else {
buzbeefa57c472012-11-21 12:06:18 -0800213 OpRegCopy(cu, dest_lo, src_lo);
214 OpRegCopy(cu, dest_hi, src_hi);
buzbeeefc63692012-11-14 16:31:52 -0800215 }
216 }
217 }
218#else
219 // Handle overlap
buzbeefa57c472012-11-21 12:06:18 -0800220 if (src_hi == dest_lo) {
221 OpRegCopy(cu, dest_hi, src_hi);
222 OpRegCopy(cu, dest_lo, src_lo);
buzbeeefc63692012-11-14 16:31:52 -0800223 } else {
buzbeefa57c472012-11-21 12:06:18 -0800224 OpRegCopy(cu, dest_lo, src_lo);
225 OpRegCopy(cu, dest_hi, src_hi);
buzbeeefc63692012-11-14 16:31:52 -0800226 }
227#endif
228}
229
buzbeefa57c472012-11-21 12:06:18 -0800230void GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir)
buzbeeefc63692012-11-14 16:31:52 -0800231{
232 UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch";
233}
234
buzbeefa57c472012-11-21 12:06:18 -0800235LIR* GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code,
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
buzbeefa57c472012-11-21 12:06:18 -0800242RegLocation GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg1, int reg2, bool is_div)
buzbeeefc63692012-11-14 16:31:52 -0800243{
buzbeefa57c472012-11-21 12:06:18 -0800244 NewLIR4(cu, kMipsDiv, r_HI, r_LO, reg1, reg2);
245 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
246 if (is_div) {
247 NewLIR2(cu, kMipsMflo, rl_result.low_reg, r_LO);
buzbeeefc63692012-11-14 16:31:52 -0800248 } else {
buzbeefa57c472012-11-21 12:06:18 -0800249 NewLIR2(cu, kMipsMfhi, rl_result.low_reg, r_HI);
buzbeeefc63692012-11-14 16:31:52 -0800250 }
buzbeefa57c472012-11-21 12:06:18 -0800251 return rl_result;
buzbeeefc63692012-11-14 16:31:52 -0800252}
253
buzbeefa57c472012-11-21 12:06:18 -0800254RegLocation GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg1, int lit, bool is_div)
buzbeeefc63692012-11-14 16:31:52 -0800255{
buzbeefa57c472012-11-21 12:06:18 -0800256 int t_reg = AllocTemp(cu);
257 NewLIR3(cu, kMipsAddiu, t_reg, r_ZERO, lit);
258 NewLIR4(cu, kMipsDiv, r_HI, r_LO, reg1, t_reg);
259 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
260 if (is_div) {
261 NewLIR2(cu, kMipsMflo, rl_result.low_reg, r_LO);
buzbeeefc63692012-11-14 16:31:52 -0800262 } else {
buzbeefa57c472012-11-21 12:06:18 -0800263 NewLIR2(cu, kMipsMfhi, rl_result.low_reg, r_HI);
buzbeeefc63692012-11-14 16:31:52 -0800264 }
buzbeefa57c472012-11-21 12:06:18 -0800265 FreeTemp(cu, t_reg);
266 return rl_result;
buzbeeefc63692012-11-14 16:31:52 -0800267}
268
buzbeefa57c472012-11-21 12:06:18 -0800269void OpLea(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800274void OpTlsCmp(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800279bool GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) {
280 DCHECK_NE(cu->instruction_set, kThumb2);
buzbeeefc63692012-11-14 16:31:52 -0800281 return false;
282}
283
buzbeefa57c472012-11-21 12:06:18 -0800284bool GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) {
285 DCHECK_NE(cu->instruction_set, kThumb2);
buzbeeefc63692012-11-14 16:31:52 -0800286 return false;
287}
288
buzbeefa57c472012-11-21 12:06:18 -0800289LIR* OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) {
buzbee52a77fc2012-11-20 19:50:46 -0800290 LOG(FATAL) << "Unexpected use of OpPcRelLoad for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800291 return NULL;
292}
293
buzbeefa57c472012-11-21 12:06:18 -0800294LIR* OpVldm(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800300LIR* OpVstm(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800306void GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src,
307 RegLocation rl_result, int lit,
308 int first_bit, int second_bit)
buzbeeefc63692012-11-14 16:31:52 -0800309{
buzbeefa57c472012-11-21 12:06:18 -0800310 int t_reg = AllocTemp(cu);
311 OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit);
312 OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg);
313 FreeTemp(cu, t_reg);
314 if (first_bit != 0) {
315 OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit);
buzbeeefc63692012-11-14 16:31:52 -0800316 }
317}
318
buzbeefa57c472012-11-21 12:06:18 -0800319void GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi)
buzbeeefc63692012-11-14 16:31:52 -0800320{
buzbeefa57c472012-11-21 12:06:18 -0800321 int t_reg = AllocTemp(cu);
322 OpRegRegReg(cu, kOpOr, t_reg, reg_lo, reg_hi);
323 GenImmedCheck(cu, kCondEq, t_reg, 0, kThrowDivZero);
324 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800325}
326
327// Test suspend flag, return target of taken suspend branch
buzbeefa57c472012-11-21 12:06:18 -0800328LIR* OpTestSuspend(CompilationUnit* cu, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800329{
buzbeefa57c472012-11-21 12:06:18 -0800330 OpRegImm(cu, kOpSub, rMIPS_SUSPEND, 1);
331 return OpCmpImmBranch(cu, (target == NULL) ? kCondEq : kCondNe, rMIPS_SUSPEND, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800332}
333
334// Decrement register and branch on condition
buzbeefa57c472012-11-21 12:06:18 -0800335LIR* OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800336{
buzbeefa57c472012-11-21 12:06:18 -0800337 OpRegImm(cu, kOpSub, reg, 1);
338 return OpCmpImmBranch(cu, c_code, reg, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800339}
340
buzbeefa57c472012-11-21 12:06:18 -0800341bool SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode,
342 RegLocation rl_src, RegLocation rl_dest, int lit)
buzbeeefc63692012-11-14 16:31:52 -0800343{
344 LOG(FATAL) << "Unexpected use of smallLiteralDive in Mips";
345 return false;
346}
347
buzbeefa57c472012-11-21 12:06:18 -0800348LIR* OpIT(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800354bool GenAddLong(CompilationUnit* cu, RegLocation rl_dest,
355 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800356{
buzbeefa57c472012-11-21 12:06:18 -0800357 rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
358 rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
359 RegLocation rl_result = EvalLoc(cu, rl_dest, 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
buzbeefa57c472012-11-21 12:06:18 -0800368 OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src2.low_reg, rl_src1.low_reg);
369 int t_reg = AllocTemp(cu);
370 OpRegRegReg(cu, kOpAdd, t_reg, rl_src2.high_reg, rl_src1.high_reg);
371 NewLIR3(cu, kMipsSltu, rl_result.high_reg, rl_result.low_reg, rl_src2.low_reg);
372 OpRegRegReg(cu, kOpAdd, rl_result.high_reg, rl_result.high_reg, t_reg);
373 FreeTemp(cu, t_reg);
374 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800375 return false;
376}
377
buzbeefa57c472012-11-21 12:06:18 -0800378bool GenSubLong(CompilationUnit* cu, RegLocation rl_dest,
379 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800380{
buzbeefa57c472012-11-21 12:06:18 -0800381 rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
382 rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
383 RegLocation rl_result = EvalLoc(cu, rl_dest, 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
buzbeefa57c472012-11-21 12:06:18 -0800392 int t_reg = AllocTemp(cu);
393 NewLIR3(cu, kMipsSltu, t_reg, rl_src1.low_reg, rl_src2.low_reg);
394 OpRegRegReg(cu, kOpSub, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
395 OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg);
396 OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg);
397 FreeTemp(cu, t_reg);
398 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800399 return false;
400}
401
buzbeefa57c472012-11-21 12:06:18 -0800402bool GenNegLong(CompilationUnit* cu, RegLocation rl_dest,
403 RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800404{
buzbeefa57c472012-11-21 12:06:18 -0800405 rl_src = LoadValueWide(cu, rl_src, kCoreReg);
406 RegLocation rl_result = EvalLoc(cu, rl_dest, 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
buzbeefa57c472012-11-21 12:06:18 -0800415 OpRegReg(cu, kOpNeg, rl_result.low_reg, rl_src.low_reg);
416 OpRegReg(cu, kOpNeg, rl_result.high_reg, rl_src.high_reg);
417 int t_reg = AllocTemp(cu);
418 NewLIR3(cu, kMipsSltu, t_reg, r_ZERO, rl_result.low_reg);
419 OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg);
420 FreeTemp(cu, t_reg);
421 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800422 return false;
423}
424
buzbeefa57c472012-11-21 12:06:18 -0800425bool GenAndLong(CompilationUnit* cu, RegLocation rl_dest,
426 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800427{
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
buzbeefa57c472012-11-21 12:06:18 -0800432bool GenOrLong(CompilationUnit* cu, RegLocation rl_dest,
433 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800434{
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
buzbeefa57c472012-11-21 12:06:18 -0800439bool GenXorLong(CompilationUnit* cu, RegLocation rl_dest,
440 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800441{
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