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