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