19bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee/*
29bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * Copyright (C) 2009 The Android Open Source Project
39bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *
49bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * Licensed under the Apache License, Version 2.0 (the "License");
59bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * you may not use this file except in compliance with the License.
69bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * You may obtain a copy of the License at
79bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *
89bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *      http://www.apache.org/licenses/LICENSE-2.0
99bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *
109bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * Unless required by applicable law or agreed to in writing, software
119bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * distributed under the License is distributed on an "AS IS" BASIS,
129bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * See the License for the specific language governing permissions and
149bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * limitations under the License.
159bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee */
169bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
179bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee/*
189bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee * This file contains codegen for the Thumb ISA and is intended to be
19270c1d64a192341be842f46734054c692bac061eBill Buzbee * includes by:
209bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *
219bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *        Codegen-$(TARGET_ARCH_VARIANT).c
229bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee *
239bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee */
249bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int coreTemps[] = {r0, r1, r2, r3, r4PC, r7, r8, r9, r10, r11, r12};
265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int fpTemps[] = {fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
27c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                        fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31};
285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeImmSingle(int value)
305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int res;
325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bitA =    (value & 0x80000000) >> 31;
335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int notBitB = (value & 0x40000000) >> 30;
345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bitB =    (value & 0x20000000) >> 29;
355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bSmear =  (value & 0x3e000000) >> 25;
365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int slice =   (value & 0x01f80000) >> 19;
375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int zeroes =  (value & 0x0007ffff);
385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (zeroes != 0)
395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return -1;
405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (bitB) {
415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if ((notBitB != 0) || (bSmear != 0x1f))
425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return -1;
435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if ((notBitB != 1) || (bSmear != 0x0))
455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return -1;
465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = (bitA << 7) | (bitB << 6) | slice;
485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *loadFPConstantValue(CompilationUnit *cUnit, int rDest,
525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                   int value)
535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int encodedImm = encodeImmSingle(value);
555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(SINGLEREG(rDest));
56c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee    if (value == 0) {
57c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee      // TODO: we need better info about the target CPU.  a vector exclusive or
58c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee      //       would probably be better here if we could rely on its existance.
59c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee      // Load an immediate +2.0 (which encodes to 0)
60c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee      newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, 0);
61c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee      // +0.0 = +2.0 - +2.0
62c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee      return newLIR3(cUnit, kThumb2Vsubs, rDest, rDest, rDest);
63c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee    } else if (encodedImm >= 0) {
645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
66385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    ArmLIR *dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (dataTarget == NULL) {
68385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng        dataTarget = addWordData(cUnit, &cUnit->literalList, value);
695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
70fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
719a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    loadPcRel->opcode = kThumb2Vldrs;
725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->generic.target = (LIR *) dataTarget;
735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->operands[0] = rDest;
7420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadPcRel->operands[1] = r15pc;
755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(loadPcRel);
76d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setMemRefType(loadPcRel, true, kLiteral);
771f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    loadPcRel->aliasInfo = dataTarget->operands[0];
785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return loadPcRel;
805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic int leadingZeros(u4 val)
831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    u4 alt;
851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int n;
861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int count;
871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    count = 16;
891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    n = 32;
901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    do {
911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        alt = val >> count;
921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (alt != 0) {
931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            n = n - count;
941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            val = alt;
951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        count >>= 1;
971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } while (count);
981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return n - val;
991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
1009bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1019bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee/*
1021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * Determine whether value can be encoded as a Thumb2 modified
1031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
1049bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee */
1051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic int modifiedImmediate(u4 value)
1061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
1071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   int zLeading;
1081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   int zTrailing;
1091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   u4 b0 = value & 0xff;
1101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
1111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Note: case of value==0 must use 0:000:0:0000000 encoding */
1121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value <= 0xFF)
1131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return b0;  // 0:000:a:bcdefgh
1141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value == ((b0 << 16) | b0))
1151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
1161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
1171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
1181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   b0 = (value >> 8) & 0xff;
1191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value == ((b0 << 24) | (b0 << 8)))
1201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
1211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Can we do it with rotation? */
1221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   zLeading = leadingZeros(value);
1231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   zTrailing = 32 - leadingZeros(~value & (value - 1));
1241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* A run of eight or fewer active bits? */
1251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if ((zLeading + zTrailing) < 24)
1261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return -1;  /* No - bail */
1271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* left-justify the constant, discarding msb (known to be 1) */
1281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   value <<= zLeading + 1;
1291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Create bcdefgh */
1301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   value >>= 25;
1311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Put it all together */
1321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
1331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
1349bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1359bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee/*
1365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Load a immediate using a shortcut if possible; otherwise
1375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * grab from the per-translation literal pool.
138bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng *
139bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng * No additional register clobbering operation performed. Use this version when
140bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng * 1) rDest is freshly returned from dvmCompilerAllocTemp or
141bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng * 2) The codegen is under fixed register usage
1429bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee */
143bd1326d0e6b82a24ee80d50921e62152ea919151Ben Chengstatic ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
144bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng                                     int value)
1459bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
1465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res;
1475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int modImm;
1489bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (FPREG(rDest)) {
1505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return loadFPConstantValue(cUnit, rDest, value);
1511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1529bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* See if the value can be constructed cheaply */
1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (LOWREG(rDest) && (value >= 0) && (value <= 255)) {
1555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return newLIR2(cUnit, kThumbMovImm, rDest, value);
1561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* Check Modified immediate special cases */
1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    modImm = modifiedImmediate(value);
1595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (modImm >= 0) {
1605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return res;
1629bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee    }
1635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    modImm = modifiedImmediate(~value);
1645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (modImm >= 0) {
1655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2MvnImmShift, rDest, modImm);
1665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return res;
167a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee    }
1685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* 16-bit immediate? */
1695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if ((value & 0xffff) == value) {
1705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
1715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return res;
172270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
1735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* No shortcut - go ahead and use literal pool */
174385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    ArmLIR *dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
1755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (dataTarget == NULL) {
176385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng        dataTarget = addWordData(cUnit, &cUnit->literalList, value);
1775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
178fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
1799a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    loadPcRel->opcode = kThumb2LdrPcRel12;
1805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->generic.target = (LIR *) dataTarget;
1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->operands[0] = rDest;
1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(loadPcRel);
183d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setMemRefType(loadPcRel, true, kLiteral);
1841f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    loadPcRel->aliasInfo = dataTarget->operands[0];
1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = loadPcRel;
1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
187270c1d64a192341be842f46734054c692bac061eBill Buzbee
1885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /*
1895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     * To save space in the constant pool, we use the ADD_RRI8 instruction to
1905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     * add up to 255 to an existing constant value.
1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     */
1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (dataTarget->operands[0] != value) {
1935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
1947ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    }
1957ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    return res;
1967ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee}
1977ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee
1985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
1995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Load an immediate value into a fixed or temp register.  Target
2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * register is clobbered, and marked inUse.
2015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
2025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
2039bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
204c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    if (dvmCompilerIsTemp(cUnit, rDest)) {
205c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rDest);
2066a55513b0d268bc0721834050a3698316854fa0aElliott Hughes        dvmCompilerMarkInUse(cUnit, rDest);
2075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
208bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng    return loadConstantNoClobber(cUnit, rDest, value);
2099bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee}
2109bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
211fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng/*
212fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng * Load a class pointer value into a fixed or temp register.  Target
213fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng * register is clobbered, and marked inUse.
214fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng */
215fe108f779db4fb3bc720a92e69e58177983088c1Ben Chengstatic ArmLIR *loadClassPointer(CompilationUnit *cUnit, int rDest, int value)
216fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng{
217fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    ArmLIR *res;
218fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    cUnit->hasClassLiterals = true;
219fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    if (dvmCompilerIsTemp(cUnit, rDest)) {
220fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng        dvmCompilerClobber(cUnit, rDest);
221fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng        dvmCompilerMarkInUse(cUnit, rDest);
222fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    }
223fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    ArmLIR *dataTarget = scanLiteralPool(cUnit->classPointerList, value, 0);
224fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    if (dataTarget == NULL) {
225fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng        dataTarget = addWordData(cUnit, &cUnit->classPointerList, value);
226fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng        /* Counts the number of class pointers in this translation */
227fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng        cUnit->numClassPointers++;
228fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    }
229fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
230fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    loadPcRel->opcode = kThumb2LdrPcRel12;
231fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    loadPcRel->generic.target = (LIR *) dataTarget;
232fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    loadPcRel->operands[0] = rDest;
233fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    setupResourceMasks(loadPcRel);
234fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    setMemRefType(loadPcRel, true, kLiteral);
235fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    loadPcRel->aliasInfo = dataTarget->operands[0];
236fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    res = loadPcRel;
237fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
238fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    return res;
239fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng}
240fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng
2411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
2429bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
2439a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
2441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
2451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpUncondBr:
2469a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumbBUncond;
247270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
248270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
249270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
250270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
2519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    return newLIR0(cUnit, opcode);
2529bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee}
2539bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
2541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
2559bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
256bff121aa3e5d3c34caf837227cb00a46bf3f1966buzbee    return newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */, cc);
2571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
2581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
2591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
2601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
2619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
2621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
26318c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        case kOpPush: {
26418c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            if ((value & 0xff00) == 0) {
26518c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPush;
26620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            } else if ((value & 0xff00) == (1 << r14lr)) {
26718c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                /* Thumb push can handle lr, which is encoded by bit 8 */
26818c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPush;
26918c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                value = (value & 0xff) | (1<<8);
27018c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else {
27118c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumb2Push;
27218c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            }
273270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
27418c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        }
27518c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        case kOpPop: {
27618c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            if ((value & 0xff00) == 0) {
27718c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPop;
27820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            } else if ((value & 0xff00) == (1 << r15pc)) {
27918c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                /* Thumb pop can handle pc, which is encoded by bit 8 */
28018c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPop;
28118c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                value = (value & 0xff) | (1<<8);
28218c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else {
28318c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumb2Pop;
28418c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            }
285270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
28618c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        }
287270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
288270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
2899bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee    }
2909a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    return newLIR1(cUnit, opcode, value);
291d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
292d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
2931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
294d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng{
2959a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
2961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
2971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpBlx:
2989a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumbBlxR;
2991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
3001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
3011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
302d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
3039a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    return newLIR1(cUnit, opcode, rDestSrc);
304d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
305d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
3061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
3071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        int rSrc2, int shift)
308270c1d64a192341be842f46734054c692bac061eBill Buzbee{
309270c1d64a192341be842f46734054c692bac061eBill Buzbee    bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
3109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
311270c1d64a192341be842f46734054c692bac061eBill Buzbee    switch (op) {
3121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdc:
3139a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
314270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAnd:
3169a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
317270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpBic:
3199a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
320270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmn:
322270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3239a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
324270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmp:
326270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (thumbForm)
3279a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpRR;
328270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
3299a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpHH;
330270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if ((shift == 0) && LOWREG(rDestSrc1))
3319a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpLH;
332270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (shift == 0)
3339a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpHL;
334dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng            else
3359a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2CmpRR;
336270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpXor:
3389a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
339270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMov:
341270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
342270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
3439a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR;
344270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
3459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR_H2H;
346270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (LOWREG(rDestSrc1))
3479a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR_H2L;
348270c1d64a192341be842f46734054c692bac061eBill Buzbee            else
3499a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR_L2H;
350270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMul:
352270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3539a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
354270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMvn:
3569a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
357270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpNeg:
359270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3609a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
361270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpOr:
3639a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
364270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSbc:
3669a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
367270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpTst:
3699a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
370270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsl:
372270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
374270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsr:
376270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
378270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAsr:
380270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3819a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
382270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpRor:
384270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3859a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
386270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
3889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
389270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
3919a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
392270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOp2Byte:
394270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
3961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOp2Short:
397270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
3991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOp2Char:
400270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
4011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
402270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
403270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
404270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
405270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
4069a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    assert(opcode >= 0);
4079a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (EncodingMap[opcode].flags & IS_BINARY_OP)
4089a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
4099a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
4109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
4119a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
412270c1d64a192341be842f46734054c692bac061eBill Buzbee        else
4139a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
4149a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
4159a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
416270c1d64a192341be842f46734054c692bac061eBill Buzbee    else {
417270c1d64a192341be842f46734054c692bac061eBill Buzbee        assert(0);
418270c1d64a192341be842f46734054c692bac061eBill Buzbee        return NULL;
419270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
420270c1d64a192341be842f46734054c692bac061eBill Buzbee}
421270c1d64a192341be842f46734054c692bac061eBill Buzbee
422270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
423270c1d64a192341be842f46734054c692bac061eBill Buzbee                        int rSrc2)
424270c1d64a192341be842f46734054c692bac061eBill Buzbee{
425270c1d64a192341be842f46734054c692bac061eBill Buzbee    return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
426270c1d64a192341be842f46734054c692bac061eBill Buzbee}
427270c1d64a192341be842f46734054c692bac061eBill Buzbee
4281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op,
4291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                int rDest, int rSrc1, int rSrc2, int shift)
4301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
4319a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
4321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
4331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                      LOWREG(rSrc2);
4341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
4351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
4369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
4371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
4399a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
4401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdc:
4429a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AdcRRR;
4431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAnd:
4459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AndRRR;
4461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpBic:
4489a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2BicRRR;
4491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpXor:
4519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2EorRRR;
4521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMul:
4541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4559a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2MulRRR;
4561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpOr:
4589a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2OrrRRR;
4591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSbc:
4619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2SbcRRR;
4621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsl:
4641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4659a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2LslRRR;
4661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsr:
4681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4699a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2LsrRRR;
4701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAsr:
4721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AsrRRR;
4741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpRor:
4761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2RorRRR;
4781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
4801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
4811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
4839a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    assert(opcode >= 0);
4849a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (EncodingMap[opcode].flags & IS_QUAD_OP)
4859a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
4861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else {
4879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        assert(EncodingMap[opcode].flags & IS_TERTIARY_OP);
4889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
4891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
4901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
4911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
4921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
4931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           int rSrc1, int rSrc2)
4941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
4951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
4961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
4971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
4981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
4991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           int rSrc1, int value)
5001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
5011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res;
5021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool neg = (value < 0);
5031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int absValue = (neg) ? -value : value;
5049a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
5059a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode altOpcode = kThumbBkpt;
5061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
5071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int modImm = modifiedImmediate(value);
5081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int modImmNeg = modifiedImmediate(-value);
5091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
5101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch(op) {
5111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsl:
5121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs)
5131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
5141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            else
5151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
5161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsr:
5171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs)
5181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
5191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            else
5201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
5211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAsr:
5221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs)
5231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
5241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            else
5251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
5261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpRor:
5271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
5281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
52920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            if (LOWREG(rDest) && (rSrc1 == r13sp) &&
5301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                (value <= 1020) && ((value & 0x3)==0)) {
5311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1,
5321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                               value >> 2);
53320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            } else if (LOWREG(rDest) && (rSrc1 == r15pc) &&
5341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                       (value <= 1020) && ((value & 0x3)==0)) {
5351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1,
5361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                               value >> 2);
5371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5389a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AddRRI8;
5399a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2AddRRR;
5401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            // Note: intentional fallthrough
5411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
5421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && ((absValue & 0x7) == absValue)) {
5431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (op == kOpAdd)
5449a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
5451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                else
5469a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
5479a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
5481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if ((absValue & 0xff) == absValue) {
5491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (op == kOpAdd)
5509a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
5511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                else
5529a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
5539a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
5541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (modImmNeg >= 0) {
5561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                op = (op == kOpAdd) ? kOpSub : kOpAdd;
5571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                modImm = modImmNeg;
5581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (op == kOpSub) {
5609a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2SubRRI8;
5619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                altOpcode = kThumb2SubRRR;
5621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdc:
5659a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AdcRRI8;
5669a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2AdcRRR;
5671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSbc:
5699a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2SbcRRI8;
5709a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2SbcRRR;
5711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpOr:
5739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2OrrRRI8;
5749a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2OrrRRR;
5751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAnd:
5779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AndRRI8;
5789a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2AndRRR;
5791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpXor:
5819a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2EorRRI8;
5829a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2EorRRR;
5831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMul:
5851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            //TUNING: power of 2, shift & add
5861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            modImm = -1;
5879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2MulRRR;
5881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmp: {
5901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            int modImm = modifiedImmediate(value);
5911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            ArmLIR *res;
5921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (modImm >= 0) {
5931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
5941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
595c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                int rTmp = dvmCompilerAllocTemp(cUnit);
5961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = loadConstant(cUnit, rTmp, value);
5971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
598c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                dvmCompilerFreeTemp(cUnit, rTmp);
5991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
6001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return res;
6011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
6021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
6031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
6041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
6051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (modImm >= 0) {
6079a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
6081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
609c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int rScratch = dvmCompilerAllocTemp(cUnit);
6101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadConstant(cUnit, rScratch, value);
6119a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
6129a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
6131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        else
6149a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
615c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, rScratch);
6161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        return res;
6171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
6181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
6191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
620270c1d64a192341be842f46734054c692bac061eBill Buzbee/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
621270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
6221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        int value)
623270c1d64a192341be842f46734054c692bac061eBill Buzbee{
624270c1d64a192341be842f46734054c692bac061eBill Buzbee    bool neg = (value < 0);
625270c1d64a192341be842f46734054c692bac061eBill Buzbee    int absValue = (neg) ? -value : value;
626270c1d64a192341be842f46734054c692bac061eBill Buzbee    bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
6279a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
628270c1d64a192341be842f46734054c692bac061eBill Buzbee    switch (op) {
6291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
63020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
631270c1d64a192341be842f46734054c692bac061eBill Buzbee                assert((value & 0x3) == 0);
6321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
633270c1d64a192341be842f46734054c692bac061eBill Buzbee            } else if (shortForm) {
6349a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
635270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
636270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
6371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
63820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
639270c1d64a192341be842f46734054c692bac061eBill Buzbee                assert((value & 0x3) == 0);
6401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
641270c1d64a192341be842f46734054c692bac061eBill Buzbee            } else if (shortForm) {
6429a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
643270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
644270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
6451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmp:
646270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (LOWREG(rDestSrc1) && shortForm)
6479a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = (shortForm) ?  kThumbCmpRI8 : kThumbCmpRR;
648270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (LOWREG(rDestSrc1))
6499a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpRR;
650270c1d64a192341be842f46734054c692bac061eBill Buzbee            else {
651270c1d64a192341be842f46734054c692bac061eBill Buzbee                shortForm = false;
6529a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpHL;
653270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
654270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
655270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
656270c1d64a192341be842f46734054c692bac061eBill Buzbee            /* Punt to opRegRegImm - if bad case catch it there */
657270c1d64a192341be842f46734054c692bac061eBill Buzbee            shortForm = false;
658270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
659270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
660270c1d64a192341be842f46734054c692bac061eBill Buzbee    if (shortForm)
6619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR2(cUnit, opcode, rDestSrc1, absValue);
6621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else {
6631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
6641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
665270c1d64a192341be842f46734054c692bac061eBill Buzbee}
666270c1d64a192341be842f46734054c692bac061eBill Buzbee
6671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/*
6685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Determine whether value can be encoded as a Thumb2 floating point
6695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * immediate.  If not, return -1.  If so return encoded 8-bit value.
6701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee */
6715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeImmDoubleHigh(int value)
6721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
6735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int res;
6745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bitA =    (value & 0x80000000) >> 31;
6755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int notBitB = (value & 0x40000000) >> 30;
6765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bitB =    (value & 0x20000000) >> 29;
6775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bSmear =  (value & 0x3fc00000) >> 22;
6785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int slice =   (value & 0x003f0000) >> 16;
6795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int zeroes =  (value & 0x0000ffff);
6805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (zeroes != 0)
6815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return -1;
6825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (bitB) {
6835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if ((notBitB != 0) || (bSmear != 0x1f))
6845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return -1;
6851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
6865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if ((notBitB != 1) || (bSmear != 0x0))
6875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return -1;
6881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
6895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = (bitA << 7) | (bitB << 6) | slice;
6905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
6915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
6921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeImmDouble(int valLo, int valHi)
6945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
6955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int res = -1;
6965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (valLo == 0)
6975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = encodeImmDoubleHigh(valHi);
6985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
6995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
7001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
7025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                     int rDestHi, int valLo, int valHi)
7035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
7045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int encodedImm = encodeImmDouble(valLo, valHi);
7055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res;
706c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee    int targetReg = S2D(rDestLo, rDestHi);
707c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee    if (FPREG(rDestLo)) {
708c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee        if ((valLo == 0) && (valHi == 0)) {
709c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          // TODO: we need better info about the target CPU.  a vector
710c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          // exclusive or would probably be better here if we could rely on
711c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          // its existance.
712c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          // Load an immediate +2.0 (which encodes to 0)
713c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          newLIR2(cUnit, kThumb2Vmovd_IMM8, targetReg, 0);
714c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          // +0.0 = +2.0 - +2.0
715c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee          res = newLIR3(cUnit, kThumb2Vsubd, targetReg, targetReg, targetReg);
716c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee        } else if (encodedImm >= 0) {
717c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            res = newLIR2(cUnit, kThumb2Vmovd_IMM8, targetReg, encodedImm);
718c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee        } else {
719c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            ArmLIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo, valHi);
720c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            if (dataTarget == NULL) {
721c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee                dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, valHi);
722c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            }
723c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
724c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            loadPcRel->opcode = kThumb2Vldrd;
725c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            loadPcRel->generic.target = (LIR *) dataTarget;
726c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            loadPcRel->operands[0] = targetReg;
727c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            loadPcRel->operands[1] = r15pc;
728c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            setupResourceMasks(loadPcRel);
729c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            setMemRefType(loadPcRel, true, kLiteral);
730c1757a6deab0ca0bfd42c38612d92b2f26c41dbebuzbee            // TODO: rework literal load disambiguation to more cleanly handle 64-bit loads
731c1757a6deab0ca0bfd42c38612d92b2f26c41dbebuzbee            loadPcRel->aliasInfo = (uintptr_t)dataTarget;
732c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
733c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee            res =  loadPcRel;
734c8129911e598ad0ca8d7b31012444ab6ce8bce45buzbee        }
7351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
736bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        res = loadConstantNoClobber(cUnit, rDestLo, valLo);
737bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        loadConstantNoClobber(cUnit, rDestHi, valHi);
7381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
7401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
7411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeShift(int code, int amount) {
7435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return ((amount & 0x1f) << 2) | code;
7441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
7451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
7471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                               int rIndex, int rDest, int scale, OpSize size)
7481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
7491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
7509e45c0b968d63ea38353c99252d233879c2efdafjeffhao    ArmLIR *load;
7519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
7521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumbForm = (allLowRegs && (scale == 0));
7531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
7541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (FPREG(rDest)) {
7561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert(SINGLEREG(rDest));
7571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert((size == kWord) || (size == kSingle));
7589a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        opcode = kThumb2Vldrs;
7591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        size = kSingle;
7601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
7611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (size == kSingle)
7621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            size = kWord;
7631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
7661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
767c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            regPtr = dvmCompilerAllocTemp(cUnit);
7681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (scale) {
7691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
7701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        encodeShift(kArmLsl, scale));
7711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
7721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
7731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
7749a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
7759e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
7769e45c0b968d63ea38353c99252d233879c2efdafjeffhao            if (cUnit->heapMemOp)
777d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                load->flags.insertWrapper = true;
7789e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
7799e45c0b968d63ea38353c99252d233879c2efdafjeffhao            return load;
7801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
7819a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
782270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
7849a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
785270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
7879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
788270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
7909a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
791270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
7939a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
794270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
7961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
7971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (thumbForm)
7999a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
8001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else
8019a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
8029e45c0b968d63ea38353c99252d233879c2efdafjeffhao
8039e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
8049e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
805d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        load->flags.insertWrapper = true;
8069e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
8079e45c0b968d63ea38353c99252d233879c2efdafjeffhao    return load;
8081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
8091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
8111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                int rIndex, int rSrc, int scale, OpSize size)
8121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
8131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
8149e45c0b968d63ea38353c99252d233879c2efdafjeffhao    ArmLIR *store;
8159a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
8161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumbForm = (allLowRegs && (scale == 0));
8171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
8181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (FPREG(rSrc)) {
8201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert(SINGLEREG(rSrc));
821749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        assert((size == kWord) || (size == kSingle));
8229a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        opcode = kThumb2Vstrs;
823749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        size = kSingle;
8241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
8251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (size == kSingle)
8261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            size = kWord;
8271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
8281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
8301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
831c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            regPtr = dvmCompilerAllocTemp(cUnit);
8321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (scale) {
8331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
8341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        encodeShift(kArmLsl, scale));
8351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
8361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
8371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
8389a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
8399e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
8409e45c0b968d63ea38353c99252d233879c2efdafjeffhao            if (cUnit->heapMemOp)
841d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                store->flags.insertWrapper = true;
8429e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
8439e45c0b968d63ea38353c99252d233879c2efdafjeffhao            return store;
8441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
8459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
846270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
8471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
8481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
8499a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
850270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
8511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
8521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
8539a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
854270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
8551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
8561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
8571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
8581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (thumbForm)
8599a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
8601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else
8619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
8629e45c0b968d63ea38353c99252d233879c2efdafjeffhao
8639e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
8649e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
865d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        store->flags.insertWrapper = true;
8669e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
8679e45c0b968d63ea38353c99252d233879c2efdafjeffhao    return store;
8681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
8691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/*
8711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * Load value from base + displacement.  Optionally perform null check
8721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * on base (which must have an associated sReg and MIR).  If not
8731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * performing null check, incoming MIR can be null.
8741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee */
8751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
8761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                int displacement, int rDest, int rDestHi,
8775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                OpSize size, int sReg)
8781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
8791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res, *load;
8809a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
8811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool shortForm = false;
8821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumb2Form = (displacement < 4092 && displacement >= 0);
8831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
8841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int encodedDisp = displacement;
8851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
8871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kDouble:
8881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kLong:
8891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (FPREG(rDest)) {
8901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (SINGLEREG(rDest)) {
8911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    assert(FPREG(rDestHi));
8921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    rDest = S2D(rDest, rDestHi);
8931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
8949a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2Vldrd;
8951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (displacement <= 1020) {
8961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    shortForm = true;
8971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    encodedDisp >>= 2;
8981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
8991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                break;
9001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
9011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest,
9025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                       -1, kWord, sReg);
9031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi,
9045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                 -1, kWord, INVALID_SREG);
9051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return res;
9061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
9071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
9081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
9091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (FPREG(rDest)) {
9109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2Vldrs;
9111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (displacement <= 1020) {
9121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    shortForm = true;
9131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    encodedDisp >>= 2;
9141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
9151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                break;
9161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
91720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            if (LOWREG(rDest) && (rBase == r15pc) &&
9181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                (displacement <= 1020) && (displacement >= 0)) {
9191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
9219a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrPcRel;
92220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            } else if (LOWREG(rDest) && (rBase == r13sp) &&
9231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                      (displacement <= 1020) && (displacement >= 0)) {
9241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
9269a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrSpRel;
9271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (allLowRegs && displacement < 128 && displacement >= 0) {
9281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x3) == 0);
9291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
9319a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrRRI5;
9321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
9331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9349a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrRRI12;
9351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
936270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
9381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 64 && displacement >= 0) {
9391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x1) == 0);
9401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 1;
9429a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrhRRI5;
9431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (displacement < 4092 && displacement >= 0) {
9441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrhRRI12;
9461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
947270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
9491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (thumb2Form) {
9501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrshRRI12;
9521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
953270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
9551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 32 && displacement >= 0) {
9561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9579a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrbRRI5;
9581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
9591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9609a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrbRRI12;
9611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
962270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
9641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (thumb2Form) {
9651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9669a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrsbRRI12;
9671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
968270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
969270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
970270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
971270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
9725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
9731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (shortForm) {
9749a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
9751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
976c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int regOffset = dvmCompilerAllocTemp(cUnit);
9771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = loadConstant(cUnit, regOffset, encodedDisp);
9781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
979c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regOffset);
9801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
9811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
98220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    if (rBase == r5FP) {
9831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
984270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
9859e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
9869e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
987d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        load->flags.insertWrapper = true;
9889e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
989fe108f779db4fb3bc720a92e69e58177983088c1Ben Cheng    return load;
990270c1d64a192341be842f46734054c692bac061eBill Buzbee}
991270c1d64a192341be842f46734054c692bac061eBill Buzbee
9921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
9931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                            int displacement, int rDest, OpSize size,
9945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            int sReg)
995270c1d64a192341be842f46734054c692bac061eBill Buzbee{
9961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
9975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            size, sReg);
998270c1d64a192341be842f46734054c692bac061eBill Buzbee}
999270c1d64a192341be842f46734054c692bac061eBill Buzbee
10005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic  ArmLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
1001c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 int displacement, int rDestLo, int rDestHi,
1002c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 int sReg)
1003270c1d64a192341be842f46734054c692bac061eBill Buzbee{
10041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
10055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            kLong, sReg);
10061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
1007270c1d64a192341be842f46734054c692bac061eBill Buzbee
10081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
1010c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 int displacement, int rSrc, int rSrcHi,
1011c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 OpSize size)
10121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res, *store;
10149a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
10151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool shortForm = false;
10161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumb2Form = (displacement < 4092 && displacement >= 0);
10171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
10181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int encodedDisp = displacement;
10191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
10211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kLong:
10221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kDouble:
10231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (!FPREG(rSrc)) {
10241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = storeBaseDispBody(cUnit, rBase, displacement, rSrc,
10251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                        -1, kWord);
10261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi,
10271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                  -1, kWord);
10281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return res;
1029270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
10301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (SINGLEREG(rSrc)) {
10311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert(FPREG(rSrcHi));
10321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                rSrc = S2D(rSrc, rSrcHi);
1033270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
10349a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2Vstrd;
10351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (displacement <= 1020) {
10361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
1038270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
1039270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
10401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
10411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
10421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (FPREG(rSrc)) {
10431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert(SINGLEREG(rSrc));
10449a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2Vstrs;
10451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (displacement <= 1020) {
10461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    shortForm = true;
10471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    encodedDisp >>= 2;
10481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
1049270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
10501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
10511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 128 && displacement >= 0) {
10521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x3) == 0);
10531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
10559a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbStrRRI5;
10561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
10571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10589a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2StrRRI12;
10591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
1060270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
10611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
10621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
10631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 64 && displacement >= 0) {
10641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x1) == 0);
10651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 1;
10679a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbStrhRRI5;
10681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
10691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10709a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2StrhRRI12;
10711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
1072270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
10731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
10741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
10751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 32 && displacement >= 0) {
10761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbStrbRRI5;
10781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
10791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10809a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2StrbRRI12;
10811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
1082270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
1083270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
1084270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
1085270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
10861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (shortForm) {
10879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
10881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
1089c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int rScratch = dvmCompilerAllocTemp(cUnit);
10901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = loadConstant(cUnit, rScratch, encodedDisp);
10911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
1092c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, rScratch);
10931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
10941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
109520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    if (rBase == r5FP) {
10961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
10971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
10989e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
10999e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
1100d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        store->flags.insertWrapper = true;
11019e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
11021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return res;
11031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
11061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                             int displacement, int rSrc, OpSize size)
11071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
11081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
11091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
11121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                 int displacement, int rSrcLo, int rSrcHi)
11131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
11141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
11151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
11181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
11191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res;
11201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
11211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
11221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumbLdmia, rBase, rMask);
11231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
11241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumb2Ldmia, rBase, rMask);
11251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1126121ea790080b5a6bb713a07452c19f87d209de48jeffhao#if defined(WITH_SELF_VERIFICATION)
1127121ea790080b5a6bb713a07452c19f87d209de48jeffhao    if (cUnit->heapMemOp)
1128d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.insertWrapper = true;
1129121ea790080b5a6bb713a07452c19f87d209de48jeffhao#endif
11301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
11311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return res;
11321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
11351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
11361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res;
11371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
11381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
11391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumbStmia, rBase, rMask);
11401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
11411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumb2Stmia, rBase, rMask);
11421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1143121ea790080b5a6bb713a07452c19f87d209de48jeffhao#if defined(WITH_SELF_VERIFICATION)
1144121ea790080b5a6bb713a07452c19f87d209de48jeffhao    if (cUnit->heapMemOp)
1145d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.insertWrapper = true;
1146121ea790080b5a6bb713a07452c19f87d209de48jeffhao#endif
11471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
11481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return res;
11491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
11521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
11531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
11541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
11571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
11585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
11591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
11601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/*
11628f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee * Generate a register comparison to an immediate and branch.  Caller
11638f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee * is responsible for setting branch target field.
1164a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee */
11658f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbeestatic ArmLIR *genCmpImmBranch(CompilationUnit *cUnit,
1166c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                              ArmConditionCode cond, int reg,
11678f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee                              int checkValue)
1168a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee{
11691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *branch;
11701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int modImm;
1171bff121aa3e5d3c34caf837227cb00a46bf3f1966buzbee    if ((LOWREG(reg)) && (checkValue == 0) &&
11721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       ((cond == kArmCondEq) || (cond == kArmCondNe))) {
11731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        branch = newLIR2(cUnit,
11741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         (cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
11751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         reg, 0);
11761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
11771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        modImm = modifiedImmediate(checkValue);
11781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
11791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
11801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        } else if (modImm >= 0) {
11811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
11821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        } else {
1183c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
11841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadConstant(cUnit, tReg, checkValue);
11851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpCmp, reg, tReg);
11861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
11871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        branch = newLIR2(cUnit, kThumbBCond, 0, cond);
11881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
11898f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    return branch;
1190a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee}
1191a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee
11925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
1193270c1d64a192341be842f46734054c692bac061eBill Buzbee{
1194fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ArmLIR* res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
11955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[0] = rDest;
11965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[1] = rSrc;
11975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rDest == rSrc) {
1198d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.isNop = true;
11995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
12005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        assert(DOUBLEREG(rDest) == DOUBLEREG(rSrc));
12015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if (DOUBLEREG(rDest)) {
12029a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            res->opcode = kThumb2Vmovd;
12035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
12045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            if (SINGLEREG(rDest)) {
12059a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                res->opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
12065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            } else {
12075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                assert(SINGLEREG(rSrc));
12089a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                res->opcode = kThumb2Fmrs;
12095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            }
12105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
12115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res->operands[0] = rDest;
12125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res->operands[1] = rSrc;
12135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
12145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(res);
12155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1216270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1217270c1d64a192341be842f46734054c692bac061eBill Buzbee
12185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
1219270c1d64a192341be842f46734054c692bac061eBill Buzbee{
12205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR* res;
12219a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode;
12225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (FPREG(rDest) || FPREG(rSrc))
12235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return fpRegCopy(cUnit, rDest, rSrc);
1224fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
12255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (LOWREG(rDest) && LOWREG(rSrc))
12269a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        opcode = kThumbMovRR;
12275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    else if (!LOWREG(rDest) && !LOWREG(rSrc))
12289a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         opcode = kThumbMovRR_H2H;
12295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    else if (LOWREG(rDest))
12309a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         opcode = kThumbMovRR_H2L;
12315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    else
12329a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         opcode = kThumbMovRR_L2H;
1233270c1d64a192341be842f46734054c692bac061eBill Buzbee
12345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[0] = rDest;
12355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[1] = rSrc;
12369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    res->opcode = opcode;
12375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(res);
12385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rDest == rSrc) {
1239d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.isNop = true;
12405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
12415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1242270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1243270c1d64a192341be842f46734054c692bac061eBill Buzbee
12445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
1245270c1d64a192341be842f46734054c692bac061eBill Buzbee{
12465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc);
12475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    dvmCompilerAppendLIR(cUnit, (LIR*)res);
12485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1249270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1250270c1d64a192341be842f46734054c692bac061eBill Buzbee
12515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
12525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           int srcLo, int srcHi)
1253270c1d64a192341be842f46734054c692bac061eBill Buzbee{
12545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    bool destFP = FPREG(destLo) && FPREG(destHi);
12555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    bool srcFP = FPREG(srcLo) && FPREG(srcHi);
12565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(FPREG(srcLo) == FPREG(srcHi));
12575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(FPREG(destLo) == FPREG(destHi));
12585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (destFP) {
12595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if (srcFP) {
12605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
12615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
12625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
12635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
12645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
12655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if (srcFP) {
12665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
12675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
12685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            // Handle overlap
12695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            if (srcHi == destLo) {
12705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destHi, srcHi);
12715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destLo, srcLo);
12725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            } else {
12735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destLo, srcLo);
12745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destHi, srcHi);
12755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            }
12765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
12775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1278270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1279d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng
1280d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#if defined(WITH_SELF_VERIFICATION)
1281d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Chengstatic void genSelfVerificationPreBranch(CompilationUnit *cUnit,
1282d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                                         ArmLIR *origLIR) {
1283d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    ArmLIR *push = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
1284d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    push->opcode = kThumbPush;
1285d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    /* Thumb push can handle LR (encoded at bit 8) */
128620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    push->operands[0] = (1 << r5FP | 1 << 8);
1287d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setupResourceMasks(push);
1288d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    dvmCompilerInsertLIRBefore((LIR *) origLIR, (LIR *) push);
1289d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng}
1290d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng
1291d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Chengstatic void genSelfVerificationPostBranch(CompilationUnit *cUnit,
1292d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                                         ArmLIR *origLIR) {
1293d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    ArmLIR *pop = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
1294d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    /* Thumb pop cannot store into LR - use Thumb2 here */
1295d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    pop->opcode = kThumb2Pop;
129620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    pop->operands[0] = (1 << r5FP | 1 << r14lr);
1297d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setupResourceMasks(pop);
1298d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    dvmCompilerInsertLIRAfter((LIR *) origLIR, (LIR *) pop);
1299d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng}
1300d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#endif
1301