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