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 */ 29 static 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 40 static 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 52 static 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 63 static bool partialOverlap(int sreg1, int sreg2) 64 { 65 return abs(sreg1 - sreg2) == 1; 66 } 67 68 static 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 113 void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit) 114 { 115 int numTemps = sizeof(coreTemps)/sizeof(int); 116 RegisterPool *pool = dvmCompilerNew(sizeof(*pool), true); 117 cUnit->regPool = pool; 118 pool->numCoreTemps = numTemps; 119 pool->coreTemps = 120 dvmCompilerNew(numTemps * sizeof(*pool->coreTemps), true); 121 pool->numFPTemps = 0; 122 pool->FPTemps = NULL; 123 pool->numCoreRegs = 0; 124 pool->coreRegs = NULL; 125 pool->numFPRegs = 0; 126 pool->FPRegs = NULL; 127 dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps); 128 dvmCompilerInitPool(pool->FPTemps, NULL, 0); 129 dvmCompilerInitPool(pool->coreRegs, NULL, 0); 130 dvmCompilerInitPool(pool->FPRegs, NULL, 0); 131 pool->nullCheckedRegs = 132 dvmCompilerAllocBitVector(cUnit->numSSARegs, false); 133 } 134 135 /* Export the Dalvik PC assicated with an instruction to the StackSave area */ 136 static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir) 137 { 138 ArmLIR *res; 139 int rDPC = dvmCompilerAllocTemp(cUnit); 140 int rAddr = dvmCompilerAllocTemp(cUnit); 141 int offset = offsetof(StackSaveArea, xtra.currentPc); 142 res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset)); 143 newLIR2(cUnit, kThumbMovRR, rAddr, rFP); 144 newLIR2(cUnit, kThumbSubRI8, rAddr, sizeof(StackSaveArea) - offset); 145 storeWordDisp( cUnit, rAddr, 0, rDPC); 146 return res; 147 } 148 149 static void genMonitor(CompilationUnit *cUnit, MIR *mir) 150 { 151 genMonitorPortable(cUnit, mir); 152 } 153 154 static void genCmpLong(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, 155 RegLocation rlSrc1, RegLocation rlSrc2) 156 { 157 RegLocation rlResult; 158 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1); 159 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3); 160 genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG); 161 rlResult = dvmCompilerGetReturn(cUnit); 162 storeValue(cUnit, rlDest, rlResult); 163 } 164 165 static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir) 166 { 167 int offset = offsetof(InterpState, retval); 168 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); 169 int reg0 = loadValue(cUnit, rlSrc, kCoreReg).lowReg; 170 int signMask = dvmCompilerAllocTemp(cUnit); 171 loadConstant(cUnit, signMask, 0x7fffffff); 172 newLIR2(cUnit, kThumbAndRR, reg0, signMask); 173 dvmCompilerFreeTemp(cUnit, signMask); 174 storeWordDisp(cUnit, rGLUE, offset, reg0); 175 //TUNING: rewrite this to not clobber 176 dvmCompilerClobber(cUnit, reg0); 177 return true; 178 } 179 180 static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir) 181 { 182 int offset = offsetof(InterpState, retval); 183 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1); 184 RegLocation regSrc = loadValueWide(cUnit, rlSrc, kCoreReg); 185 int reglo = regSrc.lowReg; 186 int reghi = regSrc.highReg; 187 int signMask = dvmCompilerAllocTemp(cUnit); 188 loadConstant(cUnit, signMask, 0x7fffffff); 189 storeWordDisp(cUnit, rGLUE, offset, reglo); 190 newLIR2(cUnit, kThumbAndRR, reghi, signMask); 191 dvmCompilerFreeTemp(cUnit, signMask); 192 storeWordDisp(cUnit, rGLUE, offset + 4, reghi); 193 //TUNING: rewrite this to not clobber 194 dvmCompilerClobber(cUnit, reghi); 195 return true; 196 } 197 198 /* No select in thumb, so we need to branch. Thumb2 will do better */ 199 static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin) 200 { 201 int offset = offsetof(InterpState, retval); 202 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0); 203 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1); 204 int reg0 = loadValue(cUnit, rlSrc1, kCoreReg).lowReg; 205 int reg1 = loadValue(cUnit, rlSrc2, kCoreReg).lowReg; 206 newLIR2(cUnit, kThumbCmpRR, reg0, reg1); 207 ArmLIR *branch1 = newLIR2(cUnit, kThumbBCond, 2, 208 isMin ? kArmCondLt : kArmCondGt); 209 newLIR2(cUnit, kThumbMovRR, reg0, reg1); 210 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel); 211 target->defMask = ENCODE_ALL; 212 newLIR3(cUnit, kThumbStrRRI5, reg0, rGLUE, offset >> 2); 213 branch1->generic.target = (LIR *)target; 214 //TUNING: rewrite this to not clobber 215 dvmCompilerClobber(cUnit,reg0); 216 return false; 217 } 218 219 static void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit, 220 RegLocation rlSrc, RegLocation rlResult, int lit, 221 int firstBit, int secondBit) 222 { 223 // We can't implement "add src, src, src, lsl#shift" on Thumb, so we have 224 // to do a regular multiply. 225 opRegRegImm(cUnit, kOpMul, rlResult.lowReg, rlSrc.lowReg, lit); 226 } 227