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