CompilerTemplateAsm-armv5te-vfp.S revision 342806dae77556290dfe0760e6fe3117d812c7ba
1/* 2 * This file was generated automatically by gen-template.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24#if defined(WITH_JIT) 25 26/* 27 * ARMv5 definitions and declarations. 28 */ 29 30/* 31ARM EABI general notes: 32 33r0-r3 hold first 4 args to a method; they are not preserved across method calls 34r4-r8 are available for general use 35r9 is given special treatment in some situations, but not for us 36r10 (sl) seems to be generally available 37r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 38r12 (ip) is scratch -- not preserved across method calls 39r13 (sp) should be managed carefully in case a signal arrives 40r14 (lr) must be preserved 41r15 (pc) can be tinkered with directly 42 43r0 holds returns of <= 4 bytes 44r0-r1 hold returns of 8 bytes, low word in r0 45 46Callee must save/restore r4+ (except r12) if it modifies them. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59JIT and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 67The following registers have fixed assignments in mterp but are scratch 68registers in compiled code 69 70 reg nick purpose 71 r4 rPC interpreted program counter, used for fetching instructions 72 r7 rINST first 16-bit code unit of current instruction 73 r8 rIBASE interpreted instruction base pointer, used for computed goto 74 75Macros are provided for common operations. Each macro MUST emit only 76one instruction to make instruction-counting easier. They MUST NOT alter 77unspecified registers or condition codes. 78*/ 79 80/* single-purpose registers, given names for clarity */ 81#define rPC r4 82#define rFP r5 83#define rGLUE r6 84#define rINST r7 85#define rIBASE r8 86 87/* 88 * Given a frame pointer, find the stack save area. 89 * 90 * In C this is "((StackSaveArea*)(_fp) -1)". 91 */ 92#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 93 sub _reg, _fpreg, #sizeofStackSaveArea 94 95#define EXPORT_PC() \ 96 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 97 98/* 99 * This is a #include, not a %include, because we want the C pre-processor 100 * to expand the macros into assembler assignment statements. 101 */ 102#include "../../../mterp/common/asm-constants.h" 103 104 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 * Save & restore for callee-save FP registers. 125 * On entry: 126 * r0 : pointer to save area of JIT_CALLEE_SAVE_WORD_SIZE 127 */ 128 .text 129 .align 2 130 .global dvmJitCalleeSave 131 .type dvmJitCalleeSave, %function 132dvmJitCalleeSave: 133 vstmia r0, {d8-d15} 134 bx lr 135 136 .global dvmJitCalleeRestore 137 .type dvmJitCalleeRestore, %function 138dvmJitCalleeRestore: 139 vldmia r0, {d8-d15} 140 bx lr 141 142 143 144 .global dvmCompilerTemplateStart 145 .type dvmCompilerTemplateStart, %function 146 .text 147 148dvmCompilerTemplateStart: 149 150/* ------------------------------ */ 151 .balign 4 152 .global dvmCompiler_TEMPLATE_CMP_LONG 153dvmCompiler_TEMPLATE_CMP_LONG: 154/* File: armv5te/TEMPLATE_CMP_LONG.S */ 155 /* 156 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 157 * register based on the results of the comparison. 158 * 159 * We load the full values with LDM, but in practice many values could 160 * be resolved by only looking at the high word. This could be made 161 * faster or slower by splitting the LDM into a pair of LDRs. 162 * 163 * If we just wanted to set condition flags, we could do this: 164 * subs ip, r0, r2 165 * sbcs ip, r1, r3 166 * subeqs ip, r0, r2 167 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 168 * integer value, which we can do with 2 conditional mov/mvn instructions 169 * (set 1, set -1; if they're equal we already have 0 in ip), giving 170 * us a constant 5-cycle path plus a branch at the end to the 171 * instruction epilogue code. The multi-compare approach below needs 172 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 173 * in the worst case (the 64-bit values are equal). 174 */ 175 /* cmp-long vAA, vBB, vCC */ 176 cmp r1, r3 @ compare (vBB+1, vCC+1) 177 blt .LTEMPLATE_CMP_LONG_less @ signed compare on high part 178 bgt .LTEMPLATE_CMP_LONG_greater 179 subs r0, r0, r2 @ r0<- r0 - r2 180 bxeq lr 181 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part 182.LTEMPLATE_CMP_LONG_less: 183 mvn r0, #0 @ r0<- -1 184 bx lr 185.LTEMPLATE_CMP_LONG_greater: 186 mov r0, #1 @ r0<- 1 187 bx lr 188 189 190/* ------------------------------ */ 191 .balign 4 192 .global dvmCompiler_TEMPLATE_RETURN 193dvmCompiler_TEMPLATE_RETURN: 194/* File: armv5te/TEMPLATE_RETURN.S */ 195 /* 196 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX. 197 * If the stored value in returnAddr 198 * is non-zero, the caller is compiled by the JIT thus return to the 199 * address in the code cache following the invoke instruction. Otherwise 200 * return to the special dvmJitToInterpNoChain entry point. 201 */ 202 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 203 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame 204 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 205 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc 206#if !defined(WITH_SELF_VERIFICATION) 207 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret 208#else 209 mov r9, #0 @ disable chaining 210#endif 211 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)] 212 @ r2<- method we're returning to 213 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 214 cmp r2, #0 @ break frame? 215#if !defined(WITH_SELF_VERIFICATION) 216 beq 1f @ bail to interpreter 217#else 218 blxeq lr @ punt to interpreter and compare state 219#endif 220 ldr r1, .LdvmJitToInterpNoChain @ defined in footer.S 221 mov rFP, r10 @ publish new FP 222 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 223 ldr r8, [r8] @ r8<- suspendCount 224 225 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 226 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex 227 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 228 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes) 229 str r0, [rGLUE, #offGlue_methodClassDex] 230 cmp r8, #0 @ check the suspendCount 231 movne r9, #0 @ clear the chaining cell address 232 cmp r9, #0 @ chaining cell exists? 233 blxne r9 @ jump to the chaining cell 234#if defined(EXIT_STATS) 235 mov r0, #kCallsiteInterpreted 236#endif 237 mov pc, r1 @ callsite is interpreted 2381: 239 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE() 240 ldr r2, .LdvmMterpStdBail @ defined in footer.S 241 mov r1, #0 @ changeInterp = false 242 mov r0, rGLUE @ Expecting rGLUE in r0 243 blx r2 @ exit the interpreter 244 245/* ------------------------------ */ 246 .balign 4 247 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT 248dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT: 249/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */ 250 /* 251 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC 252 * into rPC then jump to dvmJitToInterpNoChain to dispatch the 253 * runtime-resolved callee. 254 */ 255 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 256 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 257 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 258 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 259 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 260 add r3, r1, #1 @ Thumb addr is odd 261 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 262 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 263 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 264 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 265 ldr r8, [r8] @ r3<- suspendCount (int) 266 cmp r10, r9 @ bottom < interpStackEnd? 267 bxlt lr @ return to raise stack overflow excep. 268 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 269 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 270 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags 271 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 272 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 273 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 274 275 276 @ set up newSaveArea 277 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 278 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 279 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 280 cmp r8, #0 @ suspendCount != 0 281 bxne lr @ bail to the interpreter 282 tst r10, #ACC_NATIVE 283#if !defined(WITH_SELF_VERIFICATION) 284 bne .LinvokeNative 285#else 286 bxne lr @ bail to the interpreter 287#endif 288 289 ldr r10, .LdvmJitToInterpNoChain 290 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 291 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 292 293 @ Update "glue" values for the new method 294 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 295 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 296 mov rFP, r1 @ fp = newFp 297 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 298 299 @ Start executing the callee 300#if defined(EXIT_STATS) 301 mov r0, #kInlineCacheMiss 302#endif 303 mov pc, r10 @ dvmJitToInterpNoChain 304 305/* ------------------------------ */ 306 .balign 4 307 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN 308dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN: 309/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */ 310 /* 311 * For monomorphic callsite, setup the Dalvik frame and return to the 312 * Thumb code through the link register to transfer control to the callee 313 * method through a dedicated chaining cell. 314 */ 315 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 316 @ methodToCall is guaranteed to be non-native 317.LinvokeChain: 318 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 319 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize 320 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 321 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 322 add r3, r1, #1 @ Thumb addr is odd 323 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 324 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 325 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 326 add r12, lr, #2 @ setup the punt-to-interp address 327 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize) 328 ldr r8, [r8] @ r3<- suspendCount (int) 329 cmp r10, r9 @ bottom < interpStackEnd? 330 bxlt r12 @ return to raise stack overflow excep. 331 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 332 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz 333 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 334 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 335 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 336 337 338 @ set up newSaveArea 339 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 340 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 341 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 342 cmp r8, #0 @ suspendCount != 0 343 bxne r12 @ bail to the interpreter 344 345 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 346 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 347 348 @ Update "glue" values for the new method 349 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 350 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 351 mov rFP, r1 @ fp = newFp 352 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp 353 354 bx lr @ return to the callee-chaining cell 355 356 357 358/* ------------------------------ */ 359 .balign 4 360 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN 361dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN: 362/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */ 363 /* 364 * For polymorphic callsite, check whether the cached class pointer matches 365 * the current one. If so setup the Dalvik frame and return to the 366 * Thumb code through the link register to transfer control to the callee 367 * method through a dedicated chaining cell. 368 * 369 * The predicted chaining cell is declared in ArmLIR.h with the 370 * following layout: 371 * 372 * typedef struct PredictedChainingCell { 373 * u4 branch; 374 * const ClassObject *clazz; 375 * const Method *method; 376 * u4 counter; 377 * } PredictedChainingCell; 378 * 379 * Upon returning to the callsite: 380 * - lr : to branch to the chaining cell 381 * - lr+2: to punt to the interpreter 382 * - lr+4: to fully resolve the callee and may rechain. 383 * r3 <- class 384 * r9 <- counter 385 */ 386 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite 387 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class 388 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz 389 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method 390 ldr r9, [r2, #12] @ r9 <- predictedChainCell->counter 391 cmp r3, r8 @ predicted class == actual class? 392 beq .LinvokeChain @ predicted chain is valid 393 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable 394 sub r1, r9, #1 @ count-- 395 str r1, [r2, #12] @ write back to PredictedChainingCell->counter 396 add lr, lr, #4 @ return to fully-resolve landing pad 397 /* 398 * r1 <- count 399 * r2 <- &predictedChainCell 400 * r3 <- this->class 401 * r4 <- dPC 402 * r7 <- this->class->vtable 403 */ 404 bx lr 405 406/* ------------------------------ */ 407 .balign 4 408 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE 409dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE: 410/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */ 411 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite 412 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize 413 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 414 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount 415 add r3, r1, #1 @ Thumb addr is odd 416 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 417 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize) 418 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area 419 ldr r8, [r8] @ r3<- suspendCount (int) 420 cmp r10, r9 @ bottom < interpStackEnd? 421 bxlt lr @ return to raise stack overflow excep. 422 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite 423 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 424 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)] 425 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns 426 427 428 @ set up newSaveArea 429 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)] 430 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)] 431 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 432 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)] 433 cmp r8, #0 @ suspendCount != 0 434 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc 435#if !defined(WITH_SELF_VERIFICATION) 436 bxne lr @ bail to the interpreter 437#else 438 bx lr @ bail to interpreter unconditionally 439#endif 440 441 @ go ahead and transfer control to the native code 442 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 443 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 444 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 445 @ newFp->localRefCookie=top 446 mov r9, r3 @ r9<- glue->self (preserve) 447 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 448 449 mov r2, r0 @ r2<- methodToCall 450 mov r0, r1 @ r0<- newFP 451 add r1, rGLUE, #offGlue_retval @ r1<- &retval 452 453 blx r8 @ off to the native code 454 455 @ native return; r9=self, r10=newSaveArea 456 @ equivalent to dvmPopJniLocals 457 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 458 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 459 ldr r1, [r9, #offThread_exception] @ check for exception 460 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 461 cmp r1, #0 @ null? 462 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 463 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)] 464 bne .LhandleException @ no, handle exception 465 bx r2 466 467 468/* ------------------------------ */ 469 .balign 4 470 .global dvmCompiler_TEMPLATE_MUL_LONG 471dvmCompiler_TEMPLATE_MUL_LONG: 472/* File: armv5te/TEMPLATE_MUL_LONG.S */ 473 /* 474 * Signed 64-bit integer multiply. 475 * 476 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1 477 * 478 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 479 * WX 480 * x YZ 481 * -------- 482 * ZW ZX 483 * YW YX 484 * 485 * The low word of the result holds ZX, the high word holds 486 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 487 * it doesn't fit in the low 64 bits. 488 * 489 * Unlike most ARM math operations, multiply instructions have 490 * restrictions on using the same register more than once (Rd and Rm 491 * cannot be the same). 492 */ 493 /* mul-long vAA, vBB, vCC */ 494 mul ip, r2, r1 @ ip<- ZxW 495 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 496 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 497 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 498 mov r0,r9 499 mov r1,r10 500 bx lr 501 502/* ------------------------------ */ 503 .balign 4 504 .global dvmCompiler_TEMPLATE_SHL_LONG 505dvmCompiler_TEMPLATE_SHL_LONG: 506/* File: armv5te/TEMPLATE_SHL_LONG.S */ 507 /* 508 * Long integer shift. This is different from the generic 32/64-bit 509 * binary operations because vAA/vBB are 64-bit but vCC (the shift 510 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 511 * 6 bits. 512 */ 513 /* shl-long vAA, vBB, vCC */ 514 and r2, r2, #63 @ r2<- r2 & 0x3f 515 mov r1, r1, asl r2 @ r1<- r1 << r2 516 rsb r3, r2, #32 @ r3<- 32 - r2 517 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 518 subs ip, r2, #32 @ ip<- r2 - 32 519 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 520 mov r0, r0, asl r2 @ r0<- r0 << r2 521 bx lr 522 523/* ------------------------------ */ 524 .balign 4 525 .global dvmCompiler_TEMPLATE_SHR_LONG 526dvmCompiler_TEMPLATE_SHR_LONG: 527/* File: armv5te/TEMPLATE_SHR_LONG.S */ 528 /* 529 * Long integer shift. This is different from the generic 32/64-bit 530 * binary operations because vAA/vBB are 64-bit but vCC (the shift 531 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 532 * 6 bits. 533 */ 534 /* shr-long vAA, vBB, vCC */ 535 and r2, r2, #63 @ r0<- r0 & 0x3f 536 mov r0, r0, lsr r2 @ r0<- r2 >> r2 537 rsb r3, r2, #32 @ r3<- 32 - r2 538 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 539 subs ip, r2, #32 @ ip<- r2 - 32 540 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 541 mov r1, r1, asr r2 @ r1<- r1 >> r2 542 bx lr 543 544 545/* ------------------------------ */ 546 .balign 4 547 .global dvmCompiler_TEMPLATE_USHR_LONG 548dvmCompiler_TEMPLATE_USHR_LONG: 549/* File: armv5te/TEMPLATE_USHR_LONG.S */ 550 /* 551 * Long integer shift. This is different from the generic 32/64-bit 552 * binary operations because vAA/vBB are 64-bit but vCC (the shift 553 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low 554 * 6 bits. 555 */ 556 /* ushr-long vAA, vBB, vCC */ 557 and r2, r2, #63 @ r0<- r0 & 0x3f 558 mov r0, r0, lsr r2 @ r0<- r2 >> r2 559 rsb r3, r2, #32 @ r3<- 32 - r2 560 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 561 subs ip, r2, #32 @ ip<- r2 - 32 562 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 563 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 564 bx lr 565 566 567/* ------------------------------ */ 568 .balign 4 569 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP 570dvmCompiler_TEMPLATE_ADD_FLOAT_VFP: 571/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */ 572/* File: armv5te-vfp/fbinop.S */ 573 /* 574 * Generic 32-bit floating point operation. Provide an "instr" line that 575 * specifies an instruction that performs s2 = s0 op s1. 576 * 577 * On entry: 578 * r0 = target dalvik register address 579 * r1 = op1 address 580 * r2 = op2 address 581 */ 582 flds s0,[r1] 583 flds s1,[r2] 584 fadds s2, s0, s1 585 fsts s2,[r0] 586 bx lr 587 588 589/* ------------------------------ */ 590 .balign 4 591 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP 592dvmCompiler_TEMPLATE_SUB_FLOAT_VFP: 593/* File: armv5te-vfp/TEMPLATE_SUB_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 fsubs s2, s0, s1 607 fsts s2,[r0] 608 bx lr 609 610 611/* ------------------------------ */ 612 .balign 4 613 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP 614dvmCompiler_TEMPLATE_MUL_FLOAT_VFP: 615/* File: armv5te-vfp/TEMPLATE_MUL_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 fmuls s2, s0, s1 629 fsts s2,[r0] 630 bx lr 631 632 633/* ------------------------------ */ 634 .balign 4 635 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP 636dvmCompiler_TEMPLATE_DIV_FLOAT_VFP: 637/* File: armv5te-vfp/TEMPLATE_DIV_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 fdivs s2, s0, s1 651 fsts s2,[r0] 652 bx lr 653 654 655/* ------------------------------ */ 656 .balign 4 657 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP 658dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP: 659/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */ 660/* File: armv5te-vfp/fbinopWide.S */ 661 /* 662 * Generic 64-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 fldd d0,[r1] 671 fldd d1,[r2] 672 faddd d2, d0, d1 673 fstd d2,[r0] 674 bx lr 675 676 677/* ------------------------------ */ 678 .balign 4 679 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP 680dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP: 681/* File: armv5te-vfp/TEMPLATE_SUB_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 fsubd d2, d0, d1 695 fstd d2,[r0] 696 bx lr 697 698 699/* ------------------------------ */ 700 .balign 4 701 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP 702dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP: 703/* File: armv5te-vfp/TEMPLATE_MUL_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 fmuld d2, d0, d1 717 fstd d2,[r0] 718 bx lr 719 720 721/* ------------------------------ */ 722 .balign 4 723 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP 724dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP: 725/* File: armv5te-vfp/TEMPLATE_DIV_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 fdivd d2, d0, d1 739 fstd d2,[r0] 740 bx lr 741 742 743/* ------------------------------ */ 744 .balign 4 745 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP 746dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP: 747/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */ 748/* File: armv5te-vfp/funopNarrower.S */ 749 /* 750 * Generic 64bit-to-32bit floating point unary operation. Provide an 751 * "instr" line that specifies an instruction that performs "s0 = op d0". 752 * 753 * For: double-to-int, double-to-float 754 * 755 * On entry: 756 * r0 = target dalvik register address 757 * r1 = src dalvik register address 758 */ 759 /* unop vA, vB */ 760 fldd d0, [r1] @ d0<- vB 761 fcvtsd s0, d0 @ s0<- op d0 762 fsts s0, [r0] @ vA<- s0 763 bx lr 764 765 766/* ------------------------------ */ 767 .balign 4 768 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP 769dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP: 770/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */ 771/* File: armv5te-vfp/funopNarrower.S */ 772 /* 773 * Generic 64bit-to-32bit floating point unary operation. Provide an 774 * "instr" line that specifies an instruction that performs "s0 = op d0". 775 * 776 * For: double-to-int, double-to-float 777 * 778 * On entry: 779 * r0 = target dalvik register address 780 * r1 = src dalvik register address 781 */ 782 /* unop vA, vB */ 783 fldd d0, [r1] @ d0<- vB 784 ftosizd s0, d0 @ s0<- op d0 785 fsts s0, [r0] @ vA<- s0 786 bx lr 787 788 789/* ------------------------------ */ 790 .balign 4 791 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP 792dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP: 793/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */ 794/* File: armv5te-vfp/funopWider.S */ 795 /* 796 * Generic 32bit-to-64bit floating point unary operation. Provide an 797 * "instr" line that specifies an instruction that performs "d0 = op s0". 798 * 799 * For: int-to-double, float-to-double 800 * 801 * On entry: 802 * r0 = target dalvik register address 803 * r1 = src dalvik register address 804 */ 805 /* unop vA, vB */ 806 flds s0, [r1] @ s0<- vB 807 fcvtds d0, s0 @ d0<- op s0 808 fstd d0, [r0] @ vA<- d0 809 bx lr 810 811 812/* ------------------------------ */ 813 .balign 4 814 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP 815dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP: 816/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */ 817/* File: armv5te-vfp/funop.S */ 818 /* 819 * Generic 32bit-to-32bit floating point unary operation. Provide an 820 * "instr" line that specifies an instruction that performs "s1 = op s0". 821 * 822 * For: float-to-int, int-to-float 823 * 824 * On entry: 825 * r0 = target dalvik register address 826 * r1 = src dalvik register address 827 */ 828 /* unop vA, vB */ 829 flds s0, [r1] @ s0<- vB 830 ftosizs s1, s0 @ s1<- op s0 831 fsts s1, [r0] @ vA<- s1 832 bx lr 833 834 835/* ------------------------------ */ 836 .balign 4 837 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP 838dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP: 839/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */ 840/* File: armv5te-vfp/funopWider.S */ 841 /* 842 * Generic 32bit-to-64bit floating point unary operation. Provide an 843 * "instr" line that specifies an instruction that performs "d0 = op s0". 844 * 845 * For: int-to-double, float-to-double 846 * 847 * On entry: 848 * r0 = target dalvik register address 849 * r1 = src dalvik register address 850 */ 851 /* unop vA, vB */ 852 flds s0, [r1] @ s0<- vB 853 fsitod d0, s0 @ d0<- op s0 854 fstd d0, [r0] @ vA<- d0 855 bx lr 856 857 858/* ------------------------------ */ 859 .balign 4 860 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP 861dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP: 862/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */ 863/* File: armv5te-vfp/funop.S */ 864 /* 865 * Generic 32bit-to-32bit floating point unary operation. Provide an 866 * "instr" line that specifies an instruction that performs "s1 = op s0". 867 * 868 * For: float-to-int, int-to-float 869 * 870 * On entry: 871 * r0 = target dalvik register address 872 * r1 = src dalvik register address 873 */ 874 /* unop vA, vB */ 875 flds s0, [r1] @ s0<- vB 876 fsitos s1, s0 @ s1<- op s0 877 fsts s1, [r0] @ vA<- s1 878 bx lr 879 880 881/* ------------------------------ */ 882 .balign 4 883 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP 884dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP: 885/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */ 886 /* 887 * Compare two floating-point values. Puts 0, 1, or -1 into the 888 * destination register based on the results of the comparison. 889 * 890 * int compare(x, y) { 891 * if (x == y) { 892 * return 0; 893 * } else if (x < y) { 894 * return -1; 895 * } else if (x > y) { 896 * return 1; 897 * } else { 898 * return 1; 899 * } 900 * } 901 * 902 * On entry: 903 * r0 = &op1 [vBB] 904 * r1 = &op2 [vCC] 905 */ 906 /* op vAA, vBB, vCC */ 907 fldd d0, [r0] @ d0<- vBB 908 fldd d1, [r1] @ d1<- vCC 909 fcmpd d0, d1 @ compare (vBB, vCC) 910 mov r0, #1 @ r0<- 1 (default) 911 fmstat @ export status flags 912 mvnmi r0, #0 @ (less than) r0<- -1 913 moveq r0, #0 @ (equal) r0<- 0 914 bx lr 915 916 917/* ------------------------------ */ 918 .balign 4 919 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP 920dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP: 921/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */ 922 /* 923 * Compare two floating-point values. Puts 0, 1, or -1 into the 924 * destination register based on the results of the comparison. 925 * 926 * int compare(x, y) { 927 * if (x == y) { 928 * return 0; 929 * } else if (x > y) { 930 * return 1; 931 * } else if (x < y) { 932 * return -1; 933 * } else { 934 * return -1; 935 * } 936 * } 937 * On entry: 938 * r0 = &op1 [vBB] 939 * r1 = &op2 [vCC] 940 */ 941 /* op vAA, vBB, vCC */ 942 fldd d0, [r0] @ d0<- vBB 943 fldd d1, [r1] @ d1<- vCC 944 fcmped d0, d1 @ compare (vBB, vCC) 945 mvn r0, #0 @ r0<- -1 (default) 946 fmstat @ export status flags 947 movgt r0, #1 @ (greater than) r0<- 1 948 moveq r0, #0 @ (equal) r0<- 0 949 bx lr 950 951/* ------------------------------ */ 952 .balign 4 953 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP 954dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP: 955/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */ 956 /* 957 * Compare two floating-point values. Puts 0, 1, or -1 into the 958 * destination register based on the results of the comparison. 959 * 960 * int compare(x, y) { 961 * if (x == y) { 962 * return 0; 963 * } else if (x < y) { 964 * return -1; 965 * } else if (x > y) { 966 * return 1; 967 * } else { 968 * return 1; 969 * } 970 * } 971 * On entry: 972 * r0 = &op1 [vBB] 973 * r1 = &op2 [vCC] 974 */ 975 /* op vAA, vBB, vCC */ 976 flds s0, [r0] @ d0<- vBB 977 flds s1, [r1] @ d1<- vCC 978 fcmps s0, s1 @ compare (vBB, vCC) 979 mov r0, #1 @ r0<- 1 (default) 980 fmstat @ export status flags 981 mvnmi r0, #0 @ (less than) r0<- -1 982 moveq r0, #0 @ (equal) r0<- 0 983 bx lr 984 985/* ------------------------------ */ 986 .balign 4 987 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP 988dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP: 989/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */ 990 /* 991 * Compare two floating-point values. Puts 0, 1, or -1 into the 992 * destination register based on the results of the comparison. 993 * 994 * int compare(x, y) { 995 * if (x == y) { 996 * return 0; 997 * } else if (x > y) { 998 * return 1; 999 * } else if (x < y) { 1000 * return -1; 1001 * } else { 1002 * return -1; 1003 * } 1004 * } 1005 * On entry: 1006 * r0 = &op1 [vBB] 1007 * r1 = &op2 [vCC] 1008 */ 1009 /* op vAA, vBB, vCC */ 1010 flds s0, [r0] @ d0<- vBB 1011 flds s1, [r1] @ d1<- vCC 1012 fcmps s0, s1 @ compare (vBB, vCC) 1013 mvn r0, #0 @ r0<- -1 (default) 1014 fmstat @ export status flags 1015 movgt r0, #1 @ (greater than) r0<- 1 1016 moveq r0, #0 @ (equal) r0<- 0 1017 bx lr 1018 1019/* ------------------------------ */ 1020 .balign 4 1021 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP 1022dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP: 1023/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */ 1024 /* 1025 * 64-bit floating point vfp sqrt operation. 1026 * If the result is a NaN, bail out to library code to do 1027 * the right thing. 1028 * 1029 * On entry: 1030 * r2 src addr of op1 1031 * On exit: 1032 * r0,r1 = res 1033 */ 1034 fldd d0, [r2] 1035 fsqrtd d1, d0 1036 fcmpd d1, d1 1037 fmstat 1038 fmrrd r0, r1, d1 1039 bxeq lr @ Result OK - return 1040 ldr r2, .Lsqrt 1041 fmrrd r0, r1, d0 @ reload orig operand 1042 bx r2 @ tail call to sqrt library routine 1043 1044.Lsqrt: 1045 .word sqrt 1046 1047/* ------------------------------ */ 1048 .balign 4 1049 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON 1050dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON: 1051/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */ 1052 /* 1053 * Throw an exception from JIT'ed code. 1054 * On entry: 1055 * r0 Dalvik PC that raises the exception 1056 */ 1057 b .LhandleException 1058 1059/* ------------------------------ */ 1060 .balign 4 1061 .global dvmCompiler_TEMPLATE_SAVE_STATE 1062dvmCompiler_TEMPLATE_SAVE_STATE: 1063/* File: armv5te-vfp/TEMPLATE_SAVE_STATE.S */ 1064 /* 1065 * This handler performs a register save for selfVerification mode. 1066 * On entry: 1067 * Top of stack + 4: r7 value to save 1068 * Top of stack + 0: r0 value to save 1069 * r0 - offset from rGLUE to the beginning of the heapArgSpace record 1070 * r7 - the value of regMap 1071 * 1072 * The handler must save regMap, r0-r12 and then return with r0-r12 1073 * with their original values (note that this means r0 and r7 must take 1074 * the values on the stack - not the ones in those registers on entry. 1075 * Finally, the two registers previously pushed must be popped. 1076 */ 1077 add r0, r0, rGLUE @ pointer to heapArgSpace 1078 stmia r0!, {r7} @ save regMap 1079 ldr r7, [r13, #0] @ recover r0 value 1080 stmia r0!, {r7} @ save r0 1081 ldr r7, [r13, #4] @ recover r7 value 1082 stmia r0!, {r1-r12} 1083 add r0, #12 @ move to start of FP save regio 1084 vstmia r0, {d0-d15} 1085 pop {r0, r7} @ recover r0, r7 1086 bx lr 1087 1088/* ------------------------------ */ 1089 .balign 4 1090 .global dvmCompiler_TEMPLATE_RESTORE_STATE 1091dvmCompiler_TEMPLATE_RESTORE_STATE: 1092/* File: armv5te-vfp/TEMPLATE_RESTORE_STATE.S */ 1093 /* 1094 * This handler restores state following a selfVerification memory access. 1095 * On entry: 1096 * r0 - offset from rGLUE to the 1st element of the coreRegs save array. 1097 */ 1098 add r0, r0, rGLUE @ pointer to heapArgSpace.coreRegs[0] 1099 add r0, #64 @ pointer to heapArgSpace.fpRegs[0] 1100 vldmia r0, {d0-d15} 1101 sub r0, #64 @ pointer to heapArgSpace.coreRegs[0] 1102 ldmia r0, {r0-r12} 1103 bx lr 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/* ------------------------------ */ 1246 .balign 4 1247 .global dvmCompiler_TEMPLATE_STRING_INDEXOF 1248dvmCompiler_TEMPLATE_STRING_INDEXOF: 1249/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */ 1250 /* 1251 * String's indexOf. 1252 * 1253 * Requires r0 to have been previously checked for null. Will 1254 * return index of match of r1 in r0. 1255 * 1256 * IMPORTANT NOTE: 1257 * 1258 * This code relies on hard-coded offsets for string objects, and must be 1259 * kept in sync wth definitions in UtfString.h See asm-constants.h 1260 * 1261 * On entry: 1262 * r0: string object pointer 1263 * r1: char to match 1264 * r2: Starting offset in string data 1265 */ 1266 1267 ldr r7, [r0, #STRING_FIELDOFF_OFFSET] 1268 ldr r8, [r0, #STRING_FIELDOFF_COUNT] 1269 ldr r0, [r0, #STRING_FIELDOFF_VALUE] 1270 1271 /* 1272 * At this point, we have: 1273 * r0: object pointer 1274 * r1: char to match 1275 * r2: starting offset 1276 * r7: offset 1277 * r8: string length 1278 */ 1279 1280 /* Build pointer to start of string data */ 1281 add r0, #16 1282 add r0, r0, r7, lsl #1 1283 1284 /* Save a copy of starting data in r7 */ 1285 mov r7, r0 1286 1287 /* Clamp start to [0..count] */ 1288 cmp r2, #0 1289 movlt r2, #0 1290 cmp r2, r8 1291 movgt r2, r8 1292 1293 /* Build pointer to start of data to compare and pre-bias */ 1294 add r0, r0, r2, lsl #1 1295 sub r0, #2 1296 1297 /* Compute iteration count */ 1298 sub r8, r2 1299 1300 /* 1301 * At this point we have: 1302 * r0: start of data to test 1303 * r1: chat to compare 1304 * r8: iteration count 1305 * r7: original start of string 1306 * r3, r4, r9, r10, r11, r12 available for loading string data 1307 */ 1308 1309 subs r8, #4 1310 blt indexof_remainder 1311 1312indexof_loop4: 1313 ldrh r3, [r0, #2]! 1314 ldrh r4, [r0, #2]! 1315 ldrh r10, [r0, #2]! 1316 ldrh r11, [r0, #2]! 1317 cmp r3, r1 1318 beq match_0 1319 cmp r4, r1 1320 beq match_1 1321 cmp r10, r1 1322 beq match_2 1323 cmp r11, r1 1324 beq match_3 1325 subs r8, #4 1326 bge indexof_loop4 1327 1328indexof_remainder: 1329 adds r8, #4 1330 beq indexof_nomatch 1331 1332indexof_loop1: 1333 ldrh r3, [r0, #2]! 1334 cmp r3, r1 1335 beq match_3 1336 subs r8, #1 1337 bne indexof_loop1 1338 1339indexof_nomatch: 1340 mov r0, #-1 1341 bx lr 1342 1343match_0: 1344 sub r0, #6 1345 sub r0, r7 1346 asr r0, r0, #1 1347 bx lr 1348match_1: 1349 sub r0, #4 1350 sub r0, r7 1351 asr r0, r0, #1 1352 bx lr 1353match_2: 1354 sub r0, #2 1355 sub r0, r7 1356 asr r0, r0, #1 1357 bx lr 1358match_3: 1359 sub r0, r7 1360 asr r0, r0, #1 1361 bx lr 1362 1363 1364/* ------------------------------ */ 1365 .balign 4 1366 .global dvmCompiler_TEMPLATE_INTERPRET 1367dvmCompiler_TEMPLATE_INTERPRET: 1368/* File: armv5te/TEMPLATE_INTERPRET.S */ 1369 /* 1370 * This handler transfers control to the interpeter without performing 1371 * any lookups. It may be called either as part of a normal chaining 1372 * operation, or from the transition code in header.S. We distinquish 1373 * the two cases by looking at the link register. If called from a 1374 * translation chain, it will point to the chaining Dalvik PC + 1. 1375 * On entry: 1376 * lr - if NULL: 1377 * r1 - the Dalvik PC to begin interpretation. 1378 * else 1379 * [lr, #-1] contains Dalvik PC to begin interpretation 1380 * rGLUE - pointer to interpState 1381 * rFP - Dalvik frame pointer 1382 */ 1383 cmp lr, #0 1384 ldrne r1,[lr, #-1] 1385 ldr r2, .LinterpPunt 1386 mov r0, r1 @ set Dalvik PC 1387 bx r2 1388 @ doesn't return 1389 1390.LinterpPunt: 1391 .word dvmJitToInterpPunt 1392 1393 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart 1394/* File: armv5te/footer.S */ 1395/* 1396 * =========================================================================== 1397 * Common subroutines and data 1398 * =========================================================================== 1399 */ 1400 1401 .text 1402 .align 2 1403.LinvokeNative: 1404 @ Prep for the native call 1405 @ r1 = newFP, r0 = methodToCall 1406 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 1407 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 1408 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 1409 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)] 1410 @ newFp->localRefCookie=top 1411 mov r9, r3 @ r9<- glue->self (preserve) 1412 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area 1413 1414 mov r2, r0 @ r2<- methodToCall 1415 mov r0, r1 @ r0<- newFP 1416 add r1, rGLUE, #offGlue_retval @ r1<- &retval 1417 1418 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 1419 1420 @ native return; r9=self, r10=newSaveArea 1421 @ equivalent to dvmPopJniLocals 1422 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret 1423 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top 1424 ldr r1, [r9, #offThread_exception] @ check for exception 1425 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 1426 cmp r1, #0 @ null? 1427 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 1428 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC 1429 bne .LhandleException @ no, handle exception 1430 bx r2 1431 1432/* 1433 * On entry: 1434 * r0 Faulting Dalvik PC 1435 */ 1436.LhandleException: 1437 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func 1438 ldr rIBASE, .LdvmAsmInstructionStart @ same as above 1439 mov rPC, r0 @ reload the faulting Dalvik address 1440 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown 1441 1442 .align 2 1443.LdvmAsmInstructionStart: 1444 .word dvmAsmInstructionStart 1445.LdvmJitToInterpNoChain: 1446 .word dvmJitToInterpNoChain 1447.LdvmMterpStdBail: 1448 .word dvmMterpStdBail 1449.LdvmMterpCommonExceptionThrown: 1450 .word dvmMterpCommonExceptionThrown 1451.L__aeabi_cdcmple: 1452 .word __aeabi_cdcmple 1453.L__aeabi_cfcmple: 1454 .word __aeabi_cfcmple 1455 1456 .global dmvCompilerTemplateEnd 1457dmvCompilerTemplateEnd: 1458 1459#endif /* WITH_JIT */ 1460 1461