diff options
Diffstat (limited to 'vm/compiler/codegen/arm/CodegenDriver.cpp')
| -rw-r--r-- | vm/compiler/codegen/arm/CodegenDriver.cpp | 148 |
1 files changed, 147 insertions, 1 deletions
diff --git a/vm/compiler/codegen/arm/CodegenDriver.cpp b/vm/compiler/codegen/arm/CodegenDriver.cpp index ad8fd81ff..1585aa0d0 100644 --- a/vm/compiler/codegen/arm/CodegenDriver.cpp +++ b/vm/compiler/codegen/arm/CodegenDriver.cpp @@ -398,6 +398,149 @@ static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size, } } + +/* + * Generate array load + */ +static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size, + RegLocation rlArray, RegLocation rlIndex, + RegLocation rlDest, int scale) +{ + RegisterClass regClass = dvmCompilerRegClassBySize(size); + int lenOffset = OFFSETOF_MEMBER(ArrayObject, length); + int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents); + RegLocation rlResult; + rlArray = loadValue(cUnit, rlArray, kCoreReg); + rlIndex = loadValue(cUnit, rlIndex, kCoreReg); + int regPtr; + + /* null object? */ + ArmLIR * pcrLabel = NULL; + + if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) { + pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, + rlArray.lowReg, mir->offset, NULL); + } + + regPtr = dvmCompilerAllocTemp(cUnit); + + if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) { + int regLen = dvmCompilerAllocTemp(cUnit); + /* Get len */ + loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); + /* regPtr -> array data */ + opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset); + genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset, + pcrLabel); + dvmCompilerFreeTemp(cUnit, regLen); + } else { + /* regPtr -> array data */ + opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset); + } + if ((size == kLong) || (size == kDouble)) { + if (scale) { + int rNewIndex = dvmCompilerAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); + opRegReg(cUnit, kOpAdd, regPtr, rNewIndex); + dvmCompilerFreeTemp(cUnit, rNewIndex); + } else { + opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); + } + rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true); + + HEAP_ACCESS_SHADOW(true); + loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); + HEAP_ACCESS_SHADOW(false); + + dvmCompilerFreeTemp(cUnit, regPtr); + storeValueWide(cUnit, rlDest, rlResult); + } else { + rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true); + + HEAP_ACCESS_SHADOW(true); + loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg, + scale, size); + HEAP_ACCESS_SHADOW(false); + + dvmCompilerFreeTemp(cUnit, regPtr); + storeValue(cUnit, rlDest, rlResult); + } +} + +/* + * Generate array store + * + */ +static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size, + RegLocation rlArray, RegLocation rlIndex, + RegLocation rlSrc, int scale) +{ + RegisterClass regClass = dvmCompilerRegClassBySize(size); + int lenOffset = OFFSETOF_MEMBER(ArrayObject, length); + int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents); + + int regPtr; + rlArray = loadValue(cUnit, rlArray, kCoreReg); + rlIndex = loadValue(cUnit, rlIndex, kCoreReg); + + if (dvmCompilerIsTemp(cUnit, rlArray.lowReg)) { + dvmCompilerClobber(cUnit, rlArray.lowReg); + regPtr = rlArray.lowReg; + } else { + regPtr = dvmCompilerAllocTemp(cUnit); + genRegCopy(cUnit, regPtr, rlArray.lowReg); + } + + /* null object? */ + ArmLIR * pcrLabel = NULL; + + if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) { + pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, + mir->offset, NULL); + } + + if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) { + int regLen = dvmCompilerAllocTemp(cUnit); + //NOTE: max live temps(4) here. + /* Get len */ + loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); + /* regPtr -> array data */ + opRegImm(cUnit, kOpAdd, regPtr, dataOffset); + genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset, + pcrLabel); + dvmCompilerFreeTemp(cUnit, regLen); + } else { + /* regPtr -> array data */ + opRegImm(cUnit, kOpAdd, regPtr, dataOffset); + } + /* at this point, regPtr points to array, 2 live temps */ + if ((size == kLong) || (size == kDouble)) { + //TODO: need specific wide routine that can handle fp regs + if (scale) { + int rNewIndex = dvmCompilerAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); + opRegReg(cUnit, kOpAdd, regPtr, rNewIndex); + dvmCompilerFreeTemp(cUnit, rNewIndex); + } else { + opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); + } + rlSrc = loadValueWide(cUnit, rlSrc, regClass); + + HEAP_ACCESS_SHADOW(true); + storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg); + HEAP_ACCESS_SHADOW(false); + + dvmCompilerFreeTemp(cUnit, regPtr); + } else { + rlSrc = loadValue(cUnit, rlSrc, regClass); + + HEAP_ACCESS_SHADOW(true); + storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg, + scale, size); + HEAP_ACCESS_SHADOW(false); + } +} + /* * Generate array object store * Must use explicit register allocation here because of @@ -2114,7 +2257,10 @@ static bool handleEasyMultiply(CompilationUnit *cUnit, } else { // Reverse subtract: (src << (shift + 1)) - src. assert(powerOfTwoMinusOne); - genMultiplyByShiftAndReverseSubtract(cUnit, rlSrc, rlResult, lowestSetBit(lit + 1)); + // TODO: rsb dst, src, src lsl#lowestSetBit(lit + 1) + int tReg = dvmCompilerAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1)); + opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg); } storeValue(cUnit, rlDest, rlResult); return true; |
