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