blob: f5466eeffef3c7ecc52138903ca0976ab5bcf1b5 [file] [log] [blame]
buzbeee88dfbf2012-03-05 11:19:57 -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/*
buzbeea7678db2012-03-05 15:35:46 -080018 * This file contains codegen for the X86 ISA and is intended to be
buzbeee88dfbf2012-03-05 11:19:57 -080019 * includes by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 */
24
25namespace art {
26
buzbee16da88c2012-03-20 10:38:17 -070027void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
28 SpecialCaseHandler specialCase)
29{
Bill Buzbeea114add2012-05-03 15:00:40 -070030 // TODO
buzbee16da88c2012-03-20 10:38:17 -070031}
32
buzbeee88dfbf2012-03-05 11:19:57 -080033/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080034 * Perform register memory operation.
35 */
36LIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode,
buzbee408ad162012-06-06 16:45:18 -070037 int reg1, int base, int offset, ThrowKind kind)
Ian Rogersb5d09b22012-03-06 22:14:17 -080038{
Bill Buzbeea114add2012-05-03 15:00:40 -070039 LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind,
buzbee408ad162012-06-06 16:45:18 -070040 cUnit->currentDalvikOffset, reg1, base, offset);
Bill Buzbeea114add2012-05-03 15:00:40 -070041 opRegMem(cUnit, kOpCmp, reg1, base, offset);
42 LIR* branch = opCondBranch(cUnit, cCode, tgt);
43 // Remember branch target - will process later
44 oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
45 return branch;
Ian Rogersb5d09b22012-03-06 22:14:17 -080046}
47
48/*
Ian Rogers55bd45f2012-04-04 17:31:20 -070049 * The sparse table in the literal pool is an array of <key,displacement>
50 * pairs.
buzbeee88dfbf2012-03-05 11:19:57 -080051 */
Ian Rogers55bd45f2012-04-04 17:31:20 -070052BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
53 bool split, bool create, BasicBlock** immedPredBlockP);
buzbee408ad162012-06-06 16:45:18 -070054void genSparseSwitch(CompilationUnit* cUnit, uint32_t tableOffset,
55 RegLocation rlSrc, LIR* labelList)
Bill Buzbeea114add2012-05-03 15:00:40 -070056{
buzbee408ad162012-06-06 16:45:18 -070057 const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
Ian Rogers55bd45f2012-04-04 17:31:20 -070058 if (cUnit->printMe) {
59 dumpSparseSwitchTable(table);
60 }
61 int entries = table[1];
62 int* keys = (int*)&table[2];
63 int* targets = &keys[entries];
64 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
65 for (int i = 0; i < entries; i++) {
66 int key = keys[i];
buzbee408ad162012-06-06 16:45:18 -070067 BasicBlock* case_block = findBlock(cUnit,
68 cUnit->currentDalvikOffset + targets[i],
Ian Rogers55bd45f2012-04-04 17:31:20 -070069 false, false, NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -070070 opCmpImmBranch(cUnit, kCondEq, rlSrc.lowReg, key,
71 &labelList[case_block->id]);
Ian Rogers55bd45f2012-04-04 17:31:20 -070072 }
buzbeee88dfbf2012-03-05 11:19:57 -080073}
74
75/*
76 * Code pattern will look something like:
77 *
Ian Rogers55bd45f2012-04-04 17:31:20 -070078 * mov rVal, ..
79 * call 0
80 * pop rStartOfMethod
81 * sub rStartOfMethod, ..
82 * mov rKeyReg, rVal
83 * sub rKeyReg, lowKey
84 * cmp rKeyReg, size-1 ; bound check
85 * ja done
86 * mov rDisp, [rStartOfMethod + rKeyReg * 4 + tableOffset]
87 * add rStartOfMethod, rDisp
88 * jmp rStartOfMethod
buzbeee88dfbf2012-03-05 11:19:57 -080089 * done:
90 */
buzbee408ad162012-06-06 16:45:18 -070091void genPackedSwitch(CompilationUnit* cUnit, uint32_t tableOffset,
92 RegLocation rlSrc)
Bill Buzbeea114add2012-05-03 15:00:40 -070093{
buzbee408ad162012-06-06 16:45:18 -070094 const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
Ian Rogers7caad772012-03-30 01:07:54 -070095 if (cUnit->printMe) {
96 dumpPackedSwitchTable(table);
97 }
98 // Add the table to the list - we'll process it later
99 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
100 true, kAllocData);
101 tabRec->table = table;
buzbee408ad162012-06-06 16:45:18 -0700102 tabRec->vaddr = cUnit->currentDalvikOffset;
Ian Rogers7caad772012-03-30 01:07:54 -0700103 int size = table[1];
104 tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
105 kAllocLIR);
106 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800107
Ian Rogers7caad772012-03-30 01:07:54 -0700108 // Get the switch value
109 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
110 int startOfMethodReg = oatAllocTemp(cUnit);
111 // Materialize a pointer to the switch table
112 //newLIR0(cUnit, kX86Bkpt);
113 newLIR1(cUnit, kX86StartOfMethod, startOfMethodReg);
114 int lowKey = s4FromSwitchData(&table[2]);
115 int keyReg;
116 // Remove the bias, if necessary
117 if (lowKey == 0) {
118 keyReg = rlSrc.lowReg;
119 } else {
120 keyReg = oatAllocTemp(cUnit);
121 opRegRegImm(cUnit, kOpSub, keyReg, rlSrc.lowReg, lowKey);
122 }
123 // Bounds check - if < 0 or >= size continue following switch
124 opRegImm(cUnit, kOpCmp, keyReg, size-1);
125 LIR* branchOver = opCondBranch(cUnit, kCondHi, NULL);
buzbeee88dfbf2012-03-05 11:19:57 -0800126
Ian Rogers7caad772012-03-30 01:07:54 -0700127 // Load the displacement from the switch table
128 int dispReg = oatAllocTemp(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 newLIR5(cUnit, kX86PcRelLoadRA, dispReg, startOfMethodReg, keyReg, 2,
130 (intptr_t)tabRec);
Ian Rogers7caad772012-03-30 01:07:54 -0700131 // Add displacement to start of method
132 opRegReg(cUnit, kOpAdd, startOfMethodReg, dispReg);
133 // ..and go!
134 LIR* switchBranch = newLIR1(cUnit, kX86JmpR, startOfMethodReg);
135 tabRec->anchor = switchBranch;
buzbeee88dfbf2012-03-05 11:19:57 -0800136
Ian Rogers7caad772012-03-30 01:07:54 -0700137 /* branchOver target here */
138 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
139 branchOver->target = (LIR*)target;
buzbeee88dfbf2012-03-05 11:19:57 -0800140}
141
Bill Buzbeea114add2012-05-03 15:00:40 -0700142void callRuntimeHelperRegReg(CompilationUnit* cUnit, int helperOffset,
143 int arg0, int arg1);
buzbeee88dfbf2012-03-05 11:19:57 -0800144/*
145 * Array data table format:
146 * ushort ident = 0x0300 magic value
147 * ushort width width of each element in the table
148 * uint size number of elements in the table
149 * ubyte data[size*width] table of data values (may contain a single-byte
150 * padding at the end)
151 *
152 * Total size is 4+(width * size + 1)/2 16-bit code units.
153 */
buzbee408ad162012-06-06 16:45:18 -0700154void genFillArrayData(CompilationUnit* cUnit, uint32_t tableOffset,
155 RegLocation rlSrc)
buzbeee88dfbf2012-03-05 11:19:57 -0800156{
buzbee408ad162012-06-06 16:45:18 -0700157 const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
Ian Rogers7caad772012-03-30 01:07:54 -0700158 // Add the table to the list - we'll process it later
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 FillArrayData *tabRec = (FillArrayData *)oatNew(cUnit, sizeof(FillArrayData),
160 true, kAllocData);
Ian Rogers7caad772012-03-30 01:07:54 -0700161 tabRec->table = table;
buzbee408ad162012-06-06 16:45:18 -0700162 tabRec->vaddr = cUnit->currentDalvikOffset;
Ian Rogers7caad772012-03-30 01:07:54 -0700163 u2 width = tabRec->table[1];
164 u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
165 tabRec->size = (size * width) + 8;
buzbeee88dfbf2012-03-05 11:19:57 -0800166
Ian Rogers7caad772012-03-30 01:07:54 -0700167 oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800168
Ian Rogers7caad772012-03-30 01:07:54 -0700169 // Making a call - use explicit registers
170 oatFlushAllRegs(cUnit); /* Everything to home location */
171 loadValueDirectFixed(cUnit, rlSrc, rARG0);
172 // Materialize a pointer to the fill data image
173 newLIR1(cUnit, kX86StartOfMethod, rARG2);
174 newLIR2(cUnit, kX86PcRelAdr, rARG1, (intptr_t)tabRec);
175 newLIR2(cUnit, kX86Add32RR, rARG1, rARG2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 callRuntimeHelperRegReg(cUnit,
177 ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode),
178 rARG0, rARG1);
buzbeee88dfbf2012-03-05 11:19:57 -0800179}
180
181void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
182{
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 UNIMPLEMENTED(WARNING) << "genNegFloat "
184 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
185 newLIR0(cUnit, kX86Bkpt);
buzbeea7678db2012-03-05 15:35:46 -0800186#if 0
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 RegLocation rlResult;
188 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
189 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
190 opRegRegImm(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, 0x80000000);
191 storeValue(cUnit, rlDest, rlResult);
buzbeee88dfbf2012-03-05 11:19:57 -0800192#endif
193}
194
195void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
196{
Bill Buzbeea114add2012-05-03 15:00:40 -0700197 UNIMPLEMENTED(WARNING) << "genNegDouble"
198 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
199 newLIR0(cUnit, kX86Bkpt);
buzbeee88dfbf2012-03-05 11:19:57 -0800200#if 0
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 RegLocation rlResult;
202 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
203 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
204 opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg, 0x80000000);
205 opRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
206 storeValueWide(cUnit, rlDest, rlResult);
buzbeee88dfbf2012-03-05 11:19:57 -0800207#endif
208}
209
buzbee408ad162012-06-06 16:45:18 -0700210LIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, int optFlags);
Ian Rogers7caad772012-03-30 01:07:54 -0700211void callRuntimeHelperReg(CompilationUnit* cUnit, int helperOffset, int arg0);
212
buzbeee88dfbf2012-03-05 11:19:57 -0800213/*
214 * TODO: implement fast path to short-circuit thin-lock case
215 */
buzbee408ad162012-06-06 16:45:18 -0700216void genMonitorEnter(CompilationUnit* cUnit, int optFlags, RegLocation rlSrc)
buzbeee88dfbf2012-03-05 11:19:57 -0800217{
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 oatFlushAllRegs(cUnit);
219 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
220 oatLockCallTemps(cUnit); // Prepare for explicit register usage
buzbee408ad162012-06-06 16:45:18 -0700221 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700222 // Go expensive route - artLockObjectFromCode(self, obj);
223 callRuntimeHelperReg(cUnit, ENTRYPOINT_OFFSET(pLockObjectFromCode), rARG0);
buzbeee88dfbf2012-03-05 11:19:57 -0800224}
225
226/*
227 * TODO: implement fast path to short-circuit thin-lock case
228 */
buzbee408ad162012-06-06 16:45:18 -0700229void genMonitorExit(CompilationUnit* cUnit, int optFlags, RegLocation rlSrc)
buzbeee88dfbf2012-03-05 11:19:57 -0800230{
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 oatFlushAllRegs(cUnit);
232 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
233 oatLockCallTemps(cUnit); // Prepare for explicit register usage
buzbee408ad162012-06-06 16:45:18 -0700234 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 // Go expensive route - UnlockObjectFromCode(obj);
236 callRuntimeHelperReg(cUnit, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARG0);
buzbeee88dfbf2012-03-05 11:19:57 -0800237}
238
239/*
240 * Compare two 64-bit values
241 * x = y return 0
242 * x < y return -1
243 * x > y return 1
244 *
245 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
246 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
247 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
248 * bnez res, finish
249 * sltu t0, x.lo, y.lo
250 * sgtu r1, x.lo, y.lo
251 * subu res, t0, t1
252 * finish:
253 *
254 */
buzbee408ad162012-06-06 16:45:18 -0700255void genCmpLong(CompilationUnit* cUnit, RegLocation rlDest,
buzbeee88dfbf2012-03-05 11:19:57 -0800256 RegLocation rlSrc1, RegLocation rlSrc2)
257{
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 oatFlushAllRegs(cUnit);
259 oatLockCallTemps(cUnit); // Prepare for explicit register usage
260 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
jeffhao644d5312012-05-03 19:04:49 -0700261 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
262 // Compute (r1:r0) = (r1:r0) - (r3:r2)
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 opRegReg(cUnit, kOpSub, r0, r2); // r0 = r0 - r2
264 opRegReg(cUnit, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
jeffhao1395b1e2012-06-13 18:05:13 -0700265 newLIR2(cUnit, kX86Set8R, r2, kX86CondL); // r2 = (r1:r0) < (r3:r2) ? 1 : 0
266 newLIR2(cUnit, kX86Movzx8RR, r2, r2);
267 opReg(cUnit, kOpNeg, r2); // r2 = -r2
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 opRegReg(cUnit, kOpOr, r0, r1); // r0 = high | low - sets ZF
jeffhao644d5312012-05-03 19:04:49 -0700269 newLIR2(cUnit, kX86Set8R, r0, kX86CondNz); // r0 = (r1:r0) != (r3:r2) ? 1 : 0
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 newLIR2(cUnit, kX86Movzx8RR, r0, r0);
jeffhao1395b1e2012-06-13 18:05:13 -0700271 opRegReg(cUnit, kOpOr, r0, r2); // r0 = r0 | r2
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 RegLocation rlResult = LOC_C_RETURN;
273 storeValue(cUnit, rlDest, rlResult);
buzbeee88dfbf2012-03-05 11:19:57 -0800274}
275
Ian Rogersb5d09b22012-03-06 22:14:17 -0800276X86ConditionCode oatX86ConditionEncoding(ConditionCode cond) {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700277 switch (cond) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800278 case kCondEq: return kX86CondEq;
279 case kCondNe: return kX86CondNe;
280 case kCondCs: return kX86CondC;
281 case kCondCc: return kX86CondNc;
282 case kCondMi: return kX86CondS;
283 case kCondPl: return kX86CondNs;
284 case kCondVs: return kX86CondO;
285 case kCondVc: return kX86CondNo;
286 case kCondHi: return kX86CondA;
287 case kCondLs: return kX86CondBe;
288 case kCondGe: return kX86CondGe;
289 case kCondLt: return kX86CondL;
290 case kCondGt: return kX86CondG;
291 case kCondLe: return kX86CondLe;
292 case kCondAl:
293 case kCondNv: LOG(FATAL) << "Should not reach here";
294 }
295 return kX86CondO;
296}
297
Bill Buzbeea114add2012-05-03 15:00:40 -0700298LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
299 int src2, LIR* target)
buzbeee88dfbf2012-03-05 11:19:57 -0800300{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800301 newLIR2(cUnit, kX86Cmp32RR, src1, src2);
302 X86ConditionCode cc = oatX86ConditionEncoding(cond);
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* lir operand for Jcc offset */ ,
304 cc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800305 branch->target = target;
306 return branch;
buzbeee88dfbf2012-03-05 11:19:57 -0800307}
308
309LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
310 int checkValue, LIR* target)
311{
Ian Rogers7caad772012-03-30 01:07:54 -0700312 if (false && (checkValue == 0) && (cond == kCondEq || cond == kCondNe)) {
313 // TODO: when checkValue == 0 and reg is rCX, use the jcxz/nz opcode
314 // newLIR2(cUnit, kX86Test32RR, reg, reg);
315 } else {
316 newLIR2(cUnit, kX86Cmp32RI, reg, checkValue);
317 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800318 X86ConditionCode cc = oatX86ConditionEncoding(cond);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700319 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800320 branch->target = target;
321 return branch;
buzbeee88dfbf2012-03-05 11:19:57 -0800322}
323
324LIR* opRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
325{
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 if (FPREG(rDest) || FPREG(rSrc))
327 return fpRegCopy(cUnit, rDest, rSrc);
328 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, kX86Mov32RR,
329 rDest, rSrc);
330 if (rDest == rSrc) {
331 res->flags.isNop = true;
332 }
333 return res;
buzbeee88dfbf2012-03-05 11:19:57 -0800334}
335
336LIR* opRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
337{
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 LIR *res = opRegCopyNoInsert(cUnit, rDest, rSrc);
339 oatAppendLIR(cUnit, res);
340 return res;
buzbeee88dfbf2012-03-05 11:19:57 -0800341}
342
343void opRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 int srcLo, int srcHi)
345{
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700346 bool destFP = FPREG(destLo) && FPREG(destHi);
347 bool srcFP = FPREG(srcLo) && FPREG(srcHi);
348 assert(FPREG(srcLo) == FPREG(srcHi));
349 assert(FPREG(destLo) == FPREG(destHi));
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700350 if (destFP) {
351 if (srcFP) {
352 opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
buzbeee88dfbf2012-03-05 11:19:57 -0800353 } else {
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700354 UNIMPLEMENTED(WARNING);
Ian Rogers7caad772012-03-30 01:07:54 -0700355 newLIR0(cUnit, kX86Bkpt);
buzbeee88dfbf2012-03-05 11:19:57 -0800356 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700357 } else {
358 if (srcFP) {
359 UNIMPLEMENTED(WARNING);
Ian Rogers7caad772012-03-30 01:07:54 -0700360 newLIR0(cUnit, kX86Bkpt);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700361 } else {
362 // Handle overlap
363 if (srcHi == destLo) {
buzbeee88dfbf2012-03-05 11:19:57 -0800364 opRegCopy(cUnit, destHi, srcHi);
365 opRegCopy(cUnit, destLo, srcLo);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700366 } else {
buzbeee88dfbf2012-03-05 11:19:57 -0800367 opRegCopy(cUnit, destLo, srcLo);
368 opRegCopy(cUnit, destHi, srcHi);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700369 }
buzbeee88dfbf2012-03-05 11:19:57 -0800370 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700371 }
buzbeee88dfbf2012-03-05 11:19:57 -0800372}
373
374} // namespace art