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