CompilerTemplateAsm-armv5te.S revision 9a3147c7412f4794434b4c2604aa2ba784867774
1/* 2 * This file was generated automatically by gen-template.py for 'armv5te'. 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 rSELF thread 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 rSELF 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/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=rSELF 173 mov lr, pc 174 ldr pc, .LdvmFastMethodTraceExit 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 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 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 cmp r2, #0 @ break frame? 189#if !defined(WITH_SELF_VERIFICATION) 190 beq 1f @ bail to interpreter 191#else 192 blxeq lr @ punt to interpreter and compare state 193#endif 194 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S 195 mov rFP, r10 @ publish new FP 196 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 197 198 str r2, [rSELF, #offThread_method]@ self->method = newSave->method 199 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 200 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp 201 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 202 str r0, [rSELF, #offThread_methodClassDex] 203 cmp r8, #0 @ check the break flags 204 movne r9, #0 @ clear the chaining cell address 205 str r9, [rSELF, #offThread_inJitCodeCache] @ in code cache or not 206 cmp r9, #0 @ chaining cell exists? 207 blxne r9 @ jump to the chaining cell 208#if defined(WITH_JIT_TUNING) 209 mov r0, #kCallsiteInterpreted 210#endif 211 mov pc, r1 @ callsite is interpreted 2121: 213 stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF() 214 ldr r2, .LdvmMterpStdBail @ defined in footer.S 215 mov r0, rSELF @ Expecting rSELF in r0 216 blx r2 @ exit the interpreter 217 218/* ------------------------------ */ 219 .balign 4 220 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT 221dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT: 222/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 223 /* 224 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 225 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 226 * runtime-resolved callee. 227 */ 228 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 229 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 230 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 231 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 232 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 233 add r3, r1, #1 @ Thumb addr is odd 234 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 235 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 236 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 237 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 238 cmp r10, r9 @ bottom < interpStackEnd? 239 bxlo lr @ return to raise stack overflow excep. 240 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 241 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 242 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 243 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 244 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 245 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 246 247 248 @ set up newSaveArea 249 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 250 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 251 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 252 cmp r8, #0 @ breakFlags != 0 253 bxne lr @ bail to the interpreter 254 tst r10, #ACC_NATIVE 255#if !defined(WITH_SELF_VERIFICATION) 256 bne .LinvokeNative 257#else 258 bxne lr @ bail to the interpreter 259#endif 260 261 ldr r10, .LdvmJitToInterpTraceSelectNoChain 262 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 263 264 @ Update "thread" values for the new method 265 str r0, [rSELF, #offThread_method] @ self->method = methodToCall 266 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ... 267 mov rFP, r1 @ fp = newFp 268 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 269#if defined(TEMPLATE_INLINE_PROFILING) 270 stmfd sp!, {r0-r3} @ preserve r0-r3 271 mov r1, r6 272 @ r0=methodToCall, r1=rSELF 273 mov lr, pc 274 ldr pc, .LdvmFastMethodTraceEnter 275 ldmfd sp!, {r0-r3} @ restore r0-r3 276#endif 277 278 @ Start executing the callee 279#if defined(WITH_JIT_TUNING) 280 mov r0, #kInlineCacheMiss 281#endif 282 mov pc, r10 @ dvmJitToInterpTraceSelectNoChain 283 284/* ------------------------------ */ 285 .balign 4 286 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN 287dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN: 288/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 289 /* 290 * For monomorphic callsite, setup the Dalvik frame and return to the 291 * Thumb code through the link register to transfer control to the callee 292 * method through a dedicated chaining cell. 293 */ 294 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize 295 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize 296 @ methodToCall is guaranteed to be non-native 297.LinvokeChain: 298 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 299 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 300 add r3, r1, #1 @ Thumb addr is odd 301 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 302 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 303 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 304 add r12, lr, #2 @ setup the punt-to-interp address 305 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 306 cmp r10, r9 @ bottom < interpStackEnd? 307 bxlo r12 @ return to raise stack overflow excep. 308 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 309 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 310 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 311 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 312 313 @ set up newSaveArea 314 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 315 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 316 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 317 cmp r8, #0 @ breakFlags != 0 318 bxne r12 @ bail to the interpreter 319 320 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 321 322 @ Update "thread" values for the new method 323 str r0, [rSELF, #offThread_method] @ self->method = methodToCall 324 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ... 325 mov rFP, r1 @ fp = newFp 326 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 327#if defined(TEMPLATE_INLINE_PROFILING) 328 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers 329 mov r1, r6 330 @ r0=methodToCall, r1=rSELF 331 mov lr, pc 332 ldr pc, .LdvmFastMethodTraceEnter 333 ldmfd sp!, {r0-r2,lr} @ restore registers 334#endif 335 336 bx lr @ return to the callee-chaining cell 337 338/* ------------------------------ */ 339 .balign 4 340 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN 341dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN: 342/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 343 /* 344 * For polymorphic callsite, check whether the cached class pointer matches 345 * the current one. If so setup the Dalvik frame and return to the 346 * Thumb code through the link register to transfer control to the callee 347 * method through a dedicated chaining cell. 348 * 349 * The predicted chaining cell is declared in ArmLIR.h with the 350 * following layout: 351 * 352 * typedef struct PredictedChainingCell { 353 * u4 branch; 354 * const ClassObject *clazz; 355 * const Method *method; 356 * u4 counter; 357 * } PredictedChainingCell; 358 * 359 * Upon returning to the callsite: 360 * - lr : to branch to the chaining cell 361 * - lr+2: to punt to the interpreter 362 * - lr+4: to fully resolve the callee and may rechain. 363 * r3 <- class 364 * r9 <- counter 365 */ 366 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 367 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 368 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 369 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 370 ldr r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount 371 cmp r3, r8 @ predicted class == actual class? 372#if defined(WITH_JIT_TUNING) 373 ldr r7, .LdvmICHitCount 374#if defined(WORKAROUND_CORTEX_A9_745320) 375 /* Don't use conditional loads if the HW defect exists */ 376 bne 101f 377 ldr r10, [r7, #0] 378101: 379#else 380 ldreq r10, [r7, #0] 381#endif 382 add r10, r10, #1 383 streq r10, [r7, #0] 384#endif 385 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 386 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 387 beq .LinvokeChain @ predicted chain is valid 388 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 389 cmp r8, #0 @ initialized class or not 390 moveq r1, #0 391 subne r1, r9, #1 @ count-- 392 strne r1, [rSELF, #offThread_icRechainCount] @ write back to thread 393 add lr, lr, #4 @ return to fully-resolve landing pad 394 /* 395 * r1 <- count 396 * r2 <- &predictedChainCell 397 * r3 <- this->class 398 * r4 <- dPC 399 * r7 <- this->class->vtable 400 */ 401 bx lr 402 403/* ------------------------------ */ 404 .balign 4 405 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE 406dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE: 407/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 408 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 409 @ r7 = methodToCall->registersSize 410 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 411 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 412 add r3, r1, #1 @ Thumb addr is odd 413 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 414 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 415 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 416 cmp r10, r9 @ bottom < interpStackEnd? 417 bxlo lr @ return to raise stack overflow excep. 418 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 419 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 420 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 421 422 @ set up newSaveArea 423 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 424 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 425 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 426 cmp r8, #0 @ breakFlags != 0 427 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 428#if !defined(WITH_SELF_VERIFICATION) 429 bxne lr @ bail to the interpreter 430#else 431 bx lr @ bail to interpreter unconditionally 432#endif 433 434 @ go ahead and transfer control to the native code 435 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->... 436 mov r2, #0 437 str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 438 str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache 439 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 440 @ newFp->localRefCookie=top 441 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 442 443 mov r2, r0 @ arg2<- methodToCall 444 mov r0, r1 @ arg0<- newFP 445 add r1, rSELF, #offThread_retval @ arg1<- &retval 446 mov r3, rSELF @ arg3<- self 447#if defined(TEMPLATE_INLINE_PROFILING) 448 @ r2=methodToCall, r6=rSELF 449 stmfd sp!, {r2,r6} @ to be consumed after JNI return 450 stmfd sp!, {r0-r3} @ preserve r0-r3 451 mov r0, r2 452 mov r1, r6 453 @ r0=JNIMethod, r1=rSELF 454 mov lr, pc 455 ldr pc, .LdvmFastMethodTraceEnter 456 ldmfd sp!, {r0-r3} @ restore r0-r3 457#endif 458 459 blx r8 @ off to the native code 460 461#if defined(TEMPLATE_INLINE_PROFILING) 462 ldmfd sp!, {r0-r1} @ restore r2 and r6 463 @ r0=JNIMethod, r1=rSELF 464 mov lr, pc 465 ldr pc, .LdvmFastNativeMethodTraceExit 466#endif 467 @ native return; r10=newSaveArea 468 @ equivalent to dvmPopJniLocals 469 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 470 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 471 ldr r1, [rSELF, #offThread_exception] @ check for exception 472 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp 473 cmp r1, #0 @ null? 474 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top 475 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 476 477 @ r0 = dalvikCallsitePC 478 bne .LhandleException @ no, handle exception 479 480 str r2, [rSELF, #offThread_inJitCodeCache] @ set the mode properly 481 cmp r2, #0 @ return chaining cell still exists? 482 bxne r2 @ yes - go ahead 483 484 @ continue executing the next instruction through the interpreter 485 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 486 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 487#if defined(WITH_JIT_TUNING) 488 mov r0, #kCallsiteInterpreted 489#endif 490 mov pc, r1 491 492/* ------------------------------ */ 493 .balign 4 494 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE 495dvmCompiler_TEMPLATE_CMPG_DOUBLE: 496/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */ 497/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */ 498 /* 499 * For the JIT: incoming arguments in r0-r1, r2-r3 500 * result in r0 501 * 502 * Compare two floating-point values. Puts 0, 1, or -1 into the 503 * destination register based on the results of the comparison. 504 * 505 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 506 * on what value we'd like to return when one of the operands is NaN. 507 * 508 * See OP_CMPL_FLOAT for an explanation. 509 * 510 * For: cmpl-double, cmpg-double 511 */ 512 /* op vAA, vBB, vCC */ 513 push {r0-r3} @ save operands 514 mov r11, lr @ save return address 515 mov lr, pc 516 ldr pc, .L__aeabi_cdcmple @ PIC way of "bl __aeabi_cdcmple" 517 bhi .LTEMPLATE_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 518 mvncc r0, #0 @ (less than) r1<- -1 519 moveq r0, #0 @ (equal) r1<- 0, trumps less than 520 add sp, #16 @ drop unused operands 521 bx r11 522 523 @ Test for NaN with a second comparison. EABI forbids testing bit 524 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 525 @ make the library call. 526.LTEMPLATE_CMPG_DOUBLE_gt_or_nan: 527 pop {r2-r3} @ restore operands in reverse order 528 pop {r0-r1} @ restore operands in reverse order 529 mov lr, pc 530 ldr pc, .L__aeabi_cdcmple @ r0<- Z set if eq, C clear if < 531 movcc r0, #1 @ (greater than) r1<- 1 532 bxcc r11 533 mov r0, #1 @ r1<- 1 or -1 for NaN 534 bx r11 535 536 537/* ------------------------------ */ 538 .balign 4 539 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE 540dvmCompiler_TEMPLATE_CMPL_DOUBLE: 541/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */ 542 /* 543 * For the JIT: incoming arguments in r0-r1, r2-r3 544 * result in r0 545 * 546 * Compare two floating-point values. Puts 0, 1, or -1 into the 547 * destination register based on the results of the comparison. 548 * 549 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 550 * on what value we'd like to return when one of the operands is NaN. 551 * 552 * See OP_CMPL_FLOAT for an explanation. 553 * 554 * For: cmpl-double, cmpg-double 555 */ 556 /* op vAA, vBB, vCC */ 557 push {r0-r3} @ save operands 558 mov r11, lr @ save return address 559 mov lr, pc 560 ldr pc, .L__aeabi_cdcmple @ PIC way of "bl __aeabi_cdcmple" 561 bhi .LTEMPLATE_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate 562 mvncc r0, #0 @ (less than) r1<- -1 563 moveq r0, #0 @ (equal) r1<- 0, trumps less than 564 add sp, #16 @ drop unused operands 565 bx r11 566 567 @ Test for NaN with a second comparison. EABI forbids testing bit 568 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 569 @ make the library call. 570.LTEMPLATE_CMPL_DOUBLE_gt_or_nan: 571 pop {r2-r3} @ restore operands in reverse order 572 pop {r0-r1} @ restore operands in reverse order 573 mov lr, pc 574 ldr pc, .L__aeabi_cdcmple @ r0<- Z set if eq, C clear if < 575 movcc r0, #1 @ (greater than) r1<- 1 576 bxcc r11 577 mvn r0, #0 @ r1<- 1 or -1 for NaN 578 bx r11 579 580/* ------------------------------ */ 581 .balign 4 582 .global dvmCompiler_TEMPLATE_CMPG_FLOAT 583dvmCompiler_TEMPLATE_CMPG_FLOAT: 584/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */ 585/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */ 586 /* 587 * For the JIT: incoming arguments in r0-r1, r2-r3 588 * result in r0 589 * 590 * Compare two floating-point values. Puts 0, 1, or -1 into the 591 * destination register based on the results of the comparison. 592 * 593 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 594 * on what value we'd like to return when one of the operands is NaN. 595 * 596 * The operation we're implementing is: 597 * if (x == y) 598 * return 0; 599 * else if (x < y) 600 * return -1; 601 * else if (x > y) 602 * return 1; 603 * else 604 * return {-1,1}; // one or both operands was NaN 605 * 606 * The straightforward implementation requires 3 calls to functions 607 * that return a result in r0. We can do it with two calls if our 608 * EABI library supports __aeabi_cfcmple (only one if we want to check 609 * for NaN directly): 610 * check x <= y 611 * if <, return -1 612 * if ==, return 0 613 * check y <= x 614 * if <, return 1 615 * return {-1,1} 616 * 617 * for: cmpl-float, cmpg-float 618 */ 619 /* op vAA, vBB, vCC */ 620 mov r9, r0 @ Save copies - we may need to redo 621 mov r10, r1 622 mov r11, lr @ save return address 623 mov lr, pc 624 ldr pc, .L__aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 625 bhi .LTEMPLATE_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 626 mvncc r0, #0 @ (less than) r0<- -1 627 moveq r0, #0 @ (equal) r0<- 0, trumps less than 628 bx r11 629 @ Test for NaN with a second comparison. EABI forbids testing bit 630 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 631 @ make the library call. 632.LTEMPLATE_CMPG_FLOAT_gt_or_nan: 633 mov r0, r10 @ restore in reverse order 634 mov r1, r9 635 mov lr, pc 636 ldr pc, .L__aeabi_cfcmple @ r0<- Z set if eq, C clear if < 637 movcc r0, #1 @ (greater than) r1<- 1 638 bxcc r11 639 mov r0, #1 @ r1<- 1 or -1 for NaN 640 bx r11 641 642 643/* ------------------------------ */ 644 .balign 4 645 .global dvmCompiler_TEMPLATE_CMPL_FLOAT 646dvmCompiler_TEMPLATE_CMPL_FLOAT: 647/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */ 648 /* 649 * For the JIT: incoming arguments in r0-r1, r2-r3 650 * result in r0 651 * 652 * Compare two floating-point values. Puts 0, 1, or -1 into the 653 * destination register based on the results of the comparison. 654 * 655 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending 656 * on what value we'd like to return when one of the operands is NaN. 657 * 658 * The operation we're implementing is: 659 * if (x == y) 660 * return 0; 661 * else if (x < y) 662 * return -1; 663 * else if (x > y) 664 * return 1; 665 * else 666 * return {-1,1}; // one or both operands was NaN 667 * 668 * The straightforward implementation requires 3 calls to functions 669 * that return a result in r0. We can do it with two calls if our 670 * EABI library supports __aeabi_cfcmple (only one if we want to check 671 * for NaN directly): 672 * check x <= y 673 * if <, return -1 674 * if ==, return 0 675 * check y <= x 676 * if <, return 1 677 * return {-1,1} 678 * 679 * for: cmpl-float, cmpg-float 680 */ 681 /* op vAA, vBB, vCC */ 682 mov r9, r0 @ Save copies - we may need to redo 683 mov r10, r1 684 mov r11, lr @ save return address 685 mov lr, pc 686 ldr pc, .L__aeabi_cfcmple @ cmp <=: C clear if <, Z set if eq 687 bhi .LTEMPLATE_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate 688 mvncc r0, #0 @ (less than) r0<- -1 689 moveq r0, #0 @ (equal) r0<- 0, trumps less than 690 bx r11 691 @ Test for NaN with a second comparison. EABI forbids testing bit 692 @ patterns, and we can't represent 0x7fc00000 in immediate form, so 693 @ make the library call. 694.LTEMPLATE_CMPL_FLOAT_gt_or_nan: 695 mov r0, r10 @ restore in reverse order 696 mov r1, r9 697 mov lr, pc 698 ldr pc, .L__aeabi_cfcmple @ r0<- Z set if eq, C clear if < 699 movcc r0, #1 @ (greater than) r1<- 1 700 bxcc r11 701 mvn r0, #0 @ r1<- 1 or -1 for NaN 702 bx r11 703 704/* ------------------------------ */ 705 .balign 4 706 .global dvmCompiler_TEMPLATE_MUL_LONG 707dvmCompiler_TEMPLATE_MUL_LONG: 708/* File: armv5te/TEMPLATE_MUL_LONG.S */ 709 /* 710 * Signed 64-bit integer multiply. 711 * 712 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 713 * 714 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 715 * WX 716 * x YZ 717 * -------- 718 * ZW ZX 719 * YW YX 720 * 721 * The low word of the result holds ZX, the high word holds 722 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 723 * it doesn't fit in the low 64 bits. 724 * 725 * Unlike most ARM math operations, multiply instructions have 726 * restrictions on using the same register more than once (Rd and Rm 727 * cannot be the same). 728 */ 729 /* mul-long vAA, vBB, vCC */ 730 mul ip, r2, r1 @ ip<- ZxW 731 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 732 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 733 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 734 mov r0,r9 735 mov r1,r10 736 bx lr 737 738/* ------------------------------ */ 739 .balign 4 740 .global dvmCompiler_TEMPLATE_SHL_LONG 741dvmCompiler_TEMPLATE_SHL_LONG: 742/* File: armv5te/TEMPLATE_SHL_LONG.S */ 743 /* 744 * Long integer shift. This is different from the generic 32/64-bit 745 * binary operations because vAA/vBB are 64-bit but vCC (the shift 746 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 747 * 6 bits. 748 */ 749 /* shl-long vAA, vBB, vCC */ 750 and r2, r2, #63 @ r2<- r2 & 0x3f 751 mov r1, r1, asl r2 @ r1<- r1 << r2 752 rsb r3, r2, #32 @ r3<- 32 - r2 753 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 754 subs ip, r2, #32 @ ip<- r2 - 32 755 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 756 mov r0, r0, asl r2 @ r0<- r0 << r2 757 bx lr 758 759/* ------------------------------ */ 760 .balign 4 761 .global dvmCompiler_TEMPLATE_SHR_LONG 762dvmCompiler_TEMPLATE_SHR_LONG: 763/* File: armv5te/TEMPLATE_SHR_LONG.S */ 764 /* 765 * Long integer shift. This is different from the generic 32/64-bit 766 * binary operations because vAA/vBB are 64-bit but vCC (the shift 767 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 768 * 6 bits. 769 */ 770 /* shr-long vAA, vBB, vCC */ 771 and r2, r2, #63 @ r0<- r0 & 0x3f 772 mov r0, r0, lsr r2 @ r0<- r2 >> r2 773 rsb r3, r2, #32 @ r3<- 32 - r2 774 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 775 subs ip, r2, #32 @ ip<- r2 - 32 776 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 777 mov r1, r1, asr r2 @ r1<- r1 >> r2 778 bx lr 779 780/* ------------------------------ */ 781 .balign 4 782 .global dvmCompiler_TEMPLATE_USHR_LONG 783dvmCompiler_TEMPLATE_USHR_LONG: 784/* File: armv5te/TEMPLATE_USHR_LONG.S */ 785 /* 786 * Long integer shift. This is different from the generic 32/64-bit 787 * binary operations because vAA/vBB are 64-bit but vCC (the shift 788 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 789 * 6 bits. 790 */ 791 /* ushr-long vAA, vBB, vCC */ 792 and r2, r2, #63 @ r0<- r0 & 0x3f 793 mov r0, r0, lsr r2 @ r0<- r2 >> r2 794 rsb r3, r2, #32 @ r3<- 32 - r2 795 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 796 subs ip, r2, #32 @ ip<- r2 - 32 797 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 798 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 799 bx lr 800 801/* ------------------------------ */ 802 .balign 4 803 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON 804dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON: 805/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */ 806 /* 807 * Throw an exception from JIT'ed code. 808 * On entry: 809 * r0 Dalvik PC that raises the exception 810 */ 811 b .LhandleException 812 813/* ------------------------------ */ 814 .balign 4 815 .global dvmCompiler_TEMPLATE_MEM_OP_DECODE 816dvmCompiler_TEMPLATE_MEM_OP_DECODE: 817/* File: armv5te/TEMPLATE_MEM_OP_DECODE.S */ 818#if defined(WITH_SELF_VERIFICATION) 819 /* 820 * This handler encapsulates heap memory ops for selfVerification mode. 821 * 822 * The call to the handler is inserted prior to a heap memory operation. 823 * This handler then calls a function to decode the memory op, and process 824 * it accordingly. Afterwards, the handler changes the return address to 825 * skip the memory op so it never gets executed. 826 */ 827 push {r0-r12,lr} @ save out all registers 828 ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S 829 mov r0, lr @ arg0 <- link register 830 mov r1, sp @ arg1 <- stack pointer 831 blx r2 @ decode and handle the mem op 832 pop {r0-r12,lr} @ restore all registers 833 bx lr @ return to compiled code 834#endif 835 836/* ------------------------------ */ 837 .balign 4 838 .global dvmCompiler_TEMPLATE_STRING_COMPARETO 839dvmCompiler_TEMPLATE_STRING_COMPARETO: 840/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */ 841 /* 842 * String's compareTo. 843 * 844 * Requires r0/r1 to have been previously checked for null. Will 845 * return negative if this's string is < comp, 0 if they are the 846 * same and positive if >. 847 * 848 * IMPORTANT NOTE: 849 * 850 * This code relies on hard-coded offsets for string objects, and must be 851 * kept in sync with definitions in UtfString.h. See asm-constants.h 852 * 853 * On entry: 854 * r0: this object pointer 855 * r1: comp object pointer 856 * 857 */ 858 859 mov r2, r0 @ this to r2, opening up r0 for return value 860 subs r0, r2, r1 @ Same? 861 bxeq lr 862 863 ldr r4, [r2, #STRING_FIELDOFF_OFFSET] 864 ldr r9, [r1, #STRING_FIELDOFF_OFFSET] 865 ldr r7, [r2, #STRING_FIELDOFF_COUNT] 866 ldr r10, [r1, #STRING_FIELDOFF_COUNT] 867 ldr r2, [r2, #STRING_FIELDOFF_VALUE] 868 ldr r1, [r1, #STRING_FIELDOFF_VALUE] 869 870 /* 871 * At this point, we have: 872 * value: r2/r1 873 * offset: r4/r9 874 * count: r7/r10 875 * We're going to compute 876 * r11 <- countDiff 877 * r10 <- minCount 878 */ 879 subs r11, r7, r10 880 movls r10, r7 881 882 /* Now, build pointers to the string data */ 883 add r2, r2, r4, lsl #1 884 add r1, r1, r9, lsl #1 885 /* 886 * Note: data pointers point to previous element so we can use pre-index 887 * mode with base writeback. 888 */ 889 add r2, #16-2 @ offset to contents[-1] 890 add r1, #16-2 @ offset to contents[-1] 891 892 /* 893 * At this point we have: 894 * r2: *this string data 895 * r1: *comp string data 896 * r10: iteration count for comparison 897 * r11: value to return if the first part of the string is equal 898 * r0: reserved for result 899 * r3, r4, r7, r8, r9, r12 available for loading string data 900 */ 901 902 subs r10, #2 903 blt do_remainder2 904 905 /* 906 * Unroll the first two checks so we can quickly catch early mismatch 907 * on long strings (but preserve incoming alignment) 908 */ 909 910 ldrh r3, [r2, #2]! 911 ldrh r4, [r1, #2]! 912 ldrh r7, [r2, #2]! 913 ldrh r8, [r1, #2]! 914 subs r0, r3, r4 915 subeqs r0, r7, r8 916 bxne lr 917 cmp r10, #28 918 bgt do_memcmp16 919 subs r10, #3 920 blt do_remainder 921 922loopback_triple: 923 ldrh r3, [r2, #2]! 924 ldrh r4, [r1, #2]! 925 ldrh r7, [r2, #2]! 926 ldrh r8, [r1, #2]! 927 ldrh r9, [r2, #2]! 928 ldrh r12,[r1, #2]! 929 subs r0, r3, r4 930 subeqs r0, r7, r8 931 subeqs r0, r9, r12 932 bxne lr 933 subs r10, #3 934 bge loopback_triple 935 936do_remainder: 937 adds r10, #3 938 beq returnDiff 939 940loopback_single: 941 ldrh r3, [r2, #2]! 942 ldrh r4, [r1, #2]! 943 subs r0, r3, r4 944 bxne lr 945 subs r10, #1 946 bne loopback_single 947 948returnDiff: 949 mov r0, r11 950 bx lr 951 952do_remainder2: 953 adds r10, #2 954 bne loopback_single 955 mov r0, r11 956 bx lr 957 958 /* Long string case */ 959do_memcmp16: 960 mov r4, lr 961 ldr lr, .Lmemcmp16 962 mov r7, r11 963 add r0, r2, #2 964 add r1, r1, #2 965 mov r2, r10 966 blx lr 967 cmp r0, #0 968 bxne r4 969 mov r0, r7 970 bx r4 971 972.Lmemcmp16: 973 .word __memcmp16 974 975/* ------------------------------ */ 976 .balign 4 977 .global dvmCompiler_TEMPLATE_STRING_INDEXOF 978dvmCompiler_TEMPLATE_STRING_INDEXOF: 979/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */ 980 /* 981 * String's indexOf. 982 * 983 * Requires r0 to have been previously checked for null. Will 984 * return index of match of r1 in r0. 985 * 986 * IMPORTANT NOTE: 987 * 988 * This code relies on hard-coded offsets for string objects, and must be 989 * kept in sync wth definitions in UtfString.h See asm-constants.h 990 * 991 * On entry: 992 * r0: string object pointer 993 * r1: char to match 994 * r2: Starting offset in string data 995 */ 996 997 ldr r7, [r0, #STRING_FIELDOFF_OFFSET] 998 ldr r8, [r0, #STRING_FIELDOFF_COUNT] 999 ldr r0, [r0, #STRING_FIELDOFF_VALUE] 1000 1001 /* 1002 * At this point, we have: 1003 * r0: object pointer 1004 * r1: char to match 1005 * r2: starting offset 1006 * r7: offset 1007 * r8: string length 1008 */ 1009 1010 /* Build pointer to start of string data */ 1011 add r0, #16 1012 add r0, r0, r7, lsl #1 1013 1014 /* Save a copy of starting data in r7 */ 1015 mov r7, r0 1016 1017 /* Clamp start to [0..count] */ 1018 cmp r2, #0 1019 movlt r2, #0 1020 cmp r2, r8 1021 movgt r2, r8 1022 1023 /* Build pointer to start of data to compare and pre-bias */ 1024 add r0, r0, r2, lsl #1 1025 sub r0, #2 1026 1027 /* Compute iteration count */ 1028 sub r8, r2 1029 1030 /* 1031 * At this point we have: 1032 * r0: start of data to test 1033 * r1: chat to compare 1034 * r8: iteration count 1035 * r7: original start of string 1036 * r3, r4, r9, r10, r11, r12 available for loading string data 1037 */ 1038 1039 subs r8, #4 1040 blt indexof_remainder 1041 1042indexof_loop4: 1043 ldrh r3, [r0, #2]! 1044 ldrh r4, [r0, #2]! 1045 ldrh r10, [r0, #2]! 1046 ldrh r11, [r0, #2]! 1047 cmp r3, r1 1048 beq match_0 1049 cmp r4, r1 1050 beq match_1 1051 cmp r10, r1 1052 beq match_2 1053 cmp r11, r1 1054 beq match_3 1055 subs r8, #4 1056 bge indexof_loop4 1057 1058indexof_remainder: 1059 adds r8, #4 1060 beq indexof_nomatch 1061 1062indexof_loop1: 1063 ldrh r3, [r0, #2]! 1064 cmp r3, r1 1065 beq match_3 1066 subs r8, #1 1067 bne indexof_loop1 1068 1069indexof_nomatch: 1070 mov r0, #-1 1071 bx lr 1072 1073match_0: 1074 sub r0, #6 1075 sub r0, r7 1076 asr r0, r0, #1 1077 bx lr 1078match_1: 1079 sub r0, #4 1080 sub r0, r7 1081 asr r0, r0, #1 1082 bx lr 1083match_2: 1084 sub r0, #2 1085 sub r0, r7 1086 asr r0, r0, #1 1087 bx lr 1088match_3: 1089 sub r0, r7 1090 asr r0, r0, #1 1091 bx lr 1092 1093/* ------------------------------ */ 1094 .balign 4 1095 .global dvmCompiler_TEMPLATE_INTERPRET 1096dvmCompiler_TEMPLATE_INTERPRET: 1097/* File: armv5te/TEMPLATE_INTERPRET.S */ 1098 /* 1099 * This handler transfers control to the interpeter without performing 1100 * any lookups. It may be called either as part of a normal chaining 1101 * operation, or from the transition code in header.S. We distinquish 1102 * the two cases by looking at the link register. If called from a 1103 * translation chain, it will point to the chaining Dalvik PC -3. 1104 * On entry: 1105 * lr - if NULL: 1106 * r1 - the Dalvik PC to begin interpretation. 1107 * else 1108 * [lr, #3] contains Dalvik PC to begin interpretation 1109 * rSELF - pointer to thread 1110 * rFP - Dalvik frame pointer 1111 */ 1112 cmp lr, #0 1113#if defined(WORKAROUND_CORTEX_A9_745320) 1114 /* Don't use conditional loads if the HW defect exists */ 1115 beq 101f 1116 ldr r1,[lr, #3] 1117101: 1118#else 1119 ldrne r1,[lr, #3] 1120#endif 1121 ldr r2, .LinterpPunt 1122 mov r0, r1 @ set Dalvik PC 1123 bx r2 1124 @ doesn't return 1125 1126.LinterpPunt: 1127 .word dvmJitToInterpPunt 1128 1129/* ------------------------------ */ 1130 .balign 4 1131 .global dvmCompiler_TEMPLATE_MONITOR_ENTER 1132dvmCompiler_TEMPLATE_MONITOR_ENTER: 1133/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */ 1134 /* 1135 * Call out to the runtime to lock an object. Because this thread 1136 * may have been suspended in THREAD_MONITOR state and the Jit's 1137 * translation cache subsequently cleared, we cannot return directly. 1138 * Instead, unconditionally transition to the interpreter to resume. 1139 * 1140 * On entry: 1141 * r0 - self pointer 1142 * r1 - the object (which has already been null-checked by the caller 1143 * r4 - the Dalvik PC of the following instruction. 1144 */ 1145 ldr r2, .LdvmLockObject 1146 mov r3, #0 @ Record that we're not returning 1147 str r3, [r0, #offThread_inJitCodeCache] 1148 blx r2 @ dvmLockObject(self, obj) 1149 ldr r2, .LdvmJitToInterpNoChain 1150 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1151#if defined(WITH_JIT_TUNING) 1152 mov r0, #kHeavyweightMonitor 1153#endif 1154 bx r2 1155 1156/* ------------------------------ */ 1157 .balign 4 1158 .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG 1159dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG: 1160/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */ 1161 /* 1162 * To support deadlock prediction, this version of MONITOR_ENTER 1163 * will always call the heavyweight dvmLockObject, check for an 1164 * exception and then bail out to the interpreter. 1165 * 1166 * On entry: 1167 * r0 - self pointer 1168 * r1 - the object (which has already been null-checked by the caller 1169 * r4 - the Dalvik PC of the following instruction. 1170 * 1171 */ 1172 ldr r2, .LdvmLockObject 1173 mov r3, #0 @ Record that we're not returning 1174 str r3, [r0, #offThread_inJitCodeCache] 1175 blx r2 @ dvmLockObject(self, obj) 1176 @ refresh Jit's on/off status & test for exception 1177 ldr r1, [rSELF, #offThread_exception] 1178 cmp r1, #0 1179 beq 1f 1180 ldr r2, .LhandleException 1181 sub r0, r4, #2 @ roll dPC back to this monitor instruction 1182 bx r2 11831: 1184 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1185#if defined(WITH_JIT_TUNING) 1186 mov r0, #kHeavyweightMonitor 1187#endif 1188 ldr pc, .LdvmJitToInterpNoChain 1189 1190/* ------------------------------ */ 1191 .balign 4 1192 .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING 1193dvmCompiler_TEMPLATE_PERIODIC_PROFILING: 1194/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */ 1195 /* 1196 * Increment profile counter for this trace, and decrement 1197 * sample counter. If sample counter goes below zero, turn 1198 * off profiling. 1199 * 1200 * On entry 1201 * (lr-11) is address of pointer to counter. Note: the counter 1202 * actually exists 10 bytes before the return target, but because 1203 * we are arriving from thumb mode, lr will have its low bit set. 1204 */ 1205 ldr r0, [lr,#-11] 1206 ldr r1, [rSELF, #offThread_pProfileCountdown] 1207 ldr r2, [r0] @ get counter 1208 ldr r3, [r1] @ get countdown timer 1209 add r2, #1 1210 subs r2, #1 1211 blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling 1212 str r2, [r0] 1213 str r3, [r1] 1214 bx lr 1215 1216.LTEMPLATE_PERIODIC_PROFILING_disable_profiling: 1217 mov r4, lr @ preserve lr 1218 ldr r0, .LdvmJitTraceProfilingOff 1219 blx r0 1220 bx r4 1221 1222/* ------------------------------ */ 1223 .balign 4 1224 .global dvmCompiler_TEMPLATE_RETURN_PROF 1225dvmCompiler_TEMPLATE_RETURN_PROF: 1226/* File: armv5te/TEMPLATE_RETURN_PROF.S */ 1227#define TEMPLATE_INLINE_PROFILING 1228/* File: armv5te/TEMPLATE_RETURN.S */ 1229 /* 1230 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 1231 * If the stored value in returnAddr 1232 * is non-zero, the caller is compiled by the JIT thus return to the 1233 * address in the code cache following the invoke instruction. Otherwise 1234 * return to the special dvmJitToInterpNoChain entry point. 1235 */ 1236#if defined(TEMPLATE_INLINE_PROFILING) 1237 stmfd sp!, {r0-r2,lr} @ preserve live registers 1238 mov r0, r6 1239 @ r0=rSELF 1240 mov lr, pc 1241 ldr pc, .LdvmFastMethodTraceExit 1242 ldmfd sp!, {r0-r2,lr} @ restore live registers 1243#endif 1244 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 1245 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 1246 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1247 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 1248#if !defined(WITH_SELF_VERIFICATION) 1249 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 1250#else 1251 mov r9, #0 @ disable chaining 1252#endif 1253 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 1254 @ r2<- method we're returning to 1255 cmp r2, #0 @ break frame? 1256#if !defined(WITH_SELF_VERIFICATION) 1257 beq 1f @ bail to interpreter 1258#else 1259 blxeq lr @ punt to interpreter and compare state 1260#endif 1261 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S 1262 mov rFP, r10 @ publish new FP 1263 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 1264 1265 str r2, [rSELF, #offThread_method]@ self->method = newSave->method 1266 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 1267 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp 1268 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 1269 str r0, [rSELF, #offThread_methodClassDex] 1270 cmp r8, #0 @ check the break flags 1271 movne r9, #0 @ clear the chaining cell address 1272 str r9, [rSELF, #offThread_inJitCodeCache] @ in code cache or not 1273 cmp r9, #0 @ chaining cell exists? 1274 blxne r9 @ jump to the chaining cell 1275#if defined(WITH_JIT_TUNING) 1276 mov r0, #kCallsiteInterpreted 1277#endif 1278 mov pc, r1 @ callsite is interpreted 12791: 1280 stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF() 1281 ldr r2, .LdvmMterpStdBail @ defined in footer.S 1282 mov r0, rSELF @ Expecting rSELF in r0 1283 blx r2 @ exit the interpreter 1284 1285#undef TEMPLATE_INLINE_PROFILING 1286 1287/* ------------------------------ */ 1288 .balign 4 1289 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF 1290dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF: 1291/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */ 1292#define TEMPLATE_INLINE_PROFILING 1293/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 1294 /* 1295 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 1296 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 1297 * runtime-resolved callee. 1298 */ 1299 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 1300 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 1301 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 1302 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 1303 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1304 add r3, r1, #1 @ Thumb addr is odd 1305 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1306 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1307 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1308 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 1309 cmp r10, r9 @ bottom < interpStackEnd? 1310 bxlo lr @ return to raise stack overflow excep. 1311 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1312 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 1313 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 1314 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1315 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1316 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 1317 1318 1319 @ set up newSaveArea 1320 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1321 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1322 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1323 cmp r8, #0 @ breakFlags != 0 1324 bxne lr @ bail to the interpreter 1325 tst r10, #ACC_NATIVE 1326#if !defined(WITH_SELF_VERIFICATION) 1327 bne .LinvokeNative 1328#else 1329 bxne lr @ bail to the interpreter 1330#endif 1331 1332 ldr r10, .LdvmJitToInterpTraceSelectNoChain 1333 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 1334 1335 @ Update "thread" values for the new method 1336 str r0, [rSELF, #offThread_method] @ self->method = methodToCall 1337 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ... 1338 mov rFP, r1 @ fp = newFp 1339 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 1340#if defined(TEMPLATE_INLINE_PROFILING) 1341 stmfd sp!, {r0-r3} @ preserve r0-r3 1342 mov r1, r6 1343 @ r0=methodToCall, r1=rSELF 1344 mov lr, pc 1345 ldr pc, .LdvmFastMethodTraceEnter 1346 ldmfd sp!, {r0-r3} @ restore r0-r3 1347#endif 1348 1349 @ Start executing the callee 1350#if defined(WITH_JIT_TUNING) 1351 mov r0, #kInlineCacheMiss 1352#endif 1353 mov pc, r10 @ dvmJitToInterpTraceSelectNoChain 1354 1355#undef TEMPLATE_INLINE_PROFILING 1356 1357/* ------------------------------ */ 1358 .balign 4 1359 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF 1360dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF: 1361/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */ 1362#define TEMPLATE_INLINE_PROFILING 1363/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 1364 /* 1365 * For monomorphic callsite, setup the Dalvik frame and return to the 1366 * Thumb code through the link register to transfer control to the callee 1367 * method through a dedicated chaining cell. 1368 */ 1369 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize 1370 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize 1371 @ methodToCall is guaranteed to be non-native 1372.LinvokeChainProf: 1373 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 1374 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1375 add r3, r1, #1 @ Thumb addr is odd 1376 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1377 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1378 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1379 add r12, lr, #2 @ setup the punt-to-interp address 1380 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 1381 cmp r10, r9 @ bottom < interpStackEnd? 1382 bxlo r12 @ return to raise stack overflow excep. 1383 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1384 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 1385 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1386 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1387 1388 @ set up newSaveArea 1389 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1390 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1391 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1392 cmp r8, #0 @ breakFlags != 0 1393 bxne r12 @ bail to the interpreter 1394 1395 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 1396 1397 @ Update "thread" values for the new method 1398 str r0, [rSELF, #offThread_method] @ self->method = methodToCall 1399 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ... 1400 mov rFP, r1 @ fp = newFp 1401 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 1402#if defined(TEMPLATE_INLINE_PROFILING) 1403 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers 1404 mov r1, r6 1405 @ r0=methodToCall, r1=rSELF 1406 mov lr, pc 1407 ldr pc, .LdvmFastMethodTraceEnter 1408 ldmfd sp!, {r0-r2,lr} @ restore registers 1409#endif 1410 1411 bx lr @ return to the callee-chaining cell 1412 1413#undef TEMPLATE_INLINE_PROFILING 1414 1415/* ------------------------------ */ 1416 .balign 4 1417 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF 1418dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF: 1419/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */ 1420#define TEMPLATE_INLINE_PROFILING 1421/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 1422 /* 1423 * For polymorphic callsite, check whether the cached class pointer matches 1424 * the current one. If so setup the Dalvik frame and return to the 1425 * Thumb code through the link register to transfer control to the callee 1426 * method through a dedicated chaining cell. 1427 * 1428 * The predicted chaining cell is declared in ArmLIR.h with the 1429 * following layout: 1430 * 1431 * typedef struct PredictedChainingCell { 1432 * u4 branch; 1433 * const ClassObject *clazz; 1434 * const Method *method; 1435 * u4 counter; 1436 * } PredictedChainingCell; 1437 * 1438 * Upon returning to the callsite: 1439 * - lr : to branch to the chaining cell 1440 * - lr+2: to punt to the interpreter 1441 * - lr+4: to fully resolve the callee and may rechain. 1442 * r3 <- class 1443 * r9 <- counter 1444 */ 1445 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 1446 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 1447 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 1448 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 1449 ldr r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount 1450 cmp r3, r8 @ predicted class == actual class? 1451#if defined(WITH_JIT_TUNING) 1452 ldr r7, .LdvmICHitCount 1453#if defined(WORKAROUND_CORTEX_A9_745320) 1454 /* Don't use conditional loads if the HW defect exists */ 1455 bne 101f 1456 ldr r10, [r7, #0] 1457101: 1458#else 1459 ldreq r10, [r7, #0] 1460#endif 1461 add r10, r10, #1 1462 streq r10, [r7, #0] 1463#endif 1464 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 1465 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 1466 beq .LinvokeChainProf @ predicted chain is valid 1467 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 1468 cmp r8, #0 @ initialized class or not 1469 moveq r1, #0 1470 subne r1, r9, #1 @ count-- 1471 strne r1, [rSELF, #offThread_icRechainCount] @ write back to thread 1472 add lr, lr, #4 @ return to fully-resolve landing pad 1473 /* 1474 * r1 <- count 1475 * r2 <- &predictedChainCell 1476 * r3 <- this->class 1477 * r4 <- dPC 1478 * r7 <- this->class->vtable 1479 */ 1480 bx lr 1481 1482#undef TEMPLATE_INLINE_PROFILING 1483 1484/* ------------------------------ */ 1485 .balign 4 1486 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF 1487dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF: 1488/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */ 1489#define TEMPLATE_INLINE_PROFILING 1490/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 1491 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 1492 @ r7 = methodToCall->registersSize 1493 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 1494 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1495 add r3, r1, #1 @ Thumb addr is odd 1496 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1497 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1498 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1499 cmp r10, r9 @ bottom < interpStackEnd? 1500 bxlo lr @ return to raise stack overflow excep. 1501 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1502 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1503 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1504 1505 @ set up newSaveArea 1506 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1507 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1508 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1509 cmp r8, #0 @ breakFlags != 0 1510 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 1511#if !defined(WITH_SELF_VERIFICATION) 1512 bxne lr @ bail to the interpreter 1513#else 1514 bx lr @ bail to interpreter unconditionally 1515#endif 1516 1517 @ go ahead and transfer control to the native code 1518 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->... 1519 mov r2, #0 1520 str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 1521 str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache 1522 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1523 @ newFp->localRefCookie=top 1524 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1525 1526 mov r2, r0 @ arg2<- methodToCall 1527 mov r0, r1 @ arg0<- newFP 1528 add r1, rSELF, #offThread_retval @ arg1<- &retval 1529 mov r3, rSELF @ arg3<- self 1530#if defined(TEMPLATE_INLINE_PROFILING) 1531 @ r2=methodToCall, r6=rSELF 1532 stmfd sp!, {r2,r6} @ to be consumed after JNI return 1533 stmfd sp!, {r0-r3} @ preserve r0-r3 1534 mov r0, r2 1535 mov r1, r6 1536 @ r0=JNIMethod, r1=rSELF 1537 mov lr, pc 1538 ldr pc, .LdvmFastMethodTraceEnter 1539 ldmfd sp!, {r0-r3} @ restore r0-r3 1540#endif 1541 1542 blx r8 @ off to the native code 1543 1544#if defined(TEMPLATE_INLINE_PROFILING) 1545 ldmfd sp!, {r0-r1} @ restore r2 and r6 1546 @ r0=JNIMethod, r1=rSELF 1547 mov lr, pc 1548 ldr pc, .LdvmFastNativeMethodTraceExit 1549#endif 1550 @ native return; r10=newSaveArea 1551 @ equivalent to dvmPopJniLocals 1552 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1553 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1554 ldr r1, [rSELF, #offThread_exception] @ check for exception 1555 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp 1556 cmp r1, #0 @ null? 1557 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top 1558 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1559 1560 @ r0 = dalvikCallsitePC 1561 bne .LhandleException @ no, handle exception 1562 1563 str r2, [rSELF, #offThread_inJitCodeCache] @ set the mode properly 1564 cmp r2, #0 @ return chaining cell still exists? 1565 bxne r2 @ yes - go ahead 1566 1567 @ continue executing the next instruction through the interpreter 1568 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1569 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1570#if defined(WITH_JIT_TUNING) 1571 mov r0, #kCallsiteInterpreted 1572#endif 1573 mov pc, r1 1574 1575#undef TEMPLATE_INLINE_PROFILING 1576 1577 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1578/* File: armv5te/footer.S */ 1579/* 1580 * =========================================================================== 1581 * Common subroutines and data 1582 * =========================================================================== 1583 */ 1584 1585 .text 1586 .align 2 1587.LinvokeNative: 1588 @ Prep for the native call 1589 @ r1 = newFP, r0 = methodToCall 1590 mov r2, #0 1591 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->... 1592 str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache 1593 str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp 1594 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1595 @ newFp->localRefCookie=top 1596 ldrb lr, [rSELF, #offThread_subMode] 1597 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1598 1599 mov r2, r0 @ r2<- methodToCall 1600 mov r0, r1 @ r0<- newFP 1601 add r1, rSELF, #offThread_retval @ r1<- &retval 1602 mov r3, rSELF @ arg3<- self 1603 ands lr, #kSubModeMethodTrace 1604 beq 121f @ hop if not profiling 1605 @ r2: methodToCall, r6: rSELF 1606 stmfd sp!, {r2,r6} 1607 stmfd sp!, {r0-r3} 1608 mov r0, r2 1609 mov r1, r6 1610 mov lr, pc 1611 ldr pc, .LdvmFastMethodTraceEnter 1612 ldmfd sp!, {r0-r3} 1613 1614 mov lr, pc 1615 ldr pc, [r2, #offMethod_nativeFunc] 1616 1617 ldmfd sp!, {r0-r1} 1618 mov lr, pc 1619 ldr pc, .LdvmFastNativeMethodTraceExit 1620 b 212f 1621121: 1622 mov lr, pc 1623 ldr pc, [r2, #offMethod_nativeFunc] 1624212: 1625 1626 @ native return; r10=newSaveArea 1627 @ equivalent to dvmPopJniLocals 1628 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1629 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1630 ldr r1, [rSELF, #offThread_exception] @ check for exception 1631 str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp 1632 cmp r1, #0 @ null? 1633 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top 1634 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC 1635 1636 @ r0 = dalvikCallsitePC 1637 bne .LhandleException @ no, handle exception 1638 1639 str r2, [rSELF, #offThread_inJitCodeCache] @ set the new mode 1640 cmp r2, #0 @ return chaining cell still exists? 1641 bxne r2 @ yes - go ahead 1642 1643 @ continue executing the next instruction through the interpreter 1644 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1645 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1646#if defined(WITH_JIT_TUNING) 1647 mov r0, #kCallsiteInterpreted 1648#endif 1649 mov pc, r1 1650 1651/* 1652 * On entry: 1653 * r0 Faulting Dalvik PC 1654 */ 1655.LhandleException: 1656#if defined(WITH_SELF_VERIFICATION) 1657 ldr pc, .LdeadFood @ should not see this under self-verification mode 1658.LdeadFood: 1659 .word 0xdeadf00d 1660#endif 1661 mov r2, #0 1662 str r2, [rSELF, #offThread_inJitCodeCache] @ in interpreter land 1663 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1664 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1665 mov rPC, r0 @ reload the faulting Dalvik address 1666 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown 1667 1668 .align 2 1669.LdvmAsmInstructionStart: 1670 .word dvmAsmInstructionStart 1671.LdvmJitToInterpNoChainNoProfile: 1672 .word dvmJitToInterpNoChainNoProfile 1673.LdvmJitToInterpTraceSelectNoChain: 1674 .word dvmJitToInterpTraceSelectNoChain 1675.LdvmJitToInterpNoChain: 1676 .word dvmJitToInterpNoChain 1677.LdvmMterpStdBail: 1678 .word dvmMterpStdBail 1679.LdvmMterpCommonExceptionThrown: 1680 .word dvmMterpCommonExceptionThrown 1681.LdvmLockObject: 1682 .word dvmLockObject 1683.LdvmJitTraceProfilingOff: 1684 .word dvmJitTraceProfilingOff 1685#if defined(WITH_JIT_TUNING) 1686.LdvmICHitCount: 1687 .word gDvmICHitCount 1688#endif 1689#if defined(WITH_SELF_VERIFICATION) 1690.LdvmSelfVerificationMemOpDecode: 1691 .word dvmSelfVerificationMemOpDecode 1692#endif 1693.LdvmFastMethodTraceEnter: 1694 .word dvmFastMethodTraceEnter 1695.LdvmFastNativeMethodTraceExit: 1696 .word dvmFastNativeMethodTraceExit 1697.LdvmFastMethodTraceExit: 1698 .word dvmFastMethodTraceExit 1699.L__aeabi_cdcmple: 1700 .word __aeabi_cdcmple 1701.L__aeabi_cfcmple: 1702 .word __aeabi_cfcmple 1703 1704 .global dmvCompilerTemplateEnd 1705dmvCompilerTemplateEnd: 1706 1707#endif /* WITH_JIT */ 1708 1709