blob: f6eaaf5bc0a3ca5460eb2bc0d1f4bbebb55688f5 [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 */
buzbeefa57c472012-11-21 12:06:18 -080028LIR* GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code,
buzbeeefc63692012-11-14 16:31:52 -080029 int reg1, int base, int offset, ThrowKind kind)
30{
buzbeefa57c472012-11-21 12:06:18 -080031 LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind,
32 cu->current_dalvik_offset, reg1, base, offset);
33 OpRegMem(cu, kOpCmp, reg1, base, offset);
34 LIR* branch = OpCondBranch(cu, c_code, tgt);
buzbeeefc63692012-11-14 16:31:52 -080035 // Remember branch target - will process later
buzbeefa57c472012-11-21 12:06:18 -080036 InsertGrowableList(cu, &cu->throw_launchpads, 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 */
buzbeefa57c472012-11-21 12:06:18 -080056void GenCmpLong(CompilationUnit* cu, RegLocation rl_dest,
57 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -080058{
buzbeefa57c472012-11-21 12:06:18 -080059 FlushAllRegs(cu);
60 LockCallTemps(cu); // Prepare for explicit register usage
61 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
62 LoadValueDirectWideFixed(cu, rl_src2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -080063 // Compute (r1:r0) = (r1:r0) - (r3:r2)
buzbeefa57c472012-11-21 12:06:18 -080064 OpRegReg(cu, kOpSub, r0, r2); // r0 = r0 - r2
65 OpRegReg(cu, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
66 NewLIR2(cu, kX86Set8R, r2, kX86CondL); // r2 = (r1:r0) < (r3:r2) ? 1 : 0
67 NewLIR2(cu, kX86Movzx8RR, r2, r2);
68 OpReg(cu, kOpNeg, r2); // r2 = -r2
69 OpRegReg(cu, kOpOr, r0, r1); // r0 = high | low - sets ZF
70 NewLIR2(cu, kX86Set8R, r0, kX86CondNz); // r0 = (r1:r0) != (r3:r2) ? 1 : 0
71 NewLIR2(cu, kX86Movzx8RR, r0, r0);
72 OpRegReg(cu, kOpOr, r0, r2); // r0 = r0 | r2
73 RegLocation rl_result = LocCReturn();
74 StoreValue(cu, rl_dest, rl_result);
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
buzbeefa57c472012-11-21 12:06:18 -080099LIR* OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1,
buzbeeefc63692012-11-14 16:31:52 -0800100 int src2, LIR* target)
101{
buzbeefa57c472012-11-21 12:06:18 -0800102 NewLIR2(cu, kX86Cmp32RR, src1, src2);
buzbee52a77fc2012-11-20 19:50:46 -0800103 X86ConditionCode cc = X86ConditionEncoding(cond);
buzbeefa57c472012-11-21 12:06:18 -0800104 LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* lir operand for Jcc offset */ ,
buzbeeefc63692012-11-14 16:31:52 -0800105 cc);
106 branch->target = target;
107 return branch;
108}
109
buzbeefa57c472012-11-21 12:06:18 -0800110LIR* OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg,
111 int check_value, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800112{
buzbeefa57c472012-11-21 12:06:18 -0800113 if ((check_value == 0) && (cond == kCondEq || cond == kCondNe)) {
114 // TODO: when check_value == 0 and reg is rCX, use the jcxz/nz opcode
115 NewLIR2(cu, kX86Test32RR, reg, reg);
buzbeeefc63692012-11-14 16:31:52 -0800116 } else {
buzbeefa57c472012-11-21 12:06:18 -0800117 NewLIR2(cu, IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg, check_value);
buzbeeefc63692012-11-14 16:31:52 -0800118 }
buzbee52a77fc2012-11-20 19:50:46 -0800119 X86ConditionCode cc = X86ConditionEncoding(cond);
buzbeefa57c472012-11-21 12:06:18 -0800120 LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
buzbeeefc63692012-11-14 16:31:52 -0800121 branch->target = target;
122 return branch;
123}
124
buzbeefa57c472012-11-21 12:06:18 -0800125LIR* OpRegCopyNoInsert(CompilationUnit *cu, int r_dest, int r_src)
buzbeeefc63692012-11-14 16:31:52 -0800126{
buzbeefa57c472012-11-21 12:06:18 -0800127 if (X86_FPREG(r_dest) || X86_FPREG(r_src))
128 return FpRegCopy(cu, r_dest, r_src);
129 LIR* res = RawLIR(cu, cu->current_dalvik_offset, kX86Mov32RR,
130 r_dest, r_src);
131 if (r_dest == r_src) {
132 res->flags.is_nop = true;
buzbeeefc63692012-11-14 16:31:52 -0800133 }
134 return res;
135}
136
buzbeefa57c472012-11-21 12:06:18 -0800137LIR* OpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
buzbeeefc63692012-11-14 16:31:52 -0800138{
buzbeefa57c472012-11-21 12:06:18 -0800139 LIR *res = OpRegCopyNoInsert(cu, r_dest, r_src);
140 AppendLIR(cu, res);
buzbeeefc63692012-11-14 16:31:52 -0800141 return res;
142}
143
buzbeefa57c472012-11-21 12:06:18 -0800144void OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi,
145 int src_lo, int src_hi)
buzbeeefc63692012-11-14 16:31:52 -0800146{
buzbeefa57c472012-11-21 12:06:18 -0800147 bool dest_fp = X86_FPREG(dest_lo) && X86_FPREG(dest_hi);
148 bool src_fp = X86_FPREG(src_lo) && X86_FPREG(src_hi);
149 assert(X86_FPREG(src_lo) == X86_FPREG(src_hi));
150 assert(X86_FPREG(dest_lo) == X86_FPREG(dest_hi));
151 if (dest_fp) {
152 if (src_fp) {
153 OpRegCopy(cu, S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
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.
buzbeefa57c472012-11-21 12:06:18 -0800157 NewLIR2(cu, kX86MovdxrRR, dest_lo, src_lo);
158 NewLIR2(cu, kX86MovdxrRR, dest_hi, src_hi);
159 NewLIR2(cu, kX86PsllqRI, dest_hi, 32);
160 NewLIR2(cu, kX86OrpsRR, dest_lo, dest_hi);
buzbeeefc63692012-11-14 16:31:52 -0800161 }
162 } else {
buzbeefa57c472012-11-21 12:06:18 -0800163 if (src_fp) {
164 NewLIR2(cu, kX86MovdrxRR, dest_lo, src_lo);
165 NewLIR2(cu, kX86PsrlqRI, src_lo, 32);
166 NewLIR2(cu, kX86MovdrxRR, dest_hi, src_lo);
buzbeeefc63692012-11-14 16:31:52 -0800167 } else {
168 // Handle overlap
buzbeefa57c472012-11-21 12:06:18 -0800169 if (src_hi == dest_lo) {
170 OpRegCopy(cu, dest_hi, src_hi);
171 OpRegCopy(cu, dest_lo, src_lo);
buzbeeefc63692012-11-14 16:31:52 -0800172 } else {
buzbeefa57c472012-11-21 12:06:18 -0800173 OpRegCopy(cu, dest_lo, src_lo);
174 OpRegCopy(cu, dest_hi, src_hi);
buzbeeefc63692012-11-14 16:31:52 -0800175 }
176 }
177 }
178}
179
buzbeefa57c472012-11-21 12:06:18 -0800180void GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir) {
181 LIR* label_list = cu->block_label_list;
182 LIR* taken = &label_list[bb->taken->id];
183 RegLocation rl_src1 = GetSrcWide(cu, mir, 0);
184 RegLocation rl_src2 = GetSrcWide(cu, mir, 2);
185 FlushAllRegs(cu);
186 LockCallTemps(cu); // Prepare for explicit register usage
187 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
188 LoadValueDirectWideFixed(cu, rl_src2, 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)
buzbeefa57c472012-11-21 12:06:18 -0800193 OpRegReg(cu, kOpSub, r2, r0); // r2 = r2 - r0
194 OpRegReg(cu, kOpSbc, r3, r1); // r3 = r3 - r1 - CF
buzbeeefc63692012-11-14 16:31:52 -0800195 } else {
196 // Compute (r1:r0) = (r1:r0) - (r3:r2)
buzbeefa57c472012-11-21 12:06:18 -0800197 OpRegReg(cu, kOpSub, r0, r2); // r0 = r0 - r2
198 OpRegReg(cu, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
buzbeeefc63692012-11-14 16:31:52 -0800199 }
200 switch (ccode) {
201 case kCondEq:
202 case kCondNe:
buzbeefa57c472012-11-21 12:06:18 -0800203 OpRegReg(cu, 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 }
buzbeefa57c472012-11-21 12:06:18 -0800217 OpCondBranch(cu, ccode, taken);
buzbeeefc63692012-11-14 16:31:52 -0800218}
buzbeefa57c472012-11-21 12:06:18 -0800219RegLocation GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int lit, bool is_div)
buzbeeefc63692012-11-14 16:31:52 -0800220{
buzbee52a77fc2012-11-20 19:50:46 -0800221 LOG(FATAL) << "Unexpected use of GenDivRemLit for x86";
buzbeefa57c472012-11-21 12:06:18 -0800222 return rl_dest;
buzbeeefc63692012-11-14 16:31:52 -0800223}
224
buzbeefa57c472012-11-21 12:06:18 -0800225RegLocation GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div)
buzbeeefc63692012-11-14 16:31:52 -0800226{
buzbee52a77fc2012-11-20 19:50:46 -0800227 LOG(FATAL) << "Unexpected use of GenDivRem for x86";
buzbeefa57c472012-11-21 12:06:18 -0800228 return rl_dest;
buzbeeefc63692012-11-14 16:31:52 -0800229}
230
buzbeefa57c472012-11-21 12:06:18 -0800231bool GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min)
buzbeeefc63692012-11-14 16:31:52 -0800232{
buzbeefa57c472012-11-21 12:06:18 -0800233 DCHECK_EQ(cu->instruction_set, kX86);
234 RegLocation rl_src1 = info->args[0];
235 RegLocation rl_src2 = info->args[1];
236 rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
237 rl_src2 = LoadValue(cu, rl_src2, kCoreReg);
238 RegLocation rl_dest = InlineTarget(cu, info);
239 RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
240 OpRegReg(cu, kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
241 DCHECK_EQ(cu->instruction_set, kX86);
242 LIR* branch = NewLIR2(cu, kX86Jcc8, 0, is_min ? kX86CondG : kX86CondL);
243 OpRegReg(cu, kOpMov, rl_result.low_reg, rl_src1.low_reg);
244 LIR* branch2 = NewLIR1(cu, kX86Jmp8, 0);
245 branch->target = NewLIR0(cu, kPseudoTargetLabel);
246 OpRegReg(cu, kOpMov, rl_result.low_reg, rl_src2.low_reg);
247 branch2->target = NewLIR0(cu, kPseudoTargetLabel);
248 StoreValue(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800249 return true;
250}
251
buzbeefa57c472012-11-21 12:06:18 -0800252void OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800253{
buzbeefa57c472012-11-21 12:06:18 -0800254 NewLIR5(cu, kX86Lea32RA, rBase, reg1, reg2, scale, offset);
buzbeeefc63692012-11-14 16:31:52 -0800255}
256
buzbeefa57c472012-11-21 12:06:18 -0800257void OpTlsCmp(CompilationUnit* cu, int offset, int val)
buzbeeefc63692012-11-14 16:31:52 -0800258{
buzbeefa57c472012-11-21 12:06:18 -0800259 NewLIR2(cu, kX86Cmp16TI8, offset, val);
buzbeeefc63692012-11-14 16:31:52 -0800260}
261
buzbeefa57c472012-11-21 12:06:18 -0800262bool GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) {
263 DCHECK_NE(cu->instruction_set, kThumb2);
buzbeeefc63692012-11-14 16:31:52 -0800264 return false;
265}
266
buzbeefa57c472012-11-21 12:06:18 -0800267LIR* OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) {
buzbee52a77fc2012-11-20 19:50:46 -0800268 LOG(FATAL) << "Unexpected use of OpPcRelLoad for x86";
buzbeeefc63692012-11-14 16:31:52 -0800269 return NULL;
270}
271
buzbeefa57c472012-11-21 12:06:18 -0800272LIR* OpVldm(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800278LIR* OpVstm(CompilationUnit* cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800284void GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src,
285 RegLocation rl_result, int lit,
286 int first_bit, int second_bit)
buzbeeefc63692012-11-14 16:31:52 -0800287{
buzbeefa57c472012-11-21 12:06:18 -0800288 int t_reg = AllocTemp(cu);
289 OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit);
290 OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg);
291 FreeTemp(cu, t_reg);
292 if (first_bit != 0) {
293 OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit);
buzbeeefc63692012-11-14 16:31:52 -0800294 }
295}
296
buzbeefa57c472012-11-21 12:06:18 -0800297void GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi)
buzbeeefc63692012-11-14 16:31:52 -0800298{
buzbeefa57c472012-11-21 12:06:18 -0800299 int t_reg = AllocTemp(cu);
300 OpRegRegReg(cu, kOpOr, t_reg, reg_lo, reg_hi);
301 GenImmedCheck(cu, kCondEq, t_reg, 0, kThrowDivZero);
302 FreeTemp(cu, t_reg);
buzbeeefc63692012-11-14 16:31:52 -0800303}
304
305// Test suspend flag, return target of taken suspend branch
buzbeefa57c472012-11-21 12:06:18 -0800306LIR* OpTestSuspend(CompilationUnit* cu, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800307{
buzbeefa57c472012-11-21 12:06:18 -0800308 OpTlsCmp(cu, Thread::ThreadFlagsOffset().Int32Value(), 0);
309 return OpCondBranch(cu, (target == NULL) ? kCondNe : kCondEq, target);
buzbeeefc63692012-11-14 16:31:52 -0800310}
311
312// Decrement register and branch on condition
buzbeefa57c472012-11-21 12:06:18 -0800313LIR* OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, LIR* target)
buzbeeefc63692012-11-14 16:31:52 -0800314{
buzbeefa57c472012-11-21 12:06:18 -0800315 OpRegImm(cu, kOpSub, reg, 1);
316 return OpCmpImmBranch(cu, c_code, reg, 0, target);
buzbeeefc63692012-11-14 16:31:52 -0800317}
318
buzbeefa57c472012-11-21 12:06:18 -0800319bool SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode,
320 RegLocation rl_src, RegLocation rl_dest, int lit)
buzbeeefc63692012-11-14 16:31:52 -0800321{
322 LOG(FATAL) << "Unexpected use of smallLiteralDive in x86";
323 return false;
324}
325
buzbeefa57c472012-11-21 12:06:18 -0800326LIR* OpIT(CompilationUnit* cu, 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}
buzbeefa57c472012-11-21 12:06:18 -0800331bool GenAddLong(CompilationUnit* cu, RegLocation rl_dest,
332 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800333{
buzbeefa57c472012-11-21 12:06:18 -0800334 FlushAllRegs(cu);
335 LockCallTemps(cu); // Prepare for explicit register usage
336 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
337 LoadValueDirectWideFixed(cu, rl_src2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800338 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbeefa57c472012-11-21 12:06:18 -0800339 OpRegReg(cu, kOpAdd, r0, r2); // r0 = r0 + r2
340 OpRegReg(cu, kOpAdc, r1, r3); // r1 = r1 + r3 + CF
341 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
buzbeeefc63692012-11-14 16:31:52 -0800342 INVALID_SREG, INVALID_SREG};
buzbeefa57c472012-11-21 12:06:18 -0800343 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800344 return false;
345}
346
buzbeefa57c472012-11-21 12:06:18 -0800347bool GenSubLong(CompilationUnit* cu, RegLocation rl_dest,
348 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800349{
buzbeefa57c472012-11-21 12:06:18 -0800350 FlushAllRegs(cu);
351 LockCallTemps(cu); // Prepare for explicit register usage
352 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
353 LoadValueDirectWideFixed(cu, rl_src2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800354 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbeefa57c472012-11-21 12:06:18 -0800355 OpRegReg(cu, kOpSub, r0, r2); // r0 = r0 - r2
356 OpRegReg(cu, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
357 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
buzbeeefc63692012-11-14 16:31:52 -0800358 INVALID_SREG, INVALID_SREG};
buzbeefa57c472012-11-21 12:06:18 -0800359 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800360 return false;
361}
362
buzbeefa57c472012-11-21 12:06:18 -0800363bool GenAndLong(CompilationUnit* cu, RegLocation rl_dest,
364 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800365{
buzbeefa57c472012-11-21 12:06:18 -0800366 FlushAllRegs(cu);
367 LockCallTemps(cu); // Prepare for explicit register usage
368 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
369 LoadValueDirectWideFixed(cu, rl_src2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800370 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbeefa57c472012-11-21 12:06:18 -0800371 OpRegReg(cu, kOpAnd, r0, r2); // r0 = r0 - r2
372 OpRegReg(cu, kOpAnd, r1, r3); // r1 = r1 - r3 - CF
373 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
buzbeeefc63692012-11-14 16:31:52 -0800374 INVALID_SREG, INVALID_SREG};
buzbeefa57c472012-11-21 12:06:18 -0800375 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800376 return false;
377}
378
buzbeefa57c472012-11-21 12:06:18 -0800379bool GenOrLong(CompilationUnit* cu, RegLocation rl_dest,
380 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800381{
buzbeefa57c472012-11-21 12:06:18 -0800382 FlushAllRegs(cu);
383 LockCallTemps(cu); // Prepare for explicit register usage
384 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
385 LoadValueDirectWideFixed(cu, rl_src2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800386 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbeefa57c472012-11-21 12:06:18 -0800387 OpRegReg(cu, kOpOr, r0, r2); // r0 = r0 - r2
388 OpRegReg(cu, kOpOr, r1, r3); // r1 = r1 - r3 - CF
389 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
buzbeeefc63692012-11-14 16:31:52 -0800390 INVALID_SREG, INVALID_SREG};
buzbeefa57c472012-11-21 12:06:18 -0800391 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800392 return false;
393}
394
buzbeefa57c472012-11-21 12:06:18 -0800395bool GenXorLong(CompilationUnit* cu, RegLocation rl_dest,
396 RegLocation rl_src1, RegLocation rl_src2)
buzbeeefc63692012-11-14 16:31:52 -0800397{
buzbeefa57c472012-11-21 12:06:18 -0800398 FlushAllRegs(cu);
399 LockCallTemps(cu); // Prepare for explicit register usage
400 LoadValueDirectWideFixed(cu, rl_src1, r0, r1);
401 LoadValueDirectWideFixed(cu, rl_src2, r2, r3);
buzbeeefc63692012-11-14 16:31:52 -0800402 // Compute (r1:r0) = (r1:r0) + (r2:r3)
buzbeefa57c472012-11-21 12:06:18 -0800403 OpRegReg(cu, kOpXor, r0, r2); // r0 = r0 - r2
404 OpRegReg(cu, kOpXor, r1, r3); // r1 = r1 - r3 - CF
405 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
buzbeeefc63692012-11-14 16:31:52 -0800406 INVALID_SREG, INVALID_SREG};
buzbeefa57c472012-11-21 12:06:18 -0800407 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800408 return false;
409}
410
buzbeefa57c472012-11-21 12:06:18 -0800411bool GenNegLong(CompilationUnit* cu, RegLocation rl_dest,
412 RegLocation rl_src)
buzbeeefc63692012-11-14 16:31:52 -0800413{
buzbeefa57c472012-11-21 12:06:18 -0800414 FlushAllRegs(cu);
415 LockCallTemps(cu); // Prepare for explicit register usage
416 LoadValueDirectWideFixed(cu, rl_src, r0, r1);
buzbeeefc63692012-11-14 16:31:52 -0800417 // Compute (r1:r0) = -(r1:r0)
buzbeefa57c472012-11-21 12:06:18 -0800418 OpRegReg(cu, kOpNeg, r0, r0); // r0 = -r0
419 OpRegImm(cu, kOpAdc, r1, 0); // r1 = r1 + CF
420 OpRegReg(cu, kOpNeg, r1, r1); // r1 = -r1
421 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1,
buzbeeefc63692012-11-14 16:31:52 -0800422 INVALID_SREG, INVALID_SREG};
buzbeefa57c472012-11-21 12:06:18 -0800423 StoreValueWide(cu, rl_dest, rl_result);
buzbeeefc63692012-11-14 16:31:52 -0800424 return false;
425}
426
buzbeefa57c472012-11-21 12:06:18 -0800427void OpRegThreadMem(CompilationUnit* cu, OpKind op, int r_dest, int thread_offset) {
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 }
buzbeefa57c472012-11-21 12:06:18 -0800435 NewLIR2(cu, opcode, r_dest, thread_offset);
buzbeeefc63692012-11-14 16:31:52 -0800436}
437
438} // namespace art