• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 /*
18  * This file contains codegen for the Thumb ISA and is intended to be
19  * includes by:
20  *
21  *        Codegen-$(TARGET_ARCH_VARIANT).c
22  *
23  */
24 
25 static int coreTemps[] = {r0, r1, r2, r3, r4PC, r7, r8, r9, r10, r11, r12};
26 static int fpTemps[] = {fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
27                         fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31};
28 
encodeImmSingle(int value)29 static int encodeImmSingle(int value)
30 {
31     int res;
32     int bitA =    (value & 0x80000000) >> 31;
33     int notBitB = (value & 0x40000000) >> 30;
34     int bitB =    (value & 0x20000000) >> 29;
35     int bSmear =  (value & 0x3e000000) >> 25;
36     int slice =   (value & 0x01f80000) >> 19;
37     int zeroes =  (value & 0x0007ffff);
38     if (zeroes != 0)
39         return -1;
40     if (bitB) {
41         if ((notBitB != 0) || (bSmear != 0x1f))
42             return -1;
43     } else {
44         if ((notBitB != 1) || (bSmear != 0x0))
45             return -1;
46     }
47     res = (bitA << 7) | (bitB << 6) | slice;
48     return res;
49 }
50 
loadFPConstantValue(CompilationUnit * cUnit,int rDest,int value)51 static ArmLIR *loadFPConstantValue(CompilationUnit *cUnit, int rDest,
52                                    int value)
53 {
54     int encodedImm = encodeImmSingle(value);
55     assert(SINGLEREG(rDest));
56     if (encodedImm >= 0) {
57         return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
58     }
59     ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 0);
60     if (dataTarget == NULL) {
61         dataTarget = addWordData(cUnit, value, false);
62     }
63     ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true);
64     loadPcRel->opCode = kThumb2Vldrs;
65     loadPcRel->generic.target = (LIR *) dataTarget;
66     loadPcRel->operands[0] = rDest;
67     loadPcRel->operands[1] = rpc;
68     setupResourceMasks(loadPcRel);
69     // Self-cosim workaround.
70     if (rDest != rlr)
71         setMemRefType(loadPcRel, true, kLiteral);
72     loadPcRel->aliasInfo = dataTarget->operands[0];
73     dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
74     return loadPcRel;
75 }
76 
leadingZeros(u4 val)77 static int leadingZeros(u4 val)
78 {
79     u4 alt;
80     int n;
81     int count;
82 
83     count = 16;
84     n = 32;
85     do {
86         alt = val >> count;
87         if (alt != 0) {
88             n = n - count;
89             val = alt;
90         }
91         count >>= 1;
92     } while (count);
93     return n - val;
94 }
95 
96 /*
97  * Determine whether value can be encoded as a Thumb2 modified
98  * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
99  */
modifiedImmediate(u4 value)100 static int modifiedImmediate(u4 value)
101 {
102    int zLeading;
103    int zTrailing;
104    u4 b0 = value & 0xff;
105 
106    /* Note: case of value==0 must use 0:000:0:0000000 encoding */
107    if (value <= 0xFF)
108        return b0;  // 0:000:a:bcdefgh
109    if (value == ((b0 << 16) | b0))
110        return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
111    if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
112        return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
113    b0 = (value >> 8) & 0xff;
114    if (value == ((b0 << 24) | (b0 << 8)))
115        return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
116    /* Can we do it with rotation? */
117    zLeading = leadingZeros(value);
118    zTrailing = 32 - leadingZeros(~value & (value - 1));
119    /* A run of eight or fewer active bits? */
120    if ((zLeading + zTrailing) < 24)
121        return -1;  /* No - bail */
122    /* left-justify the constant, discarding msb (known to be 1) */
123    value <<= zLeading + 1;
124    /* Create bcdefgh */
125    value >>= 25;
126    /* Put it all together */
127    return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
128 }
129 
130 /*
131  * Load a immediate using a shortcut if possible; otherwise
132  * grab from the per-translation literal pool.
133  *
134  * No additional register clobbering operation performed. Use this version when
135  * 1) rDest is freshly returned from dvmCompilerAllocTemp or
136  * 2) The codegen is under fixed register usage
137  */
loadConstantNoClobber(CompilationUnit * cUnit,int rDest,int value)138 static ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
139                                      int value)
140 {
141     ArmLIR *res;
142     int modImm;
143 
144     if (FPREG(rDest)) {
145         return loadFPConstantValue(cUnit, rDest, value);
146     }
147 
148     /* See if the value can be constructed cheaply */
149     if (LOWREG(rDest) && (value >= 0) && (value <= 255)) {
150         return newLIR2(cUnit, kThumbMovImm, rDest, value);
151     }
152     /* Check Modified immediate special cases */
153     modImm = modifiedImmediate(value);
154     if (modImm >= 0) {
155         res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
156         return res;
157     }
158     modImm = modifiedImmediate(~value);
159     if (modImm >= 0) {
160         res = newLIR2(cUnit, kThumb2MvnImmShift, rDest, modImm);
161         return res;
162     }
163     /* 16-bit immediate? */
164     if ((value & 0xffff) == value) {
165         res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
166         return res;
167     }
168     /* No shortcut - go ahead and use literal pool */
169     ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 0);
170     if (dataTarget == NULL) {
171         dataTarget = addWordData(cUnit, value, false);
172     }
173     ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true);
174     loadPcRel->opCode = kThumb2LdrPcRel12;
175     loadPcRel->generic.target = (LIR *) dataTarget;
176     loadPcRel->operands[0] = rDest;
177     setupResourceMasks(loadPcRel);
178     /*
179      * Special case for literal loads with a link register target.
180      * Self-cosim mode will insert calls prior to heap references
181      * after optimization, and those will destroy r14.  The easy
182      * workaround is to treat literal loads into r14 as heap references
183      * to prevent them from being hoisted.  Use of r14 in this manner
184      * is currently rare.  Revisit if that changes.
185      */
186     if (rDest != rlr)
187         setMemRefType(loadPcRel, true, kLiteral);
188     loadPcRel->aliasInfo = dataTarget->operands[0];
189     res = loadPcRel;
190     dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
191 
192     /*
193      * To save space in the constant pool, we use the ADD_RRI8 instruction to
194      * add up to 255 to an existing constant value.
195      */
196     if (dataTarget->operands[0] != value) {
197         opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
198     }
199     return res;
200 }
201 
202 /*
203  * Load an immediate value into a fixed or temp register.  Target
204  * register is clobbered, and marked inUse.
205  */
loadConstant(CompilationUnit * cUnit,int rDest,int value)206 static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
207 {
208     if (dvmCompilerIsTemp(cUnit, rDest)) {
209         dvmCompilerClobber(cUnit, rDest);
210         dvmCompilerMarkInUse(cUnit, rDest);
211     }
212     return loadConstantNoClobber(cUnit, rDest, value);
213 }
214 
opNone(CompilationUnit * cUnit,OpKind op)215 static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
216 {
217     ArmOpCode opCode = kThumbBkpt;
218     switch (op) {
219         case kOpUncondBr:
220             opCode = kThumbBUncond;
221             break;
222         default:
223             assert(0);
224     }
225     return newLIR0(cUnit, opCode);
226 }
227 
opCondBranch(CompilationUnit * cUnit,ArmConditionCode cc)228 static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
229 {
230     return newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */, cc);
231 }
232 
opImm(CompilationUnit * cUnit,OpKind op,int value)233 static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
234 {
235     ArmOpCode opCode = kThumbBkpt;
236     switch (op) {
237         case kOpPush:
238             opCode = ((value & 0xff00) != 0) ? kThumb2Push : kThumbPush;
239             break;
240         case kOpPop:
241             opCode = ((value & 0xff00) != 0) ? kThumb2Pop : kThumbPop;
242             break;
243         default:
244             assert(0);
245     }
246     return newLIR1(cUnit, opCode, value);
247 }
248 
opReg(CompilationUnit * cUnit,OpKind op,int rDestSrc)249 static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
250 {
251     ArmOpCode opCode = kThumbBkpt;
252     switch (op) {
253         case kOpBlx:
254             opCode = kThumbBlxR;
255             break;
256         default:
257             assert(0);
258     }
259     return newLIR1(cUnit, opCode, rDestSrc);
260 }
261 
opRegRegShift(CompilationUnit * cUnit,OpKind op,int rDestSrc1,int rSrc2,int shift)262 static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
263                         int rSrc2, int shift)
264 {
265     bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
266     ArmOpCode opCode = kThumbBkpt;
267     switch (op) {
268         case kOpAdc:
269             opCode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
270             break;
271         case kOpAnd:
272             opCode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
273             break;
274         case kOpBic:
275             opCode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
276             break;
277         case kOpCmn:
278             assert(shift == 0);
279             opCode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
280             break;
281         case kOpCmp:
282             if (thumbForm)
283                 opCode = kThumbCmpRR;
284             else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
285                 opCode = kThumbCmpHH;
286             else if ((shift == 0) && LOWREG(rDestSrc1))
287                 opCode = kThumbCmpLH;
288             else if (shift == 0)
289                 opCode = kThumbCmpHL;
290             else
291                 opCode = kThumb2CmpRR;
292             break;
293         case kOpXor:
294             opCode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
295             break;
296         case kOpMov:
297             assert(shift == 0);
298             if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
299                 opCode = kThumbMovRR;
300             else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
301                 opCode = kThumbMovRR_H2H;
302             else if (LOWREG(rDestSrc1))
303                 opCode = kThumbMovRR_H2L;
304             else
305                 opCode = kThumbMovRR_L2H;
306             break;
307         case kOpMul:
308             assert(shift == 0);
309             opCode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
310             break;
311         case kOpMvn:
312             opCode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
313             break;
314         case kOpNeg:
315             assert(shift == 0);
316             opCode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
317             break;
318         case kOpOr:
319             opCode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
320             break;
321         case kOpSbc:
322             opCode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
323             break;
324         case kOpTst:
325             opCode = (thumbForm) ? kThumbTst : kThumb2TstRR;
326             break;
327         case kOpLsl:
328             assert(shift == 0);
329             opCode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
330             break;
331         case kOpLsr:
332             assert(shift == 0);
333             opCode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
334             break;
335         case kOpAsr:
336             assert(shift == 0);
337             opCode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
338             break;
339         case kOpRor:
340             assert(shift == 0);
341             opCode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
342             break;
343         case kOpAdd:
344             opCode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
345             break;
346         case kOpSub:
347             opCode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
348             break;
349         case kOp2Byte:
350             assert(shift == 0);
351             return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
352         case kOp2Short:
353             assert(shift == 0);
354             return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
355         case kOp2Char:
356             assert(shift == 0);
357             return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
358         default:
359             assert(0);
360             break;
361     }
362     assert(opCode >= 0);
363     if (EncodingMap[opCode].flags & IS_BINARY_OP)
364         return newLIR2(cUnit, opCode, rDestSrc1, rSrc2);
365     else if (EncodingMap[opCode].flags & IS_TERTIARY_OP) {
366         if (EncodingMap[opCode].fieldLoc[2].kind == kFmtShift)
367             return newLIR3(cUnit, opCode, rDestSrc1, rSrc2, shift);
368         else
369             return newLIR3(cUnit, opCode, rDestSrc1, rDestSrc1, rSrc2);
370     } else if (EncodingMap[opCode].flags & IS_QUAD_OP)
371         return newLIR4(cUnit, opCode, rDestSrc1, rDestSrc1, rSrc2, shift);
372     else {
373         assert(0);
374         return NULL;
375     }
376 }
377 
opRegReg(CompilationUnit * cUnit,OpKind op,int rDestSrc1,int rSrc2)378 static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
379                         int rSrc2)
380 {
381     return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
382 }
383 
opRegRegRegShift(CompilationUnit * cUnit,OpKind op,int rDest,int rSrc1,int rSrc2,int shift)384 static ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op,
385                                 int rDest, int rSrc1, int rSrc2, int shift)
386 {
387     ArmOpCode opCode = kThumbBkpt;
388     bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
389                       LOWREG(rSrc2);
390     switch (op) {
391         case kOpAdd:
392             opCode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
393             break;
394         case kOpSub:
395             opCode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
396             break;
397         case kOpAdc:
398             opCode = kThumb2AdcRRR;
399             break;
400         case kOpAnd:
401             opCode = kThumb2AndRRR;
402             break;
403         case kOpBic:
404             opCode = kThumb2BicRRR;
405             break;
406         case kOpXor:
407             opCode = kThumb2EorRRR;
408             break;
409         case kOpMul:
410             assert(shift == 0);
411             opCode = kThumb2MulRRR;
412             break;
413         case kOpOr:
414             opCode = kThumb2OrrRRR;
415             break;
416         case kOpSbc:
417             opCode = kThumb2SbcRRR;
418             break;
419         case kOpLsl:
420             assert(shift == 0);
421             opCode = kThumb2LslRRR;
422             break;
423         case kOpLsr:
424             assert(shift == 0);
425             opCode = kThumb2LsrRRR;
426             break;
427         case kOpAsr:
428             assert(shift == 0);
429             opCode = kThumb2AsrRRR;
430             break;
431         case kOpRor:
432             assert(shift == 0);
433             opCode = kThumb2RorRRR;
434             break;
435         default:
436             assert(0);
437             break;
438     }
439     assert(opCode >= 0);
440     if (EncodingMap[opCode].flags & IS_QUAD_OP)
441         return newLIR4(cUnit, opCode, rDest, rSrc1, rSrc2, shift);
442     else {
443         assert(EncodingMap[opCode].flags & IS_TERTIARY_OP);
444         return newLIR3(cUnit, opCode, rDest, rSrc1, rSrc2);
445     }
446 }
447 
opRegRegReg(CompilationUnit * cUnit,OpKind op,int rDest,int rSrc1,int rSrc2)448 static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
449                            int rSrc1, int rSrc2)
450 {
451     return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
452 }
453 
opRegRegImm(CompilationUnit * cUnit,OpKind op,int rDest,int rSrc1,int value)454 static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
455                            int rSrc1, int value)
456 {
457     ArmLIR *res;
458     bool neg = (value < 0);
459     int absValue = (neg) ? -value : value;
460     ArmOpCode opCode = kThumbBkpt;
461     ArmOpCode altOpCode = kThumbBkpt;
462     bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
463     int modImm = modifiedImmediate(value);
464     int modImmNeg = modifiedImmediate(-value);
465 
466     switch(op) {
467         case kOpLsl:
468             if (allLowRegs)
469                 return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
470             else
471                 return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
472         case kOpLsr:
473             if (allLowRegs)
474                 return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
475             else
476                 return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
477         case kOpAsr:
478             if (allLowRegs)
479                 return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
480             else
481                 return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
482         case kOpRor:
483             return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
484         case kOpAdd:
485             if (LOWREG(rDest) && (rSrc1 == 13) &&
486                 (value <= 1020) && ((value & 0x3)==0)) {
487                 return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1,
488                                value >> 2);
489             } else if (LOWREG(rDest) && (rSrc1 == rpc) &&
490                        (value <= 1020) && ((value & 0x3)==0)) {
491                 return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1,
492                                value >> 2);
493             }
494             opCode = kThumb2AddRRI8;
495             altOpCode = kThumb2AddRRR;
496             // Note: intentional fallthrough
497         case kOpSub:
498             if (allLowRegs && ((absValue & 0x7) == absValue)) {
499                 if (op == kOpAdd)
500                     opCode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
501                 else
502                     opCode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
503                 return newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
504             } else if ((absValue & 0xff) == absValue) {
505                 if (op == kOpAdd)
506                     opCode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
507                 else
508                     opCode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
509                 return newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
510             }
511             if (modImmNeg >= 0) {
512                 op = (op == kOpAdd) ? kOpSub : kOpAdd;
513                 modImm = modImmNeg;
514             }
515             if (op == kOpSub) {
516                 opCode = kThumb2SubRRI8;
517                 altOpCode = kThumb2SubRRR;
518             }
519             break;
520         case kOpAdc:
521             opCode = kThumb2AdcRRI8;
522             altOpCode = kThumb2AdcRRR;
523             break;
524         case kOpSbc:
525             opCode = kThumb2SbcRRI8;
526             altOpCode = kThumb2SbcRRR;
527             break;
528         case kOpOr:
529             opCode = kThumb2OrrRRI8;
530             altOpCode = kThumb2OrrRRR;
531             break;
532         case kOpAnd:
533             opCode = kThumb2AndRRI8;
534             altOpCode = kThumb2AndRRR;
535             break;
536         case kOpXor:
537             opCode = kThumb2EorRRI8;
538             altOpCode = kThumb2EorRRR;
539             break;
540         case kOpMul:
541             //TUNING: power of 2, shift & add
542             modImm = -1;
543             altOpCode = kThumb2MulRRR;
544             break;
545         case kOpCmp: {
546             int modImm = modifiedImmediate(value);
547             ArmLIR *res;
548             if (modImm >= 0) {
549                 res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
550             } else {
551                 int rTmp = dvmCompilerAllocTemp(cUnit);
552                 res = loadConstant(cUnit, rTmp, value);
553                 opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
554                 dvmCompilerFreeTemp(cUnit, rTmp);
555             }
556             return res;
557         }
558         default:
559             assert(0);
560     }
561 
562     if (modImm >= 0) {
563         return newLIR3(cUnit, opCode, rDest, rSrc1, modImm);
564     } else {
565         int rScratch = dvmCompilerAllocTemp(cUnit);
566         loadConstant(cUnit, rScratch, value);
567         if (EncodingMap[altOpCode].flags & IS_QUAD_OP)
568             res = newLIR4(cUnit, altOpCode, rDest, rSrc1, rScratch, 0);
569         else
570             res = newLIR3(cUnit, altOpCode, rDest, rSrc1, rScratch);
571         dvmCompilerFreeTemp(cUnit, rScratch);
572         return res;
573     }
574 }
575 
576 /* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
opRegImm(CompilationUnit * cUnit,OpKind op,int rDestSrc1,int value)577 static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
578                         int value)
579 {
580     bool neg = (value < 0);
581     int absValue = (neg) ? -value : value;
582     bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
583     ArmOpCode opCode = kThumbBkpt;
584     switch (op) {
585         case kOpAdd:
586             if ( !neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
587                 assert((value & 0x3) == 0);
588                 return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
589             } else if (shortForm) {
590                 opCode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
591             }
592             break;
593         case kOpSub:
594             if (!neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
595                 assert((value & 0x3) == 0);
596                 return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
597             } else if (shortForm) {
598                 opCode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
599             }
600             break;
601         case kOpCmp:
602             if (LOWREG(rDestSrc1) && shortForm)
603                 opCode = (shortForm) ?  kThumbCmpRI8 : kThumbCmpRR;
604             else if (LOWREG(rDestSrc1))
605                 opCode = kThumbCmpRR;
606             else {
607                 shortForm = false;
608                 opCode = kThumbCmpHL;
609             }
610             break;
611         default:
612             /* Punt to opRegRegImm - if bad case catch it there */
613             shortForm = false;
614             break;
615     }
616     if (shortForm)
617         return newLIR2(cUnit, opCode, rDestSrc1, absValue);
618     else {
619         return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
620     }
621 }
622 
623 /*
624  * Determine whether value can be encoded as a Thumb2 floating point
625  * immediate.  If not, return -1.  If so return encoded 8-bit value.
626  */
encodeImmDoubleHigh(int value)627 static int encodeImmDoubleHigh(int value)
628 {
629     int res;
630     int bitA =    (value & 0x80000000) >> 31;
631     int notBitB = (value & 0x40000000) >> 30;
632     int bitB =    (value & 0x20000000) >> 29;
633     int bSmear =  (value & 0x3fc00000) >> 22;
634     int slice =   (value & 0x003f0000) >> 16;
635     int zeroes =  (value & 0x0000ffff);
636     if (zeroes != 0)
637         return -1;
638     if (bitB) {
639         if ((notBitB != 0) || (bSmear != 0x1f))
640             return -1;
641     } else {
642         if ((notBitB != 1) || (bSmear != 0x0))
643             return -1;
644     }
645     res = (bitA << 7) | (bitB << 6) | slice;
646     return res;
647 }
648 
encodeImmDouble(int valLo,int valHi)649 static int encodeImmDouble(int valLo, int valHi)
650 {
651     int res = -1;
652     if (valLo == 0)
653         res = encodeImmDoubleHigh(valHi);
654     return res;
655 }
656 
loadConstantValueWide(CompilationUnit * cUnit,int rDestLo,int rDestHi,int valLo,int valHi)657 static ArmLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
658                                      int rDestHi, int valLo, int valHi)
659 {
660     int encodedImm = encodeImmDouble(valLo, valHi);
661     ArmLIR *res;
662     if (FPREG(rDestLo) && (encodedImm >= 0)) {
663         res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi),
664                       encodedImm);
665     } else {
666         res = loadConstantNoClobber(cUnit, rDestLo, valLo);
667         loadConstantNoClobber(cUnit, rDestHi, valHi);
668     }
669     return res;
670 }
671 
encodeShift(int code,int amount)672 static int encodeShift(int code, int amount) {
673     return ((amount & 0x1f) << 2) | code;
674 }
675 
loadBaseIndexed(CompilationUnit * cUnit,int rBase,int rIndex,int rDest,int scale,OpSize size)676 static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
677                                int rIndex, int rDest, int scale, OpSize size)
678 {
679     bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
680     ArmLIR *load;
681     ArmOpCode opCode = kThumbBkpt;
682     bool thumbForm = (allLowRegs && (scale == 0));
683     int regPtr;
684 
685     if (FPREG(rDest)) {
686         assert(SINGLEREG(rDest));
687         assert((size == kWord) || (size == kSingle));
688         opCode = kThumb2Vldrs;
689         size = kSingle;
690     } else {
691         if (size == kSingle)
692             size = kWord;
693     }
694 
695     switch (size) {
696         case kSingle:
697             regPtr = dvmCompilerAllocTemp(cUnit);
698             if (scale) {
699                 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
700                         encodeShift(kArmLsl, scale));
701             } else {
702                 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
703             }
704             load = newLIR3(cUnit, opCode, rDest, regPtr, 0);
705 #if defined(WITH_SELF_VERIFICATION)
706             if (cUnit->heapMemOp)
707                 load->branchInsertSV = true;
708 #endif
709             return load;
710         case kWord:
711             opCode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
712             break;
713         case kUnsignedHalf:
714             opCode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
715             break;
716         case kSignedHalf:
717             opCode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
718             break;
719         case kUnsignedByte:
720             opCode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
721             break;
722         case kSignedByte:
723             opCode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
724             break;
725         default:
726             assert(0);
727     }
728     if (thumbForm)
729         load = newLIR3(cUnit, opCode, rDest, rBase, rIndex);
730     else
731         load = newLIR4(cUnit, opCode, rDest, rBase, rIndex, scale);
732 
733 #if defined(WITH_SELF_VERIFICATION)
734     if (cUnit->heapMemOp)
735         load->branchInsertSV = true;
736 #endif
737     return load;
738 }
739 
storeBaseIndexed(CompilationUnit * cUnit,int rBase,int rIndex,int rSrc,int scale,OpSize size)740 static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
741                                 int rIndex, int rSrc, int scale, OpSize size)
742 {
743     bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
744     ArmLIR *store;
745     ArmOpCode opCode = kThumbBkpt;
746     bool thumbForm = (allLowRegs && (scale == 0));
747     int regPtr;
748 
749     if (FPREG(rSrc)) {
750         assert(SINGLEREG(rSrc));
751         assert((size == kWord) || (size == kSingle));
752         opCode = kThumb2Vstrs;
753         size = kSingle;
754     } else {
755         if (size == kSingle)
756             size = kWord;
757     }
758 
759     switch (size) {
760         case kSingle:
761             regPtr = dvmCompilerAllocTemp(cUnit);
762             if (scale) {
763                 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
764                         encodeShift(kArmLsl, scale));
765             } else {
766                 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
767             }
768             store = newLIR3(cUnit, opCode, rSrc, regPtr, 0);
769 #if defined(WITH_SELF_VERIFICATION)
770             if (cUnit->heapMemOp)
771                 store->branchInsertSV = true;
772 #endif
773             return store;
774         case kWord:
775             opCode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
776             break;
777         case kUnsignedHalf:
778         case kSignedHalf:
779             opCode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
780             break;
781         case kUnsignedByte:
782         case kSignedByte:
783             opCode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
784             break;
785         default:
786             assert(0);
787     }
788     if (thumbForm)
789         store = newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
790     else
791         store = newLIR4(cUnit, opCode, rSrc, rBase, rIndex, scale);
792 
793 #if defined(WITH_SELF_VERIFICATION)
794     if (cUnit->heapMemOp)
795         store->branchInsertSV = true;
796 #endif
797     return store;
798 }
799 
800 /*
801  * Load value from base + displacement.  Optionally perform null check
802  * on base (which must have an associated sReg and MIR).  If not
803  * performing null check, incoming MIR can be null.
804  */
loadBaseDispBody(CompilationUnit * cUnit,MIR * mir,int rBase,int displacement,int rDest,int rDestHi,OpSize size,int sReg)805 static ArmLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
806                                 int displacement, int rDest, int rDestHi,
807                                 OpSize size, int sReg)
808 {
809     ArmLIR *res, *load;
810     ArmOpCode opCode = kThumbBkpt;
811     bool shortForm = false;
812     bool thumb2Form = (displacement < 4092 && displacement >= 0);
813     bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
814     int encodedDisp = displacement;
815 
816     switch (size) {
817         case kDouble:
818         case kLong:
819             if (FPREG(rDest)) {
820                 if (SINGLEREG(rDest)) {
821                     assert(FPREG(rDestHi));
822                     rDest = S2D(rDest, rDestHi);
823                 }
824                 opCode = kThumb2Vldrd;
825                 if (displacement <= 1020) {
826                     shortForm = true;
827                     encodedDisp >>= 2;
828                 }
829                 break;
830             } else {
831                 res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest,
832                                        -1, kWord, sReg);
833                 loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi,
834                                  -1, kWord, INVALID_SREG);
835                 return res;
836             }
837         case kSingle:
838         case kWord:
839             if (FPREG(rDest)) {
840                 opCode = kThumb2Vldrs;
841                 if (displacement <= 1020) {
842                     shortForm = true;
843                     encodedDisp >>= 2;
844                 }
845                 break;
846             }
847             if (LOWREG(rDest) && (rBase == rpc) &&
848                 (displacement <= 1020) && (displacement >= 0)) {
849                 shortForm = true;
850                 encodedDisp >>= 2;
851                 opCode = kThumbLdrPcRel;
852             } else if (LOWREG(rDest) && (rBase == r13) &&
853                       (displacement <= 1020) && (displacement >= 0)) {
854                 shortForm = true;
855                 encodedDisp >>= 2;
856                 opCode = kThumbLdrSpRel;
857             } else if (allLowRegs && displacement < 128 && displacement >= 0) {
858                 assert((displacement & 0x3) == 0);
859                 shortForm = true;
860                 encodedDisp >>= 2;
861                 opCode = kThumbLdrRRI5;
862             } else if (thumb2Form) {
863                 shortForm = true;
864                 opCode = kThumb2LdrRRI12;
865             }
866             break;
867         case kUnsignedHalf:
868             if (allLowRegs && displacement < 64 && displacement >= 0) {
869                 assert((displacement & 0x1) == 0);
870                 shortForm = true;
871                 encodedDisp >>= 1;
872                 opCode = kThumbLdrhRRI5;
873             } else if (displacement < 4092 && displacement >= 0) {
874                 shortForm = true;
875                 opCode = kThumb2LdrhRRI12;
876             }
877             break;
878         case kSignedHalf:
879             if (thumb2Form) {
880                 shortForm = true;
881                 opCode = kThumb2LdrshRRI12;
882             }
883             break;
884         case kUnsignedByte:
885             if (allLowRegs && displacement < 32 && displacement >= 0) {
886                 shortForm = true;
887                 opCode = kThumbLdrbRRI5;
888             } else if (thumb2Form) {
889                 shortForm = true;
890                 opCode = kThumb2LdrbRRI12;
891             }
892             break;
893         case kSignedByte:
894             if (thumb2Form) {
895                 shortForm = true;
896                 opCode = kThumb2LdrsbRRI12;
897             }
898             break;
899         default:
900             assert(0);
901     }
902 
903     if (shortForm) {
904         load = res = newLIR3(cUnit, opCode, rDest, rBase, encodedDisp);
905     } else {
906         int regOffset = dvmCompilerAllocTemp(cUnit);
907         res = loadConstant(cUnit, regOffset, encodedDisp);
908         load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
909         dvmCompilerFreeTemp(cUnit, regOffset);
910     }
911 
912     if (rBase == rFP) {
913         annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
914     }
915 #if defined(WITH_SELF_VERIFICATION)
916     if (cUnit->heapMemOp)
917         load->branchInsertSV = true;
918 #endif
919     return res;
920 }
921 
loadBaseDisp(CompilationUnit * cUnit,MIR * mir,int rBase,int displacement,int rDest,OpSize size,int sReg)922 static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
923                             int displacement, int rDest, OpSize size,
924                             int sReg)
925 {
926     return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
927                             size, sReg);
928 }
929 
loadBaseDispWide(CompilationUnit * cUnit,MIR * mir,int rBase,int displacement,int rDestLo,int rDestHi,int sReg)930 static  ArmLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
931                                  int displacement, int rDestLo, int rDestHi,
932                                  int sReg)
933 {
934     return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
935                             kLong, sReg);
936 }
937 
938 
storeBaseDispBody(CompilationUnit * cUnit,int rBase,int displacement,int rSrc,int rSrcHi,OpSize size)939 static ArmLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
940                                  int displacement, int rSrc, int rSrcHi,
941                                  OpSize size)
942 {
943     ArmLIR *res, *store;
944     ArmOpCode opCode = kThumbBkpt;
945     bool shortForm = false;
946     bool thumb2Form = (displacement < 4092 && displacement >= 0);
947     bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
948     int encodedDisp = displacement;
949 
950     switch (size) {
951         case kLong:
952         case kDouble:
953             if (!FPREG(rSrc)) {
954                 res = storeBaseDispBody(cUnit, rBase, displacement, rSrc,
955                                         -1, kWord);
956                 storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi,
957                                   -1, kWord);
958                 return res;
959             }
960             if (SINGLEREG(rSrc)) {
961                 assert(FPREG(rSrcHi));
962                 rSrc = S2D(rSrc, rSrcHi);
963             }
964             opCode = kThumb2Vstrd;
965             if (displacement <= 1020) {
966                 shortForm = true;
967                 encodedDisp >>= 2;
968             }
969             break;
970         case kSingle:
971         case kWord:
972             if (FPREG(rSrc)) {
973                 assert(SINGLEREG(rSrc));
974                 opCode = kThumb2Vstrs;
975                 if (displacement <= 1020) {
976                     shortForm = true;
977                     encodedDisp >>= 2;
978                 }
979             break;
980             }
981             if (allLowRegs && displacement < 128 && displacement >= 0) {
982                 assert((displacement & 0x3) == 0);
983                 shortForm = true;
984                 encodedDisp >>= 2;
985                 opCode = kThumbStrRRI5;
986             } else if (thumb2Form) {
987                 shortForm = true;
988                 opCode = kThumb2StrRRI12;
989             }
990             break;
991         case kUnsignedHalf:
992         case kSignedHalf:
993             if (allLowRegs && displacement < 64 && displacement >= 0) {
994                 assert((displacement & 0x1) == 0);
995                 shortForm = true;
996                 encodedDisp >>= 1;
997                 opCode = kThumbStrhRRI5;
998             } else if (thumb2Form) {
999                 shortForm = true;
1000                 opCode = kThumb2StrhRRI12;
1001             }
1002             break;
1003         case kUnsignedByte:
1004         case kSignedByte:
1005             if (allLowRegs && displacement < 32 && displacement >= 0) {
1006                 shortForm = true;
1007                 opCode = kThumbStrbRRI5;
1008             } else if (thumb2Form) {
1009                 shortForm = true;
1010                 opCode = kThumb2StrbRRI12;
1011             }
1012             break;
1013         default:
1014             assert(0);
1015     }
1016     if (shortForm) {
1017         store = res = newLIR3(cUnit, opCode, rSrc, rBase, encodedDisp);
1018     } else {
1019         int rScratch = dvmCompilerAllocTemp(cUnit);
1020         res = loadConstant(cUnit, rScratch, encodedDisp);
1021         store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
1022         dvmCompilerFreeTemp(cUnit, rScratch);
1023     }
1024 
1025     if (rBase == rFP) {
1026         annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
1027     }
1028 #if defined(WITH_SELF_VERIFICATION)
1029     if (cUnit->heapMemOp)
1030         store->branchInsertSV = true;
1031 #endif
1032     return res;
1033 }
1034 
storeBaseDisp(CompilationUnit * cUnit,int rBase,int displacement,int rSrc,OpSize size)1035 static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
1036                              int displacement, int rSrc, OpSize size)
1037 {
1038     return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
1039 }
1040 
storeBaseDispWide(CompilationUnit * cUnit,int rBase,int displacement,int rSrcLo,int rSrcHi)1041 static ArmLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
1042                                  int displacement, int rSrcLo, int rSrcHi)
1043 {
1044     return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
1045 }
1046 
loadMultiple(CompilationUnit * cUnit,int rBase,int rMask)1047 static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
1048 {
1049     ArmLIR *res;
1050     genBarrier(cUnit);
1051     if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
1052         res = newLIR2(cUnit, kThumbLdmia, rBase, rMask);
1053     } else {
1054         res = newLIR2(cUnit, kThumb2Ldmia, rBase, rMask);
1055     }
1056 #if defined(WITH_SELF_VERIFICATION)
1057     if (cUnit->heapMemOp)
1058         res->branchInsertSV = true;
1059 #endif
1060     genBarrier(cUnit);
1061     return res;
1062 }
1063 
storeMultiple(CompilationUnit * cUnit,int rBase,int rMask)1064 static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
1065 {
1066     ArmLIR *res;
1067     genBarrier(cUnit);
1068     if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
1069         res = newLIR2(cUnit, kThumbStmia, rBase, rMask);
1070     } else {
1071         res = newLIR2(cUnit, kThumb2Stmia, rBase, rMask);
1072     }
1073 #if defined(WITH_SELF_VERIFICATION)
1074     if (cUnit->heapMemOp)
1075         res->branchInsertSV = true;
1076 #endif
1077     genBarrier(cUnit);
1078     return res;
1079 }
1080 
storePair(CompilationUnit * cUnit,int base,int lowReg,int highReg)1081 static void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
1082 {
1083     storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
1084 }
1085 
loadPair(CompilationUnit * cUnit,int base,int lowReg,int highReg)1086 static void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
1087 {
1088     loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
1089 }
1090 
1091 
1092 /*
1093  * Perform a "reg cmp imm" operation and jump to the PCR region if condition
1094  * satisfies.
1095  */
genRegImmCheck(CompilationUnit * cUnit,ArmConditionCode cond,int reg,int checkValue,int dOffset,ArmLIR * pcrLabel)1096 static ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
1097                               ArmConditionCode cond, int reg,
1098                               int checkValue, int dOffset,
1099                               ArmLIR *pcrLabel)
1100 {
1101     ArmLIR *branch;
1102     int modImm;
1103     if ((LOWREG(reg)) && (checkValue == 0) &&
1104        ((cond == kArmCondEq) || (cond == kArmCondNe))) {
1105         branch = newLIR2(cUnit,
1106                          (cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
1107                          reg, 0);
1108     } else {
1109         modImm = modifiedImmediate(checkValue);
1110         if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
1111             newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
1112         } else if (modImm >= 0) {
1113             newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
1114         } else {
1115             int tReg = dvmCompilerAllocTemp(cUnit);
1116             loadConstant(cUnit, tReg, checkValue);
1117             opRegReg(cUnit, kOpCmp, reg, tReg);
1118         }
1119         branch = newLIR2(cUnit, kThumbBCond, 0, cond);
1120     }
1121     return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
1122 }
1123 
fpRegCopy(CompilationUnit * cUnit,int rDest,int rSrc)1124 static ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
1125 {
1126     ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
1127     res->operands[0] = rDest;
1128     res->operands[1] = rSrc;
1129     if (rDest == rSrc) {
1130         res->isNop = true;
1131     } else {
1132         assert(DOUBLEREG(rDest) == DOUBLEREG(rSrc));
1133         if (DOUBLEREG(rDest)) {
1134             res->opCode = kThumb2Vmovd;
1135         } else {
1136             if (SINGLEREG(rDest)) {
1137                 res->opCode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
1138             } else {
1139                 assert(SINGLEREG(rSrc));
1140                 res->opCode = kThumb2Fmrs;
1141             }
1142         }
1143         res->operands[0] = rDest;
1144         res->operands[1] = rSrc;
1145     }
1146     setupResourceMasks(res);
1147     return res;
1148 }
1149 
genRegCopyNoInsert(CompilationUnit * cUnit,int rDest,int rSrc)1150 static ArmLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
1151 {
1152     ArmLIR* res;
1153     ArmOpCode opCode;
1154     if (FPREG(rDest) || FPREG(rSrc))
1155         return fpRegCopy(cUnit, rDest, rSrc);
1156     res = dvmCompilerNew(sizeof(ArmLIR), true);
1157     if (LOWREG(rDest) && LOWREG(rSrc))
1158         opCode = kThumbMovRR;
1159     else if (!LOWREG(rDest) && !LOWREG(rSrc))
1160          opCode = kThumbMovRR_H2H;
1161     else if (LOWREG(rDest))
1162          opCode = kThumbMovRR_H2L;
1163     else
1164          opCode = kThumbMovRR_L2H;
1165 
1166     res->operands[0] = rDest;
1167     res->operands[1] = rSrc;
1168     res->opCode = opCode;
1169     setupResourceMasks(res);
1170     if (rDest == rSrc) {
1171         res->isNop = true;
1172     }
1173     return res;
1174 }
1175 
genRegCopy(CompilationUnit * cUnit,int rDest,int rSrc)1176 static ArmLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
1177 {
1178     ArmLIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc);
1179     dvmCompilerAppendLIR(cUnit, (LIR*)res);
1180     return res;
1181 }
1182 
genRegCopyWide(CompilationUnit * cUnit,int destLo,int destHi,int srcLo,int srcHi)1183 static void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
1184                            int srcLo, int srcHi)
1185 {
1186     bool destFP = FPREG(destLo) && FPREG(destHi);
1187     bool srcFP = FPREG(srcLo) && FPREG(srcHi);
1188     assert(FPREG(srcLo) == FPREG(srcHi));
1189     assert(FPREG(destLo) == FPREG(destHi));
1190     if (destFP) {
1191         if (srcFP) {
1192             genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
1193         } else {
1194             newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
1195         }
1196     } else {
1197         if (srcFP) {
1198             newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
1199         } else {
1200             // Handle overlap
1201             if (srcHi == destLo) {
1202                 genRegCopy(cUnit, destHi, srcHi);
1203                 genRegCopy(cUnit, destLo, srcLo);
1204             } else {
1205                 genRegCopy(cUnit, destLo, srcLo);
1206                 genRegCopy(cUnit, destHi, srcHi);
1207             }
1208         }
1209     }
1210 }
1211