1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * This file contains codegen for the Thumb ISA and is intended to be 19 * includes by: 20 * 21 * Codegen-$(TARGET_ARCH_VARIANT).c 22 * 23 */ 24 25/* 26 * Perform a "reg cmp imm" operation and jump to the PCR region if condition 27 * satisfies. 28 */ 29static void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, 30 RegLocation rlSrc) 31{ 32 RegLocation rlResult; 33 rlSrc = loadValue(cUnit, rlSrc, kCoreReg); 34 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true); 35 opRegRegImm(cUnit, kOpAdd, rlResult.lowReg, 36 rlSrc.lowReg, 0x80000000); 37 storeValue(cUnit, rlDest, rlResult); 38} 39 40static void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, 41 RegLocation rlSrc) 42{ 43 RegLocation rlResult; 44 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); 45 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true); 46 opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg, 47 0x80000000); 48 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg); 49 storeValueWide(cUnit, rlDest, rlResult); 50} 51 52static void genMulLong(CompilationUnit *cUnit, RegLocation rlDest, 53 RegLocation rlSrc1, RegLocation rlSrc2) 54{ 55 RegLocation rlResult; 56 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1); 57 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3); 58 genDispatchToHandler(cUnit, TEMPLATE_MUL_LONG); 59 rlResult = dvmCompilerGetReturnWide(cUnit); 60 storeValueWide(cUnit, rlDest, rlResult); 61} 62 63static bool partialOverlap(int sreg1, int sreg2) 64{ 65 return abs(sreg1 - sreg2) == 1; 66} 67 68static void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp, 69 OpKind secondOp, RegLocation rlDest, 70 RegLocation rlSrc1, RegLocation rlSrc2) 71{ 72 RegLocation rlResult; 73 if (partialOverlap(rlSrc1.sRegLow,rlSrc2.sRegLow) || 74 partialOverlap(rlSrc1.sRegLow,rlDest.sRegLow) || 75 partialOverlap(rlSrc2.sRegLow,rlDest.sRegLow)) { 76 // Rare case - not enough registers to properly handle 77 genInterpSingleStep(cUnit, mir); 78 } else if (rlDest.sRegLow == rlSrc1.sRegLow) { 79 // Already 2-operand 80 rlResult = loadValueWide(cUnit, rlDest, kCoreReg); 81 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 82 opRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc2.lowReg); 83 opRegReg(cUnit, secondOp, rlResult.highReg, rlSrc2.highReg); 84 storeValueWide(cUnit, rlDest, rlResult); 85 } else if (rlDest.sRegLow == rlSrc2.sRegLow) { 86 // Bad case - must use/clobber Src1 and reassign Dest 87 rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); 88 rlResult = loadValueWide(cUnit, rlDest, kCoreReg); 89 opRegReg(cUnit, firstOp, rlSrc1.lowReg, rlResult.lowReg); 90 opRegReg(cUnit, secondOp, rlSrc1.highReg, rlResult.highReg); 91 // Old reg assignments are now invalid 92 dvmCompilerClobber(cUnit, rlResult.lowReg); 93 dvmCompilerClobber(cUnit, rlResult.highReg); 94 dvmCompilerClobber(cUnit, rlSrc1.lowReg); 95 dvmCompilerClobber(cUnit, rlSrc1.highReg); 96 rlDest.location = kLocDalvikFrame; 97 assert(rlSrc1.location == kLocPhysReg); 98 // Reassign registers - rlDest will now get rlSrc1's old regs 99 storeValueWide(cUnit, rlDest, rlSrc1); 100 } else { 101 // Copy Src1 to Dest 102 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 103 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, false); 104 loadValueDirectWide(cUnit, rlSrc1, rlResult.lowReg, 105 rlResult.highReg); 106 rlResult.location = kLocPhysReg; 107 opRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc2.lowReg); 108 opRegReg(cUnit, secondOp, rlResult.highReg, rlSrc2.highReg); 109 storeValueWide(cUnit, rlDest, rlResult); 110 } 111} 112 113void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit) 114{ 115 int i; 116 int numTemps = sizeof(coreTemps)/sizeof(int); 117 RegisterPool *pool = dvmCompilerNew(sizeof(*pool), true); 118 cUnit->regPool = pool; 119 pool->numCoreTemps = numTemps; 120 pool->coreTemps = 121 dvmCompilerNew(numTemps * sizeof(*pool->coreTemps), true); 122 pool->numFPTemps = 0; 123 pool->FPTemps = NULL; 124 pool->numCoreRegs = 0; 125 pool->coreRegs = NULL; 126 pool->numFPRegs = 0; 127 pool->FPRegs = NULL; 128 dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps); 129 dvmCompilerInitPool(pool->FPTemps, NULL, 0); 130 dvmCompilerInitPool(pool->coreRegs, NULL, 0); 131 dvmCompilerInitPool(pool->FPRegs, NULL, 0); 132 pool->nullCheckedRegs = 133 dvmCompilerAllocBitVector(cUnit->numSSARegs, false); 134} 135 136/* Export the Dalvik PC assicated with an instruction to the StackSave area */ 137static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir) 138{ 139 ArmLIR *res; 140 int rDPC = dvmCompilerAllocTemp(cUnit); 141 int rAddr = dvmCompilerAllocTemp(cUnit); 142 int offset = offsetof(StackSaveArea, xtra.currentPc); 143 res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset)); 144 newLIR2(cUnit, kThumbMovRR, rAddr, rFP); 145 newLIR2(cUnit, kThumbSubRI8, rAddr, sizeof(StackSaveArea) - offset); 146 storeWordDisp( cUnit, rAddr, 0, rDPC); 147 return res; 148} 149 150static void genMonitor(CompilationUnit *cUnit, MIR *mir) 151{ 152 genMonitorPortable(cUnit, mir); 153} 154 155static void genCmpLong(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, 156 RegLocation rlSrc1, RegLocation rlSrc2) 157{ 158 RegLocation rlResult; 159 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1); 160 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3); 161 genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG); 162 rlResult = dvmCompilerGetReturn(cUnit); 163 storeValue(cUnit, rlDest, rlResult); 164} 165 166static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir) 167{ 168 int offset = offsetof(InterpState, retval); 169 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); 170 int reg0 = loadValue(cUnit, rlSrc, kCoreReg).lowReg; 171 int signMask = dvmCompilerAllocTemp(cUnit); 172 loadConstant(cUnit, signMask, 0x7fffffff); 173 newLIR2(cUnit, kThumbAndRR, reg0, signMask); 174 dvmCompilerFreeTemp(cUnit, signMask); 175 storeWordDisp(cUnit, rGLUE, offset, reg0); 176 //TUNING: rewrite this to not clobber 177 dvmCompilerClobber(cUnit, reg0); 178 return true; 179} 180 181static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir) 182{ 183 int offset = offsetof(InterpState, retval); 184 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1); 185 RegLocation regSrc = loadValueWide(cUnit, rlSrc, kCoreReg); 186 int reglo = regSrc.lowReg; 187 int reghi = regSrc.highReg; 188 int signMask = dvmCompilerAllocTemp(cUnit); 189 loadConstant(cUnit, signMask, 0x7fffffff); 190 storeWordDisp(cUnit, rGLUE, offset, reglo); 191 newLIR2(cUnit, kThumbAndRR, reghi, signMask); 192 dvmCompilerFreeTemp(cUnit, signMask); 193 storeWordDisp(cUnit, rGLUE, offset + 4, reghi); 194 //TUNING: rewrite this to not clobber 195 dvmCompilerClobber(cUnit, reghi); 196 return true; 197} 198 199/* No select in thumb, so we need to branch. Thumb2 will do better */ 200static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin) 201{ 202 int offset = offsetof(InterpState, retval); 203 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0); 204 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1); 205 int reg0 = loadValue(cUnit, rlSrc1, kCoreReg).lowReg; 206 int reg1 = loadValue(cUnit, rlSrc2, kCoreReg).lowReg; 207 newLIR2(cUnit, kThumbCmpRR, reg0, reg1); 208 ArmLIR *branch1 = newLIR2(cUnit, kThumbBCond, 2, 209 isMin ? kArmCondLt : kArmCondGt); 210 newLIR2(cUnit, kThumbMovRR, reg0, reg1); 211 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel); 212 target->defMask = ENCODE_ALL; 213 newLIR3(cUnit, kThumbStrRRI5, reg0, rGLUE, offset >> 2); 214 branch1->generic.target = (LIR *)target; 215 //TUNING: rewrite this to not clobber 216 dvmCompilerClobber(cUnit,reg0); 217 return false; 218} 219 220static void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit, 221 RegLocation rlSrc, RegLocation rlResult, int lit, 222 int firstBit, int secondBit) 223{ 224 // We can't implement "add src, src, src, lsl#shift" on Thumb, so we have 225 // to do a regular multiply. 226 opRegRegImm(cUnit, kOpMul, rlResult.lowReg, rlSrc.lowReg, lit); 227} 228