CompilerTemplateAsm-armv5te-vfp.S revision c8293e7dfe856ca95e27aef1ac2e64d750d60662
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 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 ldrne 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, r2 = methodToCall->outsSize 309 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize 310 @ methodToCall is guaranteed to be non-native 311.LinvokeChain: 312 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 313 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 314 add r3, r1, #1 @ Thumb addr is odd 315 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 316 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 317 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 318 add r12, lr, #2 @ setup the punt-to-interp address 319 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 320 ldr r8, [r8] @ r8<- suspendCount (int) 321 cmp r10, r9 @ bottom < interpStackEnd? 322 bxlo r12 @ return to raise stack overflow excep. 323 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 324 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 325 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 326 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 327 328 @ set up newSaveArea 329 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 330 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 331 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 332 cmp r8, #0 @ suspendCount != 0 333 bxne r12 @ bail to the interpreter 334 335 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 336 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 337 338 @ Update "glue" values for the new method 339 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 340 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 341 mov rFP, r1 @ fp = newFp 342 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 343#if defined(WITH_INLINE_PROFILING) 344 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers 345 mov r1, r6 346 @ r0=methodToCall, r1=rGlue 347 LDR_PC_LR ".LdvmFastMethodTraceEnter" 348 ldmfd sp!, {r0-r2,lr} @ restore registers 349#endif 350 351 bx lr @ return to the callee-chaining cell 352 353/* ------------------------------ */ 354 .balign 4 355 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN 356dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN: 357/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 358 /* 359 * For polymorphic callsite, check whether the cached class pointer matches 360 * the current one. If so setup the Dalvik frame and return to the 361 * Thumb code through the link register to transfer control to the callee 362 * method through a dedicated chaining cell. 363 * 364 * The predicted chaining cell is declared in ArmLIR.h with the 365 * following layout: 366 * 367 * typedef struct PredictedChainingCell { 368 * u4 branch; 369 * const ClassObject *clazz; 370 * const Method *method; 371 * u4 counter; 372 * } PredictedChainingCell; 373 * 374 * Upon returning to the callsite: 375 * - lr : to branch to the chaining cell 376 * - lr+2: to punt to the interpreter 377 * - lr+4: to fully resolve the callee and may rechain. 378 * r3 <- class 379 * r9 <- counter 380 */ 381 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 382 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 383 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 384 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 385 ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount 386 cmp r3, r8 @ predicted class == actual class? 387#if defined(WITH_JIT_TUNING) 388 ldr r7, .LdvmICHitCount 389 ldreq r10, [r7, #0] 390 add r10, r10, #1 391 streq r10, [r7, #0] 392#endif 393 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 394 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 395 beq .LinvokeChain @ predicted chain is valid 396 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 397 cmp r8, #0 @ initialized class or not 398 moveq r1, #0 399 subne r1, r9, #1 @ count-- 400 strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState 401 add lr, lr, #4 @ return to fully-resolve landing pad 402 /* 403 * r1 <- count 404 * r2 <- &predictedChainCell 405 * r3 <- this->class 406 * r4 <- dPC 407 * r7 <- this->class->vtable 408 */ 409 bx lr 410 411/* ------------------------------ */ 412 .balign 4 413 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE 414dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE: 415/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 416 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 417 @ r7 = methodToCall->registersSize 418 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 419 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 420 add r3, r1, #1 @ Thumb addr is odd 421 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 422 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 423 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 424 ldr r8, [r8] @ r3<- suspendCount (int) 425 cmp r10, r9 @ bottom < interpStackEnd? 426 bxlo lr @ return to raise stack overflow excep. 427 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 428 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 429 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 430 431 @ set up newSaveArea 432 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 433 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 434 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 435 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 436 cmp r8, #0 @ suspendCount != 0 437 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 438#if !defined(WITH_SELF_VERIFICATION) 439 bxne lr @ bail to the interpreter 440#else 441 bx lr @ bail to interpreter unconditionally 442#endif 443 444 @ go ahead and transfer control to the native code 445 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 446 mov r2, #0 447 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 448 str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache 449 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 450 @ newFp->localRefCookie=top 451 mov r9, r3 @ r9<- glue->self (preserve) 452 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 453 454 mov r2, r0 @ r2<- methodToCall 455 mov r0, r1 @ r0<- newFP 456 add r1, rGLUE, #offGlue_retval @ r1<- &retval 457#if defined(WITH_INLINE_PROFILING) 458 @ r2=methodToCall, r6=rGLUE 459 stmfd sp!, {r2,r6} @ to be consumed after JNI return 460 stmfd sp!, {r0-r3} @ preserve r0-r3 461 mov r0, r2 462 mov r1, r6 463 @ r0=JNIMethod, r1=rGlue 464 LDR_PC_LR ".LdvmFastMethodTraceEnter" 465 ldmfd sp!, {r0-r3} @ restore r0-r3 466#endif 467 468 blx r8 @ off to the native code 469 470#if defined(WITH_INLINE_PROFILING) 471 ldmfd sp!, {r0-r1} @ restore r2 and r6 472 @ r0=JNIMethod, r1=rGlue 473 LDR_PC_LR ".LdvmFastNativeMethodTraceExit" 474#endif 475 @ native return; r9=self, r10=newSaveArea 476 @ equivalent to dvmPopJniLocals 477 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 478 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 479 ldr r1, [r9, #offThread_exception] @ check for exception 480 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 481 cmp r1, #0 @ null? 482 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 483 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 484 485 @ r0 = dalvikCallsitePC 486 bne .LhandleException @ no, handle exception 487 488 str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly 489 cmp r2, #0 @ return chaining cell still exists? 490 bxne r2 @ yes - go ahead 491 492 @ continue executing the next instruction through the interpreter 493 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 494 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 495#if defined(WITH_JIT_TUNING) 496 mov r0, #kCallsiteInterpreted 497#endif 498 mov pc, r1 499 500/* ------------------------------ */ 501 .balign 4 502 .global dvmCompiler_TEMPLATE_MUL_LONG 503dvmCompiler_TEMPLATE_MUL_LONG: 504/* File: armv5te/TEMPLATE_MUL_LONG.S */ 505 /* 506 * Signed 64-bit integer multiply. 507 * 508 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 509 * 510 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 511 * WX 512 * x YZ 513 * -------- 514 * ZW ZX 515 * YW YX 516 * 517 * The low word of the result holds ZX, the high word holds 518 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 519 * it doesn't fit in the low 64 bits. 520 * 521 * Unlike most ARM math operations, multiply instructions have 522 * restrictions on using the same register more than once (Rd and Rm 523 * cannot be the same). 524 */ 525 /* mul-long vAA, vBB, vCC */ 526 mul ip, r2, r1 @ ip<- ZxW 527 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 528 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 529 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 530 mov r0,r9 531 mov r1,r10 532 bx lr 533 534/* ------------------------------ */ 535 .balign 4 536 .global dvmCompiler_TEMPLATE_SHL_LONG 537dvmCompiler_TEMPLATE_SHL_LONG: 538/* File: armv5te/TEMPLATE_SHL_LONG.S */ 539 /* 540 * Long integer shift. This is different from the generic 32/64-bit 541 * binary operations because vAA/vBB are 64-bit but vCC (the shift 542 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 543 * 6 bits. 544 */ 545 /* shl-long vAA, vBB, vCC */ 546 and r2, r2, #63 @ r2<- r2 & 0x3f 547 mov r1, r1, asl r2 @ r1<- r1 << r2 548 rsb r3, r2, #32 @ r3<- 32 - r2 549 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 550 subs ip, r2, #32 @ ip<- r2 - 32 551 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 552 mov r0, r0, asl r2 @ r0<- r0 << r2 553 bx lr 554 555/* ------------------------------ */ 556 .balign 4 557 .global dvmCompiler_TEMPLATE_SHR_LONG 558dvmCompiler_TEMPLATE_SHR_LONG: 559/* File: armv5te/TEMPLATE_SHR_LONG.S */ 560 /* 561 * Long integer shift. This is different from the generic 32/64-bit 562 * binary operations because vAA/vBB are 64-bit but vCC (the shift 563 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 564 * 6 bits. 565 */ 566 /* shr-long vAA, vBB, vCC */ 567 and r2, r2, #63 @ r0<- r0 & 0x3f 568 mov r0, r0, lsr r2 @ r0<- r2 >> r2 569 rsb r3, r2, #32 @ r3<- 32 - r2 570 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 571 subs ip, r2, #32 @ ip<- r2 - 32 572 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 573 mov r1, r1, asr r2 @ r1<- r1 >> r2 574 bx lr 575 576/* ------------------------------ */ 577 .balign 4 578 .global dvmCompiler_TEMPLATE_USHR_LONG 579dvmCompiler_TEMPLATE_USHR_LONG: 580/* File: armv5te/TEMPLATE_USHR_LONG.S */ 581 /* 582 * Long integer shift. This is different from the generic 32/64-bit 583 * binary operations because vAA/vBB are 64-bit but vCC (the shift 584 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 585 * 6 bits. 586 */ 587 /* ushr-long vAA, vBB, vCC */ 588 and r2, r2, #63 @ r0<- r0 & 0x3f 589 mov r0, r0, lsr r2 @ r0<- r2 >> r2 590 rsb r3, r2, #32 @ r3<- 32 - r2 591 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 592 subs ip, r2, #32 @ ip<- r2 - 32 593 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 594 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 595 bx lr 596 597/* ------------------------------ */ 598 .balign 4 599 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP 600dvmCompiler_TEMPLATE_ADD_FLOAT_VFP: 601/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */ 602/* File: armv5te-vfp/fbinop.S */ 603 /* 604 * Generic 32-bit floating point operation. Provide an "instr" line that 605 * specifies an instruction that performs s2 = s0 op s1. 606 * 607 * On entry: 608 * r0 = target dalvik register address 609 * r1 = op1 address 610 * r2 = op2 address 611 */ 612 flds s0,[r1] 613 flds s1,[r2] 614 fadds s2, s0, s1 615 fsts s2,[r0] 616 bx lr 617 618 619/* ------------------------------ */ 620 .balign 4 621 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP 622dvmCompiler_TEMPLATE_SUB_FLOAT_VFP: 623/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */ 624/* File: armv5te-vfp/fbinop.S */ 625 /* 626 * Generic 32-bit floating point operation. Provide an "instr" line that 627 * specifies an instruction that performs s2 = s0 op s1. 628 * 629 * On entry: 630 * r0 = target dalvik register address 631 * r1 = op1 address 632 * r2 = op2 address 633 */ 634 flds s0,[r1] 635 flds s1,[r2] 636 fsubs s2, s0, s1 637 fsts s2,[r0] 638 bx lr 639 640 641/* ------------------------------ */ 642 .balign 4 643 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP 644dvmCompiler_TEMPLATE_MUL_FLOAT_VFP: 645/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */ 646/* File: armv5te-vfp/fbinop.S */ 647 /* 648 * Generic 32-bit floating point operation. Provide an "instr" line that 649 * specifies an instruction that performs s2 = s0 op s1. 650 * 651 * On entry: 652 * r0 = target dalvik register address 653 * r1 = op1 address 654 * r2 = op2 address 655 */ 656 flds s0,[r1] 657 flds s1,[r2] 658 fmuls s2, s0, s1 659 fsts s2,[r0] 660 bx lr 661 662 663/* ------------------------------ */ 664 .balign 4 665 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP 666dvmCompiler_TEMPLATE_DIV_FLOAT_VFP: 667/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */ 668/* File: armv5te-vfp/fbinop.S */ 669 /* 670 * Generic 32-bit floating point operation. Provide an "instr" line that 671 * specifies an instruction that performs s2 = s0 op s1. 672 * 673 * On entry: 674 * r0 = target dalvik register address 675 * r1 = op1 address 676 * r2 = op2 address 677 */ 678 flds s0,[r1] 679 flds s1,[r2] 680 fdivs s2, s0, s1 681 fsts s2,[r0] 682 bx lr 683 684 685/* ------------------------------ */ 686 .balign 4 687 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP 688dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP: 689/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */ 690/* File: armv5te-vfp/fbinopWide.S */ 691 /* 692 * Generic 64-bit floating point operation. Provide an "instr" line that 693 * specifies an instruction that performs s2 = s0 op s1. 694 * 695 * On entry: 696 * r0 = target dalvik register address 697 * r1 = op1 address 698 * r2 = op2 address 699 */ 700 fldd d0,[r1] 701 fldd d1,[r2] 702 faddd d2, d0, d1 703 fstd d2,[r0] 704 bx lr 705 706 707/* ------------------------------ */ 708 .balign 4 709 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP 710dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP: 711/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */ 712/* File: armv5te-vfp/fbinopWide.S */ 713 /* 714 * Generic 64-bit floating point operation. Provide an "instr" line that 715 * specifies an instruction that performs s2 = s0 op s1. 716 * 717 * On entry: 718 * r0 = target dalvik register address 719 * r1 = op1 address 720 * r2 = op2 address 721 */ 722 fldd d0,[r1] 723 fldd d1,[r2] 724 fsubd d2, d0, d1 725 fstd d2,[r0] 726 bx lr 727 728 729/* ------------------------------ */ 730 .balign 4 731 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP 732dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP: 733/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */ 734/* File: armv5te-vfp/fbinopWide.S */ 735 /* 736 * Generic 64-bit floating point operation. Provide an "instr" line that 737 * specifies an instruction that performs s2 = s0 op s1. 738 * 739 * On entry: 740 * r0 = target dalvik register address 741 * r1 = op1 address 742 * r2 = op2 address 743 */ 744 fldd d0,[r1] 745 fldd d1,[r2] 746 fmuld d2, d0, d1 747 fstd d2,[r0] 748 bx lr 749 750 751/* ------------------------------ */ 752 .balign 4 753 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP 754dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP: 755/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */ 756/* File: armv5te-vfp/fbinopWide.S */ 757 /* 758 * Generic 64-bit floating point operation. Provide an "instr" line that 759 * specifies an instruction that performs s2 = s0 op s1. 760 * 761 * On entry: 762 * r0 = target dalvik register address 763 * r1 = op1 address 764 * r2 = op2 address 765 */ 766 fldd d0,[r1] 767 fldd d1,[r2] 768 fdivd d2, d0, d1 769 fstd d2,[r0] 770 bx lr 771 772 773/* ------------------------------ */ 774 .balign 4 775 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP 776dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP: 777/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */ 778/* File: armv5te-vfp/funopNarrower.S */ 779 /* 780 * Generic 64bit-to-32bit floating point unary operation. Provide an 781 * "instr" line that specifies an instruction that performs "s0 = op d0". 782 * 783 * For: double-to-int, double-to-float 784 * 785 * On entry: 786 * r0 = target dalvik register address 787 * r1 = src dalvik register address 788 */ 789 /* unop vA, vB */ 790 fldd d0, [r1] @ d0<- vB 791 fcvtsd s0, d0 @ s0<- op d0 792 fsts s0, [r0] @ vA<- s0 793 bx lr 794 795 796/* ------------------------------ */ 797 .balign 4 798 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP 799dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP: 800/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */ 801/* File: armv5te-vfp/funopNarrower.S */ 802 /* 803 * Generic 64bit-to-32bit floating point unary operation. Provide an 804 * "instr" line that specifies an instruction that performs "s0 = op d0". 805 * 806 * For: double-to-int, double-to-float 807 * 808 * On entry: 809 * r0 = target dalvik register address 810 * r1 = src dalvik register address 811 */ 812 /* unop vA, vB */ 813 fldd d0, [r1] @ d0<- vB 814 ftosizd s0, d0 @ s0<- op d0 815 fsts s0, [r0] @ vA<- s0 816 bx lr 817 818 819/* ------------------------------ */ 820 .balign 4 821 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP 822dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP: 823/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */ 824/* File: armv5te-vfp/funopWider.S */ 825 /* 826 * Generic 32bit-to-64bit floating point unary operation. Provide an 827 * "instr" line that specifies an instruction that performs "d0 = op s0". 828 * 829 * For: int-to-double, float-to-double 830 * 831 * On entry: 832 * r0 = target dalvik register address 833 * r1 = src dalvik register address 834 */ 835 /* unop vA, vB */ 836 flds s0, [r1] @ s0<- vB 837 fcvtds d0, s0 @ d0<- op s0 838 fstd d0, [r0] @ vA<- d0 839 bx lr 840 841 842/* ------------------------------ */ 843 .balign 4 844 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP 845dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP: 846/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */ 847/* File: armv5te-vfp/funop.S */ 848 /* 849 * Generic 32bit-to-32bit floating point unary operation. Provide an 850 * "instr" line that specifies an instruction that performs "s1 = op s0". 851 * 852 * For: float-to-int, int-to-float 853 * 854 * On entry: 855 * r0 = target dalvik register address 856 * r1 = src dalvik register address 857 */ 858 /* unop vA, vB */ 859 flds s0, [r1] @ s0<- vB 860 ftosizs s1, s0 @ s1<- op s0 861 fsts s1, [r0] @ vA<- s1 862 bx lr 863 864 865/* ------------------------------ */ 866 .balign 4 867 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP 868dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP: 869/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */ 870/* File: armv5te-vfp/funopWider.S */ 871 /* 872 * Generic 32bit-to-64bit floating point unary operation. Provide an 873 * "instr" line that specifies an instruction that performs "d0 = op s0". 874 * 875 * For: int-to-double, float-to-double 876 * 877 * On entry: 878 * r0 = target dalvik register address 879 * r1 = src dalvik register address 880 */ 881 /* unop vA, vB */ 882 flds s0, [r1] @ s0<- vB 883 fsitod d0, s0 @ d0<- op s0 884 fstd d0, [r0] @ vA<- d0 885 bx lr 886 887 888/* ------------------------------ */ 889 .balign 4 890 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP 891dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP: 892/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */ 893/* File: armv5te-vfp/funop.S */ 894 /* 895 * Generic 32bit-to-32bit floating point unary operation. Provide an 896 * "instr" line that specifies an instruction that performs "s1 = op s0". 897 * 898 * For: float-to-int, int-to-float 899 * 900 * On entry: 901 * r0 = target dalvik register address 902 * r1 = src dalvik register address 903 */ 904 /* unop vA, vB */ 905 flds s0, [r1] @ s0<- vB 906 fsitos s1, s0 @ s1<- op s0 907 fsts s1, [r0] @ vA<- s1 908 bx lr 909 910 911/* ------------------------------ */ 912 .balign 4 913 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP 914dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP: 915/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */ 916 /* 917 * Compare two floating-point values. Puts 0, 1, or -1 into the 918 * destination register based on the results of the comparison. 919 * 920 * int compare(x, y) { 921 * if (x == y) { 922 * return 0; 923 * } else if (x < y) { 924 * return -1; 925 * } else if (x > y) { 926 * return 1; 927 * } else { 928 * return 1; 929 * } 930 * } 931 * 932 * On entry: 933 * r0 = &op1 [vBB] 934 * r1 = &op2 [vCC] 935 */ 936 /* op vAA, vBB, vCC */ 937 fldd d0, [r0] @ d0<- vBB 938 fldd d1, [r1] @ d1<- vCC 939 fcmpd d0, d1 @ compare (vBB, vCC) 940 mov r0, #1 @ r0<- 1 (default) 941 fmstat @ export status flags 942 mvnmi r0, #0 @ (less than) r0<- -1 943 moveq r0, #0 @ (equal) r0<- 0 944 bx lr 945 946/* ------------------------------ */ 947 .balign 4 948 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP 949dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP: 950/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */ 951 /* 952 * Compare two floating-point values. Puts 0, 1, or -1 into the 953 * destination register based on the results of the comparison. 954 * 955 * int compare(x, y) { 956 * if (x == y) { 957 * return 0; 958 * } else if (x > y) { 959 * return 1; 960 * } else if (x < y) { 961 * return -1; 962 * } else { 963 * return -1; 964 * } 965 * } 966 * On entry: 967 * r0 = &op1 [vBB] 968 * r1 = &op2 [vCC] 969 */ 970 /* op vAA, vBB, vCC */ 971 fldd d0, [r0] @ d0<- vBB 972 fldd d1, [r1] @ d1<- vCC 973 fcmped d0, d1 @ compare (vBB, vCC) 974 mvn r0, #0 @ r0<- -1 (default) 975 fmstat @ export status flags 976 movgt r0, #1 @ (greater than) r0<- 1 977 moveq r0, #0 @ (equal) r0<- 0 978 bx lr 979 980/* ------------------------------ */ 981 .balign 4 982 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP 983dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP: 984/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */ 985 /* 986 * Compare two floating-point values. Puts 0, 1, or -1 into the 987 * destination register based on the results of the comparison. 988 * 989 * int compare(x, y) { 990 * if (x == y) { 991 * return 0; 992 * } else if (x < y) { 993 * return -1; 994 * } else if (x > y) { 995 * return 1; 996 * } else { 997 * return 1; 998 * } 999 * } 1000 * On entry: 1001 * r0 = &op1 [vBB] 1002 * r1 = &op2 [vCC] 1003 */ 1004 /* op vAA, vBB, vCC */ 1005 flds s0, [r0] @ d0<- vBB 1006 flds s1, [r1] @ d1<- vCC 1007 fcmps s0, s1 @ compare (vBB, vCC) 1008 mov r0, #1 @ r0<- 1 (default) 1009 fmstat @ export status flags 1010 mvnmi r0, #0 @ (less than) r0<- -1 1011 moveq r0, #0 @ (equal) r0<- 0 1012 bx lr 1013 1014/* ------------------------------ */ 1015 .balign 4 1016 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP 1017dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP: 1018/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */ 1019 /* 1020 * Compare two floating-point values. Puts 0, 1, or -1 into the 1021 * destination register based on the results of the comparison. 1022 * 1023 * int compare(x, y) { 1024 * if (x == y) { 1025 * return 0; 1026 * } else if (x > y) { 1027 * return 1; 1028 * } else if (x < y) { 1029 * return -1; 1030 * } else { 1031 * return -1; 1032 * } 1033 * } 1034 * On entry: 1035 * r0 = &op1 [vBB] 1036 * r1 = &op2 [vCC] 1037 */ 1038 /* op vAA, vBB, vCC */ 1039 flds s0, [r0] @ d0<- vBB 1040 flds s1, [r1] @ d1<- vCC 1041 fcmps s0, s1 @ compare (vBB, vCC) 1042 mvn r0, #0 @ r0<- -1 (default) 1043 fmstat @ export status flags 1044 movgt r0, #1 @ (greater than) r0<- 1 1045 moveq r0, #0 @ (equal) r0<- 0 1046 bx lr 1047 1048/* ------------------------------ */ 1049 .balign 4 1050 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP 1051dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP: 1052/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */ 1053 /* 1054 * 64-bit floating point vfp sqrt operation. 1055 * If the result is a NaN, bail out to library code to do 1056 * the right thing. 1057 * 1058 * On entry: 1059 * r2 src addr of op1 1060 * On exit: 1061 * r0,r1 = res 1062 */ 1063 fldd d0, [r2] 1064 fsqrtd d1, d0 1065 fcmpd d1, d1 1066 fmstat 1067 fmrrd r0, r1, d1 1068 bxeq lr @ Result OK - return 1069 ldr r2, .Lsqrt 1070 fmrrd r0, r1, d0 @ reload orig operand 1071 bx r2 @ tail call to sqrt library routine 1072 1073.Lsqrt: 1074 .word sqrt 1075 1076/* ------------------------------ */ 1077 .balign 4 1078 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON 1079dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON: 1080/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */ 1081 /* 1082 * Throw an exception from JIT'ed code. 1083 * On entry: 1084 * r0 Dalvik PC that raises the exception 1085 */ 1086 b .LhandleException 1087 1088/* ------------------------------ */ 1089 .balign 4 1090 .global dvmCompiler_TEMPLATE_MEM_OP_DECODE 1091dvmCompiler_TEMPLATE_MEM_OP_DECODE: 1092/* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */ 1093#if defined(WITH_SELF_VERIFICATION) 1094 /* 1095 * This handler encapsulates heap memory ops for selfVerification mode. 1096 * 1097 * The call to the handler is inserted prior to a heap memory operation. 1098 * This handler then calls a function to decode the memory op, and process 1099 * it accordingly. Afterwards, the handler changes the return address to 1100 * skip the memory op so it never gets executed. 1101 */ 1102 vpush {d0-d15} @ save out all fp registers 1103 push {r0-r12,lr} @ save out all registers 1104 mov r0, lr @ arg0 <- link register 1105 mov r1, sp @ arg1 <- stack pointer 1106 ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S 1107 blx r2 @ decode and handle the mem op 1108 pop {r0-r12,lr} @ restore all registers 1109 vpop {d0-d15} @ restore all fp registers 1110 bx lr @ return to compiled code 1111#endif 1112 1113/* ------------------------------ */ 1114 .balign 4 1115 .global dvmCompiler_TEMPLATE_STRING_COMPARETO 1116dvmCompiler_TEMPLATE_STRING_COMPARETO: 1117/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */ 1118 /* 1119 * String's compareTo. 1120 * 1121 * Requires r0/r1 to have been previously checked for null. Will 1122 * return negative if this's string is < comp, 0 if they are the 1123 * same and positive if >. 1124 * 1125 * IMPORTANT NOTE: 1126 * 1127 * This code relies on hard-coded offsets for string objects, and must be 1128 * kept in sync with definitions in UtfString.h. See asm-constants.h 1129 * 1130 * On entry: 1131 * r0: this object pointer 1132 * r1: comp object pointer 1133 * 1134 */ 1135 1136 mov r2, r0 @ this to r2, opening up r0 for return value 1137 subs r0, r2, r1 @ Same? 1138 bxeq lr 1139 1140 ldr r4, [r2, #STRING_FIELDOFF_OFFSET] 1141 ldr r9, [r1, #STRING_FIELDOFF_OFFSET] 1142 ldr r7, [r2, #STRING_FIELDOFF_COUNT] 1143 ldr r10, [r1, #STRING_FIELDOFF_COUNT] 1144 ldr r2, [r2, #STRING_FIELDOFF_VALUE] 1145 ldr r1, [r1, #STRING_FIELDOFF_VALUE] 1146 1147 /* 1148 * At this point, we have: 1149 * value: r2/r1 1150 * offset: r4/r9 1151 * count: r7/r10 1152 * We're going to compute 1153 * r11 <- countDiff 1154 * r10 <- minCount 1155 */ 1156 subs r11, r7, r10 1157 movls r10, r7 1158 1159 /* Now, build pointers to the string data */ 1160 add r2, r2, r4, lsl #1 1161 add r1, r1, r9, lsl #1 1162 /* 1163 * Note: data pointers point to previous element so we can use pre-index 1164 * mode with base writeback. 1165 */ 1166 add r2, #16-2 @ offset to contents[-1] 1167 add r1, #16-2 @ offset to contents[-1] 1168 1169 /* 1170 * At this point we have: 1171 * r2: *this string data 1172 * r1: *comp string data 1173 * r10: iteration count for comparison 1174 * r11: value to return if the first part of the string is equal 1175 * r0: reserved for result 1176 * r3, r4, r7, r8, r9, r12 available for loading string data 1177 */ 1178 1179 subs r10, #2 1180 blt do_remainder2 1181 1182 /* 1183 * Unroll the first two checks so we can quickly catch early mismatch 1184 * on long strings (but preserve incoming alignment) 1185 */ 1186 1187 ldrh r3, [r2, #2]! 1188 ldrh r4, [r1, #2]! 1189 ldrh r7, [r2, #2]! 1190 ldrh r8, [r1, #2]! 1191 subs r0, r3, r4 1192 subeqs r0, r7, r8 1193 bxne lr 1194 cmp r10, #28 1195 bgt do_memcmp16 1196 subs r10, #3 1197 blt do_remainder 1198 1199loopback_triple: 1200 ldrh r3, [r2, #2]! 1201 ldrh r4, [r1, #2]! 1202 ldrh r7, [r2, #2]! 1203 ldrh r8, [r1, #2]! 1204 ldrh r9, [r2, #2]! 1205 ldrh r12,[r1, #2]! 1206 subs r0, r3, r4 1207 subeqs r0, r7, r8 1208 subeqs r0, r9, r12 1209 bxne lr 1210 subs r10, #3 1211 bge loopback_triple 1212 1213do_remainder: 1214 adds r10, #3 1215 beq returnDiff 1216 1217loopback_single: 1218 ldrh r3, [r2, #2]! 1219 ldrh r4, [r1, #2]! 1220 subs r0, r3, r4 1221 bxne lr 1222 subs r10, #1 1223 bne loopback_single 1224 1225returnDiff: 1226 mov r0, r11 1227 bx lr 1228 1229do_remainder2: 1230 adds r10, #2 1231 bne loopback_single 1232 mov r0, r11 1233 bx lr 1234 1235 /* Long string case */ 1236do_memcmp16: 1237 mov r4, lr 1238 ldr lr, .Lmemcmp16 1239 mov r7, r11 1240 add r0, r2, #2 1241 add r1, r1, #2 1242 mov r2, r10 1243 blx lr 1244 cmp r0, #0 1245 bxne r4 1246 mov r0, r7 1247 bx r4 1248 1249.Lmemcmp16: 1250 .word __memcmp16 1251 1252/* ------------------------------ */ 1253 .balign 4 1254 .global dvmCompiler_TEMPLATE_STRING_INDEXOF 1255dvmCompiler_TEMPLATE_STRING_INDEXOF: 1256/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */ 1257 /* 1258 * String's indexOf. 1259 * 1260 * Requires r0 to have been previously checked for null. Will 1261 * return index of match of r1 in r0. 1262 * 1263 * IMPORTANT NOTE: 1264 * 1265 * This code relies on hard-coded offsets for string objects, and must be 1266 * kept in sync wth definitions in UtfString.h See asm-constants.h 1267 * 1268 * On entry: 1269 * r0: string object pointer 1270 * r1: char to match 1271 * r2: Starting offset in string data 1272 */ 1273 1274 ldr r7, [r0, #STRING_FIELDOFF_OFFSET] 1275 ldr r8, [r0, #STRING_FIELDOFF_COUNT] 1276 ldr r0, [r0, #STRING_FIELDOFF_VALUE] 1277 1278 /* 1279 * At this point, we have: 1280 * r0: object pointer 1281 * r1: char to match 1282 * r2: starting offset 1283 * r7: offset 1284 * r8: string length 1285 */ 1286 1287 /* Build pointer to start of string data */ 1288 add r0, #16 1289 add r0, r0, r7, lsl #1 1290 1291 /* Save a copy of starting data in r7 */ 1292 mov r7, r0 1293 1294 /* Clamp start to [0..count] */ 1295 cmp r2, #0 1296 movlt r2, #0 1297 cmp r2, r8 1298 movgt r2, r8 1299 1300 /* Build pointer to start of data to compare and pre-bias */ 1301 add r0, r0, r2, lsl #1 1302 sub r0, #2 1303 1304 /* Compute iteration count */ 1305 sub r8, r2 1306 1307 /* 1308 * At this point we have: 1309 * r0: start of data to test 1310 * r1: chat to compare 1311 * r8: iteration count 1312 * r7: original start of string 1313 * r3, r4, r9, r10, r11, r12 available for loading string data 1314 */ 1315 1316 subs r8, #4 1317 blt indexof_remainder 1318 1319indexof_loop4: 1320 ldrh r3, [r0, #2]! 1321 ldrh r4, [r0, #2]! 1322 ldrh r10, [r0, #2]! 1323 ldrh r11, [r0, #2]! 1324 cmp r3, r1 1325 beq match_0 1326 cmp r4, r1 1327 beq match_1 1328 cmp r10, r1 1329 beq match_2 1330 cmp r11, r1 1331 beq match_3 1332 subs r8, #4 1333 bge indexof_loop4 1334 1335indexof_remainder: 1336 adds r8, #4 1337 beq indexof_nomatch 1338 1339indexof_loop1: 1340 ldrh r3, [r0, #2]! 1341 cmp r3, r1 1342 beq match_3 1343 subs r8, #1 1344 bne indexof_loop1 1345 1346indexof_nomatch: 1347 mov r0, #-1 1348 bx lr 1349 1350match_0: 1351 sub r0, #6 1352 sub r0, r7 1353 asr r0, r0, #1 1354 bx lr 1355match_1: 1356 sub r0, #4 1357 sub r0, r7 1358 asr r0, r0, #1 1359 bx lr 1360match_2: 1361 sub r0, #2 1362 sub r0, r7 1363 asr r0, r0, #1 1364 bx lr 1365match_3: 1366 sub r0, r7 1367 asr r0, r0, #1 1368 bx lr 1369 1370/* ------------------------------ */ 1371 .balign 4 1372 .global dvmCompiler_TEMPLATE_INTERPRET 1373dvmCompiler_TEMPLATE_INTERPRET: 1374/* File: armv5te/TEMPLATE_INTERPRET.S */ 1375 /* 1376 * This handler transfers control to the interpeter without performing 1377 * any lookups. It may be called either as part of a normal chaining 1378 * operation, or from the transition code in header.S. We distinquish 1379 * the two cases by looking at the link register. If called from a 1380 * translation chain, it will point to the chaining Dalvik PC -3. 1381 * On entry: 1382 * lr - if NULL: 1383 * r1 - the Dalvik PC to begin interpretation. 1384 * else 1385 * [lr, #3] contains Dalvik PC to begin interpretation 1386 * rGLUE - pointer to interpState 1387 * rFP - Dalvik frame pointer 1388 */ 1389 cmp lr, #0 1390 ldrne r1,[lr, #3] 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 r0, [rGLUE, #offGlue_ppJitProfTable] 1421 ldr r0, [r0] 1422 ldr r2, .LdvmJitToInterpNoChain 1423 str r0, [rGLUE, #offGlue_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 r0, [rGLUE, #offGlue_ppJitProfTable] 1452 ldr r1, [rGLUE, #offGlue_self] 1453 ldr r0, [r0] 1454 ldr r1, [r1, #offThread_exception] 1455 str r0, [rGLUE, #offGlue_pJitProfTable] 1456 cmp r1, #0 1457 beq 1f 1458 ldr r2, .LhandleException 1459 sub r0, r4, #2 @ roll dPC back to this monitor instruction 1460 bx r2 14611: 1462 @ Bail to interpreter - no chain [note - r4 still contains rPC] 1463#if defined(WITH_JIT_TUNING) 1464 mov r0, #kHeavyweightMonitor 1465#endif 1466 ldr pc, .LdvmJitToInterpNoChain 1467 1468 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1469/* File: armv5te/footer.S */ 1470/* 1471 * =========================================================================== 1472 * Common subroutines and data 1473 * =========================================================================== 1474 */ 1475 1476 .text 1477 .align 2 1478.LinvokeNative: 1479 @ Prep for the native call 1480 @ r1 = newFP, r0 = methodToCall 1481 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1482 mov r2, #0 1483 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 1484 str r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache 1485 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 1486 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1487 @ newFp->localRefCookie=top 1488 mov r9, r3 @ r9<- glue->self (preserve) 1489 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1490 1491 mov r2, r0 @ r2<- methodToCall 1492 mov r0, r1 @ r0<- newFP 1493 add r1, rGLUE, #offGlue_retval @ r1<- &retval 1494#if defined(WITH_INLINE_PROFILING) 1495 @ r2: methodToCall, r6: rGLUE 1496 stmfd sp!, {r2,r6} 1497 stmfd sp!, {r0-r3} 1498 mov r0, r2 1499 mov r1, r6 1500 LDR_PC_LR ".LdvmFastMethodTraceEnter" 1501 ldmfd sp!, {r0-r3} 1502#endif 1503 1504 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 1505 1506#if defined(WITH_INLINE_PROFILING) 1507 ldmfd sp!, {r0-r1} 1508 LDR_PC_LR ".LdvmFastNativeMethodTraceExit" 1509#endif 1510 @ Refresh Jit's on/off status 1511 ldr r3, [rGLUE, #offGlue_ppJitProfTable] 1512 1513 @ native return; r9=self, r10=newSaveArea 1514 @ equivalent to dvmPopJniLocals 1515 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1516 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1517 ldr r1, [r9, #offThread_exception] @ check for exception 1518 ldr r3, [r3] @ r1 <- pointer to Jit profile table 1519 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 1520 cmp r1, #0 @ null? 1521 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 1522 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC 1523 str r3, [rGLUE, #offGlue_pJitProfTable] @ cache current JitProfTable 1524 1525 @ r0 = dalvikCallsitePC 1526 bne .LhandleException @ no, handle exception 1527 1528 str r2, [r9, #offThread_inJitCodeCache] @ set the new mode 1529 cmp r2, #0 @ return chaining cell still exists? 1530 bxne r2 @ yes - go ahead 1531 1532 @ continue executing the next instruction through the interpreter 1533 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S 1534 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes) 1535#if defined(WITH_JIT_TUNING) 1536 mov r0, #kCallsiteInterpreted 1537#endif 1538 mov pc, r1 1539 1540/* 1541 * On entry: 1542 * r0 Faulting Dalvik PC 1543 */ 1544.LhandleException: 1545#if defined(WITH_SELF_VERIFICATION) 1546 ldr pc, .LdeadFood @ should not see this under self-verification mode 1547.LdeadFood: 1548 .word 0xdeadf00d 1549#endif 1550 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1551 mov r2, #0 1552 str r2, [r3, #offThread_inJitCodeCache] @ in interpreter land 1553 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1554 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1555 mov rPC, r0 @ reload the faulting Dalvik address 1556 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown 1557 1558 .align 2 1559.LdvmAsmInstructionStart: 1560 .word dvmAsmInstructionStart 1561.LdvmJitToInterpNoChainNoProfile: 1562 .word dvmJitToInterpNoChainNoProfile 1563.LdvmJitToInterpTraceSelectNoChain: 1564 .word dvmJitToInterpTraceSelectNoChain 1565.LdvmJitToInterpNoChain: 1566 .word dvmJitToInterpNoChain 1567.LdvmMterpStdBail: 1568 .word dvmMterpStdBail 1569.LdvmMterpCommonExceptionThrown: 1570 .word dvmMterpCommonExceptionThrown 1571.LdvmLockObject: 1572 .word dvmLockObject 1573#if defined(WITH_JIT_TUNING) 1574.LdvmICHitCount: 1575 .word gDvmICHitCount 1576#endif 1577#if defined(WITH_SELF_VERIFICATION) 1578.LdvmSelfVerificationMemOpDecode: 1579 .word dvmSelfVerificationMemOpDecode 1580#endif 1581#if defined(WITH_INLINE_PROFILING) 1582.LdvmFastMethodTraceEnter: 1583 .word dvmFastMethodTraceEnter 1584.LdvmFastNativeMethodTraceExit: 1585 .word dvmFastNativeMethodTraceExit 1586.LdvmFastJavaMethodTraceExit: 1587 .word dvmFastJavaMethodTraceExit 1588#endif 1589.L__aeabi_cdcmple: 1590 .word __aeabi_cdcmple 1591.L__aeabi_cfcmple: 1592 .word __aeabi_cfcmple 1593 1594 .global dmvCompilerTemplateEnd 1595dmvCompilerTemplateEnd: 1596 1597#endif /* WITH_JIT */ 1598 1599