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