blob: 152574a1d7a82882401808bcc7c29feb594b32eb [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/*
buzbeea7678db2012-03-05 15:35:46 -080028 * The lack of pc-relative loads on X86 presents somewhat of a challenge
buzbeee88dfbf2012-03-05 11:19:57 -080029 * for our PIC switch table strategy. To materialize the current location
30 * we'll do a dummy JAL and reference our tables using r_RA as the
31 * base register. Note that r_RA will be used both as the base to
32 * locate the switch table data and as the reference base for the switch
33 * target offsets stored in the table. We'll use a special pseudo-instruction
34 * to represent the jal and trigger the construction of the
35 * switch table offsets (which will happen after final assembly and all
36 * labels are fixed).
37 *
38 * The test loop will look something like:
39 *
40 * ori rEnd, r_ZERO, #tableSize ; size in bytes
41 * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA
42 * nop ; opportunistically fill
43 * BaseLabel:
44 * addiu rBase, r_RA, <table> - <BaseLabel> ; table relative to BaseLabel
45 addu rEnd, rEnd, rBase ; end of table
46 * lw rVal, [rSP, vRegOff] ; Test Value
47 * loop:
48 * beq rBase, rEnd, done
49 * lw rKey, 0(rBase)
50 * addu rBase, 8
51 * bne rVal, rKey, loop
52 * lw rDisp, -4(rBase)
53 * addu r_RA, rDisp
54 * jr r_RA
55 * done:
56 *
57 */
58void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
59{
60 UNIMPLEMENTED(WARNING) << "genSparseSwitch";
buzbeea7678db2012-03-05 15:35:46 -080061 return;
buzbeee88dfbf2012-03-05 11:19:57 -080062#if 0
63 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
64 if (cUnit->printMe) {
65 dumpSparseSwitchTable(table);
66 }
67 // Add the table to the list - we'll process it later
68 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
69 true, kAllocData);
70 tabRec->table = table;
71 tabRec->vaddr = mir->offset;
72 int elements = table[1];
73 tabRec->targets = (LIR* *)oatNew(cUnit, elements * sizeof(LIR*), true,
74 kAllocLIR);
75 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
76
77 // The table is composed of 8-byte key/disp pairs
78 int byteSize = elements * 8;
79
80 int sizeHi = byteSize >> 16;
81 int sizeLo = byteSize & 0xffff;
82
83 int rEnd = oatAllocTemp(cUnit);
84 if (sizeHi) {
buzbeea7678db2012-03-05 15:35:46 -080085 newLIR2(cUnit, kX86Lui, rEnd, sizeHi);
buzbeee88dfbf2012-03-05 11:19:57 -080086 }
87 // Must prevent code motion for the curr pc pair
88 genBarrier(cUnit); // Scheduling barrier
buzbeea7678db2012-03-05 15:35:46 -080089 newLIR0(cUnit, kX86CurrPC); // Really a jal to .+8
buzbeee88dfbf2012-03-05 11:19:57 -080090 // Now, fill the branch delay slot
91 if (sizeHi) {
buzbeea7678db2012-03-05 15:35:46 -080092 newLIR3(cUnit, kX86Ori, rEnd, rEnd, sizeLo);
buzbeee88dfbf2012-03-05 11:19:57 -080093 } else {
buzbeea7678db2012-03-05 15:35:46 -080094 newLIR3(cUnit, kX86Ori, rEnd, r_ZERO, sizeLo);
buzbeee88dfbf2012-03-05 11:19:57 -080095 }
96 genBarrier(cUnit); // Scheduling barrier
97
98 // Construct BaseLabel and set up table base register
99 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
100 // Remember base label so offsets can be computed later
101 tabRec->anchor = baseLabel;
102 int rBase = oatAllocTemp(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800103 newLIR4(cUnit, kX86Delta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800104 opRegRegReg(cUnit, kOpAdd, rEnd, rEnd, rBase);
105
106 // Grab switch test value
107 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
108
109 // Test loop
110 int rKey = oatAllocTemp(cUnit);
111 LIR* loopLabel = newLIR0(cUnit, kPseudoTargetLabel);
112 LIR* exitBranch = opCmpBranch(cUnit , kCondEq, rBase, rEnd, NULL);
113 loadWordDisp(cUnit, rBase, 0, rKey);
114 opRegImm(cUnit, kOpAdd, rBase, 8);
115 opCmpBranch(cUnit, kCondNe, rlSrc.lowReg, rKey, loopLabel);
116 int rDisp = oatAllocTemp(cUnit);
117 loadWordDisp(cUnit, rBase, -4, rDisp);
118 opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp);
119 opReg(cUnit, kOpBx, r_RA);
120
121 // Loop exit
122 LIR* exitLabel = newLIR0(cUnit, kPseudoTargetLabel);
123 exitBranch->target = exitLabel;
124#endif
125}
126
127/*
128 * Code pattern will look something like:
129 *
130 * lw rVal
131 * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA
132 * nop ; opportunistically fill
133 * [subiu rVal, bias] ; Remove bias if lowVal != 0
134 * bound check -> done
135 * lw rDisp, [r_RA, rVal]
136 * addu r_RA, rDisp
137 * jr r_RA
138 * done:
139 */
140void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
141{
142 UNIMPLEMENTED(WARNING) << "genPackedSwitch";
143#if 0
144 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
145 if (cUnit->printMe) {
146 dumpPackedSwitchTable(table);
147 }
148 // Add the table to the list - we'll process it later
149 SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
150 true, kAllocData);
151 tabRec->table = table;
152 tabRec->vaddr = mir->offset;
153 int size = table[1];
154 tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
155 kAllocLIR);
156 oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
157
158 // Get the switch value
159 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
160
161 // Prepare the bias. If too big, handle 1st stage here
162 int lowKey = s4FromSwitchData(&table[2]);
163 bool largeBias = false;
164 int rKey;
165 if (lowKey == 0) {
166 rKey = rlSrc.lowReg;
167 } else if ((lowKey & 0xffff) != lowKey) {
168 rKey = oatAllocTemp(cUnit);
169 loadConstant(cUnit, rKey, lowKey);
170 largeBias = true;
171 } else {
172 rKey = oatAllocTemp(cUnit);
173 }
174
175 // Must prevent code motion for the curr pc pair
176 genBarrier(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800177 newLIR0(cUnit, kX86CurrPC); // Really a jal to .+8
buzbeee88dfbf2012-03-05 11:19:57 -0800178 // Now, fill the branch delay slot with bias strip
179 if (lowKey == 0) {
buzbeea7678db2012-03-05 15:35:46 -0800180 newLIR0(cUnit, kX86Nop);
buzbeee88dfbf2012-03-05 11:19:57 -0800181 } else {
182 if (largeBias) {
183 opRegRegReg(cUnit, kOpSub, rKey, rlSrc.lowReg, rKey);
184 } else {
185 opRegRegImm(cUnit, kOpSub, rKey, rlSrc.lowReg, lowKey);
186 }
187 }
188 genBarrier(cUnit); // Scheduling barrier
189
190 // Construct BaseLabel and set up table base register
191 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
192 // Remember base label so offsets can be computed later
193 tabRec->anchor = baseLabel;
194
195 // Bounds check - if < 0 or >= size continue following switch
196 LIR* branchOver = opCmpImmBranch(cUnit, kCondHi, rKey, size-1, NULL);
197
198 // Materialize the table base pointer
199 int rBase = oatAllocTemp(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800200 newLIR4(cUnit, kX86Delta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800201
202 // Load the displacement from the switch table
203 int rDisp = oatAllocTemp(cUnit);
204 loadBaseIndexed(cUnit, rBase, rKey, rDisp, 2, kWord);
205
206 // Add to r_AP and go
207 opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp);
208 opReg(cUnit, kOpBx, r_RA);
209
210 /* branchOver target here */
211 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
212 branchOver->target = (LIR*)target;
213#endif
214}
215
216/*
217 * Array data table format:
218 * ushort ident = 0x0300 magic value
219 * ushort width width of each element in the table
220 * uint size number of elements in the table
221 * ubyte data[size*width] table of data values (may contain a single-byte
222 * padding at the end)
223 *
224 * Total size is 4+(width * size + 1)/2 16-bit code units.
225 */
226void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
227{
228 UNIMPLEMENTED(WARNING) << "genFillArrayData";
229#if 0
230 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
231 // Add the table to the list - we'll process it later
232 FillArrayData *tabRec = (FillArrayData *)
233 oatNew(cUnit, sizeof(FillArrayData), true, kAllocData);
234 tabRec->table = table;
235 tabRec->vaddr = mir->offset;
236 u2 width = tabRec->table[1];
237 u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
238 tabRec->size = (size * width) + 8;
239
240 oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
241
242 // Making a call - use explicit registers
243 oatFlushAllRegs(cUnit); /* Everything to home location */
244 oatLockCallTemps(cUnit);
245 loadValueDirectFixed(cUnit, rlSrc, rARG0);
246
247 // Must prevent code motion for the curr pc pair
248 genBarrier(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800249 newLIR0(cUnit, kX86CurrPC); // Really a jal to .+8
buzbeee88dfbf2012-03-05 11:19:57 -0800250 // Now, fill the branch delay slot with the helper load
251 int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
252 pHandleFillArrayDataFromCode));
253 genBarrier(cUnit); // Scheduling barrier
254
255 // Construct BaseLabel and set up table base register
256 LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel);
257
258 // Materialize a pointer to the fill data image
buzbeea7678db2012-03-05 15:35:46 -0800259 newLIR4(cUnit, kX86Delta, rARG1, 0, (intptr_t)baseLabel, (intptr_t)tabRec);
buzbeee88dfbf2012-03-05 11:19:57 -0800260
261 // And go...
262 callRuntimeHelper(cUnit, rTgt); // ( array*, fill_data* )
buzbeea7678db2012-03-05 15:35:46 -0800263#endif
buzbeee88dfbf2012-03-05 11:19:57 -0800264}
265
266void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
267{
buzbeea7678db2012-03-05 15:35:46 -0800268 UNIMPLEMENTED(WARNING) << "genNegFloat";
269#if 0
buzbeee88dfbf2012-03-05 11:19:57 -0800270 RegLocation rlResult;
271 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
272 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
273 opRegRegImm(cUnit, kOpAdd, rlResult.lowReg,
274 rlSrc.lowReg, 0x80000000);
275 storeValue(cUnit, rlDest, rlResult);
276#endif
277}
278
279void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
280{
281 UNIMPLEMENTED(WARNING) << "genNegDouble";
282#if 0
283 RegLocation rlResult;
284 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
285 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
286 opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg,
287 0x80000000);
288 opRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
289 storeValueWide(cUnit, rlDest, rlResult);
290#endif
291}
292
293/*
294 * TODO: implement fast path to short-circuit thin-lock case
295 */
296void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
297{
298 UNIMPLEMENTED(WARNING) << "genMonitorEnter";
299#if 0
300 oatFlushAllRegs(cUnit);
301 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
302 oatLockCallTemps(cUnit); // Prepare for explicit register usage
303 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
304 // Go expensive route - artLockObjectFromCode(self, obj);
305 int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pLockObjectFromCode));
306 callRuntimeHelper(cUnit, rTgt);
307#endif
308}
309
310/*
311 * TODO: implement fast path to short-circuit thin-lock case
312 */
313void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
314{
315 UNIMPLEMENTED(WARNING) << "genMonitor";
316#if 0
317 oatFlushAllRegs(cUnit);
318 loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
319 oatLockCallTemps(cUnit); // Prepare for explicit register usage
320 genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
321 // Go expensive route - UnlockObjectFromCode(obj);
322 int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode));
323 callRuntimeHelper(cUnit, rTgt);
324#endif
325}
326
327/*
328 * Compare two 64-bit values
329 * x = y return 0
330 * x < y return -1
331 * x > y return 1
332 *
333 * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
334 * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
335 * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
336 * bnez res, finish
337 * sltu t0, x.lo, y.lo
338 * sgtu r1, x.lo, y.lo
339 * subu res, t0, t1
340 * finish:
341 *
342 */
343void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
344 RegLocation rlSrc1, RegLocation rlSrc2)
345{
346 UNIMPLEMENTED(WARNING) << "genCmpLong";
347#if 0
348 rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
349 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
350 int t0 = oatAllocTemp(cUnit);
351 int t1 = oatAllocTemp(cUnit);
352 RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
buzbeea7678db2012-03-05 15:35:46 -0800353 newLIR3(cUnit, kX86Slt, t0, rlSrc1.highReg, rlSrc2.highReg);
354 newLIR3(cUnit, kX86Slt, t1, rlSrc2.highReg, rlSrc1.highReg);
355 newLIR3(cUnit, kX86Subu, rlResult.lowReg, t1, t0);
buzbeee88dfbf2012-03-05 11:19:57 -0800356 LIR* branch = opCmpImmBranch(cUnit, kCondNe, rlResult.lowReg, 0, NULL);
buzbeea7678db2012-03-05 15:35:46 -0800357 newLIR3(cUnit, kX86Sltu, t0, rlSrc1.lowReg, rlSrc2.lowReg);
358 newLIR3(cUnit, kX86Sltu, t1, rlSrc2.lowReg, rlSrc1.lowReg);
359 newLIR3(cUnit, kX86Subu, rlResult.lowReg, t1, t0);
buzbeee88dfbf2012-03-05 11:19:57 -0800360 oatFreeTemp(cUnit, t0);
361 oatFreeTemp(cUnit, t1);
362 LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
363 branch->target = (LIR*)target;
364 storeValue(cUnit, rlDest, rlResult);
365#endif
366}
367
368LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
369 int src2, LIR* target)
370{
371 UNIMPLEMENTED(WARNING) << "opCmpBranch";
372 return NULL;
373#if 0
374 LIR* branch;
buzbeea7678db2012-03-05 15:35:46 -0800375 X86OpCode sltOp;
376 X86OpCode brOp;
buzbeee88dfbf2012-03-05 11:19:57 -0800377 bool cmpZero = false;
378 bool swapped = false;
379 switch(cond) {
380 case kCondEq:
buzbeea7678db2012-03-05 15:35:46 -0800381 brOp = kX86Beq;
buzbeee88dfbf2012-03-05 11:19:57 -0800382 cmpZero = true;
383 break;
384 case kCondNe:
buzbeea7678db2012-03-05 15:35:46 -0800385 brOp = kX86Bne;
buzbeee88dfbf2012-03-05 11:19:57 -0800386 cmpZero = true;
387 break;
388 case kCondCc:
buzbeea7678db2012-03-05 15:35:46 -0800389 sltOp = kX86Sltu;
390 brOp = kX86Bnez;
buzbeee88dfbf2012-03-05 11:19:57 -0800391 break;
392 case kCondCs:
buzbeea7678db2012-03-05 15:35:46 -0800393 sltOp = kX86Sltu;
394 brOp = kX86Beqz;
buzbeee88dfbf2012-03-05 11:19:57 -0800395 break;
396 case kCondGe:
buzbeea7678db2012-03-05 15:35:46 -0800397 sltOp = kX86Slt;
398 brOp = kX86Beqz;
buzbeee88dfbf2012-03-05 11:19:57 -0800399 break;
400 case kCondGt:
buzbeea7678db2012-03-05 15:35:46 -0800401 sltOp = kX86Slt;
402 brOp = kX86Bnez;
buzbeee88dfbf2012-03-05 11:19:57 -0800403 swapped = true;
404 break;
405 case kCondLe:
buzbeea7678db2012-03-05 15:35:46 -0800406 sltOp = kX86Slt;
407 brOp = kX86Beqz;
buzbeee88dfbf2012-03-05 11:19:57 -0800408 swapped = true;
409 break;
410 case kCondLt:
buzbeea7678db2012-03-05 15:35:46 -0800411 sltOp = kX86Slt;
412 brOp = kX86Bnez;
buzbeee88dfbf2012-03-05 11:19:57 -0800413 break;
414 case kCondHi: // Gtu
buzbeea7678db2012-03-05 15:35:46 -0800415 sltOp = kX86Sltu;
416 brOp = kX86Bnez;
buzbeee88dfbf2012-03-05 11:19:57 -0800417 swapped = true;
418 break;
419 default:
420 LOG(FATAL) << "No support for ConditionCode: " << (int) cond;
421 return NULL;
422 }
423 if (cmpZero) {
424 branch = newLIR2(cUnit, brOp, src1, src2);
425 } else {
426 int tReg = oatAllocTemp(cUnit);
427 if (swapped) {
428 newLIR3(cUnit, sltOp, tReg, src2, src1);
429 } else {
430 newLIR3(cUnit, sltOp, tReg, src1, src2);
431 }
432 branch = newLIR1(cUnit, brOp, tReg);
433 oatFreeTemp(cUnit, tReg);
434 }
435 branch->target = target;
436 return branch;
437#endif
438}
439
440LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
441 int checkValue, LIR* target)
442{
buzbeea7678db2012-03-05 15:35:46 -0800443 UNIMPLEMENTED(WARNING) << "opCmpImmBranch";
buzbeee88dfbf2012-03-05 11:19:57 -0800444 return NULL;
445#if 0
446 LIR* branch;
447 if (checkValue != 0) {
448 // TUNING: handle s16 & kCondLt/Mi case using slti
449 int tReg = oatAllocTemp(cUnit);
450 loadConstant(cUnit, tReg, checkValue);
451 branch = opCmpBranch(cUnit, cond, reg, tReg, target);
452 oatFreeTemp(cUnit, tReg);
453 return branch;
454 }
buzbeea7678db2012-03-05 15:35:46 -0800455 X86OpCode opc;
buzbeee88dfbf2012-03-05 11:19:57 -0800456 switch(cond) {
buzbeea7678db2012-03-05 15:35:46 -0800457 case kCondEq: opc = kX86Beqz; break;
458 case kCondGe: opc = kX86Bgez; break;
459 case kCondGt: opc = kX86Bgtz; break;
460 case kCondLe: opc = kX86Blez; break;
buzbeee88dfbf2012-03-05 11:19:57 -0800461 //case KCondMi:
buzbeea7678db2012-03-05 15:35:46 -0800462 case kCondLt: opc = kX86Bltz; break;
463 case kCondNe: opc = kX86Bnez; break;
buzbeee88dfbf2012-03-05 11:19:57 -0800464 default:
465 // Tuning: use slti when applicable
466 int tReg = oatAllocTemp(cUnit);
467 loadConstant(cUnit, tReg, checkValue);
468 branch = opCmpBranch(cUnit, cond, reg, tReg, target);
469 oatFreeTemp(cUnit, tReg);
470 return branch;
471 }
472 branch = newLIR1(cUnit, opc, reg);
473 branch->target = target;
474 return branch;
475#endif
476}
477
478LIR* opRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
479{
480 UNIMPLEMENTED(WARNING) << "opRegCopyNoInsert";
481 return NULL;
482#if 0
483 if (FPREG(rDest) || FPREG(rSrc))
484 return fpRegCopy(cUnit, rDest, rSrc);
buzbeea7678db2012-03-05 15:35:46 -0800485 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, kX86Move,
buzbeee88dfbf2012-03-05 11:19:57 -0800486 rDest, rSrc);
487 if (rDest == rSrc) {
488 res->flags.isNop = true;
489 }
490 return res;
491#endif
492}
493
494LIR* opRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
495{
496 LIR *res = opRegCopyNoInsert(cUnit, rDest, rSrc);
497 oatAppendLIR(cUnit, (LIR*)res);
498 return res;
499}
500
501void opRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
502 int srcLo, int srcHi)
503{
504 UNIMPLEMENTED(WARNING) << "opRegCopyWide";
505#if 0
506 bool destFP = FPREG(destLo) && FPREG(destHi);
507 bool srcFP = FPREG(srcLo) && FPREG(srcHi);
508 assert(FPREG(srcLo) == FPREG(srcHi));
509 assert(FPREG(destLo) == FPREG(destHi));
510 if (destFP) {
511 if (srcFP) {
512 opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
513 } else {
514 /* note the operands are swapped for the mtc1 instr */
buzbeea7678db2012-03-05 15:35:46 -0800515 newLIR2(cUnit, kX86Mtc1, srcLo, destLo);
516 newLIR2(cUnit, kX86Mtc1, srcHi, destHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800517 }
518 } else {
519 if (srcFP) {
buzbeea7678db2012-03-05 15:35:46 -0800520 newLIR2(cUnit, kX86Mfc1, destLo, srcLo);
521 newLIR2(cUnit, kX86Mfc1, destHi, srcHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800522 } else {
523 // Handle overlap
524 if (srcHi == destLo) {
525 opRegCopy(cUnit, destHi, srcHi);
526 opRegCopy(cUnit, destLo, srcLo);
527 } else {
528 opRegCopy(cUnit, destLo, srcLo);
529 opRegCopy(cUnit, destHi, srcHi);
530 }
531 }
532 }
533 // Handle overlap
534 if (srcHi == destLo) {
535 opRegCopy(cUnit, destHi, srcHi);
536 opRegCopy(cUnit, destLo, srcLo);
537 } else {
538 opRegCopy(cUnit, destLo, srcLo);
539 opRegCopy(cUnit, destHi, srcHi);
540 }
541#endif
542}
543
544} // namespace art