blob: bb36dc14506b12f66cfa724631908e46090bb1ae [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"
buzbee02031b12012-11-23 09:41:35 -080021#include "codegen_mips.h"
buzbee1bc37c62012-11-20 13:35:41 -080022#include "../codegen_util.h"
23#include "../ralloc_util.h"
buzbeeefc63692012-11-14 16:31:52 -080024
25namespace art {
26
27/*
28 * Compare two 64-bit values
29 * x = y return 0
30 * x < y return -1
31 * x > y return 1
32 *
33 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
34 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
35 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
36 * bnez res, finish
37 * sltu t0, x.lo, y.lo
38 * sgtu r1, x.lo, y.lo
39 * subu res, t0, t1
40 * finish:
41 *
42 */
buzbee02031b12012-11-23 09:41:35 -080043void MipsCodegen::GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1,
44 RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -080045{
buzbeefa57c472012-11-21 12:06:18 -080046 rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
47 rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
48 int t0 = AllocTemp(cu);
49 int t1 = AllocTemp(cu);
50 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
51 NewLIR3(cu, kMipsSlt, t0, rl_src1.high_reg, rl_src2.high_reg);
52 NewLIR3(cu, kMipsSlt, t1, rl_src2.high_reg, rl_src1.high_reg);
53 NewLIR3(cu, kMipsSubu, rl_result.low_reg, t1, t0);
54 LIR* branch = OpCmpImmBranch(cu, kCondNe, rl_result.low_reg, 0, NULL);
55 NewLIR3(cu, kMipsSltu, t0, rl_src1.low_reg, rl_src2.low_reg);
56 NewLIR3(cu, kMipsSltu, t1, rl_src2.low_reg, rl_src1.low_reg);
57 NewLIR3(cu, kMipsSubu, rl_result.low_reg, t1, t0);
58 FreeTemp(cu, t0);
59 FreeTemp(cu, t1);
60 LIR* target = NewLIR0(cu, kPseudoTargetLabel);
buzbeecbd6d442012-11-17 14:11:25 -080061 branch->target = target;
buzbeefa57c472012-11-21 12:06:18 -080062 StoreValue(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -080063}
64
buzbee02031b12012-11-23 09:41:35 -080065LIR* MipsCodegen::OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2,
66 LIR* target)
buzbeeefc63692012-11-14 16:31:52 -080067{
68 LIR* branch;
buzbeefa57c472012-11-21 12:06:18 -080069 MipsOpCode slt_op;
70 MipsOpCode br_op;
71 bool cmp_zero = false;
buzbeeefc63692012-11-14 16:31:52 -080072 bool swapped = false;
73 switch (cond) {
74 case kCondEq:
buzbeefa57c472012-11-21 12:06:18 -080075 br_op = kMipsBeq;
76 cmp_zero = true;
buzbeeefc63692012-11-14 16:31:52 -080077 break;
78 case kCondNe:
buzbeefa57c472012-11-21 12:06:18 -080079 br_op = kMipsBne;
80 cmp_zero = true;
buzbeeefc63692012-11-14 16:31:52 -080081 break;
82 case kCondCc:
buzbeefa57c472012-11-21 12:06:18 -080083 slt_op = kMipsSltu;
84 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -080085 break;
86 case kCondCs:
buzbeefa57c472012-11-21 12:06:18 -080087 slt_op = kMipsSltu;
88 br_op = kMipsBeqz;
buzbeeefc63692012-11-14 16:31:52 -080089 break;
90 case kCondGe:
buzbeefa57c472012-11-21 12:06:18 -080091 slt_op = kMipsSlt;
92 br_op = kMipsBeqz;
buzbeeefc63692012-11-14 16:31:52 -080093 break;
94 case kCondGt:
buzbeefa57c472012-11-21 12:06:18 -080095 slt_op = kMipsSlt;
96 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -080097 swapped = true;
98 break;
99 case kCondLe:
buzbeefa57c472012-11-21 12:06:18 -0800100 slt_op = kMipsSlt;
101 br_op = kMipsBeqz;
buzbeeefc63692012-11-14 16:31:52 -0800102 swapped = true;
103 break;
104 case kCondLt:
buzbeefa57c472012-11-21 12:06:18 -0800105 slt_op = kMipsSlt;
106 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -0800107 break;
108 case kCondHi: // Gtu
buzbeefa57c472012-11-21 12:06:18 -0800109 slt_op = kMipsSltu;
110 br_op = kMipsBnez;
buzbeeefc63692012-11-14 16:31:52 -0800111 swapped = true;
112 break;
113 default:
buzbeecbd6d442012-11-17 14:11:25 -0800114 LOG(FATAL) << "No support for ConditionCode: " << cond;
buzbeeefc63692012-11-14 16:31:52 -0800115 return NULL;
116 }
buzbeefa57c472012-11-21 12:06:18 -0800117 if (cmp_zero) {
118 branch = NewLIR2(cu, br_op, src1, src2);
buzbeeefc63692012-11-14 16:31:52 -0800119 } else {
buzbeefa57c472012-11-21 12:06:18 -0800120 int t_reg = AllocTemp(cu);
buzbeeefc63692012-11-14 16:31:52 -0800121 if (swapped) {
buzbeefa57c472012-11-21 12:06:18 -0800122 NewLIR3(cu, slt_op, t_reg, src2, src1);
buzbeeefc63692012-11-14 16:31:52 -0800123 } else {
buzbeefa57c472012-11-21 12:06:18 -0800124 NewLIR3(cu, slt_op, t_reg, src1, src2);
buzbeeefc63692012-11-14 16:31:52 -0800125 }
buzbeefa57c472012-11-21 12:06:18 -0800126 branch = NewLIR1(cu, br_op, t_reg);
127 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800128 }
129 branch->target = target;
130 return branch;
131}
132
buzbee02031b12012-11-23 09:41:35 -0800133LIR* MipsCodegen::OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg,
134 int check_value, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800135{
136 LIR* branch;
buzbeefa57c472012-11-21 12:06:18 -0800137 if (check_value != 0) {
buzbeeefc63692012-11-14 16:31:52 -0800138 // TUNING: handle s16 & kCondLt/Mi case using slti
buzbeefa57c472012-11-21 12:06:18 -0800139 int t_reg = AllocTemp(cu);
140 LoadConstant(cu, t_reg, check_value);
141 branch = OpCmpBranch(cu, cond, reg, t_reg, target);
142 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800143 return branch;
144 }
145 MipsOpCode opc;
146 switch (cond) {
147 case kCondEq: opc = kMipsBeqz; break;
148 case kCondGe: opc = kMipsBgez; break;
149 case kCondGt: opc = kMipsBgtz; break;
150 case kCondLe: opc = kMipsBlez; break;
151 //case KCondMi:
152 case kCondLt: opc = kMipsBltz; break;
153 case kCondNe: opc = kMipsBnez; break;
154 default:
155 // Tuning: use slti when applicable
buzbeefa57c472012-11-21 12:06:18 -0800156 int t_reg = AllocTemp(cu);
157 LoadConstant(cu, t_reg, check_value);
158 branch = OpCmpBranch(cu, cond, reg, t_reg, target);
159 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800160 return branch;
161 }
buzbeefa57c472012-11-21 12:06:18 -0800162 branch = NewLIR1(cu, opc, reg);
buzbeeefc63692012-11-14 16:31:52 -0800163 branch->target = target;
164 return branch;
165}
166
buzbee02031b12012-11-23 09:41:35 -0800167LIR* MipsCodegen::OpRegCopyNoInsert(CompilationUnit *cu, int r_dest, int r_src)
buzbeeefc63692012-11-14 16:31:52 -0800168{
buzbeefa57c472012-11-21 12:06:18 -0800169 if (MIPS_FPREG(r_dest) || MIPS_FPREG(r_src))
buzbee02031b12012-11-23 09:41:35 -0800170 return OpFpRegCopy(cu, r_dest, r_src);
buzbeefa57c472012-11-21 12:06:18 -0800171 LIR* res = RawLIR(cu, cu->current_dalvik_offset, kMipsMove,
172 r_dest, r_src);
173 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
174 res->flags.is_nop = true;
buzbeeefc63692012-11-14 16:31:52 -0800175 }
176 return res;
177}
178
buzbee02031b12012-11-23 09:41:35 -0800179LIR* MipsCodegen::OpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
buzbeeefc63692012-11-14 16:31:52 -0800180{
buzbeefa57c472012-11-21 12:06:18 -0800181 LIR *res = OpRegCopyNoInsert(cu, r_dest, r_src);
182 AppendLIR(cu, res);
buzbeeefc63692012-11-14 16:31:52 -0800183 return res;
184}
185
buzbee02031b12012-11-23 09:41:35 -0800186void MipsCodegen::OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi, int src_lo,
187 int src_hi)
buzbeeefc63692012-11-14 16:31:52 -0800188{
buzbeefa57c472012-11-21 12:06:18 -0800189 bool dest_fp = MIPS_FPREG(dest_lo) && MIPS_FPREG(dest_hi);
190 bool src_fp = MIPS_FPREG(src_lo) && MIPS_FPREG(src_hi);
191 assert(MIPS_FPREG(src_lo) == MIPS_FPREG(src_hi));
192 assert(MIPS_FPREG(dest_lo) == MIPS_FPREG(dest_hi));
193 if (dest_fp) {
194 if (src_fp) {
195 OpRegCopy(cu, S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
buzbeeefc63692012-11-14 16:31:52 -0800196 } else {
197 /* note the operands are swapped for the mtc1 instr */
buzbeefa57c472012-11-21 12:06:18 -0800198 NewLIR2(cu, kMipsMtc1, src_lo, dest_lo);
199 NewLIR2(cu, kMipsMtc1, src_hi, dest_hi);
buzbeeefc63692012-11-14 16:31:52 -0800200 }
201 } else {
buzbeefa57c472012-11-21 12:06:18 -0800202 if (src_fp) {
203 NewLIR2(cu, kMipsMfc1, dest_lo, src_lo);
204 NewLIR2(cu, kMipsMfc1, dest_hi, src_hi);
buzbeeefc63692012-11-14 16:31:52 -0800205 } else {
206 // Handle overlap
buzbeefa57c472012-11-21 12:06:18 -0800207 if (src_hi == dest_lo) {
208 OpRegCopy(cu, dest_hi, src_hi);
209 OpRegCopy(cu, dest_lo, src_lo);
buzbeeefc63692012-11-14 16:31:52 -0800210 } else {
buzbeefa57c472012-11-21 12:06:18 -0800211 OpRegCopy(cu, dest_lo, src_lo);
212 OpRegCopy(cu, dest_hi, src_hi);
buzbeeefc63692012-11-14 16:31:52 -0800213 }
214 }
215 }
buzbeeefc63692012-11-14 16:31:52 -0800216}
217
buzbee02031b12012-11-23 09:41:35 -0800218void MipsCodegen::GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir)
buzbeeefc63692012-11-14 16:31:52 -0800219{
220 UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch";
221}
222
buzbee02031b12012-11-23 09:41:35 -0800223LIR* MipsCodegen::GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code,
buzbeeefc63692012-11-14 16:31:52 -0800224 int reg1, int base, int offset, ThrowKind kind)
225{
buzbee52a77fc2012-11-20 19:50:46 -0800226 LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
buzbeeefc63692012-11-14 16:31:52 -0800227 return NULL;
228}
229
buzbee02031b12012-11-23 09:41:35 -0800230RegLocation MipsCodegen::GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg1, int reg2,
231 bool is_div)
buzbeeefc63692012-11-14 16:31:52 -0800232{
buzbeefa57c472012-11-21 12:06:18 -0800233 NewLIR4(cu, kMipsDiv, r_HI, r_LO, reg1, reg2);
234 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
235 if (is_div) {
236 NewLIR2(cu, kMipsMflo, rl_result.low_reg, r_LO);
buzbeeefc63692012-11-14 16:31:52 -0800237 } else {
buzbeefa57c472012-11-21 12:06:18 -0800238 NewLIR2(cu, kMipsMfhi, rl_result.low_reg, r_HI);
buzbeeefc63692012-11-14 16:31:52 -0800239 }
buzbeefa57c472012-11-21 12:06:18 -0800240 return rl_result;
buzbeeefc63692012-11-14 16:31:52 -0800241}
242
buzbee02031b12012-11-23 09:41:35 -0800243RegLocation MipsCodegen::GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg1, int lit,
244 bool is_div)
buzbeeefc63692012-11-14 16:31:52 -0800245{
buzbeefa57c472012-11-21 12:06:18 -0800246 int t_reg = AllocTemp(cu);
247 NewLIR3(cu, kMipsAddiu, t_reg, r_ZERO, lit);
248 NewLIR4(cu, kMipsDiv, r_HI, r_LO, reg1, t_reg);
249 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
250 if (is_div) {
251 NewLIR2(cu, kMipsMflo, rl_result.low_reg, r_LO);
buzbeeefc63692012-11-14 16:31:52 -0800252 } else {
buzbeefa57c472012-11-21 12:06:18 -0800253 NewLIR2(cu, kMipsMfhi, rl_result.low_reg, r_HI);
buzbeeefc63692012-11-14 16:31:52 -0800254 }
buzbeefa57c472012-11-21 12:06:18 -0800255 FreeTemp(cu, t_reg);
256 return rl_result;
buzbeeefc63692012-11-14 16:31:52 -0800257}
258
buzbee02031b12012-11-23 09:41:35 -0800259void MipsCodegen::OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800260{
buzbee52a77fc2012-11-20 19:50:46 -0800261 LOG(FATAL) << "Unexpected use of OpLea for Arm";
buzbeeefc63692012-11-14 16:31:52 -0800262}
263
buzbee02031b12012-11-23 09:41:35 -0800264void MipsCodegen::OpTlsCmp(CompilationUnit* cu, int offset, int val)
buzbeeefc63692012-11-14 16:31:52 -0800265{
buzbee52a77fc2012-11-20 19:50:46 -0800266 LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
buzbeeefc63692012-11-14 16:31:52 -0800267}
268
buzbee02031b12012-11-23 09:41:35 -0800269bool MipsCodegen::GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) {
buzbeefa57c472012-11-21 12:06:18 -0800270 DCHECK_NE(cu->instruction_set, kThumb2);
buzbeeefc63692012-11-14 16:31:52 -0800271 return false;
272}
273
buzbee02031b12012-11-23 09:41:35 -0800274bool MipsCodegen::GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) {
buzbeefa57c472012-11-21 12:06:18 -0800275 DCHECK_NE(cu->instruction_set, kThumb2);
buzbeeefc63692012-11-14 16:31:52 -0800276 return false;
277}
278
buzbee02031b12012-11-23 09:41:35 -0800279LIR* MipsCodegen::OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) {
buzbee52a77fc2012-11-20 19:50:46 -0800280 LOG(FATAL) << "Unexpected use of OpPcRelLoad for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800281 return NULL;
282}
283
buzbee02031b12012-11-23 09:41:35 -0800284LIR* MipsCodegen::OpVldm(CompilationUnit* cu, int rBase, int count)
buzbeeefc63692012-11-14 16:31:52 -0800285{
buzbee52a77fc2012-11-20 19:50:46 -0800286 LOG(FATAL) << "Unexpected use of OpVldm for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800287 return NULL;
288}
289
buzbee02031b12012-11-23 09:41:35 -0800290LIR* MipsCodegen::OpVstm(CompilationUnit* cu, int rBase, int count)
buzbeeefc63692012-11-14 16:31:52 -0800291{
buzbee52a77fc2012-11-20 19:50:46 -0800292 LOG(FATAL) << "Unexpected use of OpVstm for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800293 return NULL;
294}
295
buzbee02031b12012-11-23 09:41:35 -0800296void MipsCodegen::GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src,
297 RegLocation rl_result, int lit,
298 int first_bit, int second_bit)
buzbeeefc63692012-11-14 16:31:52 -0800299{
buzbeefa57c472012-11-21 12:06:18 -0800300 int t_reg = AllocTemp(cu);
301 OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit);
302 OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg);
303 FreeTemp(cu, t_reg);
304 if (first_bit != 0) {
305 OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit);
buzbeeefc63692012-11-14 16:31:52 -0800306 }
307}
308
buzbee02031b12012-11-23 09:41:35 -0800309void MipsCodegen::GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi)
buzbeeefc63692012-11-14 16:31:52 -0800310{
buzbeefa57c472012-11-21 12:06:18 -0800311 int t_reg = AllocTemp(cu);
312 OpRegRegReg(cu, kOpOr, t_reg, reg_lo, reg_hi);
313 GenImmedCheck(cu, kCondEq, t_reg, 0, kThrowDivZero);
314 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800315}
316
317// Test suspend flag, return target of taken suspend branch
buzbee02031b12012-11-23 09:41:35 -0800318LIR* MipsCodegen::OpTestSuspend(CompilationUnit* cu, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800319{
buzbeefa57c472012-11-21 12:06:18 -0800320 OpRegImm(cu, kOpSub, rMIPS_SUSPEND, 1);
321 return OpCmpImmBranch(cu, (target == NULL) ? kCondEq : kCondNe, rMIPS_SUSPEND, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800322}
323
324// Decrement register and branch on condition
buzbee02031b12012-11-23 09:41:35 -0800325LIR* MipsCodegen::OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800326{
buzbeefa57c472012-11-21 12:06:18 -0800327 OpRegImm(cu, kOpSub, reg, 1);
328 return OpCmpImmBranch(cu, c_code, reg, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800329}
330
buzbee02031b12012-11-23 09:41:35 -0800331bool MipsCodegen::SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode,
332 RegLocation rl_src, RegLocation rl_dest, int lit)
buzbeeefc63692012-11-14 16:31:52 -0800333{
334 LOG(FATAL) << "Unexpected use of smallLiteralDive in Mips";
335 return false;
336}
337
buzbee02031b12012-11-23 09:41:35 -0800338LIR* MipsCodegen::OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide)
buzbeeefc63692012-11-14 16:31:52 -0800339{
buzbee52a77fc2012-11-20 19:50:46 -0800340 LOG(FATAL) << "Unexpected use of OpIT in Mips";
buzbeeefc63692012-11-14 16:31:52 -0800341 return NULL;
342}
343
buzbee02031b12012-11-23 09:41:35 -0800344bool MipsCodegen::GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1,
345 RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800346{
buzbeefa57c472012-11-21 12:06:18 -0800347 rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
348 rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
349 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800350 /*
351 * [v1 v0] = [a1 a0] + [a3 a2];
352 * addu v0,a2,a0
353 * addu t1,a3,a1
354 * sltu v1,v0,a2
355 * addu v1,v1,t1
356 */
357
buzbeefa57c472012-11-21 12:06:18 -0800358 OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src2.low_reg, rl_src1.low_reg);
359 int t_reg = AllocTemp(cu);
360 OpRegRegReg(cu, kOpAdd, t_reg, rl_src2.high_reg, rl_src1.high_reg);
361 NewLIR3(cu, kMipsSltu, rl_result.high_reg, rl_result.low_reg, rl_src2.low_reg);
362 OpRegRegReg(cu, kOpAdd, rl_result.high_reg, rl_result.high_reg, t_reg);
363 FreeTemp(cu, t_reg);
364 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800365 return false;
366}
367
buzbee02031b12012-11-23 09:41:35 -0800368bool MipsCodegen::GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1,
369 RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800370{
buzbeefa57c472012-11-21 12:06:18 -0800371 rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
372 rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
373 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800374 /*
375 * [v1 v0] = [a1 a0] - [a3 a2];
376 * sltu t1,a0,a2
377 * subu v0,a0,a2
378 * subu v1,a1,a3
379 * subu v1,v1,t1
380 */
381
buzbeefa57c472012-11-21 12:06:18 -0800382 int t_reg = AllocTemp(cu);
383 NewLIR3(cu, kMipsSltu, t_reg, rl_src1.low_reg, rl_src2.low_reg);
384 OpRegRegReg(cu, kOpSub, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
385 OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg);
386 OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg);
387 FreeTemp(cu, t_reg);
388 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800389 return false;
390}
391
buzbee02031b12012-11-23 09:41:35 -0800392bool MipsCodegen::GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800393{
buzbeefa57c472012-11-21 12:06:18 -0800394 rl_src = LoadValueWide(cu, rl_src, kCoreReg);
395 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
buzbeeefc63692012-11-14 16:31:52 -0800396 /*
397 * [v1 v0] = -[a1 a0]
398 * negu v0,a0
399 * negu v1,a1
400 * sltu t1,r_zero
401 * subu v1,v1,t1
402 */
403
buzbeefa57c472012-11-21 12:06:18 -0800404 OpRegReg(cu, kOpNeg, rl_result.low_reg, rl_src.low_reg);
405 OpRegReg(cu, kOpNeg, rl_result.high_reg, rl_src.high_reg);
406 int t_reg = AllocTemp(cu);
407 NewLIR3(cu, kMipsSltu, t_reg, r_ZERO, rl_result.low_reg);
408 OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg);
409 FreeTemp(cu, t_reg);
410 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800411 return false;
412}
413
buzbee02031b12012-11-23 09:41:35 -0800414bool MipsCodegen::GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1,
415 RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800416{
buzbee52a77fc2012-11-20 19:50:46 -0800417 LOG(FATAL) << "Unexpected use of GenAndLong for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800418 return false;
419}
420
buzbee02031b12012-11-23 09:41:35 -0800421bool MipsCodegen::GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1,
422 RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800423{
buzbee52a77fc2012-11-20 19:50:46 -0800424 LOG(FATAL) << "Unexpected use of GenOrLong for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800425 return false;
426}
427
buzbee02031b12012-11-23 09:41:35 -0800428bool MipsCodegen::GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1,
429 RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800430{
buzbee52a77fc2012-11-20 19:50:46 -0800431 LOG(FATAL) << "Unexpected use of GenXorLong for Mips";
buzbeeefc63692012-11-14 16:31:52 -0800432 return false;
433}
434
435} // namespace art