1 /* 2 * This file was generated automatically by gen-template.py for 'armv7-a-neon'. 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-vfp/platform.S */ 105 /* 106 * =========================================================================== 107 * CPU-version-specific defines and utility 108 * =========================================================================== 109 */ 110 111 112 .global dvmCompilerTemplateStart 113 .type dvmCompilerTemplateStart, %function 114 .text 115 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_MUL_LONG 497 dvmCompiler_TEMPLATE_MUL_LONG: 498 /* File: armv5te/TEMPLATE_MUL_LONG.S */ 499 /* 500 * Signed 64-bit integer multiply. 501 * 502 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 503 * 504 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 505 * WX 506 * x YZ 507 * -------- 508 * ZW ZX 509 * YW YX 510 * 511 * The low word of the result holds ZX, the high word holds 512 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 513 * it doesn't fit in the low 64 bits. 514 * 515 * Unlike most ARM math operations, multiply instructions have 516 * restrictions on using the same register more than once (Rd and Rm 517 * cannot be the same). 518 */ 519 /* mul-long vAA, vBB, vCC */ 520 mul ip, r2, r1 @ ip<- ZxW 521 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 522 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 523 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 524 mov r0,r9 525 mov r1,r10 526 bx lr 527 528 /* ------------------------------ */ 529 .balign 4 530 .global dvmCompiler_TEMPLATE_SHL_LONG 531 dvmCompiler_TEMPLATE_SHL_LONG: 532 /* File: armv5te/TEMPLATE_SHL_LONG.S */ 533 /* 534 * Long integer shift. This is different from the generic 32/64-bit 535 * binary operations because vAA/vBB are 64-bit but vCC (the shift 536 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 537 * 6 bits. 538 */ 539 /* shl-long vAA, vBB, vCC */ 540 and r2, r2, #63 @ r2<- r2 & 0x3f 541 mov r1, r1, asl r2 @ r1<- r1 << r2 542 rsb r3, r2, #32 @ r3<- 32 - r2 543 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 544 subs ip, r2, #32 @ ip<- r2 - 32 545 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 546 mov r0, r0, asl r2 @ r0<- r0 << r2 547 bx lr 548 549 /* ------------------------------ */ 550 .balign 4 551 .global dvmCompiler_TEMPLATE_SHR_LONG 552 dvmCompiler_TEMPLATE_SHR_LONG: 553 /* File: armv5te/TEMPLATE_SHR_LONG.S */ 554 /* 555 * Long integer shift. This is different from the generic 32/64-bit 556 * binary operations because vAA/vBB are 64-bit but vCC (the shift 557 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 558 * 6 bits. 559 */ 560 /* shr-long vAA, vBB, vCC */ 561 and r2, r2, #63 @ r0<- r0 & 0x3f 562 mov r0, r0, lsr r2 @ r0<- r2 >> r2 563 rsb r3, r2, #32 @ r3<- 32 - r2 564 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 565 subs ip, r2, #32 @ ip<- r2 - 32 566 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 567 mov r1, r1, asr r2 @ r1<- r1 >> r2 568 bx lr 569 570 /* ------------------------------ */ 571 .balign 4 572 .global dvmCompiler_TEMPLATE_USHR_LONG 573 dvmCompiler_TEMPLATE_USHR_LONG: 574 /* File: armv5te/TEMPLATE_USHR_LONG.S */ 575 /* 576 * Long integer shift. This is different from the generic 32/64-bit 577 * binary operations because vAA/vBB are 64-bit but vCC (the shift 578 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 579 * 6 bits. 580 */ 581 /* ushr-long vAA, vBB, vCC */ 582 and r2, r2, #63 @ r0<- r0 & 0x3f 583 mov r0, r0, lsr r2 @ r0<- r2 >> r2 584 rsb r3, r2, #32 @ r3<- 32 - r2 585 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 586 subs ip, r2, #32 @ ip<- r2 - 32 587 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 588 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 589 bx lr 590 591 /* ------------------------------ */ 592 .balign 4 593 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP 594 dvmCompiler_TEMPLATE_ADD_FLOAT_VFP: 595 /* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */ 596 /* File: armv5te-vfp/fbinop.S */ 597 /* 598 * Generic 32-bit floating point operation. Provide an "instr" line that 599 * specifies an instruction that performs s2 = s0 op s1. 600 * 601 * On entry: 602 * r0 = target dalvik register address 603 * r1 = op1 address 604 * r2 = op2 address 605 */ 606 flds s0,[r1] 607 flds s1,[r2] 608 fadds s2, s0, s1 609 fsts s2,[r0] 610 bx lr 611 612 613 /* ------------------------------ */ 614 .balign 4 615 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP 616 dvmCompiler_TEMPLATE_SUB_FLOAT_VFP: 617 /* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */ 618 /* File: armv5te-vfp/fbinop.S */ 619 /* 620 * Generic 32-bit floating point operation. Provide an "instr" line that 621 * specifies an instruction that performs s2 = s0 op s1. 622 * 623 * On entry: 624 * r0 = target dalvik register address 625 * r1 = op1 address 626 * r2 = op2 address 627 */ 628 flds s0,[r1] 629 flds s1,[r2] 630 fsubs s2, s0, s1 631 fsts s2,[r0] 632 bx lr 633 634 635 /* ------------------------------ */ 636 .balign 4 637 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP 638 dvmCompiler_TEMPLATE_MUL_FLOAT_VFP: 639 /* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */ 640 /* File: armv5te-vfp/fbinop.S */ 641 /* 642 * Generic 32-bit floating point operation. Provide an "instr" line that 643 * specifies an instruction that performs s2 = s0 op s1. 644 * 645 * On entry: 646 * r0 = target dalvik register address 647 * r1 = op1 address 648 * r2 = op2 address 649 */ 650 flds s0,[r1] 651 flds s1,[r2] 652 fmuls s2, s0, s1 653 fsts s2,[r0] 654 bx lr 655 656 657 /* ------------------------------ */ 658 .balign 4 659 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP 660 dvmCompiler_TEMPLATE_DIV_FLOAT_VFP: 661 /* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */ 662 /* File: armv5te-vfp/fbinop.S */ 663 /* 664 * Generic 32-bit floating point operation. Provide an "instr" line that 665 * specifies an instruction that performs s2 = s0 op s1. 666 * 667 * On entry: 668 * r0 = target dalvik register address 669 * r1 = op1 address 670 * r2 = op2 address 671 */ 672 flds s0,[r1] 673 flds s1,[r2] 674 fdivs s2, s0, s1 675 fsts s2,[r0] 676 bx lr 677 678 679 /* ------------------------------ */ 680 .balign 4 681 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP 682 dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP: 683 /* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */ 684 /* File: armv5te-vfp/fbinopWide.S */ 685 /* 686 * Generic 64-bit floating point operation. Provide an "instr" line that 687 * specifies an instruction that performs s2 = s0 op s1. 688 * 689 * On entry: 690 * r0 = target dalvik register address 691 * r1 = op1 address 692 * r2 = op2 address 693 */ 694 fldd d0,[r1] 695 fldd d1,[r2] 696 faddd d2, d0, d1 697 fstd d2,[r0] 698 bx lr 699 700 701 /* ------------------------------ */ 702 .balign 4 703 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP 704 dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP: 705 /* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */ 706 /* File: armv5te-vfp/fbinopWide.S */ 707 /* 708 * Generic 64-bit floating point operation. Provide an "instr" line that 709 * specifies an instruction that performs s2 = s0 op s1. 710 * 711 * On entry: 712 * r0 = target dalvik register address 713 * r1 = op1 address 714 * r2 = op2 address 715 */ 716 fldd d0,[r1] 717 fldd d1,[r2] 718 fsubd d2, d0, d1 719 fstd d2,[r0] 720 bx lr 721 722 723 /* ------------------------------ */ 724 .balign 4 725 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP 726 dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP: 727 /* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */ 728 /* File: armv5te-vfp/fbinopWide.S */ 729 /* 730 * Generic 64-bit floating point operation. Provide an "instr" line that 731 * specifies an instruction that performs s2 = s0 op s1. 732 * 733 * On entry: 734 * r0 = target dalvik register address 735 * r1 = op1 address 736 * r2 = op2 address 737 */ 738 fldd d0,[r1] 739 fldd d1,[r2] 740 fmuld d2, d0, d1 741 fstd d2,[r0] 742 bx lr 743 744 745 /* ------------------------------ */ 746 .balign 4 747 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP 748 dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP: 749 /* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */ 750 /* File: armv5te-vfp/fbinopWide.S */ 751 /* 752 * Generic 64-bit floating point operation. Provide an "instr" line that 753 * specifies an instruction that performs s2 = s0 op s1. 754 * 755 * On entry: 756 * r0 = target dalvik register address 757 * r1 = op1 address 758 * r2 = op2 address 759 */ 760 fldd d0,[r1] 761 fldd d1,[r2] 762 fdivd d2, d0, d1 763 fstd d2,[r0] 764 bx lr 765 766 767 /* ------------------------------ */ 768 .balign 4 769 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP 770 dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP: 771 /* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */ 772 /* File: armv5te-vfp/funopNarrower.S */ 773 /* 774 * Generic 64bit-to-32bit floating point unary operation. Provide an 775 * "instr" line that specifies an instruction that performs "s0 = op d0". 776 * 777 * For: double-to-int, double-to-float 778 * 779 * On entry: 780 * r0 = target dalvik register address 781 * r1 = src dalvik register address 782 */ 783 /* unop vA, vB */ 784 fldd d0, [r1] @ d0<- vB 785 fcvtsd s0, d0 @ s0<- op d0 786 fsts s0, [r0] @ vA<- s0 787 bx lr 788 789 790 /* ------------------------------ */ 791 .balign 4 792 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP 793 dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP: 794 /* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */ 795 /* File: armv5te-vfp/funopNarrower.S */ 796 /* 797 * Generic 64bit-to-32bit floating point unary operation. Provide an 798 * "instr" line that specifies an instruction that performs "s0 = op d0". 799 * 800 * For: double-to-int, double-to-float 801 * 802 * On entry: 803 * r0 = target dalvik register address 804 * r1 = src dalvik register address 805 */ 806 /* unop vA, vB */ 807 fldd d0, [r1] @ d0<- vB 808 ftosizd s0, d0 @ s0<- op d0 809 fsts s0, [r0] @ vA<- s0 810 bx lr 811 812 813 /* ------------------------------ */ 814 .balign 4 815 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP 816 dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP: 817 /* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */ 818 /* File: armv5te-vfp/funopWider.S */ 819 /* 820 * Generic 32bit-to-64bit floating point unary operation. Provide an 821 * "instr" line that specifies an instruction that performs "d0 = op s0". 822 * 823 * For: int-to-double, float-to-double 824 * 825 * On entry: 826 * r0 = target dalvik register address 827 * r1 = src dalvik register address 828 */ 829 /* unop vA, vB */ 830 flds s0, [r1] @ s0<- vB 831 fcvtds d0, s0 @ d0<- op s0 832 fstd d0, [r0] @ vA<- d0 833 bx lr 834 835 836 /* ------------------------------ */ 837 .balign 4 838 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP 839 dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP: 840 /* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */ 841 /* File: armv5te-vfp/funop.S */ 842 /* 843 * Generic 32bit-to-32bit floating point unary operation. Provide an 844 * "instr" line that specifies an instruction that performs "s1 = op s0". 845 * 846 * For: float-to-int, int-to-float 847 * 848 * On entry: 849 * r0 = target dalvik register address 850 * r1 = src dalvik register address 851 */ 852 /* unop vA, vB */ 853 flds s0, [r1] @ s0<- vB 854 ftosizs s1, s0 @ s1<- op s0 855 fsts s1, [r0] @ vA<- s1 856 bx lr 857 858 859 /* ------------------------------ */ 860 .balign 4 861 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP 862 dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP: 863 /* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */ 864 /* File: armv5te-vfp/funopWider.S */ 865 /* 866 * Generic 32bit-to-64bit floating point unary operation. Provide an 867 * "instr" line that specifies an instruction that performs "d0 = op s0". 868 * 869 * For: int-to-double, float-to-double 870 * 871 * On entry: 872 * r0 = target dalvik register address 873 * r1 = src dalvik register address 874 */ 875 /* unop vA, vB */ 876 flds s0, [r1] @ s0<- vB 877 fsitod d0, s0 @ d0<- op s0 878 fstd d0, [r0] @ vA<- d0 879 bx lr 880 881 882 /* ------------------------------ */ 883 .balign 4 884 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP 885 dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP: 886 /* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */ 887 /* File: armv5te-vfp/funop.S */ 888 /* 889 * Generic 32bit-to-32bit floating point unary operation. Provide an 890 * "instr" line that specifies an instruction that performs "s1 = op s0". 891 * 892 * For: float-to-int, int-to-float 893 * 894 * On entry: 895 * r0 = target dalvik register address 896 * r1 = src dalvik register address 897 */ 898 /* unop vA, vB */ 899 flds s0, [r1] @ s0<- vB 900 fsitos s1, s0 @ s1<- op s0 901 fsts s1, [r0] @ vA<- s1 902 bx lr 903 904 905 /* ------------------------------ */ 906 .balign 4 907 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP 908 dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP: 909 /* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */ 910 /* 911 * Compare two floating-point values. Puts 0, 1, or -1 into the 912 * destination register based on the results of the comparison. 913 * 914 * int compare(x, y) { 915 * if (x == y) { 916 * return 0; 917 * } else if (x < y) { 918 * return -1; 919 * } else if (x > y) { 920 * return 1; 921 * } else { 922 * return 1; 923 * } 924 * } 925 * 926 * On entry: 927 * r0 = &op1 [vBB] 928 * r1 = &op2 [vCC] 929 */ 930 /* op vAA, vBB, vCC */ 931 fldd d0, [r0] @ d0<- vBB 932 fldd d1, [r1] @ d1<- vCC 933 fcmpd d0, d1 @ compare (vBB, vCC) 934 mov r0, #1 @ r0<- 1 (default) 935 fmstat @ export status flags 936 mvnmi r0, #0 @ (less than) r0<- -1 937 moveq r0, #0 @ (equal) r0<- 0 938 bx lr 939 940 /* ------------------------------ */ 941 .balign 4 942 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP 943 dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP: 944 /* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */ 945 /* 946 * Compare two floating-point values. Puts 0, 1, or -1 into the 947 * destination register based on the results of the comparison. 948 * 949 * int compare(x, y) { 950 * if (x == y) { 951 * return 0; 952 * } else if (x > y) { 953 * return 1; 954 * } else if (x < y) { 955 * return -1; 956 * } else { 957 * return -1; 958 * } 959 * } 960 * On entry: 961 * r0 = &op1 [vBB] 962 * r1 = &op2 [vCC] 963 */ 964 /* op vAA, vBB, vCC */ 965 fldd d0, [r0] @ d0<- vBB 966 fldd d1, [r1] @ d1<- vCC 967 fcmped d0, d1 @ compare (vBB, vCC) 968 mvn r0, #0 @ r0<- -1 (default) 969 fmstat @ export status flags 970 movgt r0, #1 @ (greater than) r0<- 1 971 moveq r0, #0 @ (equal) r0<- 0 972 bx lr 973 974 /* ------------------------------ */ 975 .balign 4 976 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP 977 dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP: 978 /* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */ 979 /* 980 * Compare two floating-point values. Puts 0, 1, or -1 into the 981 * destination register based on the results of the comparison. 982 * 983 * int compare(x, y) { 984 * if (x == y) { 985 * return 0; 986 * } else if (x < y) { 987 * return -1; 988 * } else if (x > y) { 989 * return 1; 990 * } else { 991 * return 1; 992 * } 993 * } 994 * On entry: 995 * r0 = &op1 [vBB] 996 * r1 = &op2 [vCC] 997 */ 998 /* op vAA, vBB, vCC */ 999 flds s0, [r0] @ d0<- vBB 1000 flds s1, [r1] @ d1<- vCC 1001 fcmps s0, s1 @ compare (vBB, vCC) 1002 mov r0, #1 @ r0<- 1 (default) 1003 fmstat @ export status flags 1004 mvnmi r0, #0 @ (less than) r0<- -1 1005 moveq r0, #0 @ (equal) r0<- 0 1006 bx lr 1007 1008 /* ------------------------------ */ 1009 .balign 4 1010 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP 1011 dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP: 1012 /* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */ 1013 /* 1014 * Compare two floating-point values. Puts 0, 1, or -1 into the 1015 * destination register based on the results of the comparison. 1016 * 1017 * int compare(x, y) { 1018 * if (x == y) { 1019 * return 0; 1020 * } else if (x > y) { 1021 * return 1; 1022 * } else if (x < y) { 1023 * return -1; 1024 * } else { 1025 * return -1; 1026 * } 1027 * } 1028 * On entry: 1029 * r0 = &op1 [vBB] 1030 * r1 = &op2 [vCC] 1031 */ 1032 /* op vAA, vBB, vCC */ 1033 flds s0, [r0] @ d0<- vBB 1034 flds s1, [r1] @ d1<- vCC 1035 fcmps s0, s1 @ compare (vBB, vCC) 1036 mvn r0, #0 @ r0<- -1 (default) 1037 fmstat @ export status flags 1038 movgt r0, #1 @ (greater than) r0<- 1 1039 moveq r0, #0 @ (equal) r0<- 0 1040 bx lr 1041 1042 /* ------------------------------ */ 1043 .balign 4 1044 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP 1045 dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP: 1046 /* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */ 1047 /* 1048 * 64-bit floating point vfp sqrt operation. 1049 * If the result is a NaN, bail out to library code to do 1050 * the right thing. 1051 * 1052 * On entry: 1053 * r2 src addr of op1 1054 * On exit: 1055 * r0,r1 = res 1056 */ 1057 fldd d0, [r2] 1058 fsqrtd d1, d0 1059 fcmpd d1, d1 1060 fmstat 1061 fmrrd r0, r1, d1 1062 bxeq lr @ Result OK - return 1063 ldr r2, .Lsqrt 1064 fmrrd r0, r1, d0 @ reload orig operand 1065 bx r2 @ tail call to sqrt library routine 1066 1067 .Lsqrt: 1068 .word sqrt 1069 1070 /* ------------------------------ */ 1071 .balign 4 1072 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON 1073 dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON: 1074 /* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */ 1075 /* 1076 * Throw an exception from JIT'ed code. 1077 * On entry: 1078 * r0 Dalvik PC that raises the exception 1079 */ 1080 b .LhandleException 1081 1082 /* ------------------------------ */ 1083 .balign 4 1084 .global dvmCompiler_TEMPLATE_MEM_OP_DECODE 1085 dvmCompiler_TEMPLATE_MEM_OP_DECODE: 1086 /* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */ 1087 #if defined(WITH_SELF_VERIFICATION) 1088 /* 1089 * This handler encapsulates heap memory ops for selfVerification mode. 1090 * 1091 * The call to the handler is inserted prior to a heap memory operation. 1092 * This handler then calls a function to decode the memory op, and process 1093 * it accordingly. Afterwards, the handler changes the return address to 1094 * skip the memory op so it never gets executed. 1095 */ 1096 vpush {d0-d15} @ save out all fp registers 1097 push {r0-r12,lr} @ save out all registers 1098 ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S 1099 mov r0, lr @ arg0 <- link register 1100 mov r1, sp @ arg1 <- stack pointer 1101 blx r2 @ decode and handle the mem op 1102 pop {r0-r12,lr} @ restore all registers 1103 vpop {d0-d15} @ restore all fp registers 1104 bx lr @ return to compiled code 1105 #endif 1106 1107 /* ------------------------------ */ 1108 .balign 4 1109 .global dvmCompiler_TEMPLATE_STRING_COMPARETO 1110 dvmCompiler_TEMPLATE_STRING_COMPARETO: 1111 /* File: armv5te/TEMPLATE_STRING_COMPARETO.S */ 1112 /* 1113 * String's compareTo. 1114 * 1115 * Requires r0/r1 to have been previously checked for null. Will 1116 * return negative if this's string is < comp, 0 if they are the 1117 * same and positive if >. 1118 * 1119 * IMPORTANT NOTE: 1120 * 1121 * This code relies on hard-coded offsets for string objects, and must be 1122 * kept in sync with definitions in UtfString.h. See asm-constants.h 1123 * 1124 * On entry: 1125 * r0: this object pointer 1126 * r1: comp object pointer 1127 * 1128 */ 1129 1130 mov r2, r0 @ this to r2, opening up r0 for return value 1131 subs r0, r2, r1 @ Same? 1132 bxeq lr 1133 1134 ldr r4, [r2, #STRING_FIELDOFF_OFFSET] 1135 ldr r9, [r1, #STRING_FIELDOFF_OFFSET] 1136 ldr r7, [r2, #STRING_FIELDOFF_COUNT] 1137 ldr r10, [r1, #STRING_FIELDOFF_COUNT] 1138 ldr r2, [r2, #STRING_FIELDOFF_VALUE] 1139 ldr r1, [r1, #STRING_FIELDOFF_VALUE] 1140 1141 /* 1142 * At this point, we have: 1143 * value: r2/r1 1144 * offset: r4/r9 1145 * count: r7/r10 1146 * We're going to compute 1147 * r11 <- countDiff 1148 * r10 <- minCount 1149 */ 1150 subs r11, r7, r10 1151 movls r10, r7 1152 1153 /* Now, build pointers to the string data */ 1154 add r2, r2, r4, lsl #1 1155 add r1, r1, r9, lsl #1 1156 /* 1157 * Note: data pointers point to previous element so we can use pre-index 1158 * mode with base writeback. 1159 */ 1160 add r2, #16-2 @ offset to contents[-1] 1161 add r1, #16-2 @ offset to contents[-1] 1162 1163 /* 1164 * At this point we have: 1165 * r2: *this string data 1166 * r1: *comp string data 1167 * r10: iteration count for comparison 1168 * r11: value to return if the first part of the string is equal 1169 * r0: reserved for result 1170 * r3, r4, r7, r8, r9, r12 available for loading string data 1171 */ 1172 1173 subs r10, #2 1174 blt do_remainder2 1175 1176 /* 1177 * Unroll the first two checks so we can quickly catch early mismatch 1178 * on long strings (but preserve incoming alignment) 1179 */ 1180 1181 ldrh r3, [r2, #2]! 1182 ldrh r4, [r1, #2]! 1183 ldrh r7, [r2, #2]! 1184 ldrh r8, [r1, #2]! 1185 subs r0, r3, r4 1186 subeqs r0, r7, r8 1187 bxne lr 1188 cmp r10, #28 1189 bgt do_memcmp16 1190 subs r10, #3 1191 blt do_remainder 1192 1193 loopback_triple: 1194 ldrh r3, [r2, #2]! 1195 ldrh r4, [r1, #2]! 1196 ldrh r7, [r2, #2]! 1197 ldrh r8, [r1, #2]! 1198 ldrh r9, [r2, #2]! 1199 ldrh r12,[r1, #2]! 1200 subs r0, r3, r4 1201 subeqs r0, r7, r8 1202 subeqs r0, r9, r12 1203 bxne lr 1204 subs r10, #3 1205 bge loopback_triple 1206 1207 do_remainder: 1208 adds r10, #3 1209 beq returnDiff 1210 1211 loopback_single: 1212 ldrh r3, [r2, #2]! 1213 ldrh r4, [r1, #2]! 1214 subs r0, r3, r4 1215 bxne lr 1216 subs r10, #1 1217 bne loopback_single 1218 1219 returnDiff: 1220 mov r0, r11 1221 bx lr 1222 1223 do_remainder2: 1224 adds r10, #2 1225 bne loopback_single 1226 mov r0, r11 1227 bx lr 1228 1229 /* Long string case */ 1230 do_memcmp16: 1231 mov r4, lr 1232 ldr lr, .Lmemcmp16 1233 mov r7, r11 1234 add r0, r2, #2 1235 add r1, r1, #2 1236 mov r2, r10 1237 blx lr 1238 cmp r0, #0 1239 bxne r4 1240 mov r0, r7 1241 bx r4 1242 1243 .Lmemcmp16: 1244 .word __memcmp16 1245 1246 /* ------------------------------ */ 1247 .balign 4 1248 .global dvmCompiler_TEMPLATE_STRING_INDEXOF 1249 dvmCompiler_TEMPLATE_STRING_INDEXOF: 1250 /* File: armv5te/TEMPLATE_STRING_INDEXOF.S */ 1251 /* 1252 * String's indexOf. 1253 * 1254 * Requires r0 to have been previously checked for null. Will 1255 * return index of match of r1 in r0. 1256 * 1257 * IMPORTANT NOTE: 1258 * 1259 * This code relies on hard-coded offsets for string objects, and must be 1260 * kept in sync wth definitions in UtfString.h See asm-constants.h 1261 * 1262 * On entry: 1263 * r0: string object pointer 1264 * r1: char to match 1265 * r2: Starting offset in string data 1266 */ 1267 1268 ldr r7, [r0, #STRING_FIELDOFF_OFFSET] 1269 ldr r8, [r0, #STRING_FIELDOFF_COUNT] 1270 ldr r0, [r0, #STRING_FIELDOFF_VALUE] 1271 1272 /* 1273 * At this point, we have: 1274 * r0: object pointer 1275 * r1: char to match 1276 * r2: starting offset 1277 * r7: offset 1278 * r8: string length 1279 */ 1280 1281 /* Build pointer to start of string data */ 1282 add r0, #16 1283 add r0, r0, r7, lsl #1 1284 1285 /* Save a copy of starting data in r7 */ 1286 mov r7, r0 1287 1288 /* Clamp start to [0..count] */ 1289 cmp r2, #0 1290 movlt r2, #0 1291 cmp r2, r8 1292 movgt r2, r8 1293 1294 /* Build pointer to start of data to compare and pre-bias */ 1295 add r0, r0, r2, lsl #1 1296 sub r0, #2 1297 1298 /* Compute iteration count */ 1299 sub r8, r2 1300 1301 /* 1302 * At this point we have: 1303 * r0: start of data to test 1304 * r1: chat to compare 1305 * r8: iteration count 1306 * r7: original start of string 1307 * r3, r4, r9, r10, r11, r12 available for loading string data 1308 */ 1309 1310 subs r8, #4 1311 blt indexof_remainder 1312 1313 indexof_loop4: 1314 ldrh r3, [r0, #2]! 1315 ldrh r4, [r0, #2]! 1316 ldrh r10, [r0, #2]! 1317 ldrh r11, [r0, #2]! 1318 cmp r3, r1 1319 beq match_0 1320 cmp r4, r1 1321 beq match_1 1322 cmp r10, r1 1323 beq match_2 1324 cmp r11, r1 1325 beq match_3 1326 subs r8, #4 1327 bge indexof_loop4 1328 1329 indexof_remainder: 1330 adds r8, #4 1331 beq indexof_nomatch 1332 1333 indexof_loop1: 1334 ldrh r3, [r0, #2]! 1335 cmp r3, r1 1336 beq match_3 1337 subs r8, #1 1338 bne indexof_loop1 1339 1340 indexof_nomatch: 1341 mov r0, #-1 1342 bx lr 1343 1344 match_0: 1345 sub r0, #6 1346 sub r0, r7 1347 asr r0, r0, #1 1348 bx lr 1349 match_1: 1350 sub r0, #4 1351 sub r0, r7 1352 asr r0, r0, #1 1353 bx lr 1354 match_2: 1355 sub r0, #2 1356 sub r0, r7 1357 asr r0, r0, #1 1358 bx lr 1359 match_3: 1360 sub r0, r7 1361 asr r0, r0, #1 1362 bx lr 1363 1364 /* ------------------------------ */ 1365 .balign 4 1366 .global dvmCompiler_TEMPLATE_INTERPRET 1367 dvmCompiler_TEMPLATE_INTERPRET: 1368 /* File: armv5te/TEMPLATE_INTERPRET.S */ 1369 /* 1370 * This handler transfers control to the interpeter without performing 1371 * any lookups. It may be called either as part of a normal chaining 1372 * operation, or from the transition code in header.S. We distinquish 1373 * the two cases by looking at the link register. If called from a 1374 * translation chain, it will point to the chaining Dalvik PC -3. 1375 * On entry: 1376 * lr - if NULL: 1377 * r1 - the Dalvik PC to begin interpretation. 1378 * else 1379 * [lr, #3] contains Dalvik PC to begin interpretation 1380 * rSELF - pointer to thread 1381 * rFP - Dalvik frame pointer 1382 */ 1383 cmp lr, #0 1384 #if defined(WORKAROUND_CORTEX_A9_745320) 1385 /* Don't use conditional loads if the HW defect exists */ 1386 beq 101f 1387 ldr r1,[lr, #3] 1388 101: 1389 #else 1390 ldrne r1,[lr, #3] 1391 #endif 1392 ldr r2, .LinterpPunt 1393 mov r0, r1 @ set Dalvik PC 1394 bx r2 1395 @ doesn't return 1396 1397 .LinterpPunt: 1398 .word dvmJitToInterpPunt 1399 1400 /* ------------------------------ */ 1401 .balign 4 1402 .global dvmCompiler_TEMPLATE_MONITOR_ENTER 1403 dvmCompiler_TEMPLATE_MONITOR_ENTER: 1404 /* File: armv5te/TEMPLATE_MONITOR_ENTER.S */ 1405 /* 1406 * Call out to the runtime to lock an object. Because this thread 1407 * may have been suspended in THREAD_MONITOR state and the Jit's 1408 * translation cache subsequently cleared, we cannot return directly. 1409 * Instead, unconditionally transition to the interpreter to resume. 1410 * 1411 * On entry: 1412 * r0 - self pointer 1413 * r1 - the object (which has already been null-checked by the caller 1414 * r4 - the Dalvik PC of the following instruction. 1415 */ 1416 ldr r2, .LdvmLockObject 1417 mov r3, #0 @ Record that we're not returning 1418 str r3, [r0, #offThread_inJitCodeCache] 1419 blx r2 @ dvmLockObject(self, obj) 1420 ldr r2, .LdvmJitToInterpNoChain 1421 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1422 #if defined(WITH_JIT_TUNING) 1423 mov r0, #kHeavyweightMonitor 1424 #endif 1425 bx r2 1426 1427 /* ------------------------------ */ 1428 .balign 4 1429 .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG 1430 dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG: 1431 /* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */ 1432 /* 1433 * To support deadlock prediction, this version of MONITOR_ENTER 1434 * will always call the heavyweight dvmLockObject, check for an 1435 * exception and then bail out to the interpreter. 1436 * 1437 * On entry: 1438 * r0 - self pointer 1439 * r1 - the object (which has already been null-checked by the caller 1440 * r4 - the Dalvik PC of the following instruction. 1441 * 1442 */ 1443 ldr r2, .LdvmLockObject 1444 mov r3, #0 @ Record that we're not returning 1445 str r3, [r0, #offThread_inJitCodeCache] 1446 blx r2 @ dvmLockObject(self, obj) 1447 @ test for exception 1448 ldr r1, [rSELF, #offThread_exception] 1449 cmp r1, #0 1450 beq 1f 1451 ldr r2, .LhandleException 1452 sub r0, r4, #2 @ roll dPC back to this monitor instruction 1453 bx r2 1454 1: 1455 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1456 #if defined(WITH_JIT_TUNING) 1457 mov r0, #kHeavyweightMonitor 1458 #endif 1459 ldr pc, .LdvmJitToInterpNoChain 1460 1461 /* ------------------------------ */ 1462 .balign 4 1463 .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING 1464 dvmCompiler_TEMPLATE_PERIODIC_PROFILING: 1465 /* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */ 1466 /* 1467 * Increment profile counter for this trace, and decrement 1468 * sample counter. If sample counter goes below zero, turn 1469 * off profiling. 1470 * 1471 * On entry 1472 * (lr-11) is address of pointer to counter. Note: the counter 1473 * actually exists 10 bytes before the return target, but because 1474 * we are arriving from thumb mode, lr will have its low bit set. 1475 */ 1476 ldr r0, [lr,#-11] 1477 ldr r1, [rSELF, #offThread_pProfileCountdown] 1478 ldr r2, [r0] @ get counter 1479 ldr r3, [r1] @ get countdown timer 1480 add r2, #1 1481 subs r2, #1 1482 blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling 1483 str r2, [r0] 1484 str r3, [r1] 1485 bx lr 1486 1487 .LTEMPLATE_PERIODIC_PROFILING_disable_profiling: 1488 mov r4, lr @ preserve lr 1489 ldr r0, .LdvmJitTraceProfilingOff 1490 blx r0 1491 bx r4 1492 1493 /* ------------------------------ */ 1494 .balign 4 1495 .global dvmCompiler_TEMPLATE_RETURN_PROF 1496 dvmCompiler_TEMPLATE_RETURN_PROF: 1497 /* File: armv5te/TEMPLATE_RETURN_PROF.S */ 1498 #define TEMPLATE_INLINE_PROFILING 1499 /* File: armv5te/TEMPLATE_RETURN.S */ 1500 /* 1501 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 1502 * If the stored value in returnAddr 1503 * is non-zero, the caller is compiled by the JIT thus return to the 1504 * address in the code cache following the invoke instruction. Otherwise 1505 * return to the special dvmJitToInterpNoChain entry point. 1506 */ 1507 #if defined(TEMPLATE_INLINE_PROFILING) 1508 stmfd sp!, {r0-r2,lr} @ preserve live registers 1509 mov r0, r6 1510 @ r0=rSELF 1511 mov lr, pc 1512 ldr pc, .LdvmFastMethodTraceExit 1513 ldmfd sp!, {r0-r2,lr} @ restore live registers 1514 #endif 1515 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 1516 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 1517 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1518 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 1519 #if !defined(WITH_SELF_VERIFICATION) 1520 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 1521 #else 1522 mov r9, #0 @ disable chaining 1523 #endif 1524 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 1525 @ r2<- method we're returning to 1526 cmp r2, #0 @ break frame? 1527 #if !defined(WITH_SELF_VERIFICATION) 1528 beq 1f @ bail to interpreter 1529 #else 1530 blxeq lr @ punt to interpreter and compare state 1531 #endif 1532 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S 1533 mov rFP, r10 @ publish new FP 1534 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 1535 1536 str r2, [rSELF, #offThread_method]@ self->method = newSave->method 1537 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 1538 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp 1539 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 1540 str r0, [rSELF, #offThread_methodClassDex] 1541 cmp r8, #0 @ check the break flags 1542 movne r9, #0 @ clear the chaining cell address 1543 str r9, [rSELF, #offThread_inJitCodeCache] @ in code cache or not 1544 cmp r9, #0 @ chaining cell exists? 1545 blxne r9 @ jump to the chaining cell 1546 #if defined(WITH_JIT_TUNING) 1547 mov r0, #kCallsiteInterpreted 1548 #endif 1549 mov pc, r1 @ callsite is interpreted 1550 1: 1551 mov r0, #0 1552 str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache 1553 stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF() 1554 ldr r2, .LdvmMterpStdBail @ defined in footer.S 1555 mov r0, rSELF @ Expecting rSELF in r0 1556 blx r2 @ exit the interpreter 1557 1558 #undef TEMPLATE_INLINE_PROFILING 1559 1560 /* ------------------------------ */ 1561 .balign 4 1562 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF 1563 dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF: 1564 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */ 1565 #define TEMPLATE_INLINE_PROFILING 1566 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 1567 /* 1568 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 1569 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 1570 * runtime-resolved callee. 1571 */ 1572 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 1573 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 1574 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 1575 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 1576 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1577 add r3, r1, #1 @ Thumb addr is odd 1578 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1579 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1580 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1581 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 1582 cmp r10, r9 @ bottom < interpStackEnd? 1583 bxlo lr @ return to raise stack overflow excep. 1584 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1585 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 1586 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 1587 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1588 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1589 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 1590 1591 1592 @ set up newSaveArea 1593 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1594 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1595 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1596 cmp r8, #0 @ breakFlags != 0 1597 bxne lr @ bail to the interpreter 1598 tst r10, #ACC_NATIVE 1599 #if !defined(WITH_SELF_VERIFICATION) 1600 bne .LinvokeNative 1601 #else 1602 bxne lr @ bail to the interpreter 1603 #endif 1604 1605 ldr r10, .LdvmJitToInterpTraceSelectNoChain 1606 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 1607 1608 @ Update "thread" values for the new method 1609 str r0, [rSELF, #offThread_method] @ self->method = methodToCall 1610 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ... 1611 mov rFP, r1 @ fp = newFp 1612 str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp 1613 #if defined(TEMPLATE_INLINE_PROFILING) 1614 stmfd sp!, {r0-r3} @ preserve r0-r3 1615 mov r1, r6 1616 @ r0=methodToCall, r1=rSELF 1617 mov lr, pc 1618 ldr pc, .LdvmFastMethodTraceEnter 1619 ldmfd sp!, {r0-r3} @ restore r0-r3 1620 #endif 1621 1622 @ Start executing the callee 1623 #if defined(WITH_JIT_TUNING) 1624 mov r0, #kInlineCacheMiss 1625 #endif 1626 mov pc, r10 @ dvmJitToInterpTraceSelectNoChain 1627 1628 #undef TEMPLATE_INLINE_PROFILING 1629 1630 /* ------------------------------ */ 1631 .balign 4 1632 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF 1633 dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF: 1634 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */ 1635 #define TEMPLATE_INLINE_PROFILING 1636 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 1637 /* 1638 * For monomorphic callsite, setup the Dalvik frame and return to the 1639 * Thumb code through the link register to transfer control to the callee 1640 * method through a dedicated chaining cell. 1641 */ 1642 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize 1643 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize 1644 @ methodToCall is guaranteed to be non-native 1645 .LinvokeChainProf: 1646 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 1647 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1648 add r3, r1, #1 @ Thumb addr is odd 1649 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1650 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1651 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1652 add r12, lr, #2 @ setup the punt-to-interp address 1653 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 1654 cmp r10, r9 @ bottom < interpStackEnd? 1655 bxlo r12 @ return to raise stack overflow excep. 1656 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1657 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 1658 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1659 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1660 1661 @ set up newSaveArea 1662 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1663 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1664 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1665 cmp r8, #0 @ breakFlags != 0 1666 bxne r12 @ bail to the interpreter 1667 1668 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 1669 1670 @ Update "thread" values for the new method 1671 str r0, [rSELF, #offThread_method] @ self->method = methodToCall 1672 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ... 1673 mov rFP, r1 @ fp = newFp 1674 str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp 1675 #if defined(TEMPLATE_INLINE_PROFILING) 1676 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers 1677 mov r1, r6 1678 @ r0=methodToCall, r1=rSELF 1679 mov lr, pc 1680 ldr pc, .LdvmFastMethodTraceEnter 1681 ldmfd sp!, {r0-r2,lr} @ restore registers 1682 #endif 1683 1684 bx lr @ return to the callee-chaining cell 1685 1686 #undef TEMPLATE_INLINE_PROFILING 1687 1688 /* ------------------------------ */ 1689 .balign 4 1690 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF 1691 dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF: 1692 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */ 1693 #define TEMPLATE_INLINE_PROFILING 1694 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 1695 /* 1696 * For polymorphic callsite, check whether the cached class pointer matches 1697 * the current one. If so setup the Dalvik frame and return to the 1698 * Thumb code through the link register to transfer control to the callee 1699 * method through a dedicated chaining cell. 1700 * 1701 * The predicted chaining cell is declared in ArmLIR.h with the 1702 * following layout: 1703 * 1704 * typedef struct PredictedChainingCell { 1705 * u4 branch; 1706 * const ClassObject *clazz; 1707 * const Method *method; 1708 * u4 counter; 1709 * } PredictedChainingCell; 1710 * 1711 * Upon returning to the callsite: 1712 * - lr : to branch to the chaining cell 1713 * - lr+2: to punt to the interpreter 1714 * - lr+4: to fully resolve the callee and may rechain. 1715 * r3 <- class 1716 * r9 <- counter 1717 */ 1718 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 1719 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 1720 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 1721 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 1722 ldr r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount 1723 cmp r3, r8 @ predicted class == actual class? 1724 #if defined(WITH_JIT_TUNING) 1725 ldr r7, .LdvmICHitCount 1726 #if defined(WORKAROUND_CORTEX_A9_745320) 1727 /* Don't use conditional loads if the HW defect exists */ 1728 bne 101f 1729 ldr r10, [r7, #0] 1730 101: 1731 #else 1732 ldreq r10, [r7, #0] 1733 #endif 1734 add r10, r10, #1 1735 streq r10, [r7, #0] 1736 #endif 1737 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 1738 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 1739 beq .LinvokeChainProf @ predicted chain is valid 1740 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 1741 cmp r8, #0 @ initialized class or not 1742 moveq r1, #0 1743 subne r1, r9, #1 @ count-- 1744 strne r1, [rSELF, #offThread_icRechainCount] @ write back to thread 1745 add lr, lr, #4 @ return to fully-resolve landing pad 1746 /* 1747 * r1 <- count 1748 * r2 <- &predictedChainCell 1749 * r3 <- this->class 1750 * r4 <- dPC 1751 * r7 <- this->class->vtable 1752 */ 1753 bx lr 1754 1755 #undef TEMPLATE_INLINE_PROFILING 1756 1757 /* ------------------------------ */ 1758 .balign 4 1759 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF 1760 dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF: 1761 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */ 1762 #define TEMPLATE_INLINE_PROFILING 1763 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 1764 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 1765 @ r7 = methodToCall->registersSize 1766 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd 1767 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags 1768 add r3, r1, #1 @ Thumb addr is odd 1769 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 1770 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 1771 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 1772 cmp r10, r9 @ bottom < interpStackEnd? 1773 bxlo lr @ return to raise stack overflow excep. 1774 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 1775 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1776 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 1777 1778 @ set up newSaveArea 1779 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 1780 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 1781 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 1782 cmp r8, #0 @ breakFlags != 0 1783 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 1784 #if !defined(WITH_SELF_VERIFICATION) 1785 bxne lr @ bail to the interpreter 1786 #else 1787 bx lr @ bail to interpreter unconditionally 1788 #endif 1789 1790 @ go ahead and transfer control to the native code 1791 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->... 1792 mov r2, #0 1793 str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp 1794 str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache 1795 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1796 @ newFp->localRefCookie=top 1797 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1798 1799 mov r2, r0 @ arg2<- methodToCall 1800 mov r0, r1 @ arg0<- newFP 1801 add r1, rSELF, #offThread_retval @ arg1<- &retval 1802 mov r3, rSELF @ arg3<- self 1803 #if defined(TEMPLATE_INLINE_PROFILING) 1804 @ r2=methodToCall, r6=rSELF 1805 stmfd sp!, {r2,r6} @ to be consumed after JNI return 1806 stmfd sp!, {r0-r3} @ preserve r0-r3 1807 mov r0, r2 1808 mov r1, r6 1809 @ r0=JNIMethod, r1=rSELF 1810 mov lr, pc 1811 ldr pc, .LdvmFastMethodTraceEnter 1812 ldmfd sp!, {r0-r3} @ restore r0-r3 1813 #endif 1814 1815 blx r8 @ off to the native code 1816 1817 #if defined(TEMPLATE_INLINE_PROFILING) 1818 ldmfd sp!, {r0-r1} @ restore r2 and r6 1819 @ r0=JNIMethod, r1=rSELF 1820 mov lr, pc 1821 ldr pc, .LdvmFastNativeMethodTraceExit 1822 #endif 1823 @ native return; r10=newSaveArea 1824 @ equivalent to dvmPopJniLocals 1825 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1826 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1827 ldr r1, [rSELF, #offThread_exception] @ check for exception 1828 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp 1829 cmp r1, #0 @ null? 1830 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top 1831 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 1832 1833 @ r0 = dalvikCallsitePC 1834 bne .LhandleException @ no, handle exception 1835 1836 str r2, [rSELF, #offThread_inJitCodeCache] @ set the mode properly 1837 cmp r2, #0 @ return chaining cell still exists? 1838 bxne r2 @ yes - go ahead 1839 1840 @ continue executing the next instruction through the interpreter 1841 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1842 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1843 #if defined(WITH_JIT_TUNING) 1844 mov r0, #kCallsiteInterpreted 1845 #endif 1846 mov pc, r1 1847 1848 #undef TEMPLATE_INLINE_PROFILING 1849 1850 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1851 /* File: armv5te/footer.S */ 1852 /* 1853 * =========================================================================== 1854 * Common subroutines and data 1855 * =========================================================================== 1856 */ 1857 1858 .text 1859 .align 2 1860 .LinvokeNative: 1861 @ Prep for the native call 1862 @ r1 = newFP, r0 = methodToCall 1863 mov r2, #0 1864 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->... 1865 str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache 1866 str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp 1867 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1868 @ newFp->localRefCookie=top 1869 ldrh lr, [rSELF, #offThread_subMode] 1870 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1871 1872 mov r2, r0 @ r2<- methodToCall 1873 mov r0, r1 @ r0<- newFP 1874 add r1, rSELF, #offThread_retval @ r1<- &retval 1875 mov r3, rSELF @ arg3<- self 1876 ands lr, #kSubModeMethodTrace 1877 beq 121f @ hop if not profiling 1878 @ r2: methodToCall, r6: rSELF 1879 stmfd sp!, {r2,r6} 1880 stmfd sp!, {r0-r3} 1881 mov r0, r2 1882 mov r1, r6 1883 mov lr, pc 1884 ldr pc, .LdvmFastMethodTraceEnter 1885 ldmfd sp!, {r0-r3} 1886 1887 mov lr, pc 1888 ldr pc, [r2, #offMethod_nativeFunc] 1889 1890 ldmfd sp!, {r0-r1} 1891 mov lr, pc 1892 ldr pc, .LdvmFastNativeMethodTraceExit 1893 b 212f 1894 121: 1895 mov lr, pc 1896 ldr pc, [r2, #offMethod_nativeFunc] 1897 212: 1898 1899 @ native return; r10=newSaveArea 1900 @ equivalent to dvmPopJniLocals 1901 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1902 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1903 ldr r1, [rSELF, #offThread_exception] @ check for exception 1904 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp 1905 cmp r1, #0 @ null? 1906 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top 1907 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC 1908 1909 @ r0 = dalvikCallsitePC 1910 bne .LhandleException @ no, handle exception 1911 1912 str r2, [rSELF, #offThread_inJitCodeCache] @ set the new mode 1913 cmp r2, #0 @ return chaining cell still exists? 1914 bxne r2 @ yes - go ahead 1915 1916 @ continue executing the next instruction through the interpreter 1917 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1918 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1919 #if defined(WITH_JIT_TUNING) 1920 mov r0, #kCallsiteInterpreted 1921 #endif 1922 mov pc, r1 1923 1924 /* 1925 * On entry: 1926 * r0 Faulting Dalvik PC 1927 */ 1928 .LhandleException: 1929 #if defined(WITH_SELF_VERIFICATION) 1930 ldr pc, .LdeadFood @ should not see this under self-verification mode 1931 .LdeadFood: 1932 .word 0xdeadf00d 1933 #endif 1934 mov r2, #0 1935 str r2, [rSELF, #offThread_inJitCodeCache] @ in interpreter land 1936 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1937 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1938 mov rPC, r0 @ reload the faulting Dalvik address 1939 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown 1940 1941 .align 2 1942 .LdvmAsmInstructionStart: 1943 .word dvmAsmInstructionStart 1944 .LdvmJitToInterpNoChainNoProfile: 1945 .word dvmJitToInterpNoChainNoProfile 1946 .LdvmJitToInterpTraceSelectNoChain: 1947 .word dvmJitToInterpTraceSelectNoChain 1948 .LdvmJitToInterpNoChain: 1949 .word dvmJitToInterpNoChain 1950 .LdvmMterpStdBail: 1951 .word dvmMterpStdBail 1952 .LdvmMterpCommonExceptionThrown: 1953 .word dvmMterpCommonExceptionThrown 1954 .LdvmLockObject: 1955 .word dvmLockObject 1956 .LdvmJitTraceProfilingOff: 1957 .word dvmJitTraceProfilingOff 1958 #if defined(WITH_JIT_TUNING) 1959 .LdvmICHitCount: 1960 .word gDvmICHitCount 1961 #endif 1962 #if defined(WITH_SELF_VERIFICATION) 1963 .LdvmSelfVerificationMemOpDecode: 1964 .word dvmSelfVerificationMemOpDecode 1965 #endif 1966 .LdvmFastMethodTraceEnter: 1967 .word dvmFastMethodTraceEnter 1968 .LdvmFastNativeMethodTraceExit: 1969 .word dvmFastNativeMethodTraceExit 1970 .LdvmFastMethodTraceExit: 1971 .word dvmFastMethodTraceExit 1972 .L__aeabi_cdcmple: 1973 .word __aeabi_cdcmple 1974 .L__aeabi_cfcmple: 1975 .word __aeabi_cfcmple 1976 1977 .global dmvCompilerTemplateEnd 1978 dmvCompilerTemplateEnd: 1979 1980 #endif /* WITH_JIT */ 1981 1982