default:
return true;
}
+ flushAllRegs(cUnit); /* Send everything to home location */
loadValueDirectFixed(cUnit, rlSrc1, r0);
loadValueDirectFixed(cUnit, rlSrc2, r1);
loadConstant(cUnit, r2, (int)funct);
default:
return true;
}
+ flushAllRegs(cUnit); /* Send everything to home location */
loadConstant(cUnit, rlr, (int)funct);
loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
genLong3Addr(cUnit, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
} else {
// Adjust return regs in to handle case of rem returning r2/r3
+ flushAllRegs(cUnit); /* Send everything to home location */
loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
loadConstant(cUnit, rlr, (int) callTgt);
loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
storeValue(cUnit, rlDest, rlResult);
} else {
RegLocation rlResult;
+ flushAllRegs(cUnit); /* Send everything to home location */
loadValueDirectFixed(cUnit, rlSrc2, r1);
loadConstant(cUnit, r2, (int) callTgt);
loadValueDirectFixed(cUnit, rlSrc1, r0);
*/
RegLocation rlSrc;
RegLocation rlDest;
+ flushAllRegs(cUnit); /* Send everything to home location */
if (srcSize == 1) {
rlSrc = getSrcLoc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlSrc, r0);
static void handleMonitorPortable(CompilationUnit *cUnit, MIR *mir)
{
+ flushAllRegs(cUnit); /* Send everything to home location */
genExportPC(cUnit, mir);
RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlSrc, r1);
* with. However, Alloc might throw, so we need to genExportPC()
*/
assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
+ flushAllRegs(cUnit); /* Send everything to home location */
genExportPC(cUnit, mir);
loadConstant(cUnit, r2, (int)dvmAllocObject);
loadConstant(cUnit, r0, (int) classPtr);
*/
ClassObject *classPtr =
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
+ flushAllRegs(cUnit); /* Send everything to home location */
loadConstant(cUnit, r1, (int) classPtr );
rlSrc = getSrcLoc(cUnit, mir, 0);
rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
genInterpSingleStep(cUnit, mir);
return false;
}
+ flushAllRegs(cUnit); /* Send everything to home location */
loadValueDirectFixed(cUnit, rlSrc, r0);
clobberReg(cUnit, r0);
if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
void *classPtr = (void*)
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
assert(classPtr != NULL);
+ flushAllRegs(cUnit); /* Send everything to home location */
genExportPC(cUnit, mir);
loadValueDirectFixed(cUnit, rlSrc, r1); /* Len */
loadConstant(cUnit, r0, (int) classPtr );
ClassObject *classPtr =
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
assert(classPtr != NULL);
+ flushAllRegs(cUnit); /* Send everything to home location */
loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */
loadConstant(cUnit, r2, (int) classPtr );
//TUNING: compare to 0 primative to allow use of CB[N]Z
case OP_FILL_ARRAY_DATA: {
RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
// Making a call - use explicit registers
+ flushAllRegs(cUnit); /* Send everything to home location */
genExportPC(cUnit, mir);
loadValueDirectFixed(cUnit, rlSrc, r0);
- loadConstant(cUnit, r3, (int)dvmInterpHandleFillArrayData);
+ loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
loadConstant(cUnit, r1, (mir->dalvikInsn.vB << 1) +
(int) (cUnit->method->insns + mir->offset));
opReg(cUnit, kOpBlx, r2);
clobberCallRegs(cUnit);
- genZeroCheck(cUnit, r0, mir->offset, NULL);
+ /* generate a branch over if successful */
+ opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
+ ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
+ loadConstant(cUnit, r0,
+ (int) (cUnit->method->insns + mir->offset));
+ genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+ ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *) target;
break;
}
/*
case OP_PACKED_SWITCH:
case OP_SPARSE_SWITCH: {
RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
+ flushAllRegs(cUnit); /* Send everything to home location */
loadValueDirectFixed(cUnit, rlSrc, r1);
lockAllTemps(cUnit);
// Exit to the interpreter, setting up r4PC
}
/*
+ * This operation is complex enough that we'll do it partly inline
+ * and partly with a handler. NOTE: the handler uses hardcoded
+ * values for string object offsets and must be revisitied if the
+ * layout changes.
+ */
+static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
+{
+#if defined(USE_GLOBAL_STRING_DEFS)
+ return false;
+#else
+ ArmLIR *rollback;
+ RegLocation rlThis = getSrcLoc(cUnit, mir, 0);
+ RegLocation rlComp = getSrcLoc(cUnit, mir, 1);
+
+ loadValueDirectFixed(cUnit, rlThis, r0);
+ loadValueDirectFixed(cUnit, rlComp, r1);
+ /* Test objects for NULL */
+ rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
+ genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
+ /*
+ * TUNING: we could check for object pointer equality before invoking
+ * handler. Unclear whether the gain would be worth the added code size
+ * expansion.
+ */
+ genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
+ storeValue(cUnit, inlinedTarget(cUnit, mir, false), getReturnLoc(cUnit));
+ return true;
+#endif
+}
+
+static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
+{
+#if defined(USE_GLOBAL_STRING_DEFS)
+ return false;
+#else
+ RegLocation rlThis = getSrcLoc(cUnit, mir, 0);
+ RegLocation rlChar = getSrcLoc(cUnit, mir, 1);
+
+ loadValueDirectFixed(cUnit, rlThis, r0);
+ loadValueDirectFixed(cUnit, rlChar, r1);
+ if (!singleI) {
+ RegLocation rlStart = getSrcLoc(cUnit, mir, 2);
+ loadValueDirectFixed(cUnit, rlStart, r2);
+ } else {
+ loadConstant(cUnit, r2, 0);
+ }
+ /* Test objects for NULL */
+ genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
+ genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
+ storeValue(cUnit, inlinedTarget(cUnit, mir, false), getReturnLoc(cUnit));
+ return true;
+#endif
+}
+
+
+/*
* NOTE: We assume here that the special native inline routines
* are side-effect free. By making this assumption, we can safely
* re-execute the routine from the interpreter if it decides it
return false;
else
break; /* Handle with C routine */
- case INLINE_MATH_COS:
- case INLINE_MATH_SIN:
- break; /* Handle with C routine */
case INLINE_MATH_ABS_FLOAT:
if (genInlinedAbsFloat(cUnit, mir))
return false;
else
break;
case INLINE_STRING_COMPARETO:
- case INLINE_STRING_EQUALS:
+ if (genInlinedCompareTo(cUnit, mir))
+ return false;
+ else
+ break;
case INLINE_STRING_INDEXOF_I:
+ if (genInlinedIndexOf(cUnit, mir, true /* I */))
+ return false;
+ else
+ break;
case INLINE_STRING_INDEXOF_II:
- break;
+ if (genInlinedIndexOf(cUnit, mir, false /* I */))
+ return false;
+ else
+ break;
+ case INLINE_STRING_EQUALS:
+ case INLINE_MATH_COS:
+ case INLINE_MATH_SIN:
+ break; /* Handle with C routine */
default:
dvmAbort();
}
+ flushAllRegs(cUnit); /* Send everything to home location */
clobberCallRegs(cUnit);
clobberReg(cUnit, r4PC);
clobberReg(cUnit, r7);
JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
JIT_TEMPLATE(SAVE_STATE)
JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(STRING_COMPARETO)
+JIT_TEMPLATE(STRING_INDEXOF)
--- /dev/null
+ /*
+ * String's compareTo.
+ *
+ * Requires r0/r1 to have been previously checked for null. Will
+ * return negative if this's string is < comp, 0 if they are the
+ * same and positive if >.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync with definitions in UtfString.h. See asm-constants.h
+ *
+ * On entry:
+ * r0: this object pointer
+ * r1: comp object pointer
+ *
+ */
+
+ mov r2, r0 @ this to r2, opening up r0 for return value
+ subs r0, r2, r1 @ Same?
+ bxeq lr
+
+ ldr r4, [r2, #STRING_FIELDOFF_OFFSET]
+ ldr r9, [r1, #STRING_FIELDOFF_OFFSET]
+ ldr r7, [r2, #STRING_FIELDOFF_COUNT]
+ ldr r10, [r1, #STRING_FIELDOFF_COUNT]
+ ldr r2, [r2, #STRING_FIELDOFF_VALUE]
+ ldr r1, [r1, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r2/r1
+ * offset: r4/r9
+ * count: r7/r10
+ * We're going to compute
+ * r11 <- countDiff
+ * r10 <- minCount
+ */
+ subs r11, r7, r10
+ movls r10, r7
+
+ /* Now, build pointers to the string data */
+ add r2, r2, r4, lsl #1
+ add r1, r1, r9, lsl #1
+ /*
+ * Note: data pointers point to previous element so we can use pre-index
+ * mode with base writeback.
+ */
+ add r2, #16-2 @ offset to contents[-1]
+ add r1, #16-2 @ offset to contents[-1]
+
+ /*
+ * At this point we have:
+ * r2: *this string data
+ * r1: *comp string data
+ * r10: iteration count for comparison
+ * r11: value to return if the first part of the string is equal
+ * r0: reserved for result
+ * r3, r4, r7, r8, r9, r12 available for loading string data
+ */
+
+ cmp r10, #3
+ blt do_remainder
+loopback_triple:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ ldrh r7, [r2, #2]!
+ ldrh r8, [r1, #2]!
+ ldrh r9, [r2, #2]!
+ ldrh r12,[r1, #2]!
+ subs r0, r3, r4
+ subeqs r0, r7, r8
+ subeqs r0, r9, r12
+ bxne lr
+ subs r10, #3
+ bgt loopback_triple
+
+do_remainder:
+ cmp r10, #0
+ beq returnDiff
+
+loopback_single:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ subs r0, r3, r4
+ bxne lr
+ subs r10, #1
+ bne loopback_single
+
+returnDiff:
+ mov r0, r11
+ bx lr
+
--- /dev/null
+ /*
+ * String's indexOf.
+ *
+ * Requires r0 to have been previously checked for null. Will
+ * return index of match of r1 in r0.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync wth definitions in UtfString.h See asm-constants.h
+ *
+ * On entry:
+ * r0: string object pointer
+ * r1: char to match
+ * r2: Starting offset in string data
+ */
+
+ ldr r7, [r0, #STRING_FIELDOFF_OFFSET]
+ ldr r8, [r0, #STRING_FIELDOFF_COUNT]
+ ldr r0, [r0, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r0
+ * offset: r7
+ * count: r8
+ */
+
+ /* Clamp start to [0..count] */
+ cmp r2, #0
+ movlt r2, #0
+ cmp r2, r8
+ movgt r2, r0
+
+ /* Fold start & offset, and set data pointer to contents[-1] */
+ add r2, r7
+ add r0, r0, r2, lsl #1
+ add r0, #16-2 @ offset to contents[-1]
+ add r2, r0, #2 @ remember true start of data
+
+ /*
+ * At this point we have:
+ * r0: *next[-1] char to test
+ * r2: *start
+ * r1: char to compare
+ * r8: max count
+ * r3, r4, r7, r9, r12 available for loading string data
+ */
+
+ /* Unroll x 4 */
+
+ cmp r8, #4
+ blt do_rest
+loopback_quad:
+ ldrh r3, [r0, #2]!
+ ldrh r4, [r0, #2]!
+ ldrh r7, [r0, #2]!
+ ldrh r9, [r0, #2]!
+ cmp r3, r1
+ beq match_0
+ cmp r4, r1
+ beq match_1
+ cmp r7, r1
+ beq match_2
+ cmp r9, r1
+ beq match_3
+ subs r8, #4
+ bgt loopback_quad
+
+do_rest:
+ cmp r8, #0
+ beq no_match
+
+loopback_indexof:
+ ldrh r3, [r0, #2]!
+ cmp r3, r1
+ beq match_3
+ subs r8, #1
+ bne loopback_indexof
+
+no_match:
+ mov r0, #-1
+ bx lr
+
+match_0:
+ sub r0, #6
+ sub r0, r2
+ bx lr
+match_1:
+ sub r0, #4
+ sub r0, r2
+ bx lr
+match_2:
+ sub r0, #2
+ sub r0, r2
+ bx lr
+match_3:
+ sub r0, r2
+ bx lr
+
JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
JIT_TEMPLATE(SAVE_STATE)
JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(STRING_COMPARETO)
+JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
JIT_TEMPLATE(SAVE_STATE)
JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(STRING_COMPARETO)
+JIT_TEMPLATE(STRING_INDEXOF)
op TEMPLATE_SHR_LONG armv5te
op TEMPLATE_USHR_LONG armv5te
op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
+ op TEMPLATE_STRING_COMPARETO armv5te
+ op TEMPLATE_STRING_INDEXOF armv5te
op-end
op TEMPLATE_SHR_LONG armv5te
op TEMPLATE_USHR_LONG armv5te
op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
+ op TEMPLATE_STRING_COMPARETO armv5te
+ op TEMPLATE_STRING_INDEXOF armv5te
op-end
ldmia r0, {r0-r12}
bx lr
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_STRING_COMPARETO
+dvmCompiler_TEMPLATE_STRING_COMPARETO:
+/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
+ /*
+ * String's compareTo.
+ *
+ * Requires r0/r1 to have been previously checked for null. Will
+ * return negative if this's string is < comp, 0 if they are the
+ * same and positive if >.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync with definitions in UtfString.h. See asm-constants.h
+ *
+ * On entry:
+ * r0: this object pointer
+ * r1: comp object pointer
+ *
+ */
+
+ mov r2, r0 @ this to r2, opening up r0 for return value
+ subs r0, r2, r1 @ Same?
+ bxeq lr
+
+ ldr r4, [r2, #STRING_FIELDOFF_OFFSET]
+ ldr r9, [r1, #STRING_FIELDOFF_OFFSET]
+ ldr r7, [r2, #STRING_FIELDOFF_COUNT]
+ ldr r10, [r1, #STRING_FIELDOFF_COUNT]
+ ldr r2, [r2, #STRING_FIELDOFF_VALUE]
+ ldr r1, [r1, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r2/r1
+ * offset: r4/r9
+ * count: r7/r10
+ * We're going to compute
+ * r11 <- countDiff
+ * r10 <- minCount
+ */
+ subs r11, r7, r10
+ movls r10, r7
+
+ /* Now, build pointers to the string data */
+ add r2, r2, r4, lsl #1
+ add r1, r1, r9, lsl #1
+ /*
+ * Note: data pointers point to previous element so we can use pre-index
+ * mode with base writeback.
+ */
+ add r2, #16-2 @ offset to contents[-1]
+ add r1, #16-2 @ offset to contents[-1]
+
+ /*
+ * At this point we have:
+ * r2: *this string data
+ * r1: *comp string data
+ * r10: iteration count for comparison
+ * r11: value to return if the first part of the string is equal
+ * r0: reserved for result
+ * r3, r4, r7, r8, r9, r12 available for loading string data
+ */
+
+ cmp r10, #3
+ blt do_remainder
+loopback_triple:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ ldrh r7, [r2, #2]!
+ ldrh r8, [r1, #2]!
+ ldrh r9, [r2, #2]!
+ ldrh r12,[r1, #2]!
+ subs r0, r3, r4
+ subeqs r0, r7, r8
+ subeqs r0, r9, r12
+ bxne lr
+ subs r10, #3
+ bgt loopback_triple
+
+do_remainder:
+ cmp r10, #0
+ beq returnDiff
+
+loopback_single:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ subs r0, r3, r4
+ bxne lr
+ subs r10, #1
+ bne loopback_single
+
+returnDiff:
+ mov r0, r11
+ bx lr
+
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_STRING_INDEXOF
+dvmCompiler_TEMPLATE_STRING_INDEXOF:
+/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
+ /*
+ * String's indexOf.
+ *
+ * Requires r0 to have been previously checked for null. Will
+ * return index of match of r1 in r0.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync wth definitions in UtfString.h See asm-constants.h
+ *
+ * On entry:
+ * r0: string object pointer
+ * r1: char to match
+ * r2: Starting offset in string data
+ */
+
+ ldr r7, [r0, #STRING_FIELDOFF_OFFSET]
+ ldr r8, [r0, #STRING_FIELDOFF_COUNT]
+ ldr r0, [r0, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r0
+ * offset: r7
+ * count: r8
+ */
+
+ /* Clamp start to [0..count] */
+ cmp r2, #0
+ movlt r2, #0
+ cmp r2, r8
+ movgt r2, r0
+
+ /* Fold start & offset, and set data pointer to contents[-1] */
+ add r2, r7
+ add r0, r0, r2, lsl #1
+ add r0, #16-2 @ offset to contents[-1]
+ add r2, r0, #2 @ remember true start of data
+
+ /*
+ * At this point we have:
+ * r0: *next[-1] char to test
+ * r2: *start
+ * r1: char to compare
+ * r8: max count
+ * r3, r4, r7, r9, r12 available for loading string data
+ */
+
+ /* Unroll x 4 */
+
+ cmp r8, #4
+ blt do_rest
+loopback_quad:
+ ldrh r3, [r0, #2]!
+ ldrh r4, [r0, #2]!
+ ldrh r7, [r0, #2]!
+ ldrh r9, [r0, #2]!
+ cmp r3, r1
+ beq match_0
+ cmp r4, r1
+ beq match_1
+ cmp r7, r1
+ beq match_2
+ cmp r9, r1
+ beq match_3
+ subs r8, #4
+ bgt loopback_quad
+
+do_rest:
+ cmp r8, #0
+ beq no_match
+
+loopback_indexof:
+ ldrh r3, [r0, #2]!
+ cmp r3, r1
+ beq match_3
+ subs r8, #1
+ bne loopback_indexof
+
+no_match:
+ mov r0, #-1
+ bx lr
+
+match_0:
+ sub r0, #6
+ sub r0, r2
+ bx lr
+match_1:
+ sub r0, #4
+ sub r0, r2
+ bx lr
+match_2:
+ sub r0, #2
+ sub r0, r2
+ bx lr
+match_3:
+ sub r0, r2
+ bx lr
+
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
ldmia r0, {r0-r12}
bx lr
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_STRING_COMPARETO
+dvmCompiler_TEMPLATE_STRING_COMPARETO:
+/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
+ /*
+ * String's compareTo.
+ *
+ * Requires r0/r1 to have been previously checked for null. Will
+ * return negative if this's string is < comp, 0 if they are the
+ * same and positive if >.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync with definitions in UtfString.h. See asm-constants.h
+ *
+ * On entry:
+ * r0: this object pointer
+ * r1: comp object pointer
+ *
+ */
+
+ mov r2, r0 @ this to r2, opening up r0 for return value
+ subs r0, r2, r1 @ Same?
+ bxeq lr
+
+ ldr r4, [r2, #STRING_FIELDOFF_OFFSET]
+ ldr r9, [r1, #STRING_FIELDOFF_OFFSET]
+ ldr r7, [r2, #STRING_FIELDOFF_COUNT]
+ ldr r10, [r1, #STRING_FIELDOFF_COUNT]
+ ldr r2, [r2, #STRING_FIELDOFF_VALUE]
+ ldr r1, [r1, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r2/r1
+ * offset: r4/r9
+ * count: r7/r10
+ * We're going to compute
+ * r11 <- countDiff
+ * r10 <- minCount
+ */
+ subs r11, r7, r10
+ movls r10, r7
+
+ /* Now, build pointers to the string data */
+ add r2, r2, r4, lsl #1
+ add r1, r1, r9, lsl #1
+ /*
+ * Note: data pointers point to previous element so we can use pre-index
+ * mode with base writeback.
+ */
+ add r2, #16-2 @ offset to contents[-1]
+ add r1, #16-2 @ offset to contents[-1]
+
+ /*
+ * At this point we have:
+ * r2: *this string data
+ * r1: *comp string data
+ * r10: iteration count for comparison
+ * r11: value to return if the first part of the string is equal
+ * r0: reserved for result
+ * r3, r4, r7, r8, r9, r12 available for loading string data
+ */
+
+ cmp r10, #3
+ blt do_remainder
+loopback_triple:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ ldrh r7, [r2, #2]!
+ ldrh r8, [r1, #2]!
+ ldrh r9, [r2, #2]!
+ ldrh r12,[r1, #2]!
+ subs r0, r3, r4
+ subeqs r0, r7, r8
+ subeqs r0, r9, r12
+ bxne lr
+ subs r10, #3
+ bgt loopback_triple
+
+do_remainder:
+ cmp r10, #0
+ beq returnDiff
+
+loopback_single:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ subs r0, r3, r4
+ bxne lr
+ subs r10, #1
+ bne loopback_single
+
+returnDiff:
+ mov r0, r11
+ bx lr
+
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_STRING_INDEXOF
+dvmCompiler_TEMPLATE_STRING_INDEXOF:
+/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
+ /*
+ * String's indexOf.
+ *
+ * Requires r0 to have been previously checked for null. Will
+ * return index of match of r1 in r0.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync wth definitions in UtfString.h See asm-constants.h
+ *
+ * On entry:
+ * r0: string object pointer
+ * r1: char to match
+ * r2: Starting offset in string data
+ */
+
+ ldr r7, [r0, #STRING_FIELDOFF_OFFSET]
+ ldr r8, [r0, #STRING_FIELDOFF_COUNT]
+ ldr r0, [r0, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r0
+ * offset: r7
+ * count: r8
+ */
+
+ /* Clamp start to [0..count] */
+ cmp r2, #0
+ movlt r2, #0
+ cmp r2, r8
+ movgt r2, r0
+
+ /* Fold start & offset, and set data pointer to contents[-1] */
+ add r2, r7
+ add r0, r0, r2, lsl #1
+ add r0, #16-2 @ offset to contents[-1]
+ add r2, r0, #2 @ remember true start of data
+
+ /*
+ * At this point we have:
+ * r0: *next[-1] char to test
+ * r2: *start
+ * r1: char to compare
+ * r8: max count
+ * r3, r4, r7, r9, r12 available for loading string data
+ */
+
+ /* Unroll x 4 */
+
+ cmp r8, #4
+ blt do_rest
+loopback_quad:
+ ldrh r3, [r0, #2]!
+ ldrh r4, [r0, #2]!
+ ldrh r7, [r0, #2]!
+ ldrh r9, [r0, #2]!
+ cmp r3, r1
+ beq match_0
+ cmp r4, r1
+ beq match_1
+ cmp r7, r1
+ beq match_2
+ cmp r9, r1
+ beq match_3
+ subs r8, #4
+ bgt loopback_quad
+
+do_rest:
+ cmp r8, #0
+ beq no_match
+
+loopback_indexof:
+ ldrh r3, [r0, #2]!
+ cmp r3, r1
+ beq match_3
+ subs r8, #1
+ bne loopback_indexof
+
+no_match:
+ mov r0, #-1
+ bx lr
+
+match_0:
+ sub r0, #6
+ sub r0, r2
+ bx lr
+match_1:
+ sub r0, #4
+ sub r0, r2
+ bx lr
+match_2:
+ sub r0, #2
+ sub r0, r2
+ bx lr
+match_3:
+ sub r0, r2
+ bx lr
+
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
ldmia r0, {r0-r12}
bx lr
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_STRING_COMPARETO
+dvmCompiler_TEMPLATE_STRING_COMPARETO:
+/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
+ /*
+ * String's compareTo.
+ *
+ * Requires r0/r1 to have been previously checked for null. Will
+ * return negative if this's string is < comp, 0 if they are the
+ * same and positive if >.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync with definitions in UtfString.h. See asm-constants.h
+ *
+ * On entry:
+ * r0: this object pointer
+ * r1: comp object pointer
+ *
+ */
+
+ mov r2, r0 @ this to r2, opening up r0 for return value
+ subs r0, r2, r1 @ Same?
+ bxeq lr
+
+ ldr r4, [r2, #STRING_FIELDOFF_OFFSET]
+ ldr r9, [r1, #STRING_FIELDOFF_OFFSET]
+ ldr r7, [r2, #STRING_FIELDOFF_COUNT]
+ ldr r10, [r1, #STRING_FIELDOFF_COUNT]
+ ldr r2, [r2, #STRING_FIELDOFF_VALUE]
+ ldr r1, [r1, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r2/r1
+ * offset: r4/r9
+ * count: r7/r10
+ * We're going to compute
+ * r11 <- countDiff
+ * r10 <- minCount
+ */
+ subs r11, r7, r10
+ movls r10, r7
+
+ /* Now, build pointers to the string data */
+ add r2, r2, r4, lsl #1
+ add r1, r1, r9, lsl #1
+ /*
+ * Note: data pointers point to previous element so we can use pre-index
+ * mode with base writeback.
+ */
+ add r2, #16-2 @ offset to contents[-1]
+ add r1, #16-2 @ offset to contents[-1]
+
+ /*
+ * At this point we have:
+ * r2: *this string data
+ * r1: *comp string data
+ * r10: iteration count for comparison
+ * r11: value to return if the first part of the string is equal
+ * r0: reserved for result
+ * r3, r4, r7, r8, r9, r12 available for loading string data
+ */
+
+ cmp r10, #3
+ blt do_remainder
+loopback_triple:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ ldrh r7, [r2, #2]!
+ ldrh r8, [r1, #2]!
+ ldrh r9, [r2, #2]!
+ ldrh r12,[r1, #2]!
+ subs r0, r3, r4
+ subeqs r0, r7, r8
+ subeqs r0, r9, r12
+ bxne lr
+ subs r10, #3
+ bgt loopback_triple
+
+do_remainder:
+ cmp r10, #0
+ beq returnDiff
+
+loopback_single:
+ ldrh r3, [r2, #2]!
+ ldrh r4, [r1, #2]!
+ subs r0, r3, r4
+ bxne lr
+ subs r10, #1
+ bne loopback_single
+
+returnDiff:
+ mov r0, r11
+ bx lr
+
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_STRING_INDEXOF
+dvmCompiler_TEMPLATE_STRING_INDEXOF:
+/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
+ /*
+ * String's indexOf.
+ *
+ * Requires r0 to have been previously checked for null. Will
+ * return index of match of r1 in r0.
+ *
+ * IMPORTANT NOTE:
+ *
+ * This code relies on hard-coded offsets for string objects, and must be
+ * kept in sync wth definitions in UtfString.h See asm-constants.h
+ *
+ * On entry:
+ * r0: string object pointer
+ * r1: char to match
+ * r2: Starting offset in string data
+ */
+
+ ldr r7, [r0, #STRING_FIELDOFF_OFFSET]
+ ldr r8, [r0, #STRING_FIELDOFF_COUNT]
+ ldr r0, [r0, #STRING_FIELDOFF_VALUE]
+
+ /*
+ * At this point, we have:
+ * value: r0
+ * offset: r7
+ * count: r8
+ */
+
+ /* Clamp start to [0..count] */
+ cmp r2, #0
+ movlt r2, #0
+ cmp r2, r8
+ movgt r2, r0
+
+ /* Fold start & offset, and set data pointer to contents[-1] */
+ add r2, r7
+ add r0, r0, r2, lsl #1
+ add r0, #16-2 @ offset to contents[-1]
+ add r2, r0, #2 @ remember true start of data
+
+ /*
+ * At this point we have:
+ * r0: *next[-1] char to test
+ * r2: *start
+ * r1: char to compare
+ * r8: max count
+ * r3, r4, r7, r9, r12 available for loading string data
+ */
+
+ /* Unroll x 4 */
+
+ cmp r8, #4
+ blt do_rest
+loopback_quad:
+ ldrh r3, [r0, #2]!
+ ldrh r4, [r0, #2]!
+ ldrh r7, [r0, #2]!
+ ldrh r9, [r0, #2]!
+ cmp r3, r1
+ beq match_0
+ cmp r4, r1
+ beq match_1
+ cmp r7, r1
+ beq match_2
+ cmp r9, r1
+ beq match_3
+ subs r8, #4
+ bgt loopback_quad
+
+do_rest:
+ cmp r8, #0
+ beq no_match
+
+loopback_indexof:
+ ldrh r3, [r0, #2]!
+ cmp r3, r1
+ beq match_3
+ subs r8, #1
+ bne loopback_indexof
+
+no_match:
+ mov r0, #-1
+ bx lr
+
+match_0:
+ sub r0, #6
+ sub r0, r2
+ bx lr
+match_1:
+ sub r0, #4
+ sub r0, r2
+ bx lr
+match_2:
+ sub r0, #2
+ sub r0, r2
+ bx lr
+match_3:
+ sub r0, r2
+ bx lr
+
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
MTERP_OFFSET(offArrayObject_contents, ArrayObject, contents, 12)
#endif
+/* String fields */
+MTERP_CONSTANT(STRING_FIELDOFF_VALUE, 8)
+MTERP_CONSTANT(STRING_FIELDOFF_HASHCODE, 12)
+MTERP_CONSTANT(STRING_FIELDOFF_OFFSET, 16)
+MTERP_CONSTANT(STRING_FIELDOFF_COUNT, 20)
+
/* ClassObject fields */
MTERP_OFFSET(offClassObject_descriptor, ClassObject, descriptor, 24)
MTERP_OFFSET(offClassObject_accessFlags, ClassObject, accessFlags, 32)