blob: 6f33b56eaea6f794d22ab827aa99b7703579e57b [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
27/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080028 * Perform register memory operation.
29 */
30LIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode,
31 int reg1, int base, int offset, MIR* mir, ThrowKind kind)
32{
33 LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind,
34 mir ? mir->offset : 0, reg1, base, offset);
35 opRegMem(cUnit, kOpCmp, reg1, base, offset);
36 LIR* branch = opCondBranch(cUnit, cCode, tgt);
37 // Remember branch target - will process later
38 oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
39 return branch;
40}
41
42/*
buzbeea7678db2012-03-05 15:35:46 -080043 * The lack of pc-relative loads on X86 presents somewhat of a challenge
buzbeee88dfbf2012-03-05 11:19:57 -080044 * for our PIC switch table strategy. To materialize the current location
45 * we'll do a dummy JAL and reference our tables using r_RA as the
46 * base register. Note that r_RA will be used both as the base to
47 * locate the switch table data and as the reference base for the switch
48 * target offsets stored in the table. We'll use a special pseudo-instruction
49 * to represent the jal and trigger the construction of the
50 * switch table offsets (which will happen after final assembly and all
51 * labels are fixed).
52 *
53 * The test loop will look something like:
54 *
55 * ori rEnd, r_ZERO, #tableSize ; size in bytes
56 * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA
57 * nop ; opportunistically fill
58 * BaseLabel:
59 * addiu rBase, r_RA, <table> - <BaseLabel> ; table relative to BaseLabel
60 addu rEnd, rEnd, rBase ; end of table
61 * lw rVal, [rSP, vRegOff] ; Test Value
62 * loop:
63 * beq rBase, rEnd, done
64 * lw rKey, 0(rBase)
65 * addu rBase, 8
66 * bne rVal, rKey, loop
67 * lw rDisp, -4(rBase)
68 * addu r_RA, rDisp
69 * jr r_RA
70 * done:
71 *
72 */
73void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
74{
75 UNIMPLEMENTED(WARNING) << "genSparseSwitch";
buzbeea7678db2012-03-05 15:35:46 -080076 return;
buzbeee88dfbf2012-03-05 11:19:57 -080077#if 0
78 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
79 if (cUnit->printMe) {
80 dumpSparseSwitchTable(table);
81 }
82 // Add the table to the list - we'll process it later
83 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
84 true, kAllocData);
85 tabRec->table = table;
86 tabRec->vaddr = mir->offset;
87 int elements = table[1];
88 tabRec->targets = (LIR* *)oatNew(cUnit, elements * sizeof(LIR*), true,
89 kAllocLIR);
90 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
91
92 // The table is composed of 8-byte key/disp pairs
93 int byteSize = elements * 8;
94
95 int sizeHi = byteSize >> 16;
96 int sizeLo = byteSize & 0xffff;
97
98 int rEnd = oatAllocTemp(cUnit);
99 if (sizeHi) {
buzbeea7678db2012-03-05 15:35:46 -0800100 newLIR2(cUnit, kX86Lui, rEnd, sizeHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800101 }
102 // Must prevent code motion for the curr pc pair
103 genBarrier(cUnit); // Scheduling barrier
buzbeea7678db2012-03-05 15:35:46 -0800104 newLIR0(cUnit, kX86CurrPC); // Really a jal to .+8
buzbeee88dfbf2012-03-05 11:19:57 -0800105 // Now, fill the branch delay slot
106 if (sizeHi) {
buzbeea7678db2012-03-05 15:35:46 -0800107 newLIR3(cUnit, kX86Ori, rEnd, rEnd, sizeLo);
buzbeee88dfbf2012-03-05 11:19:57 -0800108 } else {
buzbeea7678db2012-03-05 15:35:46 -0800109 newLIR3(cUnit, kX86Ori, rEnd, r_ZERO, sizeLo);
buzbeee88dfbf2012-03-05 11:19:57 -0800110 }
111 genBarrier(cUnit); // Scheduling barrier
112
113 // Construct BaseLabel and set up table base register
114 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
115 // Remember base label so offsets can be computed later
116 tabRec->anchor = baseLabel;
117 int rBase = oatAllocTemp(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800118 newLIR4(cUnit, kX86Delta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800119 opRegRegReg(cUnit, kOpAdd, rEnd, rEnd, rBase);
120
121 // Grab switch test value
122 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
123
124 // Test loop
125 int rKey = oatAllocTemp(cUnit);
126 LIR* loopLabel = newLIR0(cUnit, kPseudoTargetLabel);
127 LIR* exitBranch = opCmpBranch(cUnit , kCondEq, rBase, rEnd, NULL);
128 loadWordDisp(cUnit, rBase, 0, rKey);
129 opRegImm(cUnit, kOpAdd, rBase, 8);
130 opCmpBranch(cUnit, kCondNe, rlSrc.lowReg, rKey, loopLabel);
131 int rDisp = oatAllocTemp(cUnit);
132 loadWordDisp(cUnit, rBase, -4, rDisp);
133 opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp);
134 opReg(cUnit, kOpBx, r_RA);
135
136 // Loop exit
137 LIR* exitLabel = newLIR0(cUnit, kPseudoTargetLabel);
138 exitBranch->target = exitLabel;
139#endif
140}
141
142/*
143 * Code pattern will look something like:
144 *
145 * lw rVal
146 * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA
147 * nop ; opportunistically fill
148 * [subiu rVal, bias] ; Remove bias if lowVal != 0
149 * bound check -> done
150 * lw rDisp, [r_RA, rVal]
151 * addu r_RA, rDisp
152 * jr r_RA
153 * done:
154 */
155void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
156{
157 UNIMPLEMENTED(WARNING) << "genPackedSwitch";
158#if 0
159 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
160 if (cUnit->printMe) {
161 dumpPackedSwitchTable(table);
162 }
163 // Add the table to the list - we'll process it later
164 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
165 true, kAllocData);
166 tabRec->table = table;
167 tabRec->vaddr = mir->offset;
168 int size = table[1];
169 tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
170 kAllocLIR);
171 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
172
173 // Get the switch value
174 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
175
176 // Prepare the bias. If too big, handle 1st stage here
177 int lowKey = s4FromSwitchData(&table[2]);
178 bool largeBias = false;
179 int rKey;
180 if (lowKey == 0) {
181 rKey = rlSrc.lowReg;
182 } else if ((lowKey & 0xffff) != lowKey) {
183 rKey = oatAllocTemp(cUnit);
184 loadConstant(cUnit, rKey, lowKey);
185 largeBias = true;
186 } else {
187 rKey = oatAllocTemp(cUnit);
188 }
189
190 // Must prevent code motion for the curr pc pair
191 genBarrier(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800192 newLIR0(cUnit, kX86CurrPC); // Really a jal to .+8
buzbeee88dfbf2012-03-05 11:19:57 -0800193 // Now, fill the branch delay slot with bias strip
194 if (lowKey == 0) {
buzbeea7678db2012-03-05 15:35:46 -0800195 newLIR0(cUnit, kX86Nop);
buzbeee88dfbf2012-03-05 11:19:57 -0800196 } else {
197 if (largeBias) {
198 opRegRegReg(cUnit, kOpSub, rKey, rlSrc.lowReg, rKey);
199 } else {
200 opRegRegImm(cUnit, kOpSub, rKey, rlSrc.lowReg, lowKey);
201 }
202 }
203 genBarrier(cUnit); // Scheduling barrier
204
205 // Construct BaseLabel and set up table base register
206 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
207 // Remember base label so offsets can be computed later
208 tabRec->anchor = baseLabel;
209
210 // Bounds check - if < 0 or >= size continue following switch
211 LIR* branchOver = opCmpImmBranch(cUnit, kCondHi, rKey, size-1, NULL);
212
213 // Materialize the table base pointer
214 int rBase = oatAllocTemp(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800215 newLIR4(cUnit, kX86Delta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800216
217 // Load the displacement from the switch table
218 int rDisp = oatAllocTemp(cUnit);
219 loadBaseIndexed(cUnit, rBase, rKey, rDisp, 2, kWord);
220
221 // Add to r_AP and go
222 opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp);
223 opReg(cUnit, kOpBx, r_RA);
224
225 /* branchOver target here */
226 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
227 branchOver->target = (LIR*)target;
228#endif
229}
230
231/*
232 * Array data table format:
233 * ushort ident = 0x0300 magic value
234 * ushort width width of each element in the table
235 * uint size number of elements in the table
236 * ubyte data[size*width] table of data values (may contain a single-byte
237 * padding at the end)
238 *
239 * Total size is 4+(width * size + 1)/2 16-bit code units.
240 */
241void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
242{
243 UNIMPLEMENTED(WARNING) << "genFillArrayData";
244#if 0
245 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
246 // Add the table to the list - we'll process it later
247 FillArrayData *tabRec = (FillArrayData *)
248 oatNew(cUnit, sizeof(FillArrayData), true, kAllocData);
249 tabRec->table = table;
250 tabRec->vaddr = mir->offset;
251 u2 width = tabRec->table[1];
252 u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
253 tabRec->size = (size * width) + 8;
254
255 oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
256
257 // Making a call - use explicit registers
258 oatFlushAllRegs(cUnit); /* Everything to home location */
259 oatLockCallTemps(cUnit);
260 loadValueDirectFixed(cUnit, rlSrc, rARG0);
261
262 // Must prevent code motion for the curr pc pair
263 genBarrier(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800264 newLIR0(cUnit, kX86CurrPC); // Really a jal to .+8
buzbeee88dfbf2012-03-05 11:19:57 -0800265 // Now, fill the branch delay slot with the helper load
266 int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
267 pHandleFillArrayDataFromCode));
268 genBarrier(cUnit); // Scheduling barrier
269
270 // Construct BaseLabel and set up table base register
271 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
272
273 // Materialize a pointer to the fill data image
buzbeea7678db2012-03-05 15:35:46 -0800274 newLIR4(cUnit, kX86Delta, rARG1, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800275
276 // And go...
277 callRuntimeHelper(cUnit, rTgt); // ( array*, fill_data* )
buzbeea7678db2012-03-05 15:35:46 -0800278#endif
buzbeee88dfbf2012-03-05 11:19:57 -0800279}
280
281void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
282{
buzbeea7678db2012-03-05 15:35:46 -0800283 UNIMPLEMENTED(WARNING) << "genNegFloat";
284#if 0
buzbeee88dfbf2012-03-05 11:19:57 -0800285 RegLocation rlResult;
286 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
287 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
288 opRegRegImm(cUnit, kOpAdd, rlResult.lowReg,
289 rlSrc.lowReg, 0x80000000);
290 storeValue(cUnit, rlDest, rlResult);
291#endif
292}
293
294void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
295{
296 UNIMPLEMENTED(WARNING) << "genNegDouble";
297#if 0
298 RegLocation rlResult;
299 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
300 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
301 opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg,
302 0x80000000);
303 opRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
304 storeValueWide(cUnit, rlDest, rlResult);
305#endif
306}
307
308/*
309 * TODO: implement fast path to short-circuit thin-lock case
310 */
311void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
312{
313 UNIMPLEMENTED(WARNING) << "genMonitorEnter";
314#if 0
315 oatFlushAllRegs(cUnit);
316 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
317 oatLockCallTemps(cUnit); // Prepare for explicit register usage
318 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
319 // Go expensive route - artLockObjectFromCode(self, obj);
320 int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pLockObjectFromCode));
321 callRuntimeHelper(cUnit, rTgt);
322#endif
323}
324
325/*
326 * TODO: implement fast path to short-circuit thin-lock case
327 */
328void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
329{
330 UNIMPLEMENTED(WARNING) << "genMonitor";
331#if 0
332 oatFlushAllRegs(cUnit);
333 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
334 oatLockCallTemps(cUnit); // Prepare for explicit register usage
335 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
336 // Go expensive route - UnlockObjectFromCode(obj);
337 int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode));
338 callRuntimeHelper(cUnit, rTgt);
339#endif
340}
341
342/*
343 * Compare two 64-bit values
344 * x = y return 0
345 * x < y return -1
346 * x > y return 1
347 *
348 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
349 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
350 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
351 * bnez res, finish
352 * sltu t0, x.lo, y.lo
353 * sgtu r1, x.lo, y.lo
354 * subu res, t0, t1
355 * finish:
356 *
357 */
358void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
359 RegLocation rlSrc1, RegLocation rlSrc2)
360{
361 UNIMPLEMENTED(WARNING) << "genCmpLong";
362#if 0
363 rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
364 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
365 int t0 = oatAllocTemp(cUnit);
366 int t1 = oatAllocTemp(cUnit);
367 RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeea7678db2012-03-05 15:35:46 -0800368 newLIR3(cUnit, kX86Slt, t0, rlSrc1.highReg, rlSrc2.highReg);
369 newLIR3(cUnit, kX86Slt, t1, rlSrc2.highReg, rlSrc1.highReg);
370 newLIR3(cUnit, kX86Subu, rlResult.lowReg, t1, t0);
buzbeee88dfbf2012-03-05 11:19:57 -0800371 LIR* branch = opCmpImmBranch(cUnit, kCondNe, rlResult.lowReg, 0, NULL);
buzbeea7678db2012-03-05 15:35:46 -0800372 newLIR3(cUnit, kX86Sltu, t0, rlSrc1.lowReg, rlSrc2.lowReg);
373 newLIR3(cUnit, kX86Sltu, t1, rlSrc2.lowReg, rlSrc1.lowReg);
374 newLIR3(cUnit, kX86Subu, rlResult.lowReg, t1, t0);
buzbeee88dfbf2012-03-05 11:19:57 -0800375 oatFreeTemp(cUnit, t0);
376 oatFreeTemp(cUnit, t1);
377 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
378 branch->target = (LIR*)target;
379 storeValue(cUnit, rlDest, rlResult);
380#endif
381}
382
Ian Rogersb5d09b22012-03-06 22:14:17 -0800383X86ConditionCode oatX86ConditionEncoding(ConditionCode cond) {
384 switch(cond) {
385 case kCondEq: return kX86CondEq;
386 case kCondNe: return kX86CondNe;
387 case kCondCs: return kX86CondC;
388 case kCondCc: return kX86CondNc;
389 case kCondMi: return kX86CondS;
390 case kCondPl: return kX86CondNs;
391 case kCondVs: return kX86CondO;
392 case kCondVc: return kX86CondNo;
393 case kCondHi: return kX86CondA;
394 case kCondLs: return kX86CondBe;
395 case kCondGe: return kX86CondGe;
396 case kCondLt: return kX86CondL;
397 case kCondGt: return kX86CondG;
398 case kCondLe: return kX86CondLe;
399 case kCondAl:
400 case kCondNv: LOG(FATAL) << "Should not reach here";
401 }
402 return kX86CondO;
403}
404
405LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, int src2, LIR* target)
buzbeee88dfbf2012-03-05 11:19:57 -0800406{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800407 newLIR2(cUnit, kX86Cmp32RR, src1, src2);
408 X86ConditionCode cc = oatX86ConditionEncoding(cond);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700409 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800410 branch->target = target;
411 return branch;
buzbeee88dfbf2012-03-05 11:19:57 -0800412}
413
414LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
415 int checkValue, LIR* target)
416{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800417 // TODO: when checkValue == 0 and reg is rCX, use the jcxz/nz opcode
418 newLIR2(cUnit, kX86Cmp32RI, reg, checkValue);
419 X86ConditionCode cc = oatX86ConditionEncoding(cond);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700420 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800421 branch->target = target;
422 return branch;
buzbeee88dfbf2012-03-05 11:19:57 -0800423}
424
425LIR* opRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
426{
buzbeee88dfbf2012-03-05 11:19:57 -0800427 if (FPREG(rDest) || FPREG(rSrc))
428 return fpRegCopy(cUnit, rDest, rSrc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800429 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, kX86Mov32RR,
buzbeee88dfbf2012-03-05 11:19:57 -0800430 rDest, rSrc);
431 if (rDest == rSrc) {
432 res->flags.isNop = true;
433 }
434 return res;
buzbeee88dfbf2012-03-05 11:19:57 -0800435}
436
437LIR* opRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
438{
439 LIR *res = opRegCopyNoInsert(cUnit, rDest, rSrc);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700440 oatAppendLIR(cUnit, res);
buzbeee88dfbf2012-03-05 11:19:57 -0800441 return res;
442}
443
444void opRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700445 int srcLo, int srcHi) {
446 bool destFP = FPREG(destLo) && FPREG(destHi);
447 bool srcFP = FPREG(srcLo) && FPREG(srcHi);
448 assert(FPREG(srcLo) == FPREG(srcHi));
449 assert(FPREG(destLo) == FPREG(destHi));
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700450 if (destFP) {
451 if (srcFP) {
452 opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
buzbeee88dfbf2012-03-05 11:19:57 -0800453 } else {
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700454 UNIMPLEMENTED(WARNING);
buzbeee88dfbf2012-03-05 11:19:57 -0800455 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700456 } else {
457 if (srcFP) {
458 UNIMPLEMENTED(WARNING);
459 } else {
460 // Handle overlap
461 if (srcHi == destLo) {
buzbeee88dfbf2012-03-05 11:19:57 -0800462 opRegCopy(cUnit, destHi, srcHi);
463 opRegCopy(cUnit, destLo, srcLo);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700464 } else {
buzbeee88dfbf2012-03-05 11:19:57 -0800465 opRegCopy(cUnit, destLo, srcLo);
466 opRegCopy(cUnit, destHi, srcHi);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700467 }
buzbeee88dfbf2012-03-05 11:19:57 -0800468 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700469 }
buzbeee88dfbf2012-03-05 11:19:57 -0800470}
471
472} // namespace art