Factory.cpp revision d72564ca7aa66c6d95b6ca34299258b65ecfd1cb
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));
565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (encodedImm >= 0) {
575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 0);
605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (dataTarget == NULL) {
615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        dataTarget = addWordData(cUnit, value, false);
625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
63fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
649a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    loadPcRel->opcode = kThumb2Vldrs;
655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->generic.target = (LIR *) dataTarget;
665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->operands[0] = rDest;
675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->operands[1] = rpc;
685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(loadPcRel);
69d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setMemRefType(loadPcRel, true, kLiteral);
701f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    loadPcRel->aliasInfo = dataTarget->operands[0];
715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return loadPcRel;
735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic int leadingZeros(u4 val)
761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    u4 alt;
781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int n;
791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int count;
801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    count = 16;
821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    n = 32;
831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    do {
841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        alt = val >> count;
851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (alt != 0) {
861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            n = n - count;
871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            val = alt;
881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        count >>= 1;
901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } while (count);
911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return n - val;
921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
939bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
949bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee/*
951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * Determine whether value can be encoded as a Thumb2 modified
961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
979bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee */
981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic int modifiedImmediate(u4 value)
991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
1001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   int zLeading;
1011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   int zTrailing;
1021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   u4 b0 = value & 0xff;
1031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
1041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Note: case of value==0 must use 0:000:0:0000000 encoding */
1051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value <= 0xFF)
1061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return b0;  // 0:000:a:bcdefgh
1071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value == ((b0 << 16) | b0))
1081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
1091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
1101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
1111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   b0 = (value >> 8) & 0xff;
1121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if (value == ((b0 << 24) | (b0 << 8)))
1131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
1141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Can we do it with rotation? */
1151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   zLeading = leadingZeros(value);
1161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   zTrailing = 32 - leadingZeros(~value & (value - 1));
1171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* A run of eight or fewer active bits? */
1181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   if ((zLeading + zTrailing) < 24)
1191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       return -1;  /* No - bail */
1201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* left-justify the constant, discarding msb (known to be 1) */
1211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   value <<= zLeading + 1;
1221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Create bcdefgh */
1231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   value >>= 25;
1241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   /* Put it all together */
1251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee   return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
1261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
1279bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1289bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee/*
1295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Load a immediate using a shortcut if possible; otherwise
1305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * grab from the per-translation literal pool.
131bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng *
132bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng * No additional register clobbering operation performed. Use this version when
133bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng * 1) rDest is freshly returned from dvmCompilerAllocTemp or
134bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng * 2) The codegen is under fixed register usage
1359bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee */
136bd1326d0e6b82a24ee80d50921e62152ea919151Ben Chengstatic ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
137bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng                                     int value)
1389bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
1395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res;
1405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int modImm;
1419bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (FPREG(rDest)) {
1435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return loadFPConstantValue(cUnit, rDest, value);
1441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1459bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
1465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* See if the value can be constructed cheaply */
1475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (LOWREG(rDest) && (value >= 0) && (value <= 255)) {
1485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return newLIR2(cUnit, kThumbMovImm, rDest, value);
1491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* Check Modified immediate special cases */
1515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    modImm = modifiedImmediate(value);
1525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (modImm >= 0) {
1535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return res;
1559bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee    }
1565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    modImm = modifiedImmediate(~value);
1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (modImm >= 0) {
1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2MvnImmShift, rDest, modImm);
1595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return res;
160a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee    }
1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* 16-bit immediate? */
1625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if ((value & 0xffff) == value) {
1635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
1645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return res;
165270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
1665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /* No shortcut - go ahead and use literal pool */
167fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee    ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 0);
1685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (dataTarget == NULL) {
1695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        dataTarget = addWordData(cUnit, value, false);
1705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
171fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
1729a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    loadPcRel->opcode = kThumb2LdrPcRel12;
1735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->generic.target = (LIR *) dataTarget;
1745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadPcRel->operands[0] = rDest;
1755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(loadPcRel);
176d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setMemRefType(loadPcRel, true, kLiteral);
1771f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    loadPcRel->aliasInfo = dataTarget->operands[0];
1785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = loadPcRel;
1795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
180270c1d64a192341be842f46734054c692bac061eBill Buzbee
1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /*
1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     * To save space in the constant pool, we use the ADD_RRI8 instruction to
1835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     * add up to 255 to an existing constant value.
1845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     */
1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (dataTarget->operands[0] != value) {
1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
1877ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    }
1887ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    return res;
1897ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee}
1907ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee
1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Load an immediate value into a fixed or temp register.  Target
1935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * register is clobbered, and marked inUse.
1945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
1955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
1969bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
197c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    if (dvmCompilerIsTemp(cUnit, rDest)) {
198c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rDest);
1996a55513b0d268bc0721834050a3698316854fa0aElliott Hughes        dvmCompilerMarkInUse(cUnit, rDest);
2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
201bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng    return loadConstantNoClobber(cUnit, rDest, value);
2029bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee}
2039bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
2041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
2059bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
2069a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
2071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
2081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpUncondBr:
2099a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumbBUncond;
210270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
211270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
212270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
213270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
2149a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    return newLIR0(cUnit, opcode);
2159bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee}
2169bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee
2171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
2189bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee{
219bff121aa3e5d3c34caf837227cb00a46bf3f1966buzbee    return newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */, cc);
2201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
2211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
2221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
2231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
2249a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
2251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
22618c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        case kOpPush: {
22718c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            if ((value & 0xff00) == 0) {
22818c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPush;
22918c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else if ((value & 0xff00) == (1 << rlr)) {
23018c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                /* Thumb push can handle lr, which is encoded by bit 8 */
23118c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPush;
23218c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                value = (value & 0xff) | (1<<8);
23318c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else {
23418c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumb2Push;
23518c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            }
236270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
23718c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        }
23818c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        case kOpPop: {
23918c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            if ((value & 0xff00) == 0) {
24018c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPop;
24118c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else if ((value & 0xff00) == (1 << rpc)) {
24218c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                /* Thumb pop can handle pc, which is encoded by bit 8 */
24318c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumbPop;
24418c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                value = (value & 0xff) | (1<<8);
24518c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else {
24618c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                opcode = kThumb2Pop;
24718c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            }
248270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
24918c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng        }
250270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
251270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
2529bc3df373ae6f4f7e6e97d554884d4e0dbad5494Bill Buzbee    }
2539a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    return newLIR1(cUnit, opcode, value);
254d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
255d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
2561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
257d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng{
2589a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
2591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
2601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpBlx:
2619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumbBlxR;
2621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
2631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
2641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
265d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
2669a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    return newLIR1(cUnit, opcode, rDestSrc);
267d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
268d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
2691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
2701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        int rSrc2, int shift)
271270c1d64a192341be842f46734054c692bac061eBill Buzbee{
272270c1d64a192341be842f46734054c692bac061eBill Buzbee    bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
2739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
274270c1d64a192341be842f46734054c692bac061eBill Buzbee    switch (op) {
2751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdc:
2769a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
277270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
2781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAnd:
2799a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
280270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
2811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpBic:
2829a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
283270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
2841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmn:
285270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
2869a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
287270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
2881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmp:
289270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (thumbForm)
2909a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpRR;
291270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
2929a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpHH;
293270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if ((shift == 0) && LOWREG(rDestSrc1))
2949a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpLH;
295270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (shift == 0)
2969a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpHL;
297dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng            else
2989a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2CmpRR;
299270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpXor:
3019a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
302270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMov:
304270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
305270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
3069a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR;
307270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
3089a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR_H2H;
309270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (LOWREG(rDestSrc1))
3109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR_H2L;
311270c1d64a192341be842f46734054c692bac061eBill Buzbee            else
3129a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbMovRR_L2H;
313270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMul:
315270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3169a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
317270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMvn:
3199a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
320270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpNeg:
322270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3239a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
324270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpOr:
3269a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
327270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSbc:
3299a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
330270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpTst:
3329a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
333270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsl:
335270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
337270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsr:
339270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3409a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
341270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAsr:
343270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3449a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
345270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpRor:
347270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3489a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
349270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
3519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
352270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
3549a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
355270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
3561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOp2Byte:
357270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
3591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOp2Short:
360270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
3621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOp2Char:
363270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(shift == 0);
3641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
365270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
366270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
367270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
368270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
3699a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    assert(opcode >= 0);
3709a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (EncodingMap[opcode].flags & IS_BINARY_OP)
3719a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
3729a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
3739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
3749a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
375270c1d64a192341be842f46734054c692bac061eBill Buzbee        else
3769a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
3779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
3789a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
379270c1d64a192341be842f46734054c692bac061eBill Buzbee    else {
380270c1d64a192341be842f46734054c692bac061eBill Buzbee        assert(0);
381270c1d64a192341be842f46734054c692bac061eBill Buzbee        return NULL;
382270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
383270c1d64a192341be842f46734054c692bac061eBill Buzbee}
384270c1d64a192341be842f46734054c692bac061eBill Buzbee
385270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
386270c1d64a192341be842f46734054c692bac061eBill Buzbee                        int rSrc2)
387270c1d64a192341be842f46734054c692bac061eBill Buzbee{
388270c1d64a192341be842f46734054c692bac061eBill Buzbee    return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
389270c1d64a192341be842f46734054c692bac061eBill Buzbee}
390270c1d64a192341be842f46734054c692bac061eBill Buzbee
3911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op,
3921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                int rDest, int rSrc1, int rSrc2, int shift)
3931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
3949a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
3951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
3961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                      LOWREG(rSrc2);
3971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (op) {
3981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
3999a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
4001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
4029a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
4031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdc:
4059a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AdcRRR;
4061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAnd:
4089a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AndRRR;
4091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpBic:
4119a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2BicRRR;
4121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpXor:
4149a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2EorRRR;
4151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMul:
4171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4189a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2MulRRR;
4191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpOr:
4219a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2OrrRRR;
4221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSbc:
4249a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2SbcRRR;
4251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsl:
4271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4289a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2LslRRR;
4291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsr:
4311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4329a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2LsrRRR;
4331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAsr:
4351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AsrRRR;
4371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpRor:
4391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(shift == 0);
4409a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2RorRRR;
4411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
4431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
4441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
4451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
4469a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    assert(opcode >= 0);
4479a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (EncodingMap[opcode].flags & IS_QUAD_OP)
4489a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
4491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else {
4509a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        assert(EncodingMap[opcode].flags & IS_TERTIARY_OP);
4519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
4521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
4531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
4541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
4551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
4561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           int rSrc1, int rSrc2)
4571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
4581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
4591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
4601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
4611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
4621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           int rSrc1, int value)
4631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
4641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res;
4651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool neg = (value < 0);
4661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int absValue = (neg) ? -value : value;
4679a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
4689a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode altOpcode = kThumbBkpt;
4691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
4701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int modImm = modifiedImmediate(value);
4711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int modImmNeg = modifiedImmediate(-value);
4721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
4731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch(op) {
4741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsl:
4751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs)
4761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
4771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            else
4781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
4791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpLsr:
4801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs)
4811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
4821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            else
4831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
4841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAsr:
4851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs)
4861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
4871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            else
4881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
4891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpRor:
4901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
4911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
4921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (LOWREG(rDest) && (rSrc1 == 13) &&
4931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                (value <= 1020) && ((value & 0x3)==0)) {
4941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1,
4951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                               value >> 2);
4961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (LOWREG(rDest) && (rSrc1 == rpc) &&
4971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                       (value <= 1020) && ((value & 0x3)==0)) {
4981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1,
4991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                               value >> 2);
5001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5019a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AddRRI8;
5029a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2AddRRR;
5031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            // Note: intentional fallthrough
5041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
5051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && ((absValue & 0x7) == absValue)) {
5061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (op == kOpAdd)
5079a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
5081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                else
5099a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
5109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
5111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if ((absValue & 0xff) == absValue) {
5121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (op == kOpAdd)
5139a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
5141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                else
5159a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                    opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
5169a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
5171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (modImmNeg >= 0) {
5191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                op = (op == kOpAdd) ? kOpSub : kOpAdd;
5201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                modImm = modImmNeg;
5211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (op == kOpSub) {
5239a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2SubRRI8;
5249a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                altOpcode = kThumb2SubRRR;
5251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdc:
5289a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AdcRRI8;
5299a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2AdcRRR;
5301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSbc:
5329a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2SbcRRI8;
5339a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2SbcRRR;
5341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpOr:
5369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2OrrRRI8;
5379a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2OrrRRR;
5381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAnd:
5409a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2AndRRI8;
5419a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2AndRRR;
5421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpXor:
5449a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2EorRRI8;
5459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2EorRRR;
5461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpMul:
5481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            //TUNING: power of 2, shift & add
5491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            modImm = -1;
5509a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            altOpcode = kThumb2MulRRR;
5511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
5521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmp: {
5531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            int modImm = modifiedImmediate(value);
5541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            ArmLIR *res;
5551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (modImm >= 0) {
5561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
5571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
558c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                int rTmp = dvmCompilerAllocTemp(cUnit);
5591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = loadConstant(cUnit, rTmp, value);
5601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
561c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                dvmCompilerFreeTemp(cUnit, rTmp);
5621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
5631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return res;
5641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
5651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
5661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
5671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
5681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
5691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (modImm >= 0) {
5709a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
5711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
572c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int rScratch = dvmCompilerAllocTemp(cUnit);
5731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadConstant(cUnit, rScratch, value);
5749a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
5759a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
5761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        else
5779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
578c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, rScratch);
5791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        return res;
5801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
5811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
5821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
583270c1d64a192341be842f46734054c692bac061eBill Buzbee/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
584270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
5851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        int value)
586270c1d64a192341be842f46734054c692bac061eBill Buzbee{
587270c1d64a192341be842f46734054c692bac061eBill Buzbee    bool neg = (value < 0);
588270c1d64a192341be842f46734054c692bac061eBill Buzbee    int absValue = (neg) ? -value : value;
589270c1d64a192341be842f46734054c692bac061eBill Buzbee    bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
5909a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
591270c1d64a192341be842f46734054c692bac061eBill Buzbee    switch (op) {
5921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpAdd:
593270c1d64a192341be842f46734054c692bac061eBill Buzbee            if ( !neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
594270c1d64a192341be842f46734054c692bac061eBill Buzbee                assert((value & 0x3) == 0);
5951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
596270c1d64a192341be842f46734054c692bac061eBill Buzbee            } else if (shortForm) {
5979a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
598270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
599270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
6001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpSub:
601270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (!neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
602270c1d64a192341be842f46734054c692bac061eBill Buzbee                assert((value & 0x3) == 0);
6031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
604270c1d64a192341be842f46734054c692bac061eBill Buzbee            } else if (shortForm) {
6059a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
606270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
607270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
6081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kOpCmp:
609270c1d64a192341be842f46734054c692bac061eBill Buzbee            if (LOWREG(rDestSrc1) && shortForm)
6109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = (shortForm) ?  kThumbCmpRI8 : kThumbCmpRR;
611270c1d64a192341be842f46734054c692bac061eBill Buzbee            else if (LOWREG(rDestSrc1))
6129a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpRR;
613270c1d64a192341be842f46734054c692bac061eBill Buzbee            else {
614270c1d64a192341be842f46734054c692bac061eBill Buzbee                shortForm = false;
6159a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbCmpHL;
616270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
617270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
618270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
619270c1d64a192341be842f46734054c692bac061eBill Buzbee            /* Punt to opRegRegImm - if bad case catch it there */
620270c1d64a192341be842f46734054c692bac061eBill Buzbee            shortForm = false;
621270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
622270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
623270c1d64a192341be842f46734054c692bac061eBill Buzbee    if (shortForm)
6249a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        return newLIR2(cUnit, opcode, rDestSrc1, absValue);
6251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else {
6261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
6271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
628270c1d64a192341be842f46734054c692bac061eBill Buzbee}
629270c1d64a192341be842f46734054c692bac061eBill Buzbee
6301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/*
6315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Determine whether value can be encoded as a Thumb2 floating point
6325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * immediate.  If not, return -1.  If so return encoded 8-bit value.
6331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee */
6345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeImmDoubleHigh(int value)
6351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
6365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int res;
6375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bitA =    (value & 0x80000000) >> 31;
6385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int notBitB = (value & 0x40000000) >> 30;
6395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bitB =    (value & 0x20000000) >> 29;
6405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int bSmear =  (value & 0x3fc00000) >> 22;
6415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int slice =   (value & 0x003f0000) >> 16;
6425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int zeroes =  (value & 0x0000ffff);
6435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (zeroes != 0)
6445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return -1;
6455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (bitB) {
6465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if ((notBitB != 0) || (bSmear != 0x1f))
6475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return -1;
6481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
6495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if ((notBitB != 1) || (bSmear != 0x0))
6505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return -1;
6511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
6525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = (bitA << 7) | (bitB << 6) | slice;
6535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
6545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
6551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeImmDouble(int valLo, int valHi)
6575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
6585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int res = -1;
6595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (valLo == 0)
6605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = encodeImmDoubleHigh(valHi);
6615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
6625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
6631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
6655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                     int rDestHi, int valLo, int valHi)
6665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
6675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int encodedImm = encodeImmDouble(valLo, valHi);
6685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res;
6695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (FPREG(rDestLo) && (encodedImm >= 0)) {
6705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi),
6715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                      encodedImm);
6721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
673bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        res = loadConstantNoClobber(cUnit, rDestLo, valLo);
674bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        loadConstantNoClobber(cUnit, rDestHi, valHi);
6751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
6765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
6771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
6781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic int encodeShift(int code, int amount) {
6805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return ((amount & 0x1f) << 2) | code;
6811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
6821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
6841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                               int rIndex, int rDest, int scale, OpSize size)
6851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
6861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
6879e45c0b968d63ea38353c99252d233879c2efdafjeffhao    ArmLIR *load;
6889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
6891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumbForm = (allLowRegs && (scale == 0));
6901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
6911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (FPREG(rDest)) {
6931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert(SINGLEREG(rDest));
6941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert((size == kWord) || (size == kSingle));
6959a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        opcode = kThumb2Vldrs;
6961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        size = kSingle;
6971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
6981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (size == kSingle)
6991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            size = kWord;
7001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
7031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
704c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            regPtr = dvmCompilerAllocTemp(cUnit);
7051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (scale) {
7061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
7071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        encodeShift(kArmLsl, scale));
7081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
7091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
7101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
7119a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
7129e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
7139e45c0b968d63ea38353c99252d233879c2efdafjeffhao            if (cUnit->heapMemOp)
714d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                load->flags.insertWrapper = true;
7159e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
7169e45c0b968d63ea38353c99252d233879c2efdafjeffhao            return load;
7171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
7189a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
719270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
7219a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
722270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
7249a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
725270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
7279a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
728270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
7309a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
731270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
7331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
7341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (thumbForm)
7369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
7371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else
7389a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
7399e45c0b968d63ea38353c99252d233879c2efdafjeffhao
7409e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
7419e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
742d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        load->flags.insertWrapper = true;
7439e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
7449e45c0b968d63ea38353c99252d233879c2efdafjeffhao    return load;
7451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
7461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
7481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                int rIndex, int rSrc, int scale, OpSize size)
7491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
7501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
7519e45c0b968d63ea38353c99252d233879c2efdafjeffhao    ArmLIR *store;
7529a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
7531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumbForm = (allLowRegs && (scale == 0));
7541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
7551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (FPREG(rSrc)) {
7571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert(SINGLEREG(rSrc));
758749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        assert((size == kWord) || (size == kSingle));
7599a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        opcode = kThumb2Vstrs;
760749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        size = kSingle;
7611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
7621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (size == kSingle)
7631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            size = kWord;
7641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
7661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
7671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
768c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            regPtr = dvmCompilerAllocTemp(cUnit);
7691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (scale) {
7701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
7711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        encodeShift(kArmLsl, scale));
7721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
7731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
7741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
7759a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
7769e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
7779e45c0b968d63ea38353c99252d233879c2efdafjeffhao            if (cUnit->heapMemOp)
778d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                store->flags.insertWrapper = true;
7799e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
7809e45c0b968d63ea38353c99252d233879c2efdafjeffhao            return store;
7811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
7829a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
783270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
7851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
7869a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
787270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
7891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
7909a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
791270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
7921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        default:
7931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            assert(0);
7941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
7951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (thumbForm)
7969a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
7971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else
7989a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
7999e45c0b968d63ea38353c99252d233879c2efdafjeffhao
8009e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
8019e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
802d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        store->flags.insertWrapper = true;
8039e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
8049e45c0b968d63ea38353c99252d233879c2efdafjeffhao    return store;
8051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
8061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/*
8081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * Load value from base + displacement.  Optionally perform null check
8091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * on base (which must have an associated sReg and MIR).  If not
8101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee * performing null check, incoming MIR can be null.
8111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee */
8121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
8131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                int displacement, int rDest, int rDestHi,
8145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                OpSize size, int sReg)
8151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
8161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res, *load;
8179a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
8181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool shortForm = false;
8191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumb2Form = (displacement < 4092 && displacement >= 0);
8201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
8211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int encodedDisp = displacement;
8221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
8231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
8241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kDouble:
8251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kLong:
8261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (FPREG(rDest)) {
8271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (SINGLEREG(rDest)) {
8281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    assert(FPREG(rDestHi));
8291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    rDest = S2D(rDest, rDestHi);
8301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
8319a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2Vldrd;
8321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (displacement <= 1020) {
8331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    shortForm = true;
8341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    encodedDisp >>= 2;
8351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
8361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                break;
8371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
8381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest,
8395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                       -1, kWord, sReg);
8401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi,
8415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                 -1, kWord, INVALID_SREG);
8421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return res;
8431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
8441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
8451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
8461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (FPREG(rDest)) {
8479a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2Vldrs;
8481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (displacement <= 1020) {
8491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    shortForm = true;
8501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    encodedDisp >>= 2;
8511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
8521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                break;
8531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
8541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (LOWREG(rDest) && (rBase == rpc) &&
8551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                (displacement <= 1020) && (displacement >= 0)) {
8561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
8589a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrPcRel;
8591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (LOWREG(rDest) && (rBase == r13) &&
8601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                      (displacement <= 1020) && (displacement >= 0)) {
8611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
8639a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrSpRel;
8641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (allLowRegs && displacement < 128 && displacement >= 0) {
8651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x3) == 0);
8661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
8689a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrRRI5;
8691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
8701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8719a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrRRI12;
8721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
873270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
8741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
8751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 64 && displacement >= 0) {
8761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x1) == 0);
8771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 1;
8799a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrhRRI5;
8801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (displacement < 4092 && displacement >= 0) {
8811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8829a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrhRRI12;
8831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
884270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
8851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
8861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (thumb2Form) {
8871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrshRRI12;
8891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
890270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
8911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
8921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 32 && displacement >= 0) {
8931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8949a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbLdrbRRI5;
8951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
8961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
8979a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrbRRI12;
8981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
899270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
9011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (thumb2Form) {
9021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9039a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2LdrsbRRI12;
9041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
905270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
906270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
907270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
908270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
9095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
9101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (shortForm) {
9119a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
9121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
913c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int regOffset = dvmCompilerAllocTemp(cUnit);
9141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = loadConstant(cUnit, regOffset, encodedDisp);
9151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
916c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regOffset);
9171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
9181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
9191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (rBase == rFP) {
9201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
921270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
9229e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
9239e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
924d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        load->flags.insertWrapper = true;
9259e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
9265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
927270c1d64a192341be842f46734054c692bac061eBill Buzbee}
928270c1d64a192341be842f46734054c692bac061eBill Buzbee
9291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
9301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                            int displacement, int rDest, OpSize size,
9315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            int sReg)
932270c1d64a192341be842f46734054c692bac061eBill Buzbee{
9331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
9345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            size, sReg);
935270c1d64a192341be842f46734054c692bac061eBill Buzbee}
936270c1d64a192341be842f46734054c692bac061eBill Buzbee
9375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic  ArmLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
938c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 int displacement, int rDestLo, int rDestHi,
939c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 int sReg)
940270c1d64a192341be842f46734054c692bac061eBill Buzbee{
9411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
9425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            kLong, sReg);
9431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
944270c1d64a192341be842f46734054c692bac061eBill Buzbee
9451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
9461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
947c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 int displacement, int rSrc, int rSrcHi,
948c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                 OpSize size)
9491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
9501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res, *store;
9519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode = kThumbBkpt;
9521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool shortForm = false;
9531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool thumb2Form = (displacement < 4092 && displacement >= 0);
9541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
9551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int encodedDisp = displacement;
9561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
9571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    switch (size) {
9581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kLong:
9591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kDouble:
9601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (!FPREG(rSrc)) {
9611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                res = storeBaseDispBody(cUnit, rBase, displacement, rSrc,
9621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                        -1, kWord);
9631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi,
9641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                  -1, kWord);
9651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                return res;
966270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
9671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (SINGLEREG(rSrc)) {
9681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert(FPREG(rSrcHi));
9691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                rSrc = S2D(rSrc, rSrcHi);
970270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
9719a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            opcode = kThumb2Vstrd;
9721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (displacement <= 1020) {
9731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
975270c1d64a192341be842f46734054c692bac061eBill Buzbee            }
976270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSingle:
9781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kWord:
9791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (FPREG(rSrc)) {
9801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert(SINGLEREG(rSrc));
9819a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2Vstrs;
9821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                if (displacement <= 1020) {
9831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    shortForm = true;
9841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    encodedDisp >>= 2;
9851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                }
986270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
9881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 128 && displacement >= 0) {
9891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x3) == 0);
9901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 2;
9929a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbStrRRI5;
9931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
9941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
9959a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2StrRRI12;
9961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
997270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
9981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedHalf:
9991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedHalf:
10001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 64 && displacement >= 0) {
10011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                assert((displacement & 0x1) == 0);
10021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                encodedDisp >>= 1;
10049a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbStrhRRI5;
10051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
10061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10079a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2StrhRRI12;
10081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
1009270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
10101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kUnsignedByte:
10111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kSignedByte:
10121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (allLowRegs && displacement < 32 && displacement >= 0) {
10131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10149a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumbStrbRRI5;
10151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else if (thumb2Form) {
10161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                shortForm = true;
10179a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                opcode = kThumb2StrbRRI12;
10181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
1019270c1d64a192341be842f46734054c692bac061eBill Buzbee            break;
1020270c1d64a192341be842f46734054c692bac061eBill Buzbee        default:
1021270c1d64a192341be842f46734054c692bac061eBill Buzbee            assert(0);
1022270c1d64a192341be842f46734054c692bac061eBill Buzbee    }
10231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (shortForm) {
10249a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
10251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
1026c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int rScratch = dvmCompilerAllocTemp(cUnit);
10271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = loadConstant(cUnit, rScratch, encodedDisp);
10281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
1029c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, rScratch);
10301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
10311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (rBase == rFP) {
10331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
10341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
10359e45c0b968d63ea38353c99252d233879c2efdafjeffhao#if defined(WITH_SELF_VERIFICATION)
10369e45c0b968d63ea38353c99252d233879c2efdafjeffhao    if (cUnit->heapMemOp)
1037d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        store->flags.insertWrapper = true;
10389e45c0b968d63ea38353c99252d233879c2efdafjeffhao#endif
10391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return res;
10401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
10431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                             int displacement, int rSrc, OpSize size)
10441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
10461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
10491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                 int displacement, int rSrcLo, int rSrcHi)
10501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
10521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
10551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res;
10571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
10581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
10591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumbLdmia, rBase, rMask);
10601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
10611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumb2Ldmia, rBase, rMask);
10621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1063121ea790080b5a6bb713a07452c19f87d209de48jeffhao#if defined(WITH_SELF_VERIFICATION)
1064121ea790080b5a6bb713a07452c19f87d209de48jeffhao    if (cUnit->heapMemOp)
1065d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.insertWrapper = true;
1066121ea790080b5a6bb713a07452c19f87d209de48jeffhao#endif
10671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
10681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return res;
10691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
10721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *res;
10741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
10751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
10761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumbStmia, rBase, rMask);
10771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
10781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        res = newLIR2(cUnit, kThumb2Stmia, rBase, rMask);
10791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1080121ea790080b5a6bb713a07452c19f87d209de48jeffhao#if defined(WITH_SELF_VERIFICATION)
1081121ea790080b5a6bb713a07452c19f87d209de48jeffhao    if (cUnit->heapMemOp)
1082d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.insertWrapper = true;
1083121ea790080b5a6bb713a07452c19f87d209de48jeffhao#endif
10841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genBarrier(cUnit);
10851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return res;
10861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
10891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
10911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
10941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
10955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
10961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
10971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/*
10998f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee * Generate a register comparison to an immediate and branch.  Caller
11008f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee * is responsible for setting branch target field.
1101a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee */
11028f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbeestatic ArmLIR *genCmpImmBranch(CompilationUnit *cUnit,
1103c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                              ArmConditionCode cond, int reg,
11048f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee                              int checkValue)
1105a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee{
11061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *branch;
11071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int modImm;
1108bff121aa3e5d3c34caf837227cb00a46bf3f1966buzbee    if ((LOWREG(reg)) && (checkValue == 0) &&
11091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee       ((cond == kArmCondEq) || (cond == kArmCondNe))) {
11101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        branch = newLIR2(cUnit,
11111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         (cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
11121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         reg, 0);
11131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
11141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        modImm = modifiedImmediate(checkValue);
11151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
11161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
11171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        } else if (modImm >= 0) {
11181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
11191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        } else {
1120c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
11211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadConstant(cUnit, tReg, checkValue);
11221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpCmp, reg, tReg);
11231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
11241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        branch = newLIR2(cUnit, kThumbBCond, 0, cond);
11251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
11268f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    return branch;
1127a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee}
1128a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee
11295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
1130270c1d64a192341be842f46734054c692bac061eBill Buzbee{
1131fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ArmLIR* res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
11325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[0] = rDest;
11335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[1] = rSrc;
11345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rDest == rSrc) {
1135d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.isNop = true;
11365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
11375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        assert(DOUBLEREG(rDest) == DOUBLEREG(rSrc));
11385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if (DOUBLEREG(rDest)) {
11399a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            res->opcode = kThumb2Vmovd;
11405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
11415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            if (SINGLEREG(rDest)) {
11429a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                res->opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
11435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            } else {
11445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                assert(SINGLEREG(rSrc));
11459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                res->opcode = kThumb2Fmrs;
11465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            }
11475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
11485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res->operands[0] = rDest;
11495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        res->operands[1] = rSrc;
11505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
11515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(res);
11525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1153270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1154270c1d64a192341be842f46734054c692bac061eBill Buzbee
11555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
1156270c1d64a192341be842f46734054c692bac061eBill Buzbee{
11575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR* res;
11589a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    ArmOpcode opcode;
11595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (FPREG(rDest) || FPREG(rSrc))
11605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return fpRegCopy(cUnit, rDest, rSrc);
1161fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
11625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (LOWREG(rDest) && LOWREG(rSrc))
11639a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        opcode = kThumbMovRR;
11645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    else if (!LOWREG(rDest) && !LOWREG(rSrc))
11659a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         opcode = kThumbMovRR_H2H;
11665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    else if (LOWREG(rDest))
11679a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         opcode = kThumbMovRR_H2L;
11685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    else
11699a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         opcode = kThumbMovRR_L2H;
1170270c1d64a192341be842f46734054c692bac061eBill Buzbee
11715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[0] = rDest;
11725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res->operands[1] = rSrc;
11739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    res->opcode = opcode;
11745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    setupResourceMasks(res);
11755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rDest == rSrc) {
1176d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        res->flags.isNop = true;
11775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
11785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1179270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1180270c1d64a192341be842f46734054c692bac061eBill Buzbee
11815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
1182270c1d64a192341be842f46734054c692bac061eBill Buzbee{
11835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc);
11845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    dvmCompilerAppendLIR(cUnit, (LIR*)res);
11855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1186270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1187270c1d64a192341be842f46734054c692bac061eBill Buzbee
11885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
11895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           int srcLo, int srcHi)
1190270c1d64a192341be842f46734054c692bac061eBill Buzbee{
11915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    bool destFP = FPREG(destLo) && FPREG(destHi);
11925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    bool srcFP = FPREG(srcLo) && FPREG(srcHi);
11935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(FPREG(srcLo) == FPREG(srcHi));
11945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(FPREG(destLo) == FPREG(destHi));
11955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (destFP) {
11965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if (srcFP) {
11975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
11985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
11995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
12005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
12015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
12025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        if (srcFP) {
12035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
12045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
12055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            // Handle overlap
12065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            if (srcHi == destLo) {
12075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destHi, srcHi);
12085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destLo, srcLo);
12095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            } else {
12105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destLo, srcLo);
12115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                genRegCopy(cUnit, destHi, srcHi);
12125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            }
12135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
12145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1215270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1216d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng
1217d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#if defined(WITH_SELF_VERIFICATION)
1218d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Chengstatic void genSelfVerificationPreBranch(CompilationUnit *cUnit,
1219d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                                         ArmLIR *origLIR) {
1220d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    ArmLIR *push = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
1221d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    push->opcode = kThumbPush;
1222d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    /* Thumb push can handle LR (encoded at bit 8) */
1223d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    push->operands[0] = (1 << rFP | 1 << 8);
1224d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setupResourceMasks(push);
1225d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    dvmCompilerInsertLIRBefore((LIR *) origLIR, (LIR *) push);
1226d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng}
1227d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng
1228d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Chengstatic void genSelfVerificationPostBranch(CompilationUnit *cUnit,
1229d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                                         ArmLIR *origLIR) {
1230d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    ArmLIR *pop = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
1231d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    /* Thumb pop cannot store into LR - use Thumb2 here */
1232d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    pop->opcode = kThumb2Pop;
1233d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    pop->operands[0] = (1 << rFP | 1 << rlr);
1234d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    setupResourceMasks(pop);
1235d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    dvmCompilerInsertLIRAfter((LIR *) origLIR, (LIR *) pop);
1236d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng}
1237d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#endif
1238