1ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
2ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Copyright (C) 2009 The Android Open Source Project
3ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
4ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Licensed under the Apache License, Version 2.0 (the "License");
5ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * you may not use this file except in compliance with the License.
6ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * You may obtain a copy of the License at
7ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
8ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *      http://www.apache.org/licenses/LICENSE-2.0
9ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
10ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Unless required by applicable law or agreed to in writing, software
11ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * distributed under the License is distributed on an "AS IS" BASIS,
12ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See the License for the specific language governing permissions and
14ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * limitations under the License.
15ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
16ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1750a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee/*
1850a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee * This file contains codegen and support common to all supported
1950a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee * ARM variants.  It is included by:
2050a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee *
2150a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee *        Codegen-$(TARGET_ARCH_VARIANT).c
2250a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee *
2350a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee * which combines this common code with specific support found in the
2450a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee * applicable directory below this one.
2550a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee */
2650a6bf2f01efba0acbff9bb03e7ee09688553e08Bill Buzbee
27919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee/*
28919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee * Mark garbage collection card. Skip if the value we're storing is null.
29919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee */
30919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbeestatic void markCard(CompilationUnit *cUnit, int valReg, int tgtAddrReg)
31919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee{
32919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    int regCardBase = dvmCompilerAllocTemp(cUnit);
33919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    int regCardNo = dvmCompilerAllocTemp(cUnit);
348f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondEq, valReg, 0);
3520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadWordDisp(cUnit, r6SELF, offsetof(Thread, cardTable),
36919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee                 regCardBase);
37919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
38919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
39919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee                     kUnsignedByte);
40919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
41919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    target->defMask = ENCODE_ALL;
42919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    branchOver->generic.target = (LIR *)target;
43baf196a7b259704137cccf4058b78da15d4c3998buzbee    dvmCompilerFreeTemp(cUnit, regCardBase);
44baf196a7b259704137cccf4058b78da15d4c3998buzbee    dvmCompilerFreeTemp(cUnit, regCardNo);
45919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee}
46919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee
475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                     int srcSize, int tgtSize)
495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    /*
515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     * Don't optimize the register usage since it calls out to template
525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     * functions
535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng     */
545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlSrc;
555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlDest;
56c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);   /* Send everything to home location */
575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (srcSize == 1) {
58c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirectFixed(cUnit, rlSrc, r0);
605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
61c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirectWideFixed(cUnit, rlSrc, r0, r1);
635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
64bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng    LOAD_FUNC_ADDR(cUnit, r2, (int)funct);
655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opReg(cUnit, kOpBlx, r2);
666a55513b0d268bc0721834050a3698316854fa0aElliott Hughes    dvmCompilerClobberCallRegs(cUnit);
675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (tgtSize == 1) {
685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        RegLocation rlResult;
69c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDest(cUnit, mir, 0);
70c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlResult = dvmCompilerGetReturn(cUnit);
715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        storeValue(cUnit, rlDest, rlResult);
725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        RegLocation rlResult;
74c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
75c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlResult = dvmCompilerGetReturnWide(cUnit);
765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        storeValueWide(cUnit, rlDest, rlResult);
775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return false;
795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                    RegLocation rlDest, RegLocation rlSrc1,
835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                    RegLocation rlSrc2)
845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    void* funct;
875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_ADD_FLOAT_2ADDR:
905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_ADD_FLOAT:
915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_fadd;
925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_SUB_FLOAT_2ADDR:
945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_SUB_FLOAT:
955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_fsub;
965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DIV_FLOAT_2ADDR:
985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DIV_FLOAT:
995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_fdiv;
1005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_MUL_FLOAT_2ADDR:
1025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_MUL_FLOAT:
1035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_fmul;
1045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_REM_FLOAT_2ADDR:
1065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_REM_FLOAT:
1075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) fmodf;
1085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_NEG_FLOAT: {
1105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genNegFloat(cUnit, rlDest, rlSrc1);
1115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return false;
1125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
1135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        default:
1145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return true;
1155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
116c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);   /* Send everything to home location */
1175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectFixed(cUnit, rlSrc1, r0);
1185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectFixed(cUnit, rlSrc2, r1);
119bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng    LOAD_FUNC_ADDR(cUnit, r2, (int)funct);
1205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opReg(cUnit, kOpBlx, r2);
1216a55513b0d268bc0721834050a3698316854fa0aElliott Hughes    dvmCompilerClobberCallRegs(cUnit);
122c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerGetReturn(cUnit);
1235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlResult);
1245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return false;
1255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genArithOpDoublePortable(CompilationUnit *cUnit, MIR *mir,
1285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                     RegLocation rlDest, RegLocation rlSrc1,
1295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                     RegLocation rlSrc2)
1305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
1325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    void* funct;
1335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1349a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
1355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_ADD_DOUBLE_2ADDR:
1365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_ADD_DOUBLE:
1375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_dadd;
1385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_SUB_DOUBLE_2ADDR:
1405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_SUB_DOUBLE:
1415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_dsub;
1425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DIV_DOUBLE_2ADDR:
1445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DIV_DOUBLE:
1455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_ddiv;
1465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_MUL_DOUBLE_2ADDR:
1485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_MUL_DOUBLE:
1495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            funct = (void*) __aeabi_dmul;
1505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_REM_DOUBLE_2ADDR:
1525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_REM_DOUBLE:
1530fbb7030fff58e25718291811394487d95d95a3eElliott Hughes            funct = (void*) (double (*)(double, double)) fmod;
1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_NEG_DOUBLE: {
1565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genNegDouble(cUnit, rlDest, rlSrc1);
1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return false;
1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
1595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        default:
1605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return true;
1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
162c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);   /* Send everything to home location */
16320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    LOAD_FUNC_ADDR(cUnit, r14lr, (int)funct);
1645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
1655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
16620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    opReg(cUnit, kOpBlx, r14lr);
1676a55513b0d268bc0721834050a3698316854fa0aElliott Hughes    dvmCompilerClobberCallRegs(cUnit);
168c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerGetReturnWide(cUnit);
1695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
170d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#if defined(WITH_SELF_VERIFICATION)
171d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng    cUnit->usesLinkRegister = true;
172d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#endif
1735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return false;
1745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
175ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genConversionPortable(CompilationUnit *cUnit, MIR *mir)
1775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1789a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode opcode = mir->dalvikInsn.opcode;
179ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1809a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (opcode) {
1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_INT_TO_FLOAT:
1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_i2f, 1, 1);
1835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_FLOAT_TO_INT:
1845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_f2iz, 1, 1);
1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DOUBLE_TO_FLOAT:
1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_d2f, 2, 1);
1875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_FLOAT_TO_DOUBLE:
1885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_f2d, 1, 2);
1895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_INT_TO_DOUBLE:
1905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_i2d, 1, 2);
1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DOUBLE_TO_INT:
1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_d2iz, 2, 1);
1935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_FLOAT_TO_LONG:
1945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)dvmJitf2l, 1, 2);
1955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_LONG_TO_FLOAT:
1965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_l2f, 2, 1);
1975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_DOUBLE_TO_LONG:
1985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)dvmJitd2l, 2, 2);
1995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case OP_LONG_TO_DOUBLE:
2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversionCall(cUnit, mir, (void*)__aeabi_l2d, 2, 2);
2015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        default:
2025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return true;
2035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
2045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return false;
2055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
206ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
20797319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#if defined(WITH_SELF_VERIFICATION)
2089a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornsteinstatic void selfVerificationBranchInsert(LIR *currentLIR, ArmOpcode opcode,
2099e45c0b968d63ea38353c99252d233879c2efdafjeffhao                          int dest, int src1)
21097319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao{
211fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro     ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
2129a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein     insn->opcode = opcode;
2139e45c0b968d63ea38353c99252d233879c2efdafjeffhao     insn->operands[0] = dest;
2149e45c0b968d63ea38353c99252d233879c2efdafjeffhao     insn->operands[1] = src1;
2159e45c0b968d63ea38353c99252d233879c2efdafjeffhao     setupResourceMasks(insn);
2169e45c0b968d63ea38353c99252d233879c2efdafjeffhao     dvmCompilerInsertLIRBefore(currentLIR, (LIR *) insn);
21797319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao}
21897319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao
219d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng/*
220d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * Example where r14 (LR) is preserved around a heap access under
221d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * self-verification mode in Thumb2:
222d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng *
22320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng * D/dalvikvm( 1538): 0x59414c5e (0026): ldr     r14, [r15pc, #220] <-hoisted
224d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c62 (002a): mla     r4, r0, r8, r4
225d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c66 (002e): adds    r3, r4, r3
226d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c6a (0032): push    <r5, r14>    ---+
227d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c6c (0034): blx_1   0x5940f494      |
228d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c6e (0036): blx_2   see above       <-MEM_OP_DECODE
229d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c70 (0038): ldr     r10, [r9, #0]   |
230d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c74 (003c): pop     <r5, r14>    ---+
231d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c78 (0040): mov     r11, r10
232d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c7a (0042): asr     r12, r11, #31
233d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c7e (0046): movs    r0, r2
234d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c80 (0048): movs    r1, r3
235d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c82 (004a): str     r2, [r5, #16]
236d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c84 (004c): mov     r2, r11
237d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c86 (004e): str     r3, [r5, #20]
238d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c88 (0050): mov     r3, r12
239d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c8a (0052): str     r11, [r5, #24]
240d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c8e (0056): str     r12, [r5, #28]
241d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng * D/dalvikvm( 1538): 0x59414c92 (005a): blx     r14             <-use of LR
242d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng *
243d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng */
2449e45c0b968d63ea38353c99252d233879c2efdafjeffhaostatic void selfVerificationBranchInsertPass(CompilationUnit *cUnit)
24597319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao{
2469e45c0b968d63ea38353c99252d233879c2efdafjeffhao    ArmLIR *thisLIR;
2479a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    TemplateOpcode opcode = TEMPLATE_MEM_OP_DECODE;
24897319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao
2499e45c0b968d63ea38353c99252d233879c2efdafjeffhao    for (thisLIR = (ArmLIR *) cUnit->firstLIRInsn;
2509e45c0b968d63ea38353c99252d233879c2efdafjeffhao         thisLIR != (ArmLIR *) cUnit->lastLIRInsn;
2519e45c0b968d63ea38353c99252d233879c2efdafjeffhao         thisLIR = NEXT_LIR(thisLIR)) {
252d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        if (!thisLIR->flags.isNop && thisLIR->flags.insertWrapper) {
253d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng            /*
254d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             * Push r5(FP) and r14(LR) onto stack. We need to make sure that
255d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             * SP is 8-byte aligned, and we use r5 as a temp to restore LR
256d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             * for Thumb-only target since LR cannot be directly accessed in
257d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             * Thumb mode. Another reason to choose r5 here is it is the Dalvik
258d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             * frame pointer and cannot be the target of the emulated heap
259d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             * load.
260d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng             */
261d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng            if (cUnit->usesLinkRegister) {
262d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                genSelfVerificationPreBranch(cUnit, thisLIR);
263d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng            }
264d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng
2659e45c0b968d63ea38353c99252d233879c2efdafjeffhao            /* Branch to mem op decode template */
2669e45c0b968d63ea38353c99252d233879c2efdafjeffhao            selfVerificationBranchInsert((LIR *) thisLIR, kThumbBlx1,
2679a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                       (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
2689a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                       (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
2699e45c0b968d63ea38353c99252d233879c2efdafjeffhao            selfVerificationBranchInsert((LIR *) thisLIR, kThumbBlx2,
2709a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                       (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
2719a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                       (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
272d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng
273d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng            /* Restore LR */
274d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng            if (cUnit->usesLinkRegister) {
275d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                genSelfVerificationPostBranch(cUnit, thisLIR);
276d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng            }
27797319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao        }
27897319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao    }
279ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
2805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng#endif
2815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
282be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee/* Generate conditional branch instructions */
283be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbeestatic ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
284be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                                    ArmConditionCode cond,
285be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                                    ArmLIR *target)
286be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee{
287be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    ArmLIR *branch = opCondBranch(cUnit, cond);
288be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    branch->generic.target = (LIR *) target;
289be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    return branch;
290be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee}
291be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
292ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Generate a unconditional branch to go to the interpreter */
29389efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbeestatic inline ArmLIR *genTrap(CompilationUnit *cUnit, int dOffset,
29489efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                  ArmLIR *pcrLabel)
295ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
2961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *branch = opNone(cUnit, kOpUncondBr);
297ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
298ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
299ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
300ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Load a wide field from an object instance */
301ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
302ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
303c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
304c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
3051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
3061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlObj = loadValue(cUnit, rlObj, kCoreReg);
307c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int regPtr = dvmCompilerAllocTemp(cUnit);
3081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
3091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    assert(rlDest.wide);
3101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
3111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
3121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                 NULL);/* null object? */
3131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
314c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
31511d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
31611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(true);
3171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
31811d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(false);
31911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
320c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, regPtr);
3211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storeValueWide(cUnit, rlDest, rlResult);
322ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
323ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
324ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Store a wide field to an object instance */
325ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
326ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
327c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
328c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 2);
3291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlObj = loadValue(cUnit, rlObj, kCoreReg);
3301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
3311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
3321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
3331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                 NULL);/* null object? */
334c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    regPtr = dvmCompilerAllocTemp(cUnit);
3351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
33611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
33711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(true);
3381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
33911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(false);
34011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
341c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, regPtr);
342ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
343ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
344ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
345ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Load a field from an object instance
346ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
347ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
348270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
349ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                    int fieldOffset, bool isVolatile)
350ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
3511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
352749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee    RegisterClass regClass = dvmCompilerRegClassBySize(size);
353c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
354c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
3551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlObj = loadValue(cUnit, rlObj, kCoreReg);
356749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
3575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
3585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                 NULL);/* null object? */
35911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
36011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(true);
3611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
3625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                 size, rlObj.sRegLow);
36311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(false);
364ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee    if (isVolatile) {
3652ce33c938286c7694238b417be65a9918f421b3dbuzbee        dvmCompilerGenMemBarrier(cUnit, kSY);
366ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee    }
36711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
3681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storeValue(cUnit, rlDest, rlResult);
369ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
370ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
371ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
372ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Store a field to an object instance
373ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
374ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
375270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
376ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                    int fieldOffset, bool isObject, bool isVolatile)
377ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
378749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee    RegisterClass regClass = dvmCompilerRegClassBySize(size);
379c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
380c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
3811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlObj = loadValue(cUnit, rlObj, kCoreReg);
382749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee    rlSrc = loadValue(cUnit, rlSrc, regClass);
3831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
3841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                 NULL);/* null object? */
38511d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
386ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee    if (isVolatile) {
3874185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee        dvmCompilerGenMemBarrier(cUnit, kST);
388ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee    }
38911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(true);
3901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
39111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(false);
3924185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee    if (isVolatile) {
3934185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee        dvmCompilerGenMemBarrier(cUnit, kSY);
3944185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee    }
395919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    if (isObject) {
396919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee        /* NOTE: marking card based on object head */
397919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee        markCard(cUnit, rlSrc.lowReg, rlObj.lowReg);
398919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    }
399ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
400ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
401ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
402ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
403ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Generate array load
404ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
405270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
4061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        RegLocation rlArray, RegLocation rlIndex,
4071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        RegLocation rlDest, int scale)
408ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
409749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee    RegisterClass regClass = dvmCompilerRegClassBySize(size);
410a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro    int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
411a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro    int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents);
4121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
4131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlArray = loadValue(cUnit, rlArray, kCoreReg);
4141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
4151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
416ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
417ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* null object? */
4184238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    ArmLIR * pcrLabel = NULL;
4194238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng
4204238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
4211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow,
4221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                rlArray.lowReg, mir->offset, NULL);
4234238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    }
4244238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng
425c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    regPtr = dvmCompilerAllocTemp(cUnit);
4261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
4274238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
428c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int regLen = dvmCompilerAllocTemp(cUnit);
4294238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng        /* Get len */
4301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
4311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        /* regPtr -> array data */
4321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
4331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
4341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                       pcrLabel);
435c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regLen);
4364238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    } else {
4371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        /* regPtr -> array data */
4381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
4394238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    }
4401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if ((size == kLong) || (size == kDouble)) {
4411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (scale) {
442c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int rNewIndex = dvmCompilerAllocTemp(cUnit);
4431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
4441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
445c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerFreeTemp(cUnit, rNewIndex);
4461465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        } else {
4471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
4481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
449749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
45011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
45111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(true);
4521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
45311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(false);
45411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
455c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regPtr);
4561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValueWide(cUnit, rlDest, rlResult);
457ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    } else {
458749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
45911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
46011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(true);
4611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
4621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        scale, size);
46311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(false);
46411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
465c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regPtr);
4661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValue(cUnit, rlDest, rlResult);
467ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
468ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
469ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
470ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
471ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Generate array store
472ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
473ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
474270c1d64a192341be842f46734054c692bac061eBill Buzbeestatic void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
4751465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        RegLocation rlArray, RegLocation rlIndex,
4761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        RegLocation rlSrc, int scale)
477ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
478749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee    RegisterClass regClass = dvmCompilerRegClassBySize(size);
479a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro    int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
480a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro    int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents);
481e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
4821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int regPtr;
4831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlArray = loadValue(cUnit, rlArray, kCoreReg);
4841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
485e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
486c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    if (dvmCompilerIsTemp(cUnit, rlArray.lowReg)) {
487c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlArray.lowReg);
4881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        regPtr = rlArray.lowReg;
4891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
490c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        regPtr = dvmCompilerAllocTemp(cUnit);
4911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        genRegCopy(cUnit, regPtr, rlArray.lowReg);
4921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
493ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
4941efc9c5e4c5c4c2fccde18e5771c68d064c33bd3Ben Cheng    /* null object? */
4954238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    ArmLIR * pcrLabel = NULL;
4964238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng
4974238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
4981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg,
4991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                mir->offset, NULL);
5004238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    }
5014238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng
5024238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
503c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        int regLen = dvmCompilerAllocTemp(cUnit);
5041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        //NOTE: max live temps(4) here.
5054238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng        /* Get len */
5061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
5071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        /* regPtr -> array data */
5081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
5091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
5101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                       pcrLabel);
511c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regLen);
5124238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    } else {
5131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        /* regPtr -> array data */
5141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
5154238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng    }
5161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    /* at this point, regPtr points to array, 2 live temps */
5171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if ((size == kLong) || (size == kDouble)) {
5181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        //TODO: need specific wide routine that can handle fp regs
5191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (scale) {
520c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int rNewIndex = dvmCompilerAllocTemp(cUnit);
5211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
5221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
523c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerFreeTemp(cUnit, rNewIndex);
5241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        } else {
5251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
5261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        }
527749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        rlSrc = loadValueWide(cUnit, rlSrc, regClass);
52811d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
52911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(true);
5301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
53111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(false);
53211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
533c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFreeTemp(cUnit, regPtr);
534ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    } else {
535749e8162846b9dec5418d4d8f2334e683af81d52Bill Buzbee        rlSrc = loadValue(cUnit, rlSrc, regClass);
53611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
53711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(true);
5381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
5391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         scale, size);
54011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng        HEAP_ACCESS_SHADOW(false);
5419e45c0b968d63ea38353c99252d233879c2efdafjeffhao    }
542ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
543ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
544be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee/*
545be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee * Generate array object store
546be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee * Must use explicit register allocation here because of
547be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee * call-out to dvmCanPutArrayElement
548be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee */
549be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbeestatic void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
550be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                              RegLocation rlArray, RegLocation rlIndex,
551be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                              RegLocation rlSrc, int scale)
552be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee{
553a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro    int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
554a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro    int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents);
555be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
556be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);
557be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
558be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    int regLen = r0;
559be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    int regPtr = r4PC;  /* Preserved across call */
560be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    int regArray = r1;
561be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    int regIndex = r7;  /* Preserved across call */
562be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
563be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    loadValueDirectFixed(cUnit, rlArray, regArray);
564be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    loadValueDirectFixed(cUnit, rlIndex, regIndex);
565be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
566be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    /* null object? */
567be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    ArmLIR * pcrLabel = NULL;
568be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
569be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
570be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, regArray,
571be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                                mir->offset, NULL);
572be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    }
573be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
574be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
575be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        /* Get len */
576be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        loadWordDisp(cUnit, regArray, lenOffset, regLen);
577be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        /* regPtr -> array data */
578be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
579be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        genBoundsCheck(cUnit, regIndex, regLen, mir->offset,
580be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                       pcrLabel);
581be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    } else {
582be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        /* regPtr -> array data */
583be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee        opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
584be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    }
585be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
586be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    /* Get object to store */
587be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    loadValueDirectFixed(cUnit, rlSrc, r0);
588bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng    LOAD_FUNC_ADDR(cUnit, r2, (int)dvmCanPutArrayElement);
589be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
590be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    /* Are we storing null?  If so, avoid check */
5918f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
592be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
593be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    /* Make sure the types are compatible */
594be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    loadWordDisp(cUnit, regArray, offsetof(Object, clazz), r1);
595be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0);
596be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    opReg(cUnit, kOpBlx, r2);
597be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    dvmCompilerClobberCallRegs(cUnit);
598900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee
599900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee    /*
600900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee     * Using fixed registers here, and counting on r4 and r7 being
601900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee     * preserved across the above call.  Tell the register allocation
602900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee     * utilities about the regs we are using directly
603900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee     */
604900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee    dvmCompilerLockTemp(cUnit, regPtr);   // r4PC
605900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee    dvmCompilerLockTemp(cUnit, regIndex); // r7
606900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee    dvmCompilerLockTemp(cUnit, r0);
607919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    dvmCompilerLockTemp(cUnit, r1);
608900a3afd0e8e0d88426b21447d601ee67e17b642Bill Buzbee
609be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    /* Bad? - roll back and re-execute if so */
610be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    genRegImmCheck(cUnit, kArmCondEq, r0, 0, mir->offset, pcrLabel);
611be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
612919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    /* Resume here - must reload element & array, regPtr & index preserved */
613be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    loadValueDirectFixed(cUnit, rlSrc, r0);
614919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    loadValueDirectFixed(cUnit, rlArray, r1);
615be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
616be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
617be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    target->defMask = ENCODE_ALL;
618be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    branchOver->generic.target = (LIR *) target;
619be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
62011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(true);
621be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee    storeBaseIndexed(cUnit, regPtr, regIndex, r0,
622be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee                     scale, kWord);
62311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    HEAP_ACCESS_SHADOW(false);
624919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee
625baf196a7b259704137cccf4058b78da15d4c3998buzbee    dvmCompilerFreeTemp(cUnit, regPtr);
626baf196a7b259704137cccf4058b78da15d4c3998buzbee    dvmCompilerFreeTemp(cUnit, regIndex);
627baf196a7b259704137cccf4058b78da15d4c3998buzbee
628919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    /* NOTE: marking card here based on object head */
629919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee    markCard(cUnit, r0, r1);
630be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee}
631be6534f384529e51dfba5c3f1b7eb90c86b66e77Bill Buzbee
6325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
6335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           RegLocation rlDest, RegLocation rlSrc1,
6345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           RegLocation rlShift)
635ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
636e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng    /*
637e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng     * Don't mess with the regsiters here as there is a particular calling
638e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng     * convention to the out-of-line handler.
639e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng     */
6401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
6411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
6421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
6431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    loadValueDirect(cUnit, rlShift, r2);
6449a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch( mir->dalvikInsn.opcode) {
645e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_SHL_LONG:
646e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_SHL_LONG_2ADDR:
647e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
648e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            break;
649e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_SHR_LONG:
650e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_SHR_LONG_2ADDR:
651e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
652e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            break;
653e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_USHR_LONG:
654e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_USHR_LONG_2ADDR:
655e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
656e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            break;
657e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        default:
658e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            return true;
659e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng    }
660c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerGetReturnWide(cUnit);
6611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    storeValueWide(cUnit, rlDest, rlResult);
662e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng    return false;
663ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
664ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
6655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genArithOpLong(CompilationUnit *cUnit, MIR *mir,
6665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           RegLocation rlDest, RegLocation rlSrc1,
6675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           RegLocation rlSrc2)
668ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
6691465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
6701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    OpKind firstOp = kOpBkpt;
6711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    OpKind secondOp = kOpBkpt;
672ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    bool callOut = false;
673ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson    bool checkZero = false;
674ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    void *callTgt;
675ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int retReg = r0;
676ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
6779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
678ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NOT_LONG:
6791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
680c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
6811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
6821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
6831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlResult);
6841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            return false;
685ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
686ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_ADD_LONG:
687ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_ADD_LONG_2ADDR:
6881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            firstOp = kOpAdd;
6891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            secondOp = kOpAdc;
690ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
691ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SUB_LONG:
692ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SUB_LONG_2ADDR:
6931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            firstOp = kOpSub;
6941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            secondOp = kOpSbc;
695ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
696ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MUL_LONG:
697ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MUL_LONG_2ADDR:
6981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            genMulLong(cUnit, rlDest, rlSrc1, rlSrc2);
699ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return false;
700ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_DIV_LONG:
701ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_DIV_LONG_2ADDR:
702ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callOut = true;
703ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            retReg = r0;
704ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson            checkZero = true;
705ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callTgt = (void*)__aeabi_ldivmod;
706ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
707ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* NOTE - result is in r2/r3 instead of r0/r1 */
708ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_REM_LONG:
709ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_REM_LONG_2ADDR:
710ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callOut = true;
711ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callTgt = (void*)__aeabi_ldivmod;
712ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            retReg = r2;
713ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson            checkZero = true;
714ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
715ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_AND_LONG_2ADDR:
7161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case OP_AND_LONG:
7171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            firstOp = kOpAnd;
7181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            secondOp = kOpAnd;
719ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
720ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_OR_LONG:
721ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_OR_LONG_2ADDR:
7221465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            firstOp = kOpOr;
7231465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            secondOp = kOpOr;
724ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
725ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_XOR_LONG:
726ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_XOR_LONG_2ADDR:
7271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            firstOp = kOpXor;
7281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            secondOp = kOpXor;
729ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
730e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_NEG_LONG: {
73151ecf60dca9f98eeda1818814de6a344e197802fBill Buzbee            //TUNING: can improve this using Thumb2 code
732c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
7331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
734c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
735bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            loadConstantNoClobber(cUnit, tReg, 0);
7361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
73751ecf60dca9f98eeda1818814de6a344e197802fBill Buzbee                        tReg, rlSrc2.lowReg);
73851ecf60dca9f98eeda1818814de6a344e197802fBill Buzbee            opRegReg(cUnit, kOpSbc, tReg, rlSrc2.highReg);
73951ecf60dca9f98eeda1818814de6a344e197802fBill Buzbee            genRegCopy(cUnit, rlResult.highReg, tReg);
7401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlResult);
741ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return false;
742e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
743ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
744c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Invalid long arith op");
745fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee            dvmCompilerAbort(cUnit);
746ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
747ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (!callOut) {
74880cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee        genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
749ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    } else {
7501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        // Adjust return regs in to handle case of rem returning r2/r3
751c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFlushAllRegs(cUnit);   /* Send everything to home location */
752ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson        loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
7531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
75420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        LOAD_FUNC_ADDR(cUnit, r14lr, (int) callTgt);
755ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson        if (checkZero) {
756ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson            int tReg = r12; // Using fixed registers during call sequence
757ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson            opRegRegReg(cUnit, kOpOr, tReg, r2, r3);
758ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson            genRegImmCheck(cUnit, kArmCondEq, tReg, 0, mir->offset, NULL);
759ac3da004fe02e855e2444ce76abf13f12e2e0050Mattias Petersson        }
76020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        opReg(cUnit, kOpBlx, r14lr);
7616a55513b0d268bc0721834050a3698316854fa0aElliott Hughes        dvmCompilerClobberCallRegs(cUnit);
7621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (retReg == r0)
763c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerGetReturnWide(cUnit);
7641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        else
765c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerGetReturnWideAlt(cUnit);
7661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValueWide(cUnit, rlDest, rlResult);
767d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#if defined(WITH_SELF_VERIFICATION)
768d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng        cUnit->usesLinkRegister = true;
769d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng#endif
770ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
771ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
772ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
773ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
7745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
7755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                          RegLocation rlDest, RegLocation rlSrc1,
7765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                          RegLocation rlSrc2)
777ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
7781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    OpKind op = kOpBkpt;
779ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    bool callOut = false;
780ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    bool checkZero = false;
7811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    bool unary = false;
782ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int retReg = r0;
7835d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro    int (*callTgt)(int, int);
7841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
7850e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee    bool shiftOp = false;
786ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
7879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
788ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NEG_INT:
7891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpNeg;
7901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            unary = true;
791ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
792ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NOT_INT:
7931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpMvn;
7941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            unary = true;
795ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
796ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_ADD_INT:
797ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_ADD_INT_2ADDR:
7981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpAdd;
799ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
800ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SUB_INT:
801ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SUB_INT_2ADDR:
8021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpSub;
803ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
804ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MUL_INT:
805ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MUL_INT_2ADDR:
8061465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpMul;
807ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
808ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_DIV_INT:
809ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_DIV_INT_2ADDR:
810ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callOut = true;
811ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            checkZero = true;
812ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callTgt = __aeabi_idiv;
813ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            retReg = r0;
814ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
815ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* NOTE: returns in r1 */
816ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_REM_INT:
817ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_REM_INT_2ADDR:
818ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callOut = true;
819ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            checkZero = true;
820ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            callTgt = __aeabi_idivmod;
821ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            retReg = r1;
822ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
823ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_AND_INT:
824ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_AND_INT_2ADDR:
8251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpAnd;
826ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
827ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_OR_INT:
828ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_OR_INT_2ADDR:
8291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpOr;
830ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
831ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_XOR_INT:
832ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_XOR_INT_2ADDR:
8331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpXor;
834ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
835ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SHL_INT:
836ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SHL_INT_2ADDR:
8370e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee            shiftOp = true;
8381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpLsl;
839ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
840ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SHR_INT:
841ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SHR_INT_2ADDR:
8420e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee            shiftOp = true;
8431465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpAsr;
844ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
845ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_USHR_INT:
846ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_USHR_INT_2ADDR:
8470e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee            shiftOp = true;
8481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            op = kOpLsr;
849ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
850ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
851c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Invalid word arith op: %#x(%d)",
8529a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                 mir->dalvikInsn.opcode, mir->dalvikInsn.opcode);
853fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee            dvmCompilerAbort(cUnit);
854ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
855ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (!callOut) {
8561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
8571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (unary) {
858c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
8591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, op, rlResult.lowReg,
8601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                     rlSrc1.lowReg);
861e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        } else {
8621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
8630e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee            if (shiftOp) {
864c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                int tReg = dvmCompilerAllocTemp(cUnit);
8650e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee                opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
866c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
8670e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee                opRegRegReg(cUnit, op, rlResult.lowReg,
8680e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee                            rlSrc1.lowReg, tReg);
869c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                dvmCompilerFreeTemp(cUnit, tReg);
8700e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee            } else {
871c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
8720e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee                opRegRegReg(cUnit, op, rlResult.lowReg,
8730e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee                            rlSrc1.lowReg, rlSrc2.lowReg);
8740e605279abe713cb54cac3b8eec90d674b6766ceBill Buzbee            }
875e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
8761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValue(cUnit, rlDest, rlResult);
877ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    } else {
8781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        RegLocation rlResult;
879c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerFlushAllRegs(cUnit);   /* Send everything to home location */
8801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadValueDirectFixed(cUnit, rlSrc2, r1);
881bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        LOAD_FUNC_ADDR(cUnit, r2, (int) callTgt);
8821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadValueDirectFixed(cUnit, rlSrc1, r0);
883ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (checkZero) {
8841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
885ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
8861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        opReg(cUnit, kOpBlx, r2);
8876a55513b0d268bc0721834050a3698316854fa0aElliott Hughes        dvmCompilerClobberCallRegs(cUnit);
8881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        if (retReg == r0)
889c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerGetReturn(cUnit);
8901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        else
891c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerGetReturnAlt(cUnit);
8921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValue(cUnit, rlDest, rlResult);
893ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
894ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
895ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
896ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
8975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genArithOp(CompilationUnit *cUnit, MIR *mir)
898ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
8999a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode opcode = mir->dalvikInsn.opcode;
9001465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlDest;
9011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlSrc1;
9021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlSrc2;
9031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    /* Deduce sizes of operands */
9041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (mir->ssaRep->numUses == 2) {
905c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
906c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
9071465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else if (mir->ssaRep->numUses == 3) {
908c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
909c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
9101465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
911c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
912c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
9131465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert(mir->ssaRep->numUses == 4);
9141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
9151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (mir->ssaRep->numDefs == 1) {
916c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDest(cUnit, mir, 0);
9171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
9181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        assert(mir->ssaRep->numDefs == 2);
919c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
9201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
921ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
9229a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_LONG_2ADDR) && (opcode <= OP_XOR_LONG_2ADDR)) {
9235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
924ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9259a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_LONG) && (opcode <= OP_XOR_LONG)) {
9265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
927ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9289a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_SHL_LONG_2ADDR) && (opcode <= OP_USHR_LONG_2ADDR)) {
9295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
930ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9319a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_SHL_LONG) && (opcode <= OP_USHR_LONG)) {
9325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
933ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9349a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_INT_2ADDR) && (opcode <= OP_USHR_INT_2ADDR)) {
9355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
936ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9379a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_INT) && (opcode <= OP_USHR_INT)) {
9385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
939ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9409a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_FLOAT_2ADDR) && (opcode <= OP_REM_FLOAT_2ADDR)) {
9415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpFloat(cUnit,mir, rlDest, rlSrc1, rlSrc2);
942ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9439a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_FLOAT) && (opcode <= OP_REM_FLOAT)) {
9445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpFloat(cUnit, mir, rlDest, rlSrc1, rlSrc2);
945ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9469a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_DOUBLE_2ADDR) && (opcode <= OP_REM_DOUBLE_2ADDR)) {
9475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
948ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
9499a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((opcode >= OP_ADD_DOUBLE) && (opcode <= OP_REM_DOUBLE)) {
9505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
951ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
952ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return true;
953ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
954ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
9551465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/* Generate unconditional branch instructions */
9561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
9571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
9581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    ArmLIR *branch = opNone(cUnit, kOpUncondBr);
9591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    branch->generic.target = (LIR *) target;
9601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    return branch;
9611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
9621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
9631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee/* Perform the actual operation for OP_RETURN_* */
9641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbeestatic void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
9651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee{
96620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
96720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                         TEMPLATE_RETURN_PROF : TEMPLATE_RETURN);
968978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
96920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    gDvmJit.returnOp++;
9701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee#endif
97120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    int dPC = (int) (cUnit->method->insns + mir->offset);
97220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* Insert branch, but defer setting of target */
97320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *branch = genUnconditionalBranch(cUnit, NULL);
97420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* Set up the place holder to reconstruct this Dalvik PC */
97520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
97620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    pcrLabel->opcode = kArmPseudoPCReconstructionCell;
97720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    pcrLabel->operands[0] = dPC;
97820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    pcrLabel->operands[1] = mir->offset;
97920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* Insert the place holder to the growable list */
98020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel);
98120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* Branch to the PC reconstruction code */
98220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    branch->generic.target = (LIR *) pcrLabel;
9831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee}
9841465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
985ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
986ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                                  DecodedInstruction *dInsn,
98789efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                  ArmLIR **pcrLabel)
988ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
989ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    unsigned int i;
990ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    unsigned int regMask = 0;
9911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlArg;
9921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int numDone = 0;
993ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
9941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    /*
9951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * Load arguments to r0..r4.  Note that these registers may contain
9961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * live values, so we clobber them immediately after loading to prevent
9971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * them from being used as sources for subsequent loads.
9981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     */
999c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerLockAllTemps(cUnit);
1000ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (i = 0; i < dInsn->vA; i++) {
1001ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        regMask |= 1 << i;
1002c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlArg = dvmCompilerGetSrc(cUnit, mir, numDone++);
10031465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        loadValueDirectFixed(cUnit, rlArg, i);
1004ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1005ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (regMask) {
1006ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
100720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        opRegRegImm(cUnit, kOpSub, r7, r5FP,
10081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                    sizeof(StackSaveArea) + (dInsn->vA << 2));
1009ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* generate null check */
1010ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (pcrLabel) {
1011c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
10121465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                     mir->offset, NULL);
1013ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1014270c1d64a192341be842f46734054c692bac061eBill Buzbee        storeMultiple(cUnit, r7, regMask);
1015ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1016ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1017ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1018ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
1019ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                                DecodedInstruction *dInsn,
102089efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                ArmLIR **pcrLabel)
1021ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
1022ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int srcOffset = dInsn->vC << 2;
1023ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int numArgs = dInsn->vA;
1024ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int regMask;
10251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
10261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    /*
10271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * Note: here, all promoted registers will have been flushed
10281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * back to the Dalvik base locations, so register usage restrictins
10291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * are lifted.  All parms loaded from original Dalvik register
10301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * region - even though some might conceivably have valid copies
10311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * cached in a preserved register.
10321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     */
1033c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerLockAllTemps(cUnit);
10341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
1035ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
103620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng     * r4PC     : &r5FP[vC]
1037ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * r7: &newFP[0]
1038ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
103920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    opRegRegImm(cUnit, kOpAdd, r4PC, r5FP, srcOffset);
1040ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* load [r0 .. min(numArgs,4)] */
1041ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
1042d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    /*
1043d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng     * Protect the loadMultiple instruction from being reordered with other
1044d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng     * Dalvik stack accesses.
1045d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng     */
104671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao    if (numArgs != 0) loadMultiple(cUnit, r4PC, regMask);
1047ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
104820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    opRegRegImm(cUnit, kOpSub, r7, r5FP,
10491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                sizeof(StackSaveArea) + (numArgs << 2));
1050ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* generate null check */
1051ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (pcrLabel) {
1052c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
10531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                 mir->offset, NULL);
1054ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1055ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1056ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
1057ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Handle remaining 4n arguments:
1058ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * store previously loaded 4 values and load the next 4 values
1059ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
1060ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (numArgs >= 8) {
106189efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee        ArmLIR *loopLabel = NULL;
1062ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /*
1063ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         * r0 contains "this" and it will be used later, so push it to the stack
106420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng         * first. Pushing r5FP is just for stack alignment purposes.
1065ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         */
106620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        opImm(cUnit, kOpPush, (1 << r0 | 1 << r5FP));
1067ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* No need to generate the loop structure if numArgs <= 11 */
1068ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (numArgs > 11) {
1069ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
10701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loopLabel = newLIR0(cUnit, kArmPseudoTargetLabel);
1071d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            loopLabel->defMask = ENCODE_ALL;
1072ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1073270c1d64a192341be842f46734054c692bac061eBill Buzbee        storeMultiple(cUnit, r7, regMask);
1074d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        /*
1075d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng         * Protect the loadMultiple instruction from being reordered with other
1076d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng         * Dalvik stack accesses.
1077d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng         */
1078270c1d64a192341be842f46734054c692bac061eBill Buzbee        loadMultiple(cUnit, r4PC, regMask);
1079ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* No need to generate the loop structure if numArgs <= 11 */
1080ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (numArgs > 11) {
108120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            opRegImm(cUnit, kOpSub, r5FP, 4);
10821465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            genConditionalBranch(cUnit, kArmCondNe, loopLabel);
1083ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1084ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1085ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1086ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Save the last batch of loaded values */
108771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao    if (numArgs != 0) storeMultiple(cUnit, r7, regMask);
1088ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1089ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Generate the loop epilogue - don't use r0 */
1090ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if ((numArgs > 4) && (numArgs % 4)) {
1091ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
1092d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        /*
1093d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng         * Protect the loadMultiple instruction from being reordered with other
1094d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng         * Dalvik stack accesses.
1095d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng         */
1096270c1d64a192341be842f46734054c692bac061eBill Buzbee        loadMultiple(cUnit, r4PC, regMask);
1097ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1098ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (numArgs >= 8)
109920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        opImm(cUnit, kOpPop, (1 << r0 | 1 << r5FP));
1100ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Save the modulo 4 arguments */
1102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if ((numArgs > 4) && (numArgs % 4)) {
1103270c1d64a192341be842f46734054c692bac061eBill Buzbee        storeMultiple(cUnit, r7, regMask);
1104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
110738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng/*
110838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * Generate code to setup the call stack then jump to the chaining cell if it
110938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * is not a native method.
111038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng */
111138329f5678fd7a4879528b02a0ab60322d38a897Ben Chengstatic void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
111289efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                     BasicBlock *bb, ArmLIR *labelList,
111389efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                     ArmLIR *pcrLabel,
111438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng                                     const Method *calleeMethod)
1115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
11161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    /*
11171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * Note: all Dalvik register state should be flushed to
11181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * memory by the point, so register usage restrictions no
11191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * longer apply.  All temp & preserved registers may be used.
11201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     */
1121c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerLockAllTemps(cUnit);
112289efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
1123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1124ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* r1 = &retChainingCell */
112520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, r15pc, 0);
1126c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng
1127ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* r4PC = dalvikCallsite */
1128ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    loadConstant(cUnit, r4PC,
1129ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 (int) (cUnit->method->insns + mir->offset));
1130ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    addrRetChain->generic.target = (LIR *) retChainingCell;
1131c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng
1132c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng    /* r7 = calleeMethod->registersSize */
1133c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng    loadConstant(cUnit, r7, calleeMethod->registersSize);
1134ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
113538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r0 = calleeMethod (loaded upon calling genInvokeSingletonCommon)
1136ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * r1 = &ChainingCell
1137c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng     * r2 = calleeMethod->outsSize (to be loaded later for Java callees)
1138ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * r4PC = callsiteDPC
1139c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng     * r7 = calleeMethod->registersSize
1140ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
1141ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (dvmIsNativeMethod(calleeMethod)) {
114218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
114318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            TEMPLATE_INVOKE_METHOD_NATIVE_PROF :
114418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            TEMPLATE_INVOKE_METHOD_NATIVE);
1145978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
114638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        gDvmJit.invokeNative++;
1147ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
1148ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    } else {
1149c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng        /* For Java callees, set up r2 to be calleeMethod->outsSize */
1150c8293e7dfe856ca95e27aef1ac2e64d750d60662Ben Cheng        loadConstant(cUnit, r2, calleeMethod->outsSize);
115118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
115218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            TEMPLATE_INVOKE_METHOD_CHAIN_PROF :
115318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            TEMPLATE_INVOKE_METHOD_CHAIN);
1154978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
115586717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng        gDvmJit.invokeMonomorphic++;
1156ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
115738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        /* Branch to the chaining cell */
1158ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1159ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1160ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Handle exceptions using the interpreter */
1161ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    genTrap(cUnit, mir->offset, pcrLabel);
1162ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1163ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
116438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng/*
116538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * Generate code to check the validity of a predicted chain and take actions
116638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * based on the result.
116738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng *
116838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99aa : ldr     r4, [pc, #72] --> r4 <- dalvikPC of this invoke
116938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99ac : add     r1, pc, #32   --> r1 <- &retChainingCell
117038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99ae : add     r2, pc, #40   --> r2 <- &predictedChainingCell
117138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99b0 : blx_1   0x426a918c    --+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
117238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99b2 : blx_2   see above     --+
117338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99b4 : b       0x426a99d8    --> off to the predicted chain
117438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99b6 : b       0x426a99c8    --> punt to the interpreter
117538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99b8 : ldr     r0, [r7, #44] --> r0 <- this->class->vtable[methodIdx]
117638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99ba : cmp     r1, #0        --> compare r1 (rechain count) against 0
117738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99bc : bgt     0x426a99c2    --> >=0? don't rechain
1178af5aa1f4ce7eecc1b47a4c038cebb67d33f08f18Ben Cheng * 0x426a99be : ldr     r7, [pc, #off]--+ dvmJitToPatchPredictedChain
117938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99c0 : blx     r7            --+
118038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99c2 : add     r1, pc, #12   --> r1 <- &retChainingCell
118138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99c4 : blx_1   0x426a9098    --+ TEMPLATE_INVOKE_METHOD_NO_OPT
118238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng * 0x426a99c6 : blx_2   see above     --+
118338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng */
118438329f5678fd7a4879528b02a0ab60322d38a897Ben Chengstatic void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
118538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng                                   int methodIndex,
118689efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                   ArmLIR *retChainingCell,
118789efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                   ArmLIR *predChainingCell,
118889efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                   ArmLIR *pcrLabel)
118938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng{
11901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    /*
11911465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * Note: all Dalvik register state should be flushed to
11921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * memory by the point, so register usage restrictions no
11931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * longer apply.  Lock temps to prevent them from being
11941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     * allocated by utility routines.
11951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee     */
1196c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerLockAllTemps(cUnit);
11971465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
11980451704c192aeaa2a2ff6c9f835afc092ad6b98eBen Cheng    /*
11990451704c192aeaa2a2ff6c9f835afc092ad6b98eBen Cheng     * For verbose printing, store the method pointer in operands[1] first as
12000451704c192aeaa2a2ff6c9f835afc092ad6b98eBen Cheng     * operands[0] will be clobbered in dvmCompilerMIR2LIR.
12010451704c192aeaa2a2ff6c9f835afc092ad6b98eBen Cheng     */
12020451704c192aeaa2a2ff6c9f835afc092ad6b98eBen Cheng    predChainingCell->operands[1] = (int) mir->meta.callsiteInfo->method;
12030451704c192aeaa2a2ff6c9f835afc092ad6b98eBen Cheng
120438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* "this" is already left in r0 by genProcessArgs* */
120538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
120638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* r4PC = dalvikCallsite */
120738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    loadConstant(cUnit, r4PC,
120838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng                 (int) (cUnit->method->insns + mir->offset));
120938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
121038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* r1 = &retChainingCell */
121120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, r15pc, 0);
121238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    addrRetChain->generic.target = (LIR *) retChainingCell;
121338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
121438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* r2 = &predictedChainingCell */
121520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *predictedChainingCell = opRegRegImm(cUnit, kOpAdd, r2, r15pc, 0);
121638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    predictedChainingCell->generic.target = (LIR *) predChainingCell;
121738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
121818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
121918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF :
122018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
122138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
122238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* return through lr - jump to the chaining cell */
122338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    genUnconditionalBranch(cUnit, predChainingCell);
122438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
122538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /*
122638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * null-check on "this" may have been eliminated, but we still need a PC-
122738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * reconstruction label for stack overflow bailout.
122838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     */
122938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    if (pcrLabel == NULL) {
123038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        int dPC = (int) (cUnit->method->insns + mir->offset);
1231fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
12329a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        pcrLabel->opcode = kArmPseudoPCReconstructionCell;
123338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        pcrLabel->operands[0] = dPC;
123438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        pcrLabel->operands[1] = mir->offset;
123538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        /* Insert the place holder to the growable list */
123600603079b8723b32c955513eae63a8f97898074dBen Cheng        dvmInsertGrowableList(&cUnit->pcReconstructionList,
123700603079b8723b32c955513eae63a8f97898074dBen Cheng                              (intptr_t) pcrLabel);
123838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    }
123938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
124038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* return through lr+2 - punt to the interpreter */
124138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    genUnconditionalBranch(cUnit, pcrLabel);
124238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
124338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /*
124438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * return through lr+4 - fully resolve the callee method.
124538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r1 <- count
124638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r2 <- &predictedChainCell
124738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r3 <- this->class
124838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r4 <- dPC
124938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r7 <- this->class->vtable
125038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     */
125138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
125238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* r0 <- calleeMethod */
1253270c1d64a192341be842f46734054c692bac061eBill Buzbee    loadWordDisp(cUnit, r7, methodIndex * 4, r0);
125438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
125538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* Check if rechain limit is reached */
12568f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    ArmLIR *bypassRechaining = genCmpImmBranch(cUnit, kArmCondGt, r1, 0);
125738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
1258af5aa1f4ce7eecc1b47a4c038cebb67d33f08f18Ben Cheng    LOAD_FUNC_ADDR(cUnit, r7, (int) dvmJitToPatchPredictedChain);
125938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
126020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genRegCopy(cUnit, r1, r6SELF);
1261b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
126238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /*
126338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r0 = calleeMethod
126438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r2 = &predictedChainingCell
126538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r3 = class
126638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     *
126738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * &returnChainingCell has been loaded into r1 but is not needed
126838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * when patching the chaining cell and will be clobbered upon
126938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * returning so it will be reconstructed again.
127038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     */
12711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    opReg(cUnit, kOpBlx, r7);
127238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
127338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* r1 = &retChainingCell */
127420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, r15pc, 0);
127538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    addrRetChain->generic.target = (LIR *) retChainingCell;
127638329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
127738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    bypassRechaining->generic.target = (LIR *) addrRetChain;
127838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /*
127938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r0 = calleeMethod,
128038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r1 = &ChainingCell,
128138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     * r4PC = callsiteDPC,
128238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng     */
128318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
128418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        TEMPLATE_INVOKE_METHOD_NO_OPT_PROF :
128518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        TEMPLATE_INVOKE_METHOD_NO_OPT);
1286978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
128786717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng    gDvmJit.invokePolymorphic++;
128838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng#endif
128938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /* Handle exceptions using the interpreter */
129038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    genTrap(cUnit, mir->offset, pcrLabel);
129138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng}
129238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
129320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng/* "this" pointer is already in r0 */
129420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Chengstatic void genInvokeVirtualWholeMethod(CompilationUnit *cUnit,
129520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                                        MIR *mir,
129620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                                        void *calleeAddr,
129720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                                        ArmLIR *retChainingCell)
129820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng{
129920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    CallsiteInfo *callsiteInfo = mir->meta.callsiteInfo;
130020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    dvmCompilerLockAllTemps(cUnit);
130120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
1302385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    loadClassPointer(cUnit, r1, (int) callsiteInfo);
130320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
130420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadWordDisp(cUnit, r0, offsetof(Object, clazz), r2);
130520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* Branch to the slow path if classes are not equal */
130620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    opRegReg(cUnit, kOpCmp, r1, r2);
130720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /*
130820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng     * Set the misPredBranchOver target so that it will be generated when the
130920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng     * code for the non-optimized invoke is generated.
131020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng     */
131120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *classCheck = opCondBranch(cUnit, kArmCondNe);
131220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
131320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* r0 = the Dalvik PC of the callsite */
131420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
131520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
131620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR2(cUnit, kThumbBl1, (int) calleeAddr, (int) calleeAddr);
131720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR2(cUnit, kThumbBl2, (int) calleeAddr, (int) calleeAddr);
131820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genUnconditionalBranch(cUnit, retChainingCell);
131920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
132020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* Target of slow path */
132120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    ArmLIR *slowPathLabel = newLIR0(cUnit, kArmPseudoTargetLabel);
132220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
132320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    slowPathLabel->defMask = ENCODE_ALL;
132420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    classCheck->generic.target = (LIR *) slowPathLabel;
132520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
132620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    // FIXME
132720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    cUnit->printMe = true;
132820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng}
132920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
133020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Chengstatic void genInvokeSingletonWholeMethod(CompilationUnit *cUnit,
133120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                                          MIR *mir,
133220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                                          void *calleeAddr,
133320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng                                          ArmLIR *retChainingCell)
133420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng{
133520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    /* r0 = the Dalvik PC of the callsite */
133620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
133720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
133820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR2(cUnit, kThumbBl1, (int) calleeAddr, (int) calleeAddr);
133920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR2(cUnit, kThumbBl2, (int) calleeAddr, (int) calleeAddr);
134020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genUnconditionalBranch(cUnit, retChainingCell);
134120d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
134220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    // FIXME
134320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    cUnit->printMe = true;
134420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng}
134520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng
1346ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Geneate a branch to go back to the interpreter */
1347ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
1348ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
1349ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* r0 = dalvik pc */
1350c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);
1351ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
135220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadWordDisp(cUnit, r6SELF, offsetof(Thread,
1353270c1d64a192341be842f46734054c692bac061eBill Buzbee                 jitToInterpEntries.dvmJitToInterpPunt), r1);
13541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    opReg(cUnit, kOpBlx, r1);
1355ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1356ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1357ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
1358ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Attempt to single step one instruction using the interpreter and return
1359ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * to the compiled code for the next Dalvik instruction
1360ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
1361ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
1362ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
1363e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein    int flags = dexGetFlagsFromOpcode(mir->dalvikInsn.opcode);
1364313d430d5b3b96b45370ccddee52a6d88a799f35Ben Cheng    int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn;
13651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
136632115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng    // Single stepping is considered loop mode breaker
136732115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng    if (cUnit->jitMode == kJitLoop) {
136832115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng        cUnit->quitLoopMode = true;
136932115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng        return;
137032115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng    }
137132115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng
13724527387dd3b5c4dce7300c764805ffd0f3d22649Bill Buzbee    //If already optimized out, just ignore
13739a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (mir->dalvikInsn.opcode == OP_NOP)
13744527387dd3b5c4dce7300c764805ffd0f3d22649Bill Buzbee        return;
13754527387dd3b5c4dce7300c764805ffd0f3d22649Bill Buzbee
13761465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    //Ugly, but necessary.  Flush all Dalvik regs so Interp can find them
1377c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);
13781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee
1379ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if ((mir->next == NULL) || (flags & flagsToCheck)) {
1380ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng       genPuntToInterp(cUnit, mir->offset);
1381ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng       return;
1382ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
13839f601a917c8878204482c37aec7005054b6776fabuzbee    int entryAddr = offsetof(Thread,
1384ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                             jitToInterpEntries.dvmJitToInterpSingleStep);
138520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadWordDisp(cUnit, r6SELF, entryAddr, r2);
1386ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* r0 = dalvik pc */
1387ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
1388ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* r1 = dalvik pc of following instruction */
1389ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
13901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    opReg(cUnit, kOpBlx, r2);
1391270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1392270c1d64a192341be842f46734054c692bac061eBill Buzbee
139301605d2b668e8e1701cfdfa302dde847b9171fc9Carl Shapiro#if defined(_ARMV5TE) || defined(_ARMV5TE_VFP)
1394c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee/*
1395c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * To prevent a thread in a monitor wait from blocking the Jit from
1396c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * resetting the code cache, heavyweight monitor lock will not
1397c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * be allowed to return to an existing translation.  Instead, we will
1398c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * handle them by branching to a handler, which will in turn call the
1399c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * runtime lock routine and then branch directly back to the
1400c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * interpreter main loop.  Given the high cost of the heavyweight
1401c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * lock operation, this additional cost should be slight (especially when
1402c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * considering that we expect the vast majority of lock operations to
1403c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee * use the fast-path thin lock bypass).
1404c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee */
14055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
1406270c1d64a192341be842f46734054c692bac061eBill Buzbee{
14079a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    bool isEnter = (mir->dalvikInsn.opcode == OP_MONITOR_ENTER);
14081465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    genExportPC(cUnit, mir);
1409c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFlushAllRegs(cUnit);   /* Send everything to home location */
1410c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
14111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    loadValueDirectFixed(cUnit, rlSrc, r1);
141220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genRegCopy(cUnit, r0, r6SELF);
1413c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
1414efbd3c5e79b9bbb71e4616a6b73d10b9d754a6e0Bill Buzbee    if (isEnter) {
1415c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee        /* Get dPC of next insn */
1416c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee        loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
1417e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein                 dexGetWidthFromOpcode(OP_MONITOR_ENTER)));
1418c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee        genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
14191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
1420bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        LOAD_FUNC_ADDR(cUnit, r2, (int)dvmUnlockObject);
1421c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee        /* Do the call */
1422c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee        opReg(cUnit, kOpBlx, r2);
14238f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee        /* Did we throw? */
14248f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee        ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
14256bbdd6b005ec5cb567ec9576190a7cd784248c5cBill Buzbee        loadConstant(cUnit, r0,
14266bbdd6b005ec5cb567ec9576190a7cd784248c5cBill Buzbee                     (int) (cUnit->method->insns + mir->offset +
1427e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein                     dexGetWidthFromOpcode(OP_MONITOR_EXIT)));
14286bbdd6b005ec5cb567ec9576190a7cd784248c5cBill Buzbee        genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
14296bbdd6b005ec5cb567ec9576190a7cd784248c5cBill Buzbee        ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
14306bbdd6b005ec5cb567ec9576190a7cd784248c5cBill Buzbee        target->defMask = ENCODE_ALL;
14316bbdd6b005ec5cb567ec9576190a7cd784248c5cBill Buzbee        branchOver->generic.target = (LIR *) target;
14326a55513b0d268bc0721834050a3698316854fa0aElliott Hughes        dvmCompilerClobberCallRegs(cUnit);
14331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1434270c1d64a192341be842f46734054c692bac061eBill Buzbee}
1435fc075c2d1ae63c26f96e0c6eeb72efc898dbebbfBen Cheng#endif
1436270c1d64a192341be842f46734054c692bac061eBill Buzbee
1437ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
14389a3147c7412f4794434b4c2604aa2ba784867774buzbee * Fetch *self->info.breakFlags. If the breakFlags are non-zero,
14397ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * punt to the interpreter.
14407ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng */
14417ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Chengstatic void genSuspendPoll(CompilationUnit *cUnit, MIR *mir)
14427ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng{
14437ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    int rTemp = dvmCompilerAllocTemp(cUnit);
14447ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    ArmLIR *ld;
14459a3147c7412f4794434b4c2604aa2ba784867774buzbee    ld = loadBaseDisp(cUnit, NULL, r6SELF,
14469a3147c7412f4794434b4c2604aa2ba784867774buzbee                      offsetof(Thread, interpBreak.ctl.breakFlags),
14479a3147c7412f4794434b4c2604aa2ba784867774buzbee                      rTemp, kUnsignedByte, INVALID_SREG);
14487ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    setMemRefType(ld, true /* isLoad */, kMustNotAlias);
14497ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    genRegImmCheck(cUnit, kArmCondNe, rTemp, 0, mir->offset, NULL);
14507ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng}
14517ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
14527ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng/*
1453ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * The following are the first-level codegen routines that analyze the format
1454ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * of each bytecode then either dispatch special purpose codegen routines
1455ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * or produce corresponding Thumb instructions directly.
1456ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
1457ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1458ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
145989efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                       BasicBlock *bb, ArmLIR *labelList)
1460ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
14617ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /* backward branch? */
14627ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    bool backwardBranch = (bb->taken->startOffset <= mir->offset);
14637ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
146432115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng    if (backwardBranch &&
146532115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng        (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
14667ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        genSuspendPoll(cUnit, mir);
14677ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    }
14687ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
14697ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    int numPredecessors = dvmCountSetBits(bb->taken->predecessors);
14707ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /*
14717ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * Things could be hoisted out of the taken block into the predecessor, so
14727ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * make sure it is dominated by the predecessor.
14737ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     */
14747ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    if (numPredecessors == 1 && bb->taken->visited == false &&
147520d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        bb->taken->blockType == kDalvikByteCode) {
14767ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        cUnit->nextCodegenBlock = bb->taken;
14777ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    } else {
14787ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
14797ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
14807ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    }
1481ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1482ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1483ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1484ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1485ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
14869a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode dalvikOpcode = mir->dalvikInsn.opcode;
14879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ((dalvikOpcode >= OP_UNUSED_3E) && (dalvikOpcode <= OP_UNUSED_43)) {
1488c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Codegen: got unused opcode %#x",dalvikOpcode);
1489ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        return true;
1490ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
14919a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (dalvikOpcode) {
1492291758c5c4902900c6f86794ba8ab9cad9b26197Andy McFadden        case OP_RETURN_VOID_BARRIER:
14932ce33c938286c7694238b417be65a9918f421b3dbuzbee            dvmCompilerGenMemBarrier(cUnit, kST);
14942ce33c938286c7694238b417be65a9918f421b3dbuzbee            // Intentional fallthrough
14952ce33c938286c7694238b417be65a9918f421b3dbuzbee        case OP_RETURN_VOID:
1496ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            genReturnCommon(cUnit,mir);
1497ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1498ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_UNUSED_73:
1499ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_UNUSED_79:
1500ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_UNUSED_7A:
1501ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_UNUSED_FF:
1502c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Codegen: got unused opcode %#x",dalvikOpcode);
1503ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
1504ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NOP:
1505ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1506ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
1507ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
1508ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1509ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1510ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1511ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1512ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1513ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
15141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlDest;
15151465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
15161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (mir->ssaRep->numDefs == 2) {
1517c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
15181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
1519c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDest(cUnit, mir, 0);
15201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1521e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
15229a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
1523ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_CONST:
1524e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_CONST_4: {
1525c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
1526bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
15271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1528ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1529e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
1530e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_CONST_WIDE_32: {
15311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            //TUNING: single routine to load constant pair for support doubles
1532964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            //TUNING: load 0/-1 separately to avoid load dependency
1533c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1534bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
15351465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
15361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        rlResult.lowReg, 31);
15371465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlResult);
1538ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1539e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
1540ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
1541ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
1542ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1543ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1544ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1545ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1546ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1547ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
15481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlDest;
15491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
15501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (mir->ssaRep->numDefs == 2) {
1551c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
15521465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else {
1553c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDest(cUnit, mir, 0);
15541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    }
1555c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
1556e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
15579a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
1558e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_CONST_HIGH16: {
1559bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            loadConstantNoClobber(cUnit, rlResult.lowReg,
1560bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng                                  mir->dalvikInsn.vB << 16);
15611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1562ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1563e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
1564e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        case OP_CONST_WIDE_HIGH16: {
15651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
15661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                                  0, mir->dalvikInsn.vB << 16);
15671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlResult);
1568ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1569e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
1570ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
1571ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
1572ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1573ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1574ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1575ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1576ab35b50311951feea3782151dd5422ee944685c2Elliott Hughesstatic bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1577ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
1578ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    /* For OP_THROW_VERIFICATION_ERROR */
1579ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    genInterpSingleStep(cUnit, mir);
1580ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1581ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1582ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1583ab35b50311951feea3782151dd5422ee944685c2Elliott Hughesstatic bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1584ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
15851465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
15861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlDest;
15871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlSrc;
1588e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
15899a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (mir->dalvikInsn.opcode) {
1590ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_CONST_STRING_JUMBO:
1591ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_CONST_STRING: {
1592ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            void *strPtr = (void*)
1593ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng              (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1594dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1595dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (strPtr == NULL) {
159632115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1597c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null string");
1598dd6e87095071e4e987910732062545f7303023e5Ben Cheng                dvmAbort();
1599dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }
1600dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1601c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1602c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1603bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            loadConstantNoClobber(cUnit, rlResult.lowReg, (int) strPtr );
16041465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1605ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1606ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1607ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_CONST_CLASS: {
1608ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            void *classPtr = (void*)
1609ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng              (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1610dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1611dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (classPtr == NULL) {
161232115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1613c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null class");
1614dd6e87095071e4e987910732062545f7303023e5Ben Cheng                dvmAbort();
1615dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }
1616dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1617c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1618c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1619bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            loadConstantNoClobber(cUnit, rlResult.lowReg, (int) classPtr );
16201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1621ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1622ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
162371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao        case OP_SGET:
1624ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee        case OP_SGET_VOLATILE:
1625ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SGET_OBJECT:
162671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao        case OP_SGET_OBJECT_VOLATILE:
1627ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SGET_BOOLEAN:
1628ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SGET_CHAR:
1629ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SGET_BYTE:
1630ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_SGET_SHORT: {
1631a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro            int valOffset = OFFSETOF_MEMBER(StaticField, value);
1632c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
1633ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee            bool isVolatile;
16347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ?
16357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                mir->meta.calleeMethod : cUnit->method;
1636ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            void *fieldPtr = (void*)
16377a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng              (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1638dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1639dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (fieldPtr == NULL) {
164032115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1641c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null static field");
1642dd6e87095071e4e987910732062545f7303023e5Ben Cheng                dvmAbort();
1643dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }
1644dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1645e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee            /*
1646e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             * On SMP systems, Dalvik opcodes found to be referencing
1647e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             * volatile fields are rewritten to their _VOLATILE variant.
1648e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             * However, this does not happen on non-SMP systems. The JIT
1649e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             * still needs to know about volatility to avoid unsafe
1650e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             * optimizations so we determine volatility based on either
1651e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             * the opcode or the field access flags.
1652e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee             */
1653e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee#if ANDROID_SMP != 0
1654e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee            Opcode opcode = mir->dalvikInsn.opcode;
1655bd7865b4fb7b1c94b7c7911ef8f83af0a3367a4ebuzbee            isVolatile = (opcode == OP_SGET_VOLATILE) ||
1656ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                         (opcode == OP_SGET_OBJECT_VOLATILE);
16578b94be1f80b135e7a5c1f542861f3e80c4c52823buzbee            assert(isVolatile == dvmIsVolatileField((Field *) fieldPtr));
1658e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee#else
1659e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee            isVolatile = dvmIsVolatileField((Field *) fieldPtr);
1660e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee#endif
1661ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee
1662c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1663c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
16641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
166511d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
1666ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee            if (isVolatile) {
16672ce33c938286c7694238b417be65a9918f421b3dbuzbee                dvmCompilerGenMemBarrier(cUnit, kSY);
1668ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee            }
166911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(true);
16701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
167111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(false);
167211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
16731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1674ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1675ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1676ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_SGET_WIDE: {
1677a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro            int valOffset = OFFSETOF_MEMBER(StaticField, value);
16787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ?
16797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                mir->meta.calleeMethod : cUnit->method;
1680ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            void *fieldPtr = (void*)
16817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng              (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1682dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1683dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (fieldPtr == NULL) {
168432115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1685c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null static field");
1686dd6e87095071e4e987910732062545f7303023e5Ben Cheng                dvmAbort();
1687dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }
1688dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1689c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
1690c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1691c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
16921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
169311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
169411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(true);
16951465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
169611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(false);
169711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
16981465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlResult);
1699ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1700ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
170171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao        case OP_SPUT:
170271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao        case OP_SPUT_VOLATILE:
1703ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SPUT_OBJECT:
1704ddc7d29baa92cb24b7bfa80395479f878109f3f8buzbee        case OP_SPUT_OBJECT_VOLATILE:
1705ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SPUT_BOOLEAN:
1706ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SPUT_CHAR:
1707ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_SPUT_BYTE:
1708ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_SPUT_SHORT: {
1709a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro            int valOffset = OFFSETOF_MEMBER(StaticField, value);
1710c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
1711d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee            int objHead;
1712ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee            bool isVolatile;
1713d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee            bool isSputObject;
17147a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ?
17157a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                mir->meta.calleeMethod : cUnit->method;
17167a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            void *fieldPtr = (void*)
17177a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng              (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1718bd7865b4fb7b1c94b7c7911ef8f83af0a3367a4ebuzbee            Opcode opcode = mir->dalvikInsn.opcode;
1719e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
172032115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng            if (fieldPtr == NULL) {
172132115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1722c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null static field");
172332115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                dvmAbort();
172432115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng            }
172532115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng
1726e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee#if ANDROID_SMP != 0
1727bd7865b4fb7b1c94b7c7911ef8f83af0a3367a4ebuzbee            isVolatile = (opcode == OP_SPUT_VOLATILE) ||
1728ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                         (opcode == OP_SPUT_OBJECT_VOLATILE);
17298b94be1f80b135e7a5c1f542861f3e80c4c52823buzbee            assert(isVolatile == dvmIsVolatileField((Field *) fieldPtr));
1730e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee#else
1731e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee            isVolatile = dvmIsVolatileField((Field *) fieldPtr);
1732e3c0b54b3f653eb9000116ec1fa18349e0f1ed9cbuzbee#endif
1733ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee
1734bd7865b4fb7b1c94b7c7911ef8f83af0a3367a4ebuzbee            isSputObject = (opcode == OP_SPUT_OBJECT) ||
1735ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                           (opcode == OP_SPUT_OBJECT_VOLATILE);
1736d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee
1737c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
17381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1739b78c76f88ea42e7a3b295c210ca9ee86e7290043buzbee            loadConstant(cUnit, tReg,  (int) fieldPtr);
1740d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee            if (isSputObject) {
1741d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee                objHead = dvmCompilerAllocTemp(cUnit);
1742a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                loadWordDisp(cUnit, tReg, OFFSETOF_MEMBER(Field, clazz), objHead);
1743d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee            }
17444185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee            if (isVolatile) {
17454185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee                dvmCompilerGenMemBarrier(cUnit, kST);
17464185972e211b0c84b9fe7d90c56b28cc15e474fabuzbee            }
174711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(true);
1748b78c76f88ea42e7a3b295c210ca9ee86e7290043buzbee            storeWordDisp(cUnit, tReg, valOffset ,rlSrc.lowReg);
1749d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee            dvmCompilerFreeTemp(cUnit, tReg);
175011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(false);
1751ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee            if (isVolatile) {
17522ce33c938286c7694238b417be65a9918f421b3dbuzbee                dvmCompilerGenMemBarrier(cUnit, kSY);
1753ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee            }
1754d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee            if (isSputObject) {
1755b78c76f88ea42e7a3b295c210ca9ee86e7290043buzbee                /* NOTE: marking card based sfield->clazz */
1756d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee                markCard(cUnit, rlSrc.lowReg, objHead);
1757d3b0a4bf6b2e38e6e9e80e203ca753e941084103buzbee                dvmCompilerFreeTemp(cUnit, objHead);
1758919eb063ce4542d3698e10e20aba9a2dfbdd0f82buzbee            }
175911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
1760ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1761ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1762ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_SPUT_WIDE: {
1763c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int tReg = dvmCompilerAllocTemp(cUnit);
1764a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro            int valOffset = OFFSETOF_MEMBER(StaticField, value);
17657a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ?
17667a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                mir->meta.calleeMethod : cUnit->method;
1767ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            void *fieldPtr = (void*)
17687a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng              (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1769e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
1770dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (fieldPtr == NULL) {
177132115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1772c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null static field");
1773dd6e87095071e4e987910732062545f7303023e5Ben Cheng                dvmAbort();
1774dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }
1775dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1776c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
17771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
17781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
177911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
178011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(true);
17811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
178211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng            HEAP_ACCESS_SHADOW(false);
1783ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1784ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1785ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_NEW_INSTANCE: {
1786e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            /*
1787e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng             * Obey the calling convention and don't mess with the register
1788e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng             * usage.
1789e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng             */
1790fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            ClassObject *classPtr = (ClassObject *)
1791ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng              (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1792dd6e87095071e4e987910732062545f7303023e5Ben Cheng
1793dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (classPtr == NULL) {
179432115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
1795c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Unexpected null class");
1796dd6e87095071e4e987910732062545f7303023e5Ben Cheng                dvmAbort();
1797dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }
1798dd6e87095071e4e987910732062545f7303023e5Ben Cheng
179979d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng            /*
180079d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng             * If it is going to throw, it should not make to the trace to begin
18011465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             * with.  However, Alloc might throw, so we need to genExportPC()
180279d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng             */
180379d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng            assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
1804c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerFlushAllRegs(cUnit);   /* Everything to home location */
18051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            genExportPC(cUnit, mir);
1806bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            LOAD_FUNC_ADDR(cUnit, r2, (int)dvmAllocObject);
1807e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            loadConstant(cUnit, r0, (int) classPtr);
1808ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
18091465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opReg(cUnit, kOpBlx, r2);
18106a55513b0d268bc0721834050a3698316854fa0aElliott Hughes            dvmCompilerClobberCallRegs(cUnit);
18114f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            /* generate a branch over if allocation is successful */
18128f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee            ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
18134f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            /*
18144f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng             * OOM exception needs to be thrown here and cannot re-execute
18154f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng             */
18164f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            loadConstant(cUnit, r0,
18174f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng                         (int) (cUnit->method->insns + mir->offset));
18184f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
18194f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            /* noreturn */
18204f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng
18211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
18224f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            target->defMask = ENCODE_ALL;
18234f48917c0741e4d9b15ca7c45956aea05fea103fBen Cheng            branchOver->generic.target = (LIR *) target;
1824c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1825c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerGetReturn(cUnit);
18261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1827ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1828ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1829ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        case OP_CHECK_CAST: {
1830e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            /*
1831e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng             * Obey the calling convention and don't mess with the register
1832e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng             * usage.
1833e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng             */
1834ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            ClassObject *classPtr =
1835ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng              (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
18364df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee            /*
18374df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             * Note: It is possible that classPtr is NULL at this point,
18384df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             * even though this instruction has been successfully interpreted.
18394df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             * If the previous interpretation had a null source, the
18404df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             * interpreter would not have bothered to resolve the clazz.
18414df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             * Bail out to the interpreter in this case, and log it
18424df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             * so that we can tell if it happens frequently.
18434df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee             */
18444df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee            if (classPtr == NULL) {
184532115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                BAIL_LOOP_COMPILATION();
184632115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                LOGVV("null clazz in OP_CHECK_CAST, single-stepping");
184732115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                genInterpSingleStep(cUnit, mir);
184832115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng                return false;
18494df41a5726f32661f9e48307a3f3d9d5ae1e6cb5Bill Buzbee            }
1850c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerFlushAllRegs(cUnit);   /* Everything to home location */
1851ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            loadConstant(cUnit, r1, (int) classPtr );
1852c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
18531465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
18548f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee            /* Null? */
18558f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee            ArmLIR *branch1 = genCmpImmBranch(cUnit, kArmCondEq,
18568f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee                                              rlSrc.lowReg, 0);
18571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            /*
18581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             *  rlSrc.lowReg now contains object->clazz.  Note that
18591465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             *  it could have been allocated r0, but we're okay so long
18601465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             *  as we don't do anything desctructive until r0 is loaded
18611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             *  with clazz.
18621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             */
1863ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            /* r0 now contains object->clazz */
18641465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0);
1865bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng            LOAD_FUNC_ADDR(cUnit, r2, (int)dvmInstanceofNonTrivial);
18661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOpCmp, r0, r1);
18671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
18681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opReg(cUnit, kOpBlx, r2);
18696a55513b0d268bc0721834050a3698316854fa0aElliott Hughes            dvmCompilerClobberCallRegs(cUnit);
18701465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            /*
18711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             * If null, check cast failed - punt to the interpreter.  Because
18721465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             * interpreter will be the one throwing, we don't need to
18731465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             * genExportPC() here.
18741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee             */
1875270c1d64a192341be842f46734054c692bac061eBill Buzbee            genZeroCheck(cUnit, r0, mir->offset, NULL);
1876ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            /* check cast passed - branch target here */
18771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
1878d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            target->defMask = ENCODE_ALL;
1879ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            branch1->generic.target = (LIR *)target;
1880ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            branch2->generic.target = (LIR *)target;
1881ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1882ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
18834d92e68103159bea0e36b98d9f18473e5805f52bbuzbee        case OP_SGET_WIDE_VOLATILE:
18844d92e68103159bea0e36b98d9f18473e5805f52bbuzbee        case OP_SPUT_WIDE_VOLATILE:
18854d92e68103159bea0e36b98d9f18473e5805f52bbuzbee            genInterpSingleStep(cUnit, mir);
18864d92e68103159bea0e36b98d9f18473e5805f52bbuzbee            break;
1887ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
1888ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
1889ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1890ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1891ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1892ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
18937a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng/*
18947a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * A typical example of inlined getter/setter from a monomorphic callsite:
18957a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *
18967a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): -------- dalvik offset: 0x0000 @ invoke-static (I)
18977a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): -------- dalvik offset: 0x0000 @ sget-object (C) v0, ...
18987a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): 0x4427fc22 (0002): ldr     r0, [pc, #56]
18997a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): 0x4427fc24 (0004): ldr     r1, [r0, #0]
19007a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): 0x4427fc26 (0006): str     r1, [r5, #0]
19017a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): 0x4427fc28 (0008): .align4
19027a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): L0x0003:
19037a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * D/dalvikvm(  289): -------- dalvik offset: 0x0003 @ move-result-object (I) v0
19047a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *
19057a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * Note the invoke-static and move-result-object with the (I) notation are
19067a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * turned into no-op.
19077a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng */
1908ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1909ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
19109a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode dalvikOpcode = mir->dalvikInsn.opcode;
19111465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
19129a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (dalvikOpcode) {
1913ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MOVE_EXCEPTION: {
1914ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            int exOffset = offsetof(Thread, exception);
1915c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int resetReg = dvmCompilerAllocTemp(cUnit);
1916c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1917c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
191820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            loadWordDisp(cUnit, r6SELF, exOffset, rlResult.lowReg);
1919f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee            loadConstant(cUnit, resetReg, 0);
192020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            storeWordDisp(cUnit, r6SELF, exOffset, resetReg);
19211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
1922ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           break;
1923ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1924ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MOVE_RESULT:
1925ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MOVE_RESULT_OBJECT: {
19267a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            /* An inlined move result is effectively no-op */
19277a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            if (mir->OptimizationFlags & MIR_INLINED)
19287a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
1929c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
19301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            RegLocation rlSrc = LOC_DALVIK_RETURN_VAL;
19311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc.fp = rlDest.fp;
19321465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlSrc);
1933ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1934ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1935ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MOVE_RESULT_WIDE: {
19367a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            /* An inlined move result is effectively no-op */
19377a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            if (mir->OptimizationFlags & MIR_INLINED)
19387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
1939c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
19401465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            RegLocation rlSrc = LOC_DALVIK_RETURN_VAL_WIDE;
19411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc.fp = rlDest.fp;
19421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlSrc);
1943ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1944ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1945ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_RETURN_WIDE: {
1946c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
19471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
19481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlDest.fp = rlSrc.fp;
19491465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlSrc);
1950ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            genReturnCommon(cUnit,mir);
1951ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1952ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
1953ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_RETURN:
1954ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_RETURN_OBJECT: {
1955c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
19561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            RegLocation rlDest = LOC_DALVIK_RETURN_VAL;
19571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlDest.fp = rlSrc.fp;
19581465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlSrc);
195920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng            genReturnCommon(cUnit, mir);
1960ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1961ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
19621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case OP_MONITOR_EXIT:
1963ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MONITOR_ENTER:
19645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genMonitor(cUnit, mir);
1965ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
196620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        case OP_THROW:
1967ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            genInterpSingleStep(cUnit, mir);
1968ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
1969ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
1970ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
1971ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1972ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
1973ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
1974ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1975d45ba37dd5aeb6b37dd3091a4d6fa0a87f75fdf9Bill Buzbeestatic bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
1976d45ba37dd5aeb6b37dd3091a4d6fa0a87f75fdf9Bill Buzbee{
19779a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode opcode = mir->dalvikInsn.opcode;
19781465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlDest;
19791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlSrc;
19801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
1981d45ba37dd5aeb6b37dd3091a4d6fa0a87f75fdf9Bill Buzbee
19829a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if ( (opcode >= OP_ADD_INT_2ADDR) && (opcode <= OP_REM_DOUBLE_2ADDR)) {
19835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        return genArithOp( cUnit, mir );
1984ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
1985ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
19861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (mir->ssaRep->numUses == 2)
1987c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
19881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else
1989c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
19901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    if (mir->ssaRep->numDefs == 2)
1991c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
19921465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    else
1993c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1994e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
19959a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (opcode) {
19961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case OP_DOUBLE_TO_INT:
1997ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_INT_TO_FLOAT:
1998ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_FLOAT_TO_INT:
1999ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_DOUBLE_TO_FLOAT:
2000ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_FLOAT_TO_DOUBLE:
2001ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_INT_TO_DOUBLE:
2002ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_FLOAT_TO_LONG:
2003ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_LONG_TO_FLOAT:
2004ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_DOUBLE_TO_LONG:
2005ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_LONG_TO_DOUBLE:
20065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genConversion(cUnit, mir);
2007ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NEG_INT:
2008ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NOT_INT:
20095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
2010ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NEG_LONG:
2011ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NOT_LONG:
20125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
2013ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NEG_FLOAT:
20145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
2015ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_NEG_DOUBLE:
20165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
20171465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case OP_MOVE_WIDE:
20181465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlSrc);
20191465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            break;
20201465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case OP_INT_TO_LONG:
2021c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
2022c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2023964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            //TUNING: shouldn't loadValueDirect already check for phys reg?
20241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            if (rlSrc.location == kLocPhysReg) {
20251465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
20261465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            } else {
20271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
20281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            }
20291465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
20301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                        rlResult.lowReg, 31);
20311465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValueWide(cUnit, rlDest, rlResult);
2032ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
20331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case OP_LONG_TO_INT:
2034c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
2035c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
20361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            // Intentional fallthrough
2037ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MOVE:
2038ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_MOVE_OBJECT:
20391465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlSrc);
2040ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2041ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_INT_TO_BYTE:
20421465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2043c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
20441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
20451465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
2046ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2047ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_INT_TO_SHORT:
20481465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2049c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
20501465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
20511465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
2052ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2053ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_INT_TO_CHAR:
20541465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2055c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
20561465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
20571465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
2058ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2059ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_ARRAY_LENGTH: {
2060a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro            int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
20611465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
20621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
20631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         mir->offset, NULL);
2064c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
20651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
20661465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                         rlResult.lowReg);
20671465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            storeValue(cUnit, rlDest, rlResult);
2068ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2069ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
2070ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
2071ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            return true;
2072ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
2073ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
2074ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
2075ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
2076ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
2077ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
20789a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode dalvikOpcode = mir->dalvikInsn.opcode;
20791465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlDest;
20801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    RegLocation rlResult;
20811465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    int BBBB = mir->dalvikInsn.vB;
20829a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (dalvikOpcode == OP_CONST_WIDE_16) {
2083c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
2084c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2085bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        loadConstantNoClobber(cUnit, rlResult.lowReg, BBBB);
2086964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        //TUNING: do high separately to avoid load dependency
20871465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
20881465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValueWide(cUnit, rlDest, rlResult);
20899a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    } else if (dalvikOpcode == OP_CONST_16) {
2090c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2091c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
2092bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng        loadConstantNoClobber(cUnit, rlResult.lowReg, BBBB);
20931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        storeValue(cUnit, rlDest, rlResult);
20941465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    } else
2095ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        return true;
2096ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
2097ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
2098ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
2099ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Compare agaist zero */
2100ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
210189efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                         ArmLIR *labelList)
2102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
21039a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    Opcode dalvikOpcode = mir->dalvikInsn.opcode;
210489efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmConditionCode cond;
21057ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /* backward branch? */
21067ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    bool backwardBranch = (bb->taken->startOffset <= mir->offset);
21077ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
210832115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng    if (backwardBranch &&
210932115a971ea00ab2421fab4e4a3afa6c50c82173Ben Cheng        (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
21107ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        genSuspendPoll(cUnit, mir);
21117ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    }
21127ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
2113c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
21141465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
21157ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
21161465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee    opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
2117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
2118270c1d64a192341be842f46734054c692bac061eBill Buzbee//TUNING: break this out to allow use of Thumb2 CB[N]Z
21199a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch (dalvikOpcode) {
2120ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_IF_EQZ:
21211465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            cond = kArmCondEq;
2122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_IF_NEZ:
21241465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            cond = kArmCondNe;
2125ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2126ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_IF_LTZ:
21271465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            cond = kArmCondLt;
2128ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2129ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_IF_GEZ:
21301465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            cond = kArmCondGe;
2131ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2132ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_IF_GTZ:
21331465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            cond = kArmCondGt;
2134ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2135ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        case OP_IF_LEZ:
21361465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee            cond = kArmCondLe;
2137ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
2138ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
21395d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro            cond = (ArmConditionCode)0;
2140c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Unexpected opcode (%d) for Fmt21t", dalvikOpcode);
2141fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee            dvmCompilerAbort(cUnit);
2142ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
2143ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
2144ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* This mostly likely will be optimized away in a later phase */
2145ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2146ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return false;
2147ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
2148ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
2149b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughesstatic bool isPowerOfTwo(int x)
2150b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes{
2151b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    return (x & (x - 1)) == 0;
2152b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes}
2153b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes
2154b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes// Returns true if no more than two bits are set in 'x'.
2155b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughesstatic bool isPopCountLE2(unsigned int x)
2156b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes{
2157b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    x &= x - 1;
2158b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    return (x & (x - 1)) == 0;
2159b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes}
2160b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes
2161b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes// Returns the index of the lowest set bit in 'x'.
2162b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughesstatic int lowestSetBit(unsigned int x) {
2163b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    int bit_posn = 0;
2164b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    while ((x & 0xf) == 0) {
2165b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        bit_posn += 4;
2166b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        x >>= 4;
2167b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    }
2168b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    while ((x & 1) == 0) {
2169b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        bit_posn++;
2170b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        x >>= 1;
2171b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    }
2172b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    return bit_posn;
2173b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes}
2174b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes
2175672511b777c05bd80955b6d1a2e1bc617429aaf7Elliott Hughes// Returns true if it added instructions to 'cUnit' to divide 'rlSrc' by 'lit'
2176672511b777c05bd80955b6d1a2e1bc617429aaf7Elliott Hughes// and store the result in 'rlDest'.
21779a1f81699cc05b58378ffb9