CompilerTemplateAsm-armv5te-vfp.S revision d72564ca7aa66c6d95b6ca34299258b65ecfd1cb
1/* 2 * This file was generated automatically by gen-template.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24#if defined(WITH_JIT) 25 26/* 27 * ARMv5 definitions and declarations. 28 */ 29 30/* 31ARM EABI general notes: 32 33r0-r3 hold first 4 args to a method; they are not preserved across method calls 34r4-r8 are available for general use 35r9 is given special treatment in some situations, but not for us 36r10 (sl) seems to be generally available 37r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 38r12 (ip) is scratch -- not preserved across method calls 39r13 (sp) should be managed carefully in case a signal arrives 40r14 (lr) must be preserved 41r15 (pc) can be tinkered with directly 42 43r0 holds returns of <= 4 bytes 44r0-r1 hold returns of 8 bytes, low word in r0 45 46Callee must save/restore r4+ (except r12) if it modifies them. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59JIT and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 67The following registers have fixed assignments in mterp but are scratch 68registers in compiled code 69 70 reg nick purpose 71 r4 rPC interpreted program counter, used for fetching instructions 72 r7 rINST first 16-bit code unit of current instruction 73 r8 rIBASE interpreted instruction base pointer, used for computed goto 74 75Macros are provided for common operations. Each macro MUST emit only 76one instruction to make instruction-counting easier. They MUST NOT alter 77unspecified registers or condition codes. 78*/ 79 80/* single-purpose registers, given names for clarity */ 81#define rPC r4 82#define rFP r5 83#define rGLUE r6 84#define rINST r7 85#define rIBASE r8 86 87/* 88 * Given a frame pointer, find the stack save area. 89 * 90 * In C this is "((StackSaveArea*)(_fp) -1)". 91 */ 92#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 93 sub _reg, _fpreg, #sizeofStackSaveArea 94 95#define EXPORT_PC() \ 96 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 97 98/* 99 * This is a #include, not a %include, because we want the C pre-processor 100 * to expand the macros into assembler assignment statements. 101 */ 102#include "../../../mterp/common/asm-constants.h" 103 104/* File: armv5te-vfp/platform.S */ 105/* 106 * =========================================================================== 107 * CPU-version-specific defines and utility 108 * =========================================================================== 109 */ 110 111 112 .global dvmCompilerTemplateStart 113 .type dvmCompilerTemplateStart, %function 114 .text 115 116dvmCompilerTemplateStart: 117 118/* ------------------------------ */ 119 .balign 4 120 .global dvmCompiler_TEMPLATE_CMP_LONG 121dvmCompiler_TEMPLATE_CMP_LONG: 122/* File: armv5te/TEMPLATE_CMP_LONG.S */ 123 /* 124 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 125 * register based on the results of the comparison. 126 * 127 * We load the full values with LDM, but in practice many values could 128 * be resolved by only looking at the high word. This could be made 129 * faster or slower by splitting the LDM into a pair of LDRs. 130 * 131 * If we just wanted to set condition flags, we could do this: 132 * subs ip, r0, r2 133 * sbcs ip, r1, r3 134 * subeqs ip, r0, r2 135 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 136 * integer value, which we can do with 2 conditional mov/mvn instructions 137 * (set 1, set -1; if they're equal we already have 0 in ip), giving 138 * us a constant 5-cycle path plus a branch at the end to the 139 * instruction epilogue code. The multi-compare approach below needs 140 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 141 * in the worst case (the 64-bit values are equal). 142 */ 143 /* cmp-long vAA, vBB, vCC */ 144 cmp r1, r3 @ compare (vBB+1, vCC+1) 145 blt .LTEMPLATE_CMP_LONG_less @ signed compare on high part 146 bgt .LTEMPLATE_CMP_LONG_greater 147 subs r0, r0, r2 @ r0<- r0 - r2 148 bxeq lr 149 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part 150.LTEMPLATE_CMP_LONG_less: 151 mvn r0, #0 @ r0<- -1 152 bx lr 153.LTEMPLATE_CMP_LONG_greater: 154 mov r0, #1 @ r0<- 1 155 bx lr 156 157/* ------------------------------ */ 158 .balign 4 159 .global dvmCompiler_TEMPLATE_RETURN 160dvmCompiler_TEMPLATE_RETURN: 161/* File: armv5te/TEMPLATE_RETURN.S */ 162 /* 163 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 164 * If the stored value in returnAddr 165 * is non-zero, the caller is compiled by the JIT thus return to the 166 * address in the code cache following the invoke instruction. Otherwise 167 * return to the special dvmJitToInterpNoChain entry point. 168 */ 169#if defined(TEMPLATE_INLINE_PROFILING) 170 stmfd sp!, {r0-r2,lr} @ preserve live registers 171 mov r0, r6 172 @ r0=rGlue 173 mov lr, pc 174 ldr pc, .LdvmFastJavaMethodTraceExit 175 ldmfd sp!, {r0-r2,lr} @ restore live registers 176#endif 177 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 178 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 179 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 180 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 181#if !defined(WITH_SELF_VERIFICATION) 182 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 183#else 184 mov r9, #0 @ disable chaining 185#endif 186 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 187 @ r2<- method we're returning to 188 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 189 cmp r2, #0 @ break frame? 190#if !defined(WITH_SELF_VERIFICATION) 191 beq 1f @ bail to interpreter 192#else 193 blxeq lr @ punt to interpreter and compare state 194#endif 195 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S 196 mov rFP, r10 @ publish new FP 197 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 198 ldr r8, [r8] @ r8<- suspendCount 199 200 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 201 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 202 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 203 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 204 str r0, [rGLUE, #offGlue_methodClassDex] 205 cmp r8, #0 @ check the suspendCount 206 movne r9, #0 @ clear the chaining cell address 207 str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not 208 cmp r9, #0 @ chaining cell exists? 209 blxne r9 @ jump to the chaining cell 210#if defined(WITH_JIT_TUNING) 211 mov r0, #kCallsiteInterpreted 212#endif 213 mov pc, r1 @ callsite is interpreted 2141: 215 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE() 216 ldr r2, .LdvmMterpStdBail @ defined in footer.S 217 mov r1, #0 @ changeInterp = false 218 mov r0, rGLUE @ Expecting rGLUE in r0 219 blx r2 @ exit the interpreter 220 221/* ------------------------------ */ 222 .balign 4 223 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT 224dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT: 225/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 226 /* 227 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 228 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 229 * runtime-resolved callee. 230 */ 231 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 232 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 233 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 234 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 235 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 236 add r3, r1, #1 @ Thumb addr is odd 237 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 238 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 239 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 240 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 241 ldr r8, [r8] @ r8<- suspendCount (int) 242 cmp r10, r9 @ bottom < interpStackEnd? 243 bxlo lr @ return to raise stack overflow excep. 244 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 245 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 246 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 247 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 248 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 249 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 250 251 252 @ set up newSaveArea 253 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 254 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 255 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 256 cmp r8, #0 @ suspendCount != 0 257 bxne lr @ bail to the interpreter 258 tst r10, #ACC_NATIVE 259#if !defined(WITH_SELF_VERIFICATION) 260 bne .LinvokeNative 261#else 262 bxne lr @ bail to the interpreter 263#endif 264 265 ldr r10, .LdvmJitToInterpTraceSelectNoChain 266 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 267 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 268 269 @ Update "glue" values for the new method 270 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 271 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 272 mov rFP, r1 @ fp = newFp 273 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 274#if defined(TEMPLATE_INLINE_PROFILING) 275 stmfd sp!, {r0-r3} @ preserve r0-r3 276 mov r1, r6 277 @ r0=methodToCall, r1=rGlue 278 mov lr, pc 279 ldr pc, .LdvmFastMethodTraceEnter 280 ldmfd sp!, {r0-r3} @ restore r0-r3 281#endif 282 283 @ Start executing the callee 284#if defined(WITH_JIT_TUNING) 285 mov r0, #kInlineCacheMiss 286#endif 287 mov pc, r10 @ dvmJitToInterpTraceSelectNoChain 288 289/* ------------------------------ */ 290 .balign 4 291 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN 292dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN: 293/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 294 /* 295 * For monomorphic callsite, setup the Dalvik frame and return to the 296 * Thumb code through the link register to transfer control to the callee 297 * method through a dedicated chaining cell. 298 */ 299 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize 300 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize 301 @ methodToCall is guaranteed to be non-native 302.LinvokeChain: 303 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 304 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 305 add r3, r1, #1 @ Thumb addr is odd 306 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 307 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 308 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 309 add r12, lr, #2 @ setup the punt-to-interp address 310 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 311 ldr r8, [r8] @ r8<- suspendCount (int) 312 cmp r10, r9 @ bottom < interpStackEnd? 313 bxlo r12 @ return to raise stack overflow excep. 314 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 315 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 316 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 317 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 318 319 @ set up newSaveArea 320 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 321 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 322 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 323 cmp r8, #0 @ suspendCount != 0 324 bxne r12 @ bail to the interpreter 325 326 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 327 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 328 329 @ Update "glue" values for the new method 330 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 331 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 332 mov rFP, r1 @ fp = newFp 333 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 334#if defined(TEMPLATE_INLINE_PROFILING) 335 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers 336 mov r1, r6 337 @ r0=methodToCall, r1=rGlue 338 mov lr, pc 339 ldr pc, .LdvmFastMethodTraceEnter 340 ldmfd sp!, {r0-r2,lr} @ restore registers 341#endif 342 343 bx lr @ return to the callee-chaining cell 344 345/* ------------------------------ */ 346 .balign 4 347 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN 348dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN: 349/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 350 /* 351 * For polymorphic callsite, check whether the cached class pointer matches 352 * the current one. If so setup the Dalvik frame and return to the 353 * Thumb code through the link register to transfer control to the callee 354 * method through a dedicated chaining cell. 355 * 356 * The predicted chaining cell is declared in ArmLIR.h with the 357 * following layout: 358 * 359 * typedef struct PredictedChainingCell { 360 * u4 branch; 361 * const ClassObject *clazz; 362 * const Method *method; 363 * u4 counter; 364 * } PredictedChainingCell; 365 * 366 * Upon returning to the callsite: 367 * - lr : to branch to the chaining cell 368 * - lr+2: to punt to the interpreter 369 * - lr+4: to fully resolve the callee and may rechain. 370 * r3 <- class 371 * r9 <- counter 372 */ 373 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 374 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 375 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 376 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 377 ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount 378 cmp r3, r8 @ predicted class == actual class? 379#if defined(WITH_JIT_TUNING) 380 ldr r7, .LdvmICHitCount 381#if defined(WORKAROUND_CORTEX_A9_745320) 382 /* Don't use conditional loads if the HW defect exists */ 383 bne 101f 384 ldr r10, [r7, #0] 385101: 386#else 387 ldreq r10, [r7, #0] 388#endif 389 add r10, r10, #1 390 streq r10, [r7, #0] 391#endif 392 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 393 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 394 beq .LinvokeChain @ predicted chain is valid 395 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 396 cmp r8, #0 @ initialized class or not 397 moveq r1, #0 398 subne r1, r9, #1 @ count-- 399 strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState 400 add lr, lr, #4 @ return to fully-resolve landing pad 401 /* 402 * r1 <- count 403 * r2 <- &predictedChainCell 404 * r3 <- this->class 405 * r4 <- dPC 406 * r7 <- this->class->vtable 407 */ 408 bx lr 409 410/* ------------------------------ */ 411 .balign 4 412 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE 413dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE: 414/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 415 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 416 @ r7 = methodToCall->registersSize 417 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 418 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 419 add r3, r1, #1 @ Thumb addr is odd 420 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 421 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 422 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 423 ldr r8, [r8] @ r3<- suspendCount (int) 424 cmp r10, r9 @ bottom < interpStackEnd? 425 bxlo lr @ return to raise stack overflow excep. 426 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 427 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 428 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 429 430 @ set up newSaveArea 431 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 432 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 433 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 434 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 435 cmp r8, #0 @ suspendCount != 0 436 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 437#if !defined(WITH_SELF_VERIFICATION) 438 bxne lr @ bail to the interpreter 439#else 440 bx lr @ bail to interpreter unconditionally 441#endif 442 443 @ go ahead and transfer control to the native code 444 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 445 mov r2, #0 446 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 447 str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache 448 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 449 @ newFp->localRefCookie=top 450 mov r9, r3 @ r9<- glue->self (preserve) 451 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 452 453 mov r2, r0 @ r2<- methodToCall 454 mov r0, r1 @ r0<- newFP 455 add r1, rGLUE, #offGlue_retval @ r1<- &retval 456#if defined(TEMPLATE_INLINE_PROFILING) 457 @ r2=methodToCall, r6=rGLUE 458 stmfd sp!, {r2,r6} @ to be consumed after JNI return 459 stmfd sp!, {r0-r3} @ preserve r0-r3 460 mov r0, r2 461 mov r1, r6 462 @ r0=JNIMethod, r1=rGlue 463 mov lr, pc 464 ldr pc, .LdvmFastMethodTraceEnter 465 ldmfd sp!, {r0-r3} @ restore r0-r3 466#endif 467 468 blx r8 @ off to the native code 469 470#if defined(TEMPLATE_INLINE_PROFILING) 471 ldmfd sp!, {r0-r1} @ restore r2 and r6 472 @ r0=JNIMethod, r1=rGlue 473 mov lr, pc 474 ldr pc, .LdvmFastNativeMethodTraceExit 475#endif 476 @ native return; r9=self, r10=newSaveArea 477 @ equivalent to dvmPopJniLocals 478 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 479 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 480 ldr r1, [r9, #offThread_exception] @ check for exception 481 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 482 cmp r1, #0 @ null? 483 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 484 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 485 486 @ r0 = dalvikCallsitePC 487 bne .LhandleException @ no, handle exception 488 489 str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly 490 cmp r2, #0 @ return chaining cell still exists? 491 bxne r2 @ yes - go ahead 492 493 @ continue executing the next instruction through the interpreter 494 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 495 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 496#if defined(WITH_JIT_TUNING) 497 mov r0, #kCallsiteInterpreted 498#endif 499 mov pc, r1 500 501/* ------------------------------ */ 502 .balign 4 503 .global dvmCompiler_TEMPLATE_MUL_LONG 504dvmCompiler_TEMPLATE_MUL_LONG: 505/* File: armv5te/TEMPLATE_MUL_LONG.S */ 506 /* 507 * Signed 64-bit integer multiply. 508 * 509 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 510 * 511 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 512 * WX 513 * x YZ 514 * -------- 515 * ZW ZX 516 * YW YX 517 * 518 * The low word of the result holds ZX, the high word holds 519 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 520 * it doesn't fit in the low 64 bits. 521 * 522 * Unlike most ARM math operations, multiply instructions have 523 * restrictions on using the same register more than once (Rd and Rm 524 * cannot be the same). 525 */ 526 /* mul-long vAA, vBB, vCC */ 527 mul ip, r2, r1 @ ip<- ZxW 528 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 529 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 530 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 531 mov r0,r9 532 mov r1,r10 533 bx lr 534 535/* ------------------------------ */ 536 .balign 4 537 .global dvmCompiler_TEMPLATE_SHL_LONG 538dvmCompiler_TEMPLATE_SHL_LONG: 539/* File: armv5te/TEMPLATE_SHL_LONG.S */ 540 /* 541 * Long integer shift. This is different from the generic 32/64-bit 542 * binary operations because vAA/vBB are 64-bit but vCC (the shift 543 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 544 * 6 bits. 545 */ 546 /* shl-long vAA, vBB, vCC */ 547 and r2, r2, #63 @ r2<- r2 & 0x3f 548 mov r1, r1, asl r2 @ r1<- r1 << r2 549 rsb r3, r2, #32 @ r3<- 32 - r2 550 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 551 subs ip, r2, #32 @ ip<- r2 - 32 552 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 553 mov r0, r0, asl r2 @ r0<- r0 << r2 554 bx lr 555 556/* ------------------------------ */ 557 .balign 4 558 .global dvmCompiler_TEMPLATE_SHR_LONG 559dvmCompiler_TEMPLATE_SHR_LONG: 560/* File: armv5te/TEMPLATE_SHR_LONG.S */ 561 /* 562 * Long integer shift. This is different from the generic 32/64-bit 563 * binary operations because vAA/vBB are 64-bit but vCC (the shift 564 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 565 * 6 bits. 566 */ 567 /* shr-long vAA, vBB, vCC */ 568 and r2, r2, #63 @ r0<- r0 & 0x3f 569 mov r0, r0, lsr r2 @ r0<- r2 >> r2 570 rsb r3, r2, #32 @ r3<- 32 - r2 571 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 572 subs ip, r2, #32 @ ip<- r2 - 32 573 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 574 mov r1, r1, asr r2 @ r1<- r1 >> r2 575 bx lr 576 577/* ------------------------------ */ 578 .balign 4 579 .global dvmCompiler_TEMPLATE_USHR_LONG 580dvmCompiler_TEMPLATE_USHR_LONG: 581/* File: armv5te/TEMPLATE_USHR_LONG.S */ 582 /* 583 * Long integer shift. This is different from the generic 32/64-bit 584 * binary operations because vAA/vBB are 64-bit but vCC (the shift 585 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 586 * 6 bits. 587 */ 588 /* ushr-long vAA, vBB, vCC */ 589 and r2, r2, #63 @ r0<- r0 & 0x3f 590 mov r0, r0, lsr r2 @ r0<- r2 >> r2 591 rsb r3, r2, #32 @ r3<- 32 - r2 592 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 593 subs ip, r2, #32 @ ip<- r2 - 32 594 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 595 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 596 bx lr 597 598/* ------------------------------ */ 599 .balign 4 600 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP 601dvmCompiler_TEMPLATE_ADD_FLOAT_VFP: 602/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */ 603/* File: armv5te-vfp/fbinop.S */ 604 /* 605 * Generic 32-bit floating point operation. Provide an "instr" line that 606 * specifies an instruction that performs s2 = s0 op s1. 607 * 608 * On entry: 609 * r0 = target dalvik register address 610 * r1 = op1 address 611 * r2 = op2 address 612 */ 613 flds s0,[r1] 614 flds s1,[r2] 615 fadds s2, s0, s1 616 fsts s2,[r0] 617 bx lr 618 619 620/* ------------------------------ */ 621 .balign 4 622 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP 623dvmCompiler_TEMPLATE_SUB_FLOAT_VFP: 624/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */ 625/* File: armv5te-vfp/fbinop.S */ 626 /* 627 * Generic 32-bit floating point operation. Provide an "instr" line that 628 * specifies an instruction that performs s2 = s0 op s1. 629 * 630 * On entry: 631 * r0 = target dalvik register address 632 * r1 = op1 address 633 * r2 = op2 address 634 */ 635 flds s0,[r1] 636 flds s1,[r2] 637 fsubs s2, s0, s1 638 fsts s2,[r0] 639 bx lr 640 641 642/* ------------------------------ */ 643 .balign 4 644 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP 645dvmCompiler_TEMPLATE_MUL_FLOAT_VFP: 646/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */ 647/* File: armv5te-vfp/fbinop.S */ 648 /* 649 * Generic 32-bit floating point operation. Provide an "instr" line that 650 * specifies an instruction that performs s2 = s0 op s1. 651 * 652 * On entry: 653 * r0 = target dalvik register address 654 * r1 = op1 address 655 * r2 = op2 address 656 */ 657 flds s0,[r1] 658 flds s1,[r2] 659 fmuls s2, s0, s1 660 fsts s2,[r0] 661 bx lr 662 663 664/* ------------------------------ */ 665 .balign 4 666 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP 667dvmCompiler_TEMPLATE_DIV_FLOAT_VFP: 668/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */ 669/* File: armv5te-vfp/fbinop.S */ 670 /* 671 * Generic 32-bit floating point operation. Provide an "instr" line that 672 * specifies an instruction that performs s2 = s0 op s1. 673 * 674 * On entry: 675 * r0 = target dalvik register address 676 * r1 = op1 address 677 * r2 = op2 address 678 */ 679 flds s0,[r1] 680 flds s1,[r2] 681 fdivs s2, s0, s1 682 fsts s2,[r0] 683 bx lr 684 685 686/* ------------------------------ */ 687 .balign 4 688 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP 689dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP: 690/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */ 691/* File: armv5te-vfp/fbinopWide.S */ 692 /* 693 * Generic 64-bit floating point operation. Provide an "instr" line that 694 * specifies an instruction that performs s2 = s0 op s1. 695 * 696 * On entry: 697 * r0 = target dalvik register address 698 * r1 = op1 address 699 * r2 = op2 address 700 */ 701 fldd d0,[r1] 702 fldd d1,[r2] 703 faddd d2, d0, d1 704 fstd d2,[r0] 705 bx lr 706 707 708/* ------------------------------ */ 709 .balign 4 710 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP 711dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP: 712/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */ 713/* File: armv5te-vfp/fbinopWide.S */ 714 /* 715 * Generic 64-bit floating point operation. Provide an "instr" line that 716 * specifies an instruction that performs s2 = s0 op s1. 717 * 718 * On entry: 719 * r0 = target dalvik register address 720 * r1 = op1 address 721 * r2 = op2 address 722 */ 723 fldd d0,[r1] 724 fldd d1,[r2] 725 fsubd d2, d0, d1 726 fstd d2,[r0] 727 bx lr 728 729 730/* ------------------------------ */ 731 .balign 4 732 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP 733dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP: 734/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */ 735/* File: armv5te-vfp/fbinopWide.S */ 736 /* 737 * Generic 64-bit floating point operation. Provide an "instr" line that 738 * specifies an instruction that performs s2 = s0 op s1. 739 * 740 * On entry: 741 * r0 = target dalvik register address 742 * r1 = op1 address 743 * r2 = op2 address 744 */ 745 fldd d0,[r1] 746 fldd d1,[r2] 747 fmuld d2, d0, d1 748 fstd d2,[r0] 749 bx lr 750 751 752/* ------------------------------ */ 753 .balign 4 754 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP 755dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP: 756/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */ 757/* File: armv5te-vfp/fbinopWide.S */ 758 /* 759 * Generic 64-bit floating point operation. Provide an "instr" line that 760 * specifies an instruction that performs s2 = s0 op s1. 761 * 762 * On entry: 763 * r0 = target dalvik register address 764 * r1 = op1 address 765 * r2 = op2 address 766 */ 767 fldd d0,[r1] 768 fldd d1,[r2] 769 fdivd d2, d0, d1 770 fstd d2,[r0] 771 bx lr 772 773 774/* ------------------------------ */ 775 .balign 4 776 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP 777dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP: 778/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */ 779/* File: armv5te-vfp/funopNarrower.S */ 780 /* 781 * Generic 64bit-to-32bit floating point unary operation. Provide an 782 * "instr" line that specifies an instruction that performs "s0 = op d0". 783 * 784 * For: double-to-int, double-to-float 785 * 786 * On entry: 787 * r0 = target dalvik register address 788 * r1 = src dalvik register address 789 */ 790 /* unop vA, vB */ 791 fldd d0, [r1] @ d0<- vB 792 fcvtsd s0, d0 @ s0<- op d0 793 fsts s0, [r0] @ vA<- s0 794 bx lr 795 796 797/* ------------------------------ */ 798 .balign 4 799 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP 800dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP: 801/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */ 802/* File: armv5te-vfp/funopNarrower.S */ 803 /* 804 * Generic 64bit-to-32bit floating point unary operation. Provide an 805 * "instr" line that specifies an instruction that performs "s0 = op d0". 806 * 807 * For: double-to-int, double-to-float 808 * 809 * On entry: 810 * r0 = target dalvik register address 811 * r1 = src dalvik register address 812 */ 813 /* unop vA, vB */ 814 fldd d0, [r1] @ d0<- vB 815 ftosizd s0, d0 @ s0<- op d0 816 fsts s0, [r0] @ vA<- s0 817 bx lr 818 819 820/* ------------------------------ */ 821 .balign 4 822 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP 823dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP: 824/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */ 825/* File: armv5te-vfp/funopWider.S */ 826 /* 827 * Generic 32bit-to-64bit floating point unary operation. Provide an 828 * "instr" line that specifies an instruction that performs "d0 = op s0". 829 * 830 * For: int-to-double, float-to-double 831 * 832 * On entry: 833 * r0 = target dalvik register address 834 * r1 = src dalvik register address 835 */ 836 /* unop vA, vB */ 837 flds s0, [r1] @ s0<- vB 838 fcvtds d0, s0 @ d0<- op s0 839 fstd d0, [r0] @ vA<- d0 840 bx lr 841 842 843/* ------------------------------ */ 844 .balign 4 845 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP 846dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP: 847/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */ 848/* File: armv5te-vfp/funop.S */ 849 /* 850 * Generic 32bit-to-32bit floating point unary operation. Provide an 851 * "instr" line that specifies an instruction that performs "s1 = op s0". 852 * 853 * For: float-to-int, int-to-float 854 * 855 * On entry: 856 * r0 = target dalvik register address 857 * r1 = src dalvik register address 858 */ 859 /* unop vA, vB */ 860 flds s0, [r1] @ s0<- vB 861 ftosizs s1, s0 @ s1<- op s0 862 fsts s1, [r0] @ vA<- s1 863 bx lr 864 865 866/* ------------------------------ */ 867 .balign 4 868 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP 869dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP: 870/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */ 871/* File: armv5te-vfp/funopWider.S */ 872 /* 873 * Generic 32bit-to-64bit floating point unary operation. Provide an 874 * "instr" line that specifies an instruction that performs "d0 = op s0". 875 * 876 * For: int-to-double, float-to-double 877 * 878 * On entry: 879 * r0 = target dalvik register address 880 * r1 = src dalvik register address 881 */ 882 /* unop vA, vB */ 883 flds s0, [r1] @ s0<- vB 884 fsitod d0, s0 @ d0<- op s0 885 fstd d0, [r0] @ vA<- d0 886 bx lr 887 888 889/* ------------------------------ */ 890 .balign 4 891 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP 892dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP: 893/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */ 894/* File: armv5te-vfp/funop.S */ 895 /* 896 * Generic 32bit-to-32bit floating point unary operation. Provide an 897 * "instr" line that specifies an instruction that performs "s1 = op s0". 898 * 899 * For: float-to-int, int-to-float 900 * 901 * On entry: 902 * r0 = target dalvik register address 903 * r1 = src dalvik register address 904 */ 905 /* unop vA, vB */ 906 flds s0, [r1] @ s0<- vB 907 fsitos s1, s0 @ s1<- op s0 908 fsts s1, [r0] @ vA<- s1 909 bx lr 910 911 912/* ------------------------------ */ 913 .balign 4 914 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP 915dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP: 916/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */ 917 /* 918 * Compare two floating-point values. Puts 0, 1, or -1 into the 919 * destination register based on the results of the comparison. 920 * 921 * int compare(x, y) { 922 * if (x == y) { 923 * return 0; 924 * } else if (x < y) { 925 * return -1; 926 * } else if (x > y) { 927 * return 1; 928 * } else { 929 * return 1; 930 * } 931 * } 932 * 933 * On entry: 934 * r0 = &op1 [vBB] 935 * r1 = &op2 [vCC] 936 */ 937 /* op vAA, vBB, vCC */ 938 fldd d0, [r0] @ d0<- vBB 939 fldd d1, [r1] @ d1<- vCC 940 fcmpd d0, d1 @ compare (vBB, vCC) 941 mov r0, #1 @ r0<- 1 (default) 942 fmstat @ export status flags 943 mvnmi r0, #0 @ (less than) r0<- -1 944 moveq r0, #0 @ (equal) r0<- 0 945 bx lr 946 947/* ------------------------------ */ 948 .balign 4 949 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP 950dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP: 951/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */ 952 /* 953 * Compare two floating-point values. Puts 0, 1, or -1 into the 954 * destination register based on the results of the comparison. 955 * 956 * int compare(x, y) { 957 * if (x == y) { 958 * return 0; 959 * } else if (x > y) { 960 * return 1; 961 * } else if (x < y) { 962 * return -1; 963 * } else { 964 * return -1; 965 * } 966 * } 967 * On entry: 968 * r0 = &op1 [vBB] 969 * r1 = &op2 [vCC] 970 */ 971 /* op vAA, vBB, vCC */ 972 fldd d0, [r0] @ d0<- vBB 973 fldd d1, [r1] @ d1<- vCC 974 fcmped d0, d1 @ compare (vBB, vCC) 975 mvn r0, #0 @ r0<- -1 (default) 976 fmstat @ export status flags 977 movgt r0, #1 @ (greater than) r0<- 1 978 moveq r0, #0 @ (equal) r0<- 0 979 bx lr 980 981/* ------------------------------ */ 982 .balign 4 983 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP 984dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP: 985/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */ 986 /* 987 * Compare two floating-point values. Puts 0, 1, or -1 into the 988 * destination register based on the results of the comparison. 989 * 990 * int compare(x, y) { 991 * if (x == y) { 992 * return 0; 993 * } else if (x < y) { 994 * return -1; 995 * } else if (x > y) { 996 * return 1; 997 * } else { 998 * return 1; 999 * } 1000 * } 1001 * On entry: 1002 * r0 = &op1 [vBB] 1003 * r1 = &op2 [vCC] 1004 */ 1005 /* op vAA, vBB, vCC */ 1006 flds s0, [r0] @ d0<- vBB 1007 flds s1, [r1] @ d1<- vCC 1008 fcmps s0, s1 @ compare (vBB, vCC) 1009 mov r0, #1 @ r0<- 1 (default) 1010 fmstat @ export status flags 1011 mvnmi r0, #0 @ (less than) r0<- -1 1012 moveq r0, #0 @ (equal) r0<- 0 1013 bx lr 1014 1015/* ------------------------------ */ 1016 .balign 4 1017 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP 1018dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP: 1019/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */ 1020 /* 1021 * Compare two floating-point values. Puts 0, 1, or -1 into the 1022 * destination register based on the results of the comparison. 1023 * 1024 * int compare(x, y) { 1025 * if (x == y) { 1026 * return 0; 1027 * } else if (x > y) { 1028 * return 1; 1029 * } else if (x < y) { 1030 * return -1; 1031 * } else { 1032 * return -1; 1033 * } 1034 * } 1035 * On entry: 1036 * r0 = &op1 [vBB] 1037 * r1 = &op2 [vCC] 1038 */ 1039 /* op vAA, vBB, vCC */ 1040 flds s0, [r0] @ d0<- vBB 1041 flds s1, [r1] @ d1<- vCC 1042 fcmps s0, s1 @ compare (vBB, vCC) 1043 mvn r0, #0 @ r0<- -1 (default) 1044 fmstat @ export status flags 1045 movgt r0, #1 @ (greater than) r0<- 1 1046 moveq r0, #0 @ (equal) r0<- 0 1047 bx lr 1048 1049/* ------------------------------ */ 1050 .balign 4 1051 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP 1052dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP: 1053/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */ 1054 /* 1055 * 64-bit floating point vfp sqrt operation. 1056 * If the result is a NaN, bail out to library code to do 1057 * the right thing. 1058 * 1059 * On entry: 1060 * r2 src addr of op1 1061 * On exit: 1062 * r0,r1 = res 1063 */ 1064 fldd d0, [r2] 1065 fsqrtd d1, d0 1066 fcmpd d1, d1 1067 fmstat 1068 fmrrd r0, r1, d1 1069 bxeq lr @ Result OK - return 1070 ldr r2, .Lsqrt 1071 fmrrd r0, r1, d0 @ reload orig operand 1072 bx r2 @ tail call to sqrt library routine 1073 1074.Lsqrt: 1075 .word sqrt 1076 1077/* ------------------------------ */ 1078 .balign 4 1079 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON 1080dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON: 1081/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */ 1082 /* 1083 * Throw an exception from JIT'ed code. 1084 * On entry: 1085 * r0 Dalvik PC that raises the exception 1086 */ 1087 b .LhandleException 1088 1089/* ------------------------------ */ 1090 .balign 4 1091 .global dvmCompiler_TEMPLATE_MEM_OP_DECODE 1092dvmCompiler_TEMPLATE_MEM_OP_DECODE: 1093/* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */ 1094#if defined(WITH_SELF_VERIFICATION) 1095 /* 1096 * This handler encapsulates heap memory ops for selfVerification mode. 1097 * 1098 * The call to the handler is inserted prior to a heap memory operation. 1099 * This handler then calls a function to decode the memory op, and process 1100 * it accordingly. Afterwards, the handler changes the return address to 1101 * skip the memory op so it never gets executed. 1102 */ 1103 vpush {d0-d15} @ save out all fp registers 1104 push {r0-r12,lr} @ save out all registers 1105 ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S 1106 mov r0, lr @ arg0 <- link register 1107 mov r1, sp @ arg1 <- stack pointer 1108 blx r2 @ decode and handle the mem op 1109 pop {r0-r12,lr} @ restore all registers 1110 vpop {d0-d15} @ restore all fp registers 1111 bx lr @ return to compiled code 1112#endif 1113 1114/* ------------------------------ */ 1115 .balign 4 1116 .global dvmCompiler_TEMPLATE_STRING_COMPARETO 1117dvmCompiler_TEMPLATE_STRING_COMPARETO: 1118/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */ 1119 /* 1120 * String's compareTo. 1121 * 1122 * Requires r0/r1 to have been previously checked for null. Will 1123 * return negative if this's string is < comp, 0 if they are the 1124 * same and positive if >. 1125 * 1126 * IMPORTANT NOTE: 1127 * 1128 * This code relies on hard-coded offsets for string objects, and must be 1129 * kept in sync with definitions in UtfString.h. See asm-constants.h 1130 * 1131 * On entry: 1132 * r0: this object pointer 1133 * r1: comp object pointer 1134 * 1135 */ 1136 1137 mov r2, r0 @ this to r2, opening up r0 for return value 1138 subs r0, r2, r1 @ Same? 1139 bxeq lr 1140 1141 ldr r4, [r2, #STRING_FIELDOFF_OFFSET] 1142 ldr r9, [r1, #STRING_FIELDOFF_OFFSET] 1143 ldr r7, [r2, #STRING_FIELDOFF_COUNT] 1144 ldr r10, [r1, #STRING_FIELDOFF_COUNT] 1145 ldr r2, [r2, #STRING_FIELDOFF_VALUE] 1146 ldr r1, [r1, #STRING_FIELDOFF_VALUE] 1147 1148 /* 1149 * At this point, we have: 1150 * value: r2/r1 1151 * offset: r4/r9 1152 * count: r7/r10 1153 * We're going to compute 1154 * r11 <- countDiff 1155 * r10 <- minCount 1156 */ 1157 subs r11, r7, r10 1158 movls r10, r7 1159 1160 /* Now, build pointers to the string data */ 1161 add r2, r2, r4, lsl #1 1162 add r1, r1, r9, lsl #1 1163 /* 1164 * Note: data pointers point to previous element so we can use pre-index 1165 * mode with base writeback. 1166 */ 1167 add r2, #16-2 @ offset to contents[-1] 1168 add r1, #16-2 @ offset to contents[-1] 1169 1170 /* 1171 * At this point we have: 1172 * r2: *this string data 1173 * r1: *comp string data 1174 * r10: iteration count for comparison 1175 * r11: value to return if the first part of the string is equal 1176 * r0: reserved for result 1177 * r3, r4, r7, r8, r9, r12 available for loading string data 1178 */ 1179 1180 subs r10, #2 1181 blt do_remainder2 1182 1183 /* 1184 * Unroll the first two checks so we can quickly catch early mismatch 1185 * on long strings (but preserve incoming alignment) 1186 */ 1187 1188 ldrh r3, [r2, #2]! 1189 ldrh r4, [r1, #2]! 1190 ldrh r7, [r2, #2]! 1191 ldrh r8, [r1, #2]! 1192 subs r0, r3, r4 1193 subeqs r0, r7, r8 1194 bxne lr 1195 cmp r10, #28 1196 bgt do_memcmp16 1197 subs r10, #3 1198 blt do_remainder 1199 1200loopback_triple: 1201 ldrh r3, [r2, #2]! 1202 ldrh r4, [r1, #2]! 1203 ldrh r7, [r2, #2]! 1204 ldrh r8, [r1, #2]! 1205 ldrh r9, [r2, #2]! 1206 ldrh r12,[r1, #2]! 1207 subs r0, r3, r4 1208 subeqs r0, r7, r8 1209 subeqs r0, r9, r12 1210 bxne lr 1211 subs r10, #3 1212 bge loopback_triple 1213 1214do_remainder: 1215 adds r10, #3 1216 beq returnDiff 1217 1218loopback_single: 1219 ldrh r3, [r2, #2]! 1220 ldrh r4, [r1, #2]! 1221 subs r0, r3, r4 1222 bxne lr 1223 subs r10, #1 1224 bne loopback_single 1225 1226returnDiff: 1227 mov r0, r11 1228 bx lr 1229 1230do_remainder2: 1231 adds r10, #2 1232 bne loopback_single 1233 mov r0, r11 1234 bx lr 1235 1236 /* Long string case */ 1237do_memcmp16: 1238 mov r4, lr 1239 ldr lr, .Lmemcmp16 1240 mov r7, r11 1241 add r0, r2, #2 1242 add r1, r1, #2 1243 mov r2, r10 1244 blx lr 1245 cmp r0, #0 1246 bxne r4 1247 mov r0, r7 1248 bx r4 1249 1250.Lmemcmp16: 1251 .word __memcmp16 1252 1253/* ------------------------------ */ 1254 .balign 4 1255 .global dvmCompiler_TEMPLATE_STRING_INDEXOF 1256dvmCompiler_TEMPLATE_STRING_INDEXOF: 1257/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */ 1258 /* 1259 * String's indexOf. 1260 * 1261 * Requires r0 to have been previously checked for null. Will 1262 * return index of match of r1 in r0. 1263 * 1264 * IMPORTANT NOTE: 1265 * 1266 * This code relies on hard-coded offsets for string objects, and must be 1267 * kept in sync wth definitions in UtfString.h See asm-constants.h 1268 * 1269 * On entry: 1270 * r0: string object pointer 1271 * r1: char to match 1272 * r2: Starting offset in string data 1273 */ 1274 1275 ldr r7, [r0, #STRING_FIELDOFF_OFFSET] 1276 ldr r8, [r0, #STRING_FIELDOFF_COUNT] 1277 ldr r0, [r0, #STRING_FIELDOFF_VALUE] 1278 1279 /* 1280 * At this point, we have: 1281 * r0: object pointer 1282 * r1: char to match 1283 * r2: starting offset 1284 * r7: offset 1285 * r8: string length 1286 */ 1287 1288 /* Build pointer to start of string data */ 1289 add r0, #16 1290 add r0, r0, r7, lsl #1 1291 1292 /* Save a copy of starting data in r7 */ 1293 mov r7, r0 1294 1295 /* Clamp start to [0..count] */ 1296 cmp r2, #0 1297 movlt r2, #0 1298 cmp r2, r8 1299 movgt r2, r8 1300 1301 /* Build pointer to start of data to compare and pre-bias */ 1302 add r0, r0, r2, lsl #1 1303 sub r0, #2 1304 1305 /* Compute iteration count */ 1306 sub r8, r2 1307 1308 /* 1309 * At this point we have: 1310 * r0: start of data to test 1311 * r1: chat to compare 1312 * r8: iteration count 1313 * r7: original start of string 1314 * r3, r4, r9, r10, r11, r12 available for loading string data 1315 */ 1316 1317 subs r8, #4 1318 blt indexof_remainder 1319 1320indexof_loop4: 1321 ldrh r3, [r0, #2]! 1322 ldrh r4, [r0, #2]! 1323 ldrh r10, [r0, #2]! 1324 ldrh r11, [r0, #2]! 1325 cmp r3, r1 1326 beq match_0 1327 cmp r4, r1 1328 beq match_1 1329 cmp r10, r1 1330 beq match_2 1331 cmp r11, r1 1332 beq match_3 1333 subs r8, #4 1334 bge indexof_loop4 1335 1336indexof_remainder: 1337 adds r8, #4 1338 beq indexof_nomatch 1339 1340indexof_loop1: 1341 ldrh r3, [r0, #2]! 1342 cmp r3, r1 1343 beq match_3 1344 subs r8, #1 1345 bne indexof_loop1 1346 1347indexof_nomatch: 1348 mov r0, #-1 1349 bx lr 1350 1351match_0: 1352 sub r0, #6 1353 sub r0, r7 1354 asr r0, r0, #1 1355 bx lr 1356match_1: 1357 sub r0, #4 1358 sub r0, r7 1359 asr r0, r0, #1 1360 bx lr 1361match_2: 1362 sub r0, #2 1363 sub r0, r7 1364 asr r0, r0, #1 1365 bx lr 1366match_3: 1367 sub r0, r7 1368 asr r0, r0, #1 1369 bx lr 1370 1371/* ------------------------------ */ 1372 .balign 4 1373 .global dvmCompiler_TEMPLATE_INTERPRET 1374dvmCompiler_TEMPLATE_INTERPRET: 1375/* File: armv5te/TEMPLATE_INTERPRET.S */ 1376 /* 1377 * This handler transfers control to the interpeter without performing 1378 * any lookups. It may be called either as part of a normal chaining 1379 * operation, or from the transition code in header.S. We distinquish 1380 * the two cases by looking at the link register. If called from a 1381 * translation chain, it will point to the chaining Dalvik PC -3. 1382 * On entry: 1383 * lr - if NULL: 1384 * r1 - the Dalvik PC to begin interpretation. 1385 * else 1386 * [lr, #3] contains Dalvik PC to begin interpretation 1387 * rGLUE - pointer to interpState 1388 * rFP - Dalvik frame pointer 1389 */ 1390 cmp lr, #0 1391#if defined(WORKAROUND_CORTEX_A9_745320) 1392 /* Don't use conditional loads if the HW defect exists */ 1393 beq 101f 1394 ldr r1,[lr, #3] 1395101: 1396#else 1397 ldrne r1,[lr, #3] 1398#endif 1399 ldr r2, .LinterpPunt 1400 mov r0, r1 @ set Dalvik PC 1401 bx r2 1402 @ doesn't return 1403 1404.LinterpPunt: 1405 .word dvmJitToInterpPunt 1406 1407/* ------------------------------ */ 1408 .balign 4 1409 .global dvmCompiler_TEMPLATE_MONITOR_ENTER 1410dvmCompiler_TEMPLATE_MONITOR_ENTER: 1411/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */ 1412 /* 1413 * Call out to the runtime to lock an object. Because this thread 1414 * may have been suspended in THREAD_MONITOR state and the Jit's 1415 * translation cache subsequently cleared, we cannot return directly. 1416 * Instead, unconditionally transition to the interpreter to resume. 1417 * 1418 * On entry: 1419 * r0 - self pointer 1420 * r1 - the object (which has already been null-checked by the caller 1421 * r4 - the Dalvik PC of the following instruction. 1422 */ 1423 ldr r2, .LdvmLockObject 1424 mov r3, #0 @ Record that we're not returning 1425 str r3, [r0, #offThread_inJitCodeCache] 1426 blx r2 @ dvmLockObject(self, obj) 1427 @ refresh Jit's on/off status 1428 ldr r0, [rGLUE, #offGlue_ppJitProfTable] 1429 ldr r0, [r0] 1430 ldr r2, .LdvmJitToInterpNoChain 1431 str r0, [rGLUE, #offGlue_pJitProfTable] 1432 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1433#if defined(WITH_JIT_TUNING) 1434 mov r0, #kHeavyweightMonitor 1435#endif 1436 bx r2 1437 1438/* ------------------------------ */ 1439 .balign 4 1440 .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG 1441dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG: 1442/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */ 1443 /* 1444 * To support deadlock prediction, this version of MONITOR_ENTER 1445 * will always call the heavyweight dvmLockObject, check for an 1446 * exception and then bail out to the interpreter. 1447 * 1448 * On entry: 1449 * r0 - self pointer 1450 * r1 - the object (which has already been null-checked by the caller 1451 * r4 - the Dalvik PC of the following instruction. 1452 * 1453 */ 1454 ldr r2, .LdvmLockObject 1455 mov r3, #0 @ Record that we're not returning 1456 str r3, [r0, #offThread_inJitCodeCache] 1457 blx r2 @ dvmLockObject(self, obj) 1458 @ refresh Jit's on/off status & test for exception 1459 ldr r0, [rGLUE, #offGlue_ppJitProfTable] 1460 ldr r1, [rGLUE, #offGlue_self] 1461 ldr r0, [r0] 1462 ldr r1, [r1, #offThread_exception] 1463 str r0, [rGLUE, #offGlue_pJitProfTable] 1464 cmp r1, #0 1465 beq 1f 1466 ldr r2, .LhandleException 1467 sub r0, r4, #2 @ roll dPC back to this monitor instruction 1468 bx r2 14691: 1470 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1471#if defined(WITH_JIT_TUNING) 1472 mov r0, #kHeavyweightMonitor 1473#endif 1474 ldr pc, .LdvmJitToInterpNoChain 1475 1476/* ------------------------------ */ 1477 .balign 4 1478 .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING 1479dvmCompiler_TEMPLATE_PERIODIC_PROFILING: 1480/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */ 1481 /* 1482 * Increment profile counter for this trace, and decrement 1483 * sample counter. If sample counter goes below zero, turn 1484 * off profiling. 1485 * 1486 * On entry 1487 * (lr-11) is address of pointer to counter. Note: the counter 1488 * actually exists 10 bytes before the return target, but because 1489 * we are arriving from thumb mode, lr will have its low bit set. 1490 */ 1491 ldr r0, [lr,#-11] 1492 ldr r1, [rGLUE, #offGlue_pProfileCountdown] 1493 ldr r2, [r0] @ get counter 1494 ldr r3, [r1] @ get countdown timer 1495 add r2, #1 1496 subs r2, #1 1497 blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling 1498 str r2, [r0] 1499 str r3, [r1] 1500 bx lr 1501 1502.LTEMPLATE_PERIODIC_PROFILING_disable_profiling: 1503 mov r4, lr @ preserve lr 1504 ldr r0, .LdvmJitTraceProfilingOff 1505 blx r0 1506 bx r4 1507 1508/* ------------------------------ */ 1509 .balign 4 1510 .global dvmCompiler_TEMPLATE_RETURN_PROF 1511dvmCompiler_TEMPLATE_RETURN_PROF: 1512/* File: armv5te/TEMPLATE_RETURN_PROF.S */ 1513#define TEMPLATE_INLINE_PROFILING 1514/* File: armv5te/TEMPLATE_RETURN.S */ 1515 /* 1516 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 1517 * If the stored value in returnAddr 1518 * is non-zero, the caller is compiled by the JIT thus return to the 1519 * address in the code cache following the invoke instruction. Otherwise 1520 * return to the special dvmJitToInterpNoChain entry point. 1521 */ 1522#if defined(TEMPLATE_INLINE_PROFILING) 1523 stmfd sp!, {r0-r2,lr} @ preserve live registers 1524 mov r0, r6 1525 @ r0=rGlue 1526 mov lr, pc 1527 ldr pc, .LdvmFastJavaMethodTraceExit 1528 ldmfd sp!, {r0-r2,lr} @ restore live registers 1529#endif 1530 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 1531 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 1532 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 1533 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 1534#if !defined(WITH_SELF_VERIFICATION) 1535 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 1536#else 1537 mov r9, #0 @ disable chaining 1538#endif 1539 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 1540 @ r2<- method we're returning to 1541 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1542 cmp r2, #0 @ break frame? 1543#if !defined(WITH_SELF_VERIFICATION) 1544 beq 1f @ bail to interpreter 1545#else 1546 blxeq lr @ punt to interpreter and compare state 1547#endif 1548 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S 1549 mov rFP, r10 @ publish new FP 1550 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 1551 ldr r8, [r8] @ r8<- suspendCount 1552 1553 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 1554 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 1555 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 1556 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 1557 str r0, [rGLUE, #offGlue_methodClassDex] 1558 cmp r8, #0 @ check the suspendCount 1559 movne r9, #0 @ clear the chaining cell address 1560 str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not 1561 cmp r9, #0 @ chaining cell exists? 1562 blxne r9 @ jump to the chaining cell 1563#if defined(WITH_JIT_TUNING) 1564 mov r0, #kCallsiteInterpreted 1565#endif 1566 mov pc, r1 @ callsite is interpreted 15671: 1568 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE() 1569 ldr r2, .LdvmMterpStdBail @ defined in footer.S 1570 mov r1, #0 @ changeInterp = false 1571 mov r0, rGLUE @ Expecting rGLUE in r0 1572 blx r2 @ exit the interpreter 1573 1574#undef TEMPLATE_INLINE_PROFILING 1575 1576/* ------------------------------ */ 1577 .balign 4 1578 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF 1579dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF: 1580/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */ 1581#define TEMPLATE_INLINE_PROFILING 1582/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 1583 /* 1584 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 1585 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 1586 * runtime-resolved callee. 1587 */ 1588 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 1589 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 1590 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 1591 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 1592 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 1593 add r3, r1, #1 @ Thumb addr is odd 1594 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1595 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1596 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1597 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 1598 ldr r8, [r8] @ r8<- suspendCount (int) 1599 cmp r10, r9 @ bottom < interpStackEnd? 1600 bxlo lr @ return to raise stack overflow excep. 1601 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1602 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 1603 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 1604 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1605 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1606 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 1607 1608 1609 @ set up newSaveArea 1610 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1611 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1612 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1613 cmp r8, #0 @ suspendCount != 0 1614 bxne lr @ bail to the interpreter 1615 tst r10, #ACC_NATIVE 1616#if !defined(WITH_SELF_VERIFICATION) 1617 bne .LinvokeNative 1618#else 1619 bxne lr @ bail to the interpreter 1620#endif 1621 1622 ldr r10, .LdvmJitToInterpTraceSelectNoChain 1623 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 1624 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 1625 1626 @ Update "glue" values for the new method 1627 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 1628 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 1629 mov rFP, r1 @ fp = newFp 1630 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 1631#if defined(TEMPLATE_INLINE_PROFILING) 1632 stmfd sp!, {r0-r3} @ preserve r0-r3 1633 mov r1, r6 1634 @ r0=methodToCall, r1=rGlue 1635 mov lr, pc 1636 ldr pc, .LdvmFastMethodTraceEnter 1637 ldmfd sp!, {r0-r3} @ restore r0-r3 1638#endif 1639 1640 @ Start executing the callee 1641#if defined(WITH_JIT_TUNING) 1642 mov r0, #kInlineCacheMiss 1643#endif 1644 mov pc, r10 @ dvmJitToInterpTraceSelectNoChain 1645 1646#undef TEMPLATE_INLINE_PROFILING 1647 1648/* ------------------------------ */ 1649 .balign 4 1650 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF 1651dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF: 1652/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */ 1653#define TEMPLATE_INLINE_PROFILING 1654/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 1655 /* 1656 * For monomorphic callsite, setup the Dalvik frame and return to the 1657 * Thumb code through the link register to transfer control to the callee 1658 * method through a dedicated chaining cell. 1659 */ 1660 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize 1661 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize 1662 @ methodToCall is guaranteed to be non-native 1663.LinvokeChainProf: 1664 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 1665 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 1666 add r3, r1, #1 @ Thumb addr is odd 1667 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1668 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1669 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1670 add r12, lr, #2 @ setup the punt-to-interp address 1671 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 1672 ldr r8, [r8] @ r8<- suspendCount (int) 1673 cmp r10, r9 @ bottom < interpStackEnd? 1674 bxlo r12 @ return to raise stack overflow excep. 1675 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1676 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 1677 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1678 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1679 1680 @ set up newSaveArea 1681 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1682 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1683 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1684 cmp r8, #0 @ suspendCount != 0 1685 bxne r12 @ bail to the interpreter 1686 1687 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 1688 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 1689 1690 @ Update "glue" values for the new method 1691 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 1692 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 1693 mov rFP, r1 @ fp = newFp 1694 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 1695#if defined(TEMPLATE_INLINE_PROFILING) 1696 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers 1697 mov r1, r6 1698 @ r0=methodToCall, r1=rGlue 1699 mov lr, pc 1700 ldr pc, .LdvmFastMethodTraceEnter 1701 ldmfd sp!, {r0-r2,lr} @ restore registers 1702#endif 1703 1704 bx lr @ return to the callee-chaining cell 1705 1706#undef TEMPLATE_INLINE_PROFILING 1707 1708/* ------------------------------ */ 1709 .balign 4 1710 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF 1711dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF: 1712/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */ 1713#define TEMPLATE_INLINE_PROFILING 1714/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 1715 /* 1716 * For polymorphic callsite, check whether the cached class pointer matches 1717 * the current one. If so setup the Dalvik frame and return to the 1718 * Thumb code through the link register to transfer control to the callee 1719 * method through a dedicated chaining cell. 1720 * 1721 * The predicted chaining cell is declared in ArmLIR.h with the 1722 * following layout: 1723 * 1724 * typedef struct PredictedChainingCell { 1725 * u4 branch; 1726 * const ClassObject *clazz; 1727 * const Method *method; 1728 * u4 counter; 1729 * } PredictedChainingCell; 1730 * 1731 * Upon returning to the callsite: 1732 * - lr : to branch to the chaining cell 1733 * - lr+2: to punt to the interpreter 1734 * - lr+4: to fully resolve the callee and may rechain. 1735 * r3 <- class 1736 * r9 <- counter 1737 */ 1738 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 1739 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 1740 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 1741 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 1742 ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount 1743 cmp r3, r8 @ predicted class == actual class? 1744#if defined(WITH_JIT_TUNING) 1745 ldr r7, .LdvmICHitCount 1746#if defined(WORKAROUND_CORTEX_A9_745320) 1747 /* Don't use conditional loads if the HW defect exists */ 1748 bne 101f 1749 ldr r10, [r7, #0] 1750101: 1751#else 1752 ldreq r10, [r7, #0] 1753#endif 1754 add r10, r10, #1 1755 streq r10, [r7, #0] 1756#endif 1757 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 1758 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 1759 beq .LinvokeChainProf @ predicted chain is valid 1760 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 1761 cmp r8, #0 @ initialized class or not 1762 moveq r1, #0 1763 subne r1, r9, #1 @ count-- 1764 strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState 1765 add lr, lr, #4 @ return to fully-resolve landing pad 1766 /* 1767 * r1 <- count 1768 * r2 <- &predictedChainCell 1769 * r3 <- this->class 1770 * r4 <- dPC 1771 * r7 <- this->class->vtable 1772 */ 1773 bx lr 1774 1775#undef TEMPLATE_INLINE_PROFILING 1776 1777/* ------------------------------ */ 1778 .balign 4 1779 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF 1780dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF: 1781/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */ 1782#define TEMPLATE_INLINE_PROFILING 1783/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 1784 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 1785 @ r7 = methodToCall->registersSize 1786 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 1787 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 1788 add r3, r1, #1 @ Thumb addr is odd 1789 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1790 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1791 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1792 ldr r8, [r8] @ r3<- suspendCount (int) 1793 cmp r10, r9 @ bottom < interpStackEnd? 1794 bxlo lr @ return to raise stack overflow excep. 1795 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1796 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1797 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1798 1799 @ set up newSaveArea 1800 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1801 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1802 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1803 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1804 cmp r8, #0 @ suspendCount != 0 1805 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 1806#if !defined(WITH_SELF_VERIFICATION) 1807 bxne lr @ bail to the interpreter 1808#else 1809 bx lr @ bail to interpreter unconditionally 1810#endif 1811 1812 @ go ahead and transfer control to the native code 1813 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 1814 mov r2, #0 1815 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 1816 str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache 1817 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1818 @ newFp->localRefCookie=top 1819 mov r9, r3 @ r9<- glue->self (preserve) 1820 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1821 1822 mov r2, r0 @ r2<- methodToCall 1823 mov r0, r1 @ r0<- newFP 1824 add r1, rGLUE, #offGlue_retval @ r1<- &retval 1825#if defined(TEMPLATE_INLINE_PROFILING) 1826 @ r2=methodToCall, r6=rGLUE 1827 stmfd sp!, {r2,r6} @ to be consumed after JNI return 1828 stmfd sp!, {r0-r3} @ preserve r0-r3 1829 mov r0, r2 1830 mov r1, r6 1831 @ r0=JNIMethod, r1=rGlue 1832 mov lr, pc 1833 ldr pc, .LdvmFastMethodTraceEnter 1834 ldmfd sp!, {r0-r3} @ restore r0-r3 1835#endif 1836 1837 blx r8 @ off to the native code 1838 1839#if defined(TEMPLATE_INLINE_PROFILING) 1840 ldmfd sp!, {r0-r1} @ restore r2 and r6 1841 @ r0=JNIMethod, r1=rGlue 1842 mov lr, pc 1843 ldr pc, .LdvmFastNativeMethodTraceExit 1844#endif 1845 @ native return; r9=self, r10=newSaveArea 1846 @ equivalent to dvmPopJniLocals 1847 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1848 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1849 ldr r1, [r9, #offThread_exception] @ check for exception 1850 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 1851 cmp r1, #0 @ null? 1852 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 1853 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1854 1855 @ r0 = dalvikCallsitePC 1856 bne .LhandleException @ no, handle exception 1857 1858 str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly 1859 cmp r2, #0 @ return chaining cell still exists? 1860 bxne r2 @ yes - go ahead 1861 1862 @ continue executing the next instruction through the interpreter 1863 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1864 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1865#if defined(WITH_JIT_TUNING) 1866 mov r0, #kCallsiteInterpreted 1867#endif 1868 mov pc, r1 1869 1870#undef TEMPLATE_INLINE_PROFILING 1871 1872 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1873/* File: armv5te/footer.S */ 1874/* 1875 * =========================================================================== 1876 * Common subroutines and data 1877 * =========================================================================== 1878 */ 1879 1880 .text 1881 .align 2 1882.LinvokeNative: 1883 @ Prep for the native call 1884 @ r1 = newFP, r0 = methodToCall 1885 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1886 mov r2, #0 1887 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 1888 str r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache 1889 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 1890 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1891 @ newFp->localRefCookie=top 1892 mov r9, r3 @ r9<- glue->self (preserve) 1893 ldr lr, [rGLUE, #offGlue_pInterpBreak] 1894 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1895 1896 mov r2, r0 @ r2<- methodToCall 1897 ldr lr, [lr] @ lr<- set of active profilers 1898 mov r0, r1 @ r0<- newFP 1899 add r1, rGLUE, #offGlue_retval @ r1<- &retval 1900 ands lr, #kSubModeMethodTrace 1901 beq 121f @ hop if not profiling 1902 @ r2: methodToCall, r6: rGLUE 1903 stmfd sp!, {r2,r6} 1904 stmfd sp!, {r0-r3} 1905 mov r0, r2 1906 mov r1, r6 1907 mov lr, pc 1908 ldr pc, .LdvmFastMethodTraceEnter 1909 ldmfd sp!, {r0-r3} 1910 1911 mov lr, pc 1912 ldr pc, [r2, #offMethod_nativeFunc] 1913 1914 ldmfd sp!, {r0-r1} 1915 mov lr, pc 1916 ldr pc, .LdvmFastNativeMethodTraceExit 1917 b 212f 1918121: 1919 mov lr, pc 1920 ldr pc, [r2, #offMethod_nativeFunc] 1921212: 1922 @ Refresh Jit's on/off status 1923 ldr r3, [rGLUE, #offGlue_ppJitProfTable] 1924 1925 @ native return; r9=self, r10=newSaveArea 1926 @ equivalent to dvmPopJniLocals 1927 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1928 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1929 ldr r1, [r9, #offThread_exception] @ check for exception 1930 ldr r3, [r3] @ r1 <- pointer to Jit profile table 1931 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 1932 cmp r1, #0 @ null? 1933 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 1934 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC 1935 str r3, [rGLUE, #offGlue_pJitProfTable] @ cache current JitProfTable 1936 1937 @ r0 = dalvikCallsitePC 1938 bne .LhandleException @ no, handle exception 1939 1940 str r2, [r9, #offThread_inJitCodeCache] @ set the new mode 1941 cmp r2, #0 @ return chaining cell still exists? 1942 bxne r2 @ yes - go ahead 1943 1944 @ continue executing the next instruction through the interpreter 1945 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1946 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1947#if defined(WITH_JIT_TUNING) 1948 mov r0, #kCallsiteInterpreted 1949#endif 1950 mov pc, r1 1951 1952/* 1953 * On entry: 1954 * r0 Faulting Dalvik PC 1955 */ 1956.LhandleException: 1957#if defined(WITH_SELF_VERIFICATION) 1958 ldr pc, .LdeadFood @ should not see this under self-verification mode 1959.LdeadFood: 1960 .word 0xdeadf00d 1961#endif 1962 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1963 mov r2, #0 1964 str r2, [r3, #offThread_inJitCodeCache] @ in interpreter land 1965 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1966 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1967 mov rPC, r0 @ reload the faulting Dalvik address 1968 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown 1969 1970 .align 2 1971.LdvmAsmInstructionStart: 1972 .word dvmAsmInstructionStart 1973.LdvmJitToInterpNoChainNoProfile: 1974 .word dvmJitToInterpNoChainNoProfile 1975.LdvmJitToInterpTraceSelectNoChain: 1976 .word dvmJitToInterpTraceSelectNoChain 1977.LdvmJitToInterpNoChain: 1978 .word dvmJitToInterpNoChain 1979.LdvmMterpStdBail: 1980 .word dvmMterpStdBail 1981.LdvmMterpCommonExceptionThrown: 1982 .word dvmMterpCommonExceptionThrown 1983.LdvmLockObject: 1984 .word dvmLockObject 1985.LdvmJitTraceProfilingOff: 1986 .word dvmJitTraceProfilingOff 1987#if defined(WITH_JIT_TUNING) 1988.LdvmICHitCount: 1989 .word gDvmICHitCount 1990#endif 1991#if defined(WITH_SELF_VERIFICATION) 1992.LdvmSelfVerificationMemOpDecode: 1993 .word dvmSelfVerificationMemOpDecode 1994#endif 1995.LdvmFastMethodTraceEnter: 1996 .word dvmFastMethodTraceEnter 1997.LdvmFastNativeMethodTraceExit: 1998 .word dvmFastNativeMethodTraceExit 1999.LdvmFastJavaMethodTraceExit: 2000 .word dvmFastJavaMethodTraceExit 2001.L__aeabi_cdcmple: 2002 .word __aeabi_cdcmple 2003.L__aeabi_cfcmple: 2004 .word __aeabi_cfcmple 2005 2006 .global dmvCompilerTemplateEnd 2007dmvCompilerTemplateEnd: 2008 2009#endif /* WITH_JIT */ 2010 2011