blob: c501bc32e99a54606c9793803957e1b7565c488f [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 X86 ISA */
18
buzbee1bc37c62012-11-20 13:35:41 -080019#include "x86_lir.h"
20#include "../codegen_util.h"
21#include "../ralloc_util.h"
22
buzbeeefc63692012-11-14 16:31:52 -080023namespace art {
24
25/*
26 * Perform register memory operation.
27 */
buzbee52a77fc2012-11-20 19:50:46 -080028LIR* GenRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode,
buzbeeefc63692012-11-14 16:31:52 -080029 int reg1, int base, int offset, ThrowKind kind)
30{
buzbee52a77fc2012-11-20 19:50:46 -080031 LIR* tgt = RawLIR(cUnit, 0, kPseudoThrowTarget, kind,
buzbeeefc63692012-11-14 16:31:52 -080032 cUnit->currentDalvikOffset, reg1, base, offset);
buzbee52a77fc2012-11-20 19:50:46 -080033 OpRegMem(cUnit, kOpCmp, reg1, base, offset);
34 LIR* branch = OpCondBranch(cUnit, cCode, tgt);
buzbeeefc63692012-11-14 16:31:52 -080035 // Remember branch target - will process later
buzbee52a77fc2012-11-20 19:50:46 -080036 InsertGrowableList(cUnit, &cUnit->throwLaunchpads, reinterpret_cast<uintptr_t>(tgt));
buzbeeefc63692012-11-14 16:31:52 -080037 return branch;
38}
39
40/*
41 * Compare two 64-bit values
42 * x = y return 0
43 * x < y return -1
44 * x > y return 1
45 *
46 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
47 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
48 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
49 * bnez res, finish
50 * sltu t0, x.lo, y.lo
51 * sgtu r1, x.lo, y.lo
52 * subu res, t0, t1
53 * finish:
54 *
55 */
buzbee52a77fc2012-11-20 19:50:46 -080056void GenCmpLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -080057 RegLocation rlSrc1, RegLocation rlSrc2)
58{
buzbee52a77fc2012-11-20 19:50:46 -080059 FlushAllRegs(cUnit);
60 LockCallTemps(cUnit); // Prepare for explicit register usage
61 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
62 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -080063 // Compute (r1:r0) = (r1:r0) - (r3:r2)
buzbee52a77fc2012-11-20 19:50:46 -080064 OpRegReg(cUnit, kOpSub, r0, r2); // r0 = r0 - r2
65 OpRegReg(cUnit, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
66 NewLIR2(cUnit, kX86Set8R, r2, kX86CondL); // r2 = (r1:r0) < (r3:r2) ? 1 : 0
67 NewLIR2(cUnit, kX86Movzx8RR, r2, r2);
68 OpReg(cUnit, kOpNeg, r2); // r2 = -r2
69 OpRegReg(cUnit, kOpOr, r0, r1); // r0 = high | low - sets ZF
70 NewLIR2(cUnit, kX86Set8R, r0, kX86CondNz); // r0 = (r1:r0) != (r3:r2) ? 1 : 0
71 NewLIR2(cUnit, kX86Movzx8RR, r0, r0);
72 OpRegReg(cUnit, kOpOr, r0, r2); // r0 = r0 | r2
73 RegLocation rlResult = LocCReturn();
74 StoreValue(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -080075}
76
buzbee52a77fc2012-11-20 19:50:46 -080077X86ConditionCode X86ConditionEncoding(ConditionCode cond) {
buzbeeefc63692012-11-14 16:31:52 -080078 switch (cond) {
79 case kCondEq: return kX86CondEq;
80 case kCondNe: return kX86CondNe;
81 case kCondCs: return kX86CondC;
82 case kCondCc: return kX86CondNc;
83 case kCondMi: return kX86CondS;
84 case kCondPl: return kX86CondNs;
85 case kCondVs: return kX86CondO;
86 case kCondVc: return kX86CondNo;
87 case kCondHi: return kX86CondA;
88 case kCondLs: return kX86CondBe;
89 case kCondGe: return kX86CondGe;
90 case kCondLt: return kX86CondL;
91 case kCondGt: return kX86CondG;
92 case kCondLe: return kX86CondLe;
93 case kCondAl:
94 case kCondNv: LOG(FATAL) << "Should not reach here";
95 }
96 return kX86CondO;
97}
98
buzbee52a77fc2012-11-20 19:50:46 -080099LIR* OpCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
buzbeeefc63692012-11-14 16:31:52 -0800100 int src2, LIR* target)
101{
buzbee52a77fc2012-11-20 19:50:46 -0800102 NewLIR2(cUnit, kX86Cmp32RR, src1, src2);
103 X86ConditionCode cc = X86ConditionEncoding(cond);
104 LIR* branch = NewLIR2(cUnit, kX86Jcc8, 0 /* lir operand for Jcc offset */ ,
buzbeeefc63692012-11-14 16:31:52 -0800105 cc);
106 branch->target = target;
107 return branch;
108}
109
buzbee52a77fc2012-11-20 19:50:46 -0800110LIR* OpCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
buzbeeefc63692012-11-14 16:31:52 -0800111 int checkValue, LIR* target)
112{
113 if ((checkValue == 0) && (cond == kCondEq || cond == kCondNe)) {
114 // TODO: when checkValue == 0 and reg is rCX, use the jcxz/nz opcode
buzbee52a77fc2012-11-20 19:50:46 -0800115 NewLIR2(cUnit, kX86Test32RR, reg, reg);
buzbeeefc63692012-11-14 16:31:52 -0800116 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800117 NewLIR2(cUnit, IS_SIMM8(checkValue) ? kX86Cmp32RI8 : kX86Cmp32RI, reg, checkValue);
buzbeeefc63692012-11-14 16:31:52 -0800118 }
buzbee52a77fc2012-11-20 19:50:46 -0800119 X86ConditionCode cc = X86ConditionEncoding(cond);
120 LIR* branch = NewLIR2(cUnit, kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
buzbeeefc63692012-11-14 16:31:52 -0800121 branch->target = target;
122 return branch;
123}
124
buzbee52a77fc2012-11-20 19:50:46 -0800125LIR* OpRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeeefc63692012-11-14 16:31:52 -0800126{
127 if (X86_FPREG(rDest) || X86_FPREG(rSrc))
buzbee52a77fc2012-11-20 19:50:46 -0800128 return FpRegCopy(cUnit, rDest, rSrc);
129 LIR* res = RawLIR(cUnit, cUnit->currentDalvikOffset, kX86Mov32RR,
buzbeeefc63692012-11-14 16:31:52 -0800130 rDest, rSrc);
131 if (rDest == rSrc) {
132 res->flags.isNop = true;
133 }
134 return res;
135}
136
buzbee52a77fc2012-11-20 19:50:46 -0800137LIR* OpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeeefc63692012-11-14 16:31:52 -0800138{
buzbee52a77fc2012-11-20 19:50:46 -0800139 LIR *res = OpRegCopyNoInsert(cUnit, rDest, rSrc);
140 AppendLIR(cUnit, res);
buzbeeefc63692012-11-14 16:31:52 -0800141 return res;
142}
143
buzbee52a77fc2012-11-20 19:50:46 -0800144void OpRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
buzbeeefc63692012-11-14 16:31:52 -0800145 int srcLo, int srcHi)
146{
147 bool destFP = X86_FPREG(destLo) && X86_FPREG(destHi);
148 bool srcFP = X86_FPREG(srcLo) && X86_FPREG(srcHi);
149 assert(X86_FPREG(srcLo) == X86_FPREG(srcHi));
150 assert(X86_FPREG(destLo) == X86_FPREG(destHi));
151 if (destFP) {
152 if (srcFP) {
buzbee52a77fc2012-11-20 19:50:46 -0800153 OpRegCopy(cUnit, S2d(destLo, destHi), S2d(srcLo, srcHi));
buzbeeefc63692012-11-14 16:31:52 -0800154 } else {
155 // TODO: Prevent this from happening in the code. The result is often
156 // unused or could have been loaded more easily from memory.
buzbee52a77fc2012-11-20 19:50:46 -0800157 NewLIR2(cUnit, kX86MovdxrRR, destLo, srcLo);
158 NewLIR2(cUnit, kX86MovdxrRR, destHi, srcHi);
159 NewLIR2(cUnit, kX86PsllqRI, destHi, 32);
160 NewLIR2(cUnit, kX86OrpsRR, destLo, destHi);
buzbeeefc63692012-11-14 16:31:52 -0800161 }
162 } else {
163 if (srcFP) {
buzbee52a77fc2012-11-20 19:50:46 -0800164 NewLIR2(cUnit, kX86MovdrxRR, destLo, srcLo);
165 NewLIR2(cUnit, kX86PsrlqRI, srcLo, 32);
166 NewLIR2(cUnit, kX86MovdrxRR, destHi, srcLo);
buzbeeefc63692012-11-14 16:31:52 -0800167 } else {
168 // Handle overlap
169 if (srcHi == destLo) {
buzbee52a77fc2012-11-20 19:50:46 -0800170 OpRegCopy(cUnit, destHi, srcHi);
171 OpRegCopy(cUnit, destLo, srcLo);
buzbeeefc63692012-11-14 16:31:52 -0800172 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800173 OpRegCopy(cUnit, destLo, srcLo);
174 OpRegCopy(cUnit, destHi, srcHi);
buzbeeefc63692012-11-14 16:31:52 -0800175 }
176 }
177 }
178}
179
buzbee52a77fc2012-11-20 19:50:46 -0800180void GenFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) {
buzbeeefc63692012-11-14 16:31:52 -0800181 LIR* labelList = cUnit->blockLabelList;
182 LIR* taken = &labelList[bb->taken->id];
buzbee52a77fc2012-11-20 19:50:46 -0800183 RegLocation rlSrc1 = GetSrcWide(cUnit, mir, 0);
184 RegLocation rlSrc2 = GetSrcWide(cUnit, mir, 2);
185 FlushAllRegs(cUnit);
186 LockCallTemps(cUnit); // Prepare for explicit register usage
187 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
188 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800189 ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
190 // Swap operands and condition code to prevent use of zero flag.
191 if (ccode == kCondLe || ccode == kCondGt) {
192 // Compute (r3:r2) = (r3:r2) - (r1:r0)
buzbee52a77fc2012-11-20 19:50:46 -0800193 OpRegReg(cUnit, kOpSub, r2, r0); // r2 = r2 - r0
194 OpRegReg(cUnit, kOpSbc, r3, r1); // r3 = r3 - r1 - CF
buzbeeefc63692012-11-14 16:31:52 -0800195 } else {
196 // Compute (r1:r0) = (r1:r0) - (r3:r2)
buzbee52a77fc2012-11-20 19:50:46 -0800197 OpRegReg(cUnit, kOpSub, r0, r2); // r0 = r0 - r2
198 OpRegReg(cUnit, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
buzbeeefc63692012-11-14 16:31:52 -0800199 }
200 switch (ccode) {
201 case kCondEq:
202 case kCondNe:
buzbee52a77fc2012-11-20 19:50:46 -0800203 OpRegReg(cUnit, kOpOr, r0, r1); // r0 = r0 | r1
buzbeeefc63692012-11-14 16:31:52 -0800204 break;
205 case kCondLe:
206 ccode = kCondGe;
207 break;
208 case kCondGt:
209 ccode = kCondLt;
210 break;
211 case kCondLt:
212 case kCondGe:
213 break;
214 default:
buzbeecbd6d442012-11-17 14:11:25 -0800215 LOG(FATAL) << "Unexpected ccode: " << ccode;
buzbeeefc63692012-11-14 16:31:52 -0800216 }
buzbee52a77fc2012-11-20 19:50:46 -0800217 OpCondBranch(cUnit, ccode, taken);
buzbeeefc63692012-11-14 16:31:52 -0800218}
buzbee52a77fc2012-11-20 19:50:46 -0800219RegLocation GenDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int regLo, int lit, bool isDiv)
buzbeeefc63692012-11-14 16:31:52 -0800220{
buzbee52a77fc2012-11-20 19:50:46 -0800221 LOG(FATAL) << "Unexpected use of GenDivRemLit for x86";
buzbeeefc63692012-11-14 16:31:52 -0800222 return rlDest;
223}
224
buzbee52a77fc2012-11-20 19:50:46 -0800225RegLocation GenDivRem(CompilationUnit* cUnit, RegLocation rlDest, int regLo, int regHi, bool isDiv)
buzbeeefc63692012-11-14 16:31:52 -0800226{
buzbee52a77fc2012-11-20 19:50:46 -0800227 LOG(FATAL) << "Unexpected use of GenDivRem for x86";
buzbeeefc63692012-11-14 16:31:52 -0800228 return rlDest;
229}
230
buzbee52a77fc2012-11-20 19:50:46 -0800231bool GenInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin)
buzbeeefc63692012-11-14 16:31:52 -0800232{
233 DCHECK_EQ(cUnit->instructionSet, kX86);
234 RegLocation rlSrc1 = info->args[0];
235 RegLocation rlSrc2 = info->args[1];
buzbee52a77fc2012-11-20 19:50:46 -0800236 rlSrc1 = LoadValue(cUnit, rlSrc1, kCoreReg);
237 rlSrc2 = LoadValue(cUnit, rlSrc2, kCoreReg);
238 RegLocation rlDest = InlineTarget(cUnit, info);
239 RegLocation rlResult = EvalLoc(cUnit, rlDest, kCoreReg, true);
240 OpRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
buzbeeefc63692012-11-14 16:31:52 -0800241 DCHECK_EQ(cUnit->instructionSet, kX86);
buzbee52a77fc2012-11-20 19:50:46 -0800242 LIR* branch = NewLIR2(cUnit, kX86Jcc8, 0, isMin ? kX86CondG : kX86CondL);
243 OpRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
244 LIR* branch2 = NewLIR1(cUnit, kX86Jmp8, 0);
245 branch->target = NewLIR0(cUnit, kPseudoTargetLabel);
246 OpRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
247 branch2->target = NewLIR0(cUnit, kPseudoTargetLabel);
248 StoreValue(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800249 return true;
250}
251
buzbee52a77fc2012-11-20 19:50:46 -0800252void OpLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800253{
buzbee52a77fc2012-11-20 19:50:46 -0800254 NewLIR5(cUnit, kX86Lea32RA, rBase, reg1, reg2, scale, offset);
buzbeeefc63692012-11-14 16:31:52 -0800255}
256
buzbee52a77fc2012-11-20 19:50:46 -0800257void OpTlsCmp(CompilationUnit* cUnit, int offset, int val)
buzbeeefc63692012-11-14 16:31:52 -0800258{
buzbee52a77fc2012-11-20 19:50:46 -0800259 NewLIR2(cUnit, kX86Cmp16TI8, offset, val);
buzbeeefc63692012-11-14 16:31:52 -0800260}
261
buzbee52a77fc2012-11-20 19:50:46 -0800262bool GenInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) {
buzbeeefc63692012-11-14 16:31:52 -0800263 DCHECK_NE(cUnit->instructionSet, kThumb2);
264 return false;
265}
266
buzbee52a77fc2012-11-20 19:50:46 -0800267LIR* OpPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target) {
268 LOG(FATAL) << "Unexpected use of OpPcRelLoad for x86";
buzbeeefc63692012-11-14 16:31:52 -0800269 return NULL;
270}
271
buzbee52a77fc2012-11-20 19:50:46 -0800272LIR* OpVldm(CompilationUnit* cUnit, int rBase, int count)
buzbeeefc63692012-11-14 16:31:52 -0800273{
buzbee52a77fc2012-11-20 19:50:46 -0800274 LOG(FATAL) << "Unexpected use of OpVldm for x86";
buzbeeefc63692012-11-14 16:31:52 -0800275 return NULL;
276}
277
buzbee52a77fc2012-11-20 19:50:46 -0800278LIR* OpVstm(CompilationUnit* cUnit, int rBase, int count)
buzbeeefc63692012-11-14 16:31:52 -0800279{
buzbee52a77fc2012-11-20 19:50:46 -0800280 LOG(FATAL) << "Unexpected use of OpVstm for x86";
buzbeeefc63692012-11-14 16:31:52 -0800281 return NULL;
282}
283
buzbee52a77fc2012-11-20 19:50:46 -0800284void GenMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc,
buzbeeefc63692012-11-14 16:31:52 -0800285 RegLocation rlResult, int lit,
286 int firstBit, int secondBit)
287{
buzbee52a77fc2012-11-20 19:50:46 -0800288 int tReg = AllocTemp(cUnit);
289 OpRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, secondBit - firstBit);
290 OpRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, tReg);
291 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800292 if (firstBit != 0) {
buzbee52a77fc2012-11-20 19:50:46 -0800293 OpRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
buzbeeefc63692012-11-14 16:31:52 -0800294 }
295}
296
buzbee52a77fc2012-11-20 19:50:46 -0800297void GenDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi)
buzbeeefc63692012-11-14 16:31:52 -0800298{
buzbee52a77fc2012-11-20 19:50:46 -0800299 int tReg = AllocTemp(cUnit);
300 OpRegRegReg(cUnit, kOpOr, tReg, regLo, regHi);
301 GenImmedCheck(cUnit, kCondEq, tReg, 0, kThrowDivZero);
302 FreeTemp(cUnit, tReg);
buzbeeefc63692012-11-14 16:31:52 -0800303}
304
305// Test suspend flag, return target of taken suspend branch
buzbee52a77fc2012-11-20 19:50:46 -0800306LIR* OpTestSuspend(CompilationUnit* cUnit, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800307{
buzbee52a77fc2012-11-20 19:50:46 -0800308 OpTlsCmp(cUnit, Thread::ThreadFlagsOffset().Int32Value(), 0);
309 return OpCondBranch(cUnit, (target == NULL) ? kCondNe : kCondEq, target);
buzbeeefc63692012-11-14 16:31:52 -0800310}
311
312// Decrement register and branch on condition
buzbee52a77fc2012-11-20 19:50:46 -0800313LIR* OpDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800314{
buzbee52a77fc2012-11-20 19:50:46 -0800315 OpRegImm(cUnit, kOpSub, reg, 1);
316 return OpCmpImmBranch(cUnit, cCode, reg, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800317}
318
buzbee52a77fc2012-11-20 19:50:46 -0800319bool SmallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode,
buzbeeefc63692012-11-14 16:31:52 -0800320 RegLocation rlSrc, RegLocation rlDest, int lit)
321{
322 LOG(FATAL) << "Unexpected use of smallLiteralDive in x86";
323 return false;
324}
325
buzbee52a77fc2012-11-20 19:50:46 -0800326LIR* OpIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide)
buzbeeefc63692012-11-14 16:31:52 -0800327{
buzbee52a77fc2012-11-20 19:50:46 -0800328 LOG(FATAL) << "Unexpected use of OpIT in x86";
buzbeeefc63692012-11-14 16:31:52 -0800329 return NULL;
330}
buzbee52a77fc2012-11-20 19:50:46 -0800331bool GenAddLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800332 RegLocation rlSrc1, RegLocation rlSrc2)
333{
buzbee52a77fc2012-11-20 19:50:46 -0800334 FlushAllRegs(cUnit);
335 LockCallTemps(cUnit); // Prepare for explicit register usage
336 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
337 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800338 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbee52a77fc2012-11-20 19:50:46 -0800339 OpRegReg(cUnit, kOpAdd, r0, r2); // r0 = r0 + r2
340 OpRegReg(cUnit, kOpAdc, r1, r3); // r1 = r1 + r3 + CF
buzbeeefc63692012-11-14 16:31:52 -0800341 RegLocation rlResult = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
342 INVALID_SREG, INVALID_SREG};
buzbee52a77fc2012-11-20 19:50:46 -0800343 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800344 return false;
345}
346
buzbee52a77fc2012-11-20 19:50:46 -0800347bool GenSubLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800348 RegLocation rlSrc1, RegLocation rlSrc2)
349{
buzbee52a77fc2012-11-20 19:50:46 -0800350 FlushAllRegs(cUnit);
351 LockCallTemps(cUnit); // Prepare for explicit register usage
352 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
353 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800354 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbee52a77fc2012-11-20 19:50:46 -0800355 OpRegReg(cUnit, kOpSub, r0, r2); // r0 = r0 - r2
356 OpRegReg(cUnit, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
buzbeeefc63692012-11-14 16:31:52 -0800357 RegLocation rlResult = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
358 INVALID_SREG, INVALID_SREG};
buzbee52a77fc2012-11-20 19:50:46 -0800359 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800360 return false;
361}
362
buzbee52a77fc2012-11-20 19:50:46 -0800363bool GenAndLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800364 RegLocation rlSrc1, RegLocation rlSrc2)
365{
buzbee52a77fc2012-11-20 19:50:46 -0800366 FlushAllRegs(cUnit);
367 LockCallTemps(cUnit); // Prepare for explicit register usage
368 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
369 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800370 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbee52a77fc2012-11-20 19:50:46 -0800371 OpRegReg(cUnit, kOpAnd, r0, r2); // r0 = r0 - r2
372 OpRegReg(cUnit, kOpAnd, r1, r3); // r1 = r1 - r3 - CF
buzbeeefc63692012-11-14 16:31:52 -0800373 RegLocation rlResult = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
374 INVALID_SREG, INVALID_SREG};
buzbee52a77fc2012-11-20 19:50:46 -0800375 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800376 return false;
377}
378
buzbee52a77fc2012-11-20 19:50:46 -0800379bool GenOrLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800380 RegLocation rlSrc1, RegLocation rlSrc2)
381{
buzbee52a77fc2012-11-20 19:50:46 -0800382 FlushAllRegs(cUnit);
383 LockCallTemps(cUnit); // Prepare for explicit register usage
384 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
385 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800386 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbee52a77fc2012-11-20 19:50:46 -0800387 OpRegReg(cUnit, kOpOr, r0, r2); // r0 = r0 - r2
388 OpRegReg(cUnit, kOpOr, r1, r3); // r1 = r1 - r3 - CF
buzbeeefc63692012-11-14 16:31:52 -0800389 RegLocation rlResult = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
390 INVALID_SREG, INVALID_SREG};
buzbee52a77fc2012-11-20 19:50:46 -0800391 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800392 return false;
393}
394
buzbee52a77fc2012-11-20 19:50:46 -0800395bool GenXorLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800396 RegLocation rlSrc1, RegLocation rlSrc2)
397{
buzbee52a77fc2012-11-20 19:50:46 -0800398 FlushAllRegs(cUnit);
399 LockCallTemps(cUnit); // Prepare for explicit register usage
400 LoadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
401 LoadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800402 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbee52a77fc2012-11-20 19:50:46 -0800403 OpRegReg(cUnit, kOpXor, r0, r2); // r0 = r0 - r2
404 OpRegReg(cUnit, kOpXor, r1, r3); // r1 = r1 - r3 - CF
buzbeeefc63692012-11-14 16:31:52 -0800405 RegLocation rlResult = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
406 INVALID_SREG, INVALID_SREG};
buzbee52a77fc2012-11-20 19:50:46 -0800407 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800408 return false;
409}
410
buzbee52a77fc2012-11-20 19:50:46 -0800411bool GenNegLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeeefc63692012-11-14 16:31:52 -0800412 RegLocation rlSrc)
413{
buzbee52a77fc2012-11-20 19:50:46 -0800414 FlushAllRegs(cUnit);
415 LockCallTemps(cUnit); // Prepare for explicit register usage
416 LoadValueDirectWideFixed(cUnit, rlSrc, r0, r1);
buzbeeefc63692012-11-14 16:31:52 -0800417 // Compute (r1:r0) = -(r1:r0)
buzbee52a77fc2012-11-20 19:50:46 -0800418 OpRegReg(cUnit, kOpNeg, r0, r0); // r0 = -r0
419 OpRegImm(cUnit, kOpAdc, r1, 0); // r1 = r1 + CF
420 OpRegReg(cUnit, kOpNeg, r1, r1); // r1 = -r1
buzbeeefc63692012-11-14 16:31:52 -0800421 RegLocation rlResult = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
422 INVALID_SREG, INVALID_SREG};
buzbee52a77fc2012-11-20 19:50:46 -0800423 StoreValueWide(cUnit, rlDest, rlResult);
buzbeeefc63692012-11-14 16:31:52 -0800424 return false;
425}
426
buzbee52a77fc2012-11-20 19:50:46 -0800427void OpRegThreadMem(CompilationUnit* cUnit, OpKind op, int rDest, int threadOffset) {
buzbeeefc63692012-11-14 16:31:52 -0800428 X86OpCode opcode = kX86Bkpt;
429 switch (op) {
430 case kOpCmp: opcode = kX86Cmp32RT; break;
431 default:
432 LOG(FATAL) << "Bad opcode: " << op;
433 break;
434 }
buzbee52a77fc2012-11-20 19:50:46 -0800435 NewLIR2(cUnit, opcode, rDest, threadOffset);
buzbeeefc63692012-11-14 16:31:52 -0800436}
437
438} // namespace art