15d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* 25d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Copyright (C) 2009 The Android Open Source Project 35d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 45d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 55d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * you may not use this file except in compliance with the License. 65d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * You may obtain a copy of the License at 75d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 85d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * http://www.apache.org/licenses/LICENSE-2.0 95d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Unless required by applicable law or agreed to in writing, software 115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * distributed under the License is distributed on an "AS IS" BASIS, 125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * See the License for the specific language governing permissions and 145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * limitations under the License. 155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */ 165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* 182e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * This file contains codegen for the Thumb2 ISA and is intended to be 195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * includes by: 205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Codegen-$(TARGET_ARCH_VARIANT).c 225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */ 245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 252e152baec01433de9c63633ebc6f4adf1cea3a87buzbee/* 262e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * Reserve 6 bytes at the beginning of the trace 272e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * +----------------------------+ 282e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * | prof count addr (4 bytes) | 292e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * +----------------------------+ 302e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * | chain cell offset (2 bytes)| 312e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * +----------------------------+ 322e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * 332e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * ...and then code to increment the execution 342e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * 352e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * For continuous profiling (10 bytes) 362e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * ldr r0, [pc-8] @ get prof count addr [4 bytes] 372e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * ldr r1, [r0] @ load counter [2 bytes] 382e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * add r1, #1 @ increment [2 bytes] 392e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * str r1, [r0] @ store [2 bytes] 402e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * 412e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * For periodic profiling (4 bytes) 422e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * call TEMPLATE_PERIODIC_PROFILING 432e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * 442e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * and return the size (in bytes) of the generated code. 452e152baec01433de9c63633ebc6f4adf1cea3a87buzbee */ 462e152baec01433de9c63633ebc6f4adf1cea3a87buzbee 472e152baec01433de9c63633ebc6f4adf1cea3a87buzbeestatic int genTraceProfileEntry(CompilationUnit *cUnit) 482e152baec01433de9c63633ebc6f4adf1cea3a87buzbee{ 492e152baec01433de9c63633ebc6f4adf1cea3a87buzbee intptr_t addr = (intptr_t)dvmJitNextTraceCounter(); 502e152baec01433de9c63633ebc6f4adf1cea3a87buzbee assert(__BYTE_ORDER == __LITTLE_ENDIAN); 512e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR1(cUnit, kArm16BitData, addr & 0xffff); 522e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR1(cUnit, kArm16BitData, (addr >> 16) & 0xffff); 532e152baec01433de9c63633ebc6f4adf1cea3a87buzbee cUnit->chainCellOffsetLIR = 542e152baec01433de9c63633ebc6f4adf1cea3a87buzbee (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG); 552e152baec01433de9c63633ebc6f4adf1cea3a87buzbee cUnit->headerSize = 6; 562e152baec01433de9c63633ebc6f4adf1cea3a87buzbee if ((gDvmJit.profileMode == kTraceProfilingContinuous) || 572e152baec01433de9c63633ebc6f4adf1cea3a87buzbee (gDvmJit.profileMode == kTraceProfilingDisabled)) { 582e152baec01433de9c63633ebc6f4adf1cea3a87buzbee /* Thumb[2] instruction used directly here to ensure correct size */ 592e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR2(cUnit, kThumb2LdrPcReln12, r0, 8); 602e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0); 612e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR2(cUnit, kThumbAddRI8, r1, 1); 622e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0); 632e152baec01433de9c63633ebc6f4adf1cea3a87buzbee return 10; 642e152baec01433de9c63633ebc6f4adf1cea3a87buzbee } else { 652e152baec01433de9c63633ebc6f4adf1cea3a87buzbee int opcode = TEMPLATE_PERIODIC_PROFILING; 662e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR2(cUnit, kThumbBlx1, 672e152baec01433de9c63633ebc6f4adf1cea3a87buzbee (int) gDvmJit.codeCache + templateEntryOffsets[opcode], 682e152baec01433de9c63633ebc6f4adf1cea3a87buzbee (int) gDvmJit.codeCache + templateEntryOffsets[opcode]); 692e152baec01433de9c63633ebc6f4adf1cea3a87buzbee newLIR2(cUnit, kThumbBlx2, 702e152baec01433de9c63633ebc6f4adf1cea3a87buzbee (int) gDvmJit.codeCache + templateEntryOffsets[opcode], 712e152baec01433de9c63633ebc6f4adf1cea3a87buzbee (int) gDvmJit.codeCache + templateEntryOffsets[opcode]); 722e152baec01433de9c63633ebc6f4adf1cea3a87buzbee return 4; 732e152baec01433de9c63633ebc6f4adf1cea3a87buzbee } 742e152baec01433de9c63633ebc6f4adf1cea3a87buzbee} 752e152baec01433de9c63633ebc6f4adf1cea3a87buzbee 765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, 775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlSrc) 785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlResult; 805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc = loadValue(cUnit, rlSrc, kFPReg); 81c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true); 825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR2(cUnit, kThumb2Vnegs, rlResult.lowReg, rlSrc.lowReg); 835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValue(cUnit, rlDest, rlResult); 845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, 87c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlSrc) 885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlResult; 905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); 91c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true); 925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR2(cUnit, kThumb2Vnegd, S2D(rlResult.lowReg, rlResult.highReg), 935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng S2D(rlSrc.lowReg, rlSrc.highReg)); 945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValueWide(cUnit, rlDest, rlResult); 955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* 985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * To avoid possible conflicts, we use a lot of temps here. Note that 995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * our usage of Thumb2 instruction forms avoids the problems with register 1005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * reuse for multiply instructions prior to arm6. 1015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */ 1025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genMulLong(CompilationUnit *cUnit, RegLocation rlDest, 1035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlSrc1, RegLocation rlSrc2) 1045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 1055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlResult; 106c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee int resLo = dvmCompilerAllocTemp(cUnit); 107c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee int resHi = dvmCompilerAllocTemp(cUnit); 108c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee int tmp1 = dvmCompilerAllocTemp(cUnit); 1095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 1105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); 1115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 1125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 1135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR3(cUnit, kThumb2MulRRR, tmp1, rlSrc2.lowReg, rlSrc1.highReg); 1145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR4(cUnit, kThumb2Umull, resLo, resHi, rlSrc2.lowReg, rlSrc1.lowReg); 1155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR4(cUnit, kThumb2Mla, tmp1, rlSrc1.lowReg, rlSrc2.highReg, tmp1); 1165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR4(cUnit, kThumb2AddRRR, resHi, tmp1, resHi, 0); 117c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee dvmCompilerFreeTemp(cUnit, tmp1); 1185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 119c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee rlResult = dvmCompilerGetReturnWide(cUnit); // Just as a template, will patch 1205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlResult.lowReg = resLo; 1215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlResult.highReg = resHi; 1225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValueWide(cUnit, rlDest, rlResult); 1235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 1245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 12580cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbeestatic void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp, 1265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng OpKind secondOp, RegLocation rlDest, 1275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlSrc1, RegLocation rlSrc2) 1285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 1295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlResult; 1305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); 1315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 132c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true); 1335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); 1345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg, 1355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc2.highReg); 1365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValueWide(cUnit, rlDest, rlResult); 1375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 1385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 1395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengvoid dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit) 1405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 1415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int numTemps = sizeof(coreTemps)/sizeof(int); 1425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int numFPTemps = sizeof(fpTemps)/sizeof(int); 143fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro RegisterPool *pool = (RegisterPool *)dvmCompilerNew(sizeof(*pool), true); 1445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng cUnit->regPool = pool; 1455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng pool->numCoreTemps = numTemps; 146fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro pool->coreTemps = (RegisterInfo *) 1475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng dvmCompilerNew(numTemps * sizeof(*cUnit->regPool->coreTemps), true); 1485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng pool->numFPTemps = numFPTemps; 149fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro pool->FPTemps = (RegisterInfo *) 1505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng dvmCompilerNew(numFPTemps * sizeof(*cUnit->regPool->FPTemps), true); 151c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps); 152c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee dvmCompilerInitPool(pool->FPTemps, fpTemps, pool->numFPTemps); 1535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng pool->nullCheckedRegs = 1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng dvmCompilerAllocBitVector(cUnit->numSSARegs, false); 1555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 1565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* 1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Generate a Thumb2 IT instruction, which can nullify up to 1595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * four subsequent instructions based on a condition and its 1605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * inverse. The condition applies to the first instruction, which 1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * is executed if the condition is met. The string "guide" consists 1625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * of 0 to 3 chars, and applies to the 2nd through 4th instruction. 1635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * A "T" means the instruction is executed if the condition is 1645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * met, and an "E" means the instruction is executed if the condition 1655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * is not met. 1665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */ 1675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *genIT(CompilationUnit *cUnit, ArmConditionCode code, 1685d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro const char *guide) 1695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 1705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int mask; 1715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int condBit = code & 1; 1725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int altBit = condBit ^ 1; 1735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int mask3 = 0; 1745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int mask2 = 0; 1755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int mask1 = 0; 1765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 1775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng //Note: case fallthroughs intentional 1785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng switch(strlen(guide)) { 1795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng case 3: 1805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng mask1 = (guide[2] == 'T') ? condBit : altBit; 1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng case 2: 1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng mask2 = (guide[1] == 'T') ? condBit : altBit; 1835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng case 1: 1845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng mask3 = (guide[0] == 'T') ? condBit : altBit; 1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng break; 1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng case 0: 1875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng break; 1885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng default: 189c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Jit: bad case in genIT"); 190fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee dvmCompilerAbort(cUnit); 1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng } 1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) | 1935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng (1 << (3 - strlen(guide))); 1945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng return newLIR2(cUnit, kThumb2It, code, mask); 1955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 1965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 1975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* Export the Dalvik PC assicated with an instruction to the StackSave area */ 1985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir) 1995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *res; 2015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng int offset = offsetof(StackSaveArea, xtra.currentPc); 202c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee int rDPC = dvmCompilerAllocTemp(cUnit); 2035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset)); 20420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng newLIR3(cUnit, kThumb2StrRRI8Predec, rDPC, r5FP, 2055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng sizeof(StackSaveArea) - offset); 206c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee dvmCompilerFreeTemp(cUnit, rDPC); 2075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng return res; 2085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 2095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 2105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* 2115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Handle simple case (thin lock) inline. If it's complicated, bail 2125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * out to the heavyweight lock/unlock routines. We'll use dedicated 2135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * registers here in order to be in the right position in case we 2145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * to bail to dvm[Lock/Unlock]Object(self, object) 2155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 2165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r0 -> self pointer [arg0 for dvm[Lock/Unlock]Object 2175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r1 -> object [arg1 for dvm[Lock/Unlock]Object 21815812f132f22da443c24609e37298f130acfcfa4Carl Shapiro * r2 -> intial contents of object->lock, later result of strex 2195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r3 -> self->threadId 2205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r7 -> temp to hold new lock value [unlock only] 2215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r4 -> allow to be used by utilities as general temp 2225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 2235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * The result of the strex is 0 if we acquire the lock. 224d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * 225d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * See comments in Sync.c for the layout of the lock word. 226d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * Of particular interest to this code is the test for the 227d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * simple case - which we handle inline. For monitor enter, the 228d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * simple case is thin lock, held by no-one. For monitor exit, 229d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * the simple case is thin lock, held by the unlocking thread with 230d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * a recurse count of 0. 231d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * 232d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * A minor complication is that there is a field in the lock word 233d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * unrelated to locking: the hash state. This field must be ignored, but 234d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * preserved. 235d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * 2365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */ 2375d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbeestatic void genMonitorEnter(CompilationUnit *cUnit, MIR *mir) 2385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 239c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); 2405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *target; 2415d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee ArmLIR *hopTarget; 2425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *branch; 2435d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee ArmLIR *hopBranch; 2445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 245d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee assert(LW_SHAPE_THIN == 0); 2465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj 247c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee dvmCompilerLockAllTemps(cUnit); // Prepare for explicit register usage 248c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee dvmCompilerFreeTemp(cUnit, r4PC); // Free up r4 for general use 2495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); 25020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng loadWordDisp(cUnit, r6SELF, offsetof(Thread, threadId), r3); // Get threadId 2515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR3(cUnit, kThumb2Ldrex, r2, r1, 25215812f132f22da443c24609e37298f130acfcfa4Carl Shapiro offsetof(Object, lock) >> 2); // Get object->lock 253d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner 25415812f132f22da443c24609e37298f130acfcfa4Carl Shapiro // Is lock unheld on lock or held by us (==threadId) on unlock? 2555d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee newLIR4(cUnit, kThumb2Bfi, r3, r2, 0, LW_LOCK_OWNER_SHIFT - 1); 2565d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT, 2575d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee LW_LOCK_OWNER_SHIFT - 1); 2585d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopBranch = newLIR2(cUnit, kThumb2Cbnz, r2, 0); 2595d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee newLIR4(cUnit, kThumb2Strex, r2, r3, r1, offsetof(Object, lock) >> 2); 2602ce33c938286c7694238b417be65a9918f421b3dbuzbee dvmCompilerGenMemBarrier(cUnit, kSY); 2615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng branch = newLIR2(cUnit, kThumb2Cbz, r2, 0); 2625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 2635d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel); 2645d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopTarget->defMask = ENCODE_ALL; 2655d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopBranch->generic.target = (LIR *)hopTarget; 2665d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 267c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee // Export PC (part 1) 268c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset)); 269c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee 2705d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee /* Get dPC of next insn */ 2715d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset + 272e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein dexGetWidthFromOpcode(OP_MONITOR_ENTER))); 2735d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee // Export PC (part 2) 27420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng newLIR3(cUnit, kThumb2StrRRI8Predec, r3, r5FP, 2755d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee sizeof(StackSaveArea) - 2765d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee offsetof(StackSaveArea, xtra.currentPc)); 2775d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee /* Call template, and don't return */ 27820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng genRegCopy(cUnit, r0, r6SELF); 2795d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER); 2805d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee // Resume here 2815d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee target = newLIR0(cUnit, kArmPseudoTargetLabel); 2825d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee target->defMask = ENCODE_ALL; 2835d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee branch->generic.target = (LIR *)target; 2845d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee} 2855d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 2865d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee/* 2875d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * For monitor unlock, we don't have to use ldrex/strex. Once 2885d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * we've determined that the lock is thin and that we own it with 2895d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * a zero recursion count, it's safe to punch it back to the 2905d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * initial, unlock thin state with a store word. 2915d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee */ 2925d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbeestatic void genMonitorExit(CompilationUnit *cUnit, MIR *mir) 2935d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee{ 2945d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); 2955d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee ArmLIR *target; 2965d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee ArmLIR *branch; 2975d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee ArmLIR *hopTarget; 2985d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee ArmLIR *hopBranch; 2995d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 3005d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee assert(LW_SHAPE_THIN == 0); 3015d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj 3025d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee dvmCompilerLockAllTemps(cUnit); // Prepare for explicit register usage 3035d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee dvmCompilerFreeTemp(cUnit, r4PC); // Free up r4 for general use 3045d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); 3055d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee loadWordDisp(cUnit, r1, offsetof(Object, lock), r2); // Get object->lock 30620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng loadWordDisp(cUnit, r6SELF, offsetof(Thread, threadId), r3); // Get threadId 3075d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee // Is lock unheld on lock or held by us (==threadId) on unlock? 3085d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee opRegRegImm(cUnit, kOpAnd, r7, r2, 3095d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); 3105d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner 3115d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT, 3125d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee LW_LOCK_OWNER_SHIFT - 1); 3135d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee opRegReg(cUnit, kOpSub, r2, r3); 3145d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopBranch = opCondBranch(cUnit, kArmCondNe); 3152ce33c938286c7694238b417be65a9918f421b3dbuzbee dvmCompilerGenMemBarrier(cUnit, kSY); 3165d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee storeWordDisp(cUnit, r1, offsetof(Object, lock), r7); 3175d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee branch = opNone(cUnit, kOpUncondBr); 3185d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 3195d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel); 3205d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopTarget->defMask = ENCODE_ALL; 3215d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee hopBranch->generic.target = (LIR *)hopTarget; 3225d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 3235d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee // Export PC (part 1) 3245d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset)); 3255d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 326bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng LOAD_FUNC_ADDR(cUnit, r7, (int)dvmUnlockObject); 32720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng genRegCopy(cUnit, r0, r6SELF); 3285d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee // Export PC (part 2) 32920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng newLIR3(cUnit, kThumb2StrRRI8Predec, r3, r5FP, 3305d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee sizeof(StackSaveArea) - 3315d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee offsetof(StackSaveArea, xtra.currentPc)); 3325d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee opReg(cUnit, kOpBlx, r7); 3338f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee /* Did we throw? */ 3348f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0); 3355d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee loadConstant(cUnit, r0, 3365d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee (int) (cUnit->method->insns + mir->offset + 337e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein dexGetWidthFromOpcode(OP_MONITOR_EXIT))); 3385d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON); 3395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 3405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng // Resume here 3415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng target = newLIR0(cUnit, kArmPseudoTargetLabel); 3425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng target->defMask = ENCODE_ALL; 3435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng branch->generic.target = (LIR *)target; 3445d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee branchOver->generic.target = (LIR *) target; 3455d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee} 3465d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee 3475d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbeestatic void genMonitor(CompilationUnit *cUnit, MIR *mir) 3485d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee{ 3499a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein if (mir->dalvikInsn.opcode == OP_MONITOR_ENTER) 3505d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee genMonitorEnter(cUnit, mir); 3515d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee else 3525d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee genMonitorExit(cUnit, mir); 3535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 3545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 3555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* 3565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 64-bit 3way compare function. 3575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * mov r7, #-1 3585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * cmp op1hi, op2hi 3595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * blt done 3605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * bgt flip 3615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * sub r7, op1lo, op2lo (treat as unsigned) 3625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * beq done 3635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * ite hi 3645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * mov(hi) r7, #-1 3655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * mov(!hi) r7, #1 3665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * flip: 3675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * neg r7 3685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * done: 3695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */ 3705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genCmpLong(CompilationUnit *cUnit, MIR *mir, 3715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlDest, RegLocation rlSrc1, 3725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlSrc2) 3735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 3745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change 3755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *target1; 3765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *target2; 3775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); 3785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 379c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee rlTemp.lowReg = dvmCompilerAllocTemp(cUnit); 3805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng loadConstant(cUnit, rlTemp.lowReg, -1); 3815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); 3825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *branch1 = opCondBranch(cUnit, kArmCondLt); 3835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *branch2 = opCondBranch(cUnit, kArmCondGt); 3845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegRegReg(cUnit, kOpSub, rlTemp.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); 3855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng ArmLIR *branch3 = opCondBranch(cUnit, kArmCondEq); 3865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 3875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng genIT(cUnit, kArmCondHi, "E"); 3885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR2(cUnit, kThumb2MovImmShift, rlTemp.lowReg, modifiedImmediate(-1)); 3895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng loadConstant(cUnit, rlTemp.lowReg, 1); 3905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng genBarrier(cUnit); 3915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 3925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng target2 = newLIR0(cUnit, kArmPseudoTargetLabel); 3935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng target2->defMask = -1; 3945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegReg(cUnit, kOpNeg, rlTemp.lowReg, rlTemp.lowReg); 3955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 3965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng target1 = newLIR0(cUnit, kArmPseudoTargetLabel); 3975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng target1->defMask = -1; 3985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 3995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValue(cUnit, rlDest, rlTemp); 4005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 4015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng branch1->generic.target = (LIR *)target1; 4025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng branch2->generic.target = (LIR *)target2; 4035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng branch3->generic.target = branch1->generic.target; 4045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 4055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 4065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir) 4075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 408c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); 4095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlDest = inlinedTarget(cUnit, mir, true); 4105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc = loadValue(cUnit, rlSrc, kFPReg); 411c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true); 4125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR2(cUnit, kThumb2Vabss, rlResult.lowReg, rlSrc.lowReg); 4135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValue(cUnit, rlDest, rlResult); 4147e914f110323165e7f683eece444ef83a499596dElliott Hughes return false; 4155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 4165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 4175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir) 4185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 419c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1); 4205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlDest = inlinedTargetWide(cUnit, mir, true); 4215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); 422c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true); 4235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng newLIR2(cUnit, kThumb2Vabsd, S2D(rlResult.lowReg, rlResult.highReg), 4245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng S2D(rlSrc.lowReg, rlSrc.highReg)); 4255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValueWide(cUnit, rlDest, rlResult); 4267e914f110323165e7f683eece444ef83a499596dElliott Hughes return false; 4275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 4285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 4295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin) 4305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{ 431c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0); 432c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1); 4335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); 4345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); 4355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng RegLocation rlDest = inlinedTarget(cUnit, mir, false); 436c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true); 4375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); 4385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng genIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E"); 4395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg); 4405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg); 4415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng genBarrier(cUnit); 4425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng storeValue(cUnit, rlDest, rlResult); 4435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng return false; 4445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng} 4455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng 446b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughesstatic void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit, 447b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes RegLocation rlSrc, RegLocation rlResult, int lit, 448b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes int firstBit, int secondBit) 449b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes{ 450b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg, 451b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes encodeShift(kArmLsl, secondBit - firstBit)); 452b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes if (firstBit != 0) { 453b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit); 454b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes } 455b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes} 45620111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson 45720111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilssonstatic void genMultiplyByShiftAndReverseSubtract(CompilationUnit *cUnit, 45820111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson RegLocation rlSrc, RegLocation rlResult, int lit) 45920111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson{ 46020111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson newLIR4(cUnit, kThumb2RsbRRR, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg, 46120111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson encodeShift(kArmLsl, lit)); 46220111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson} 463