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