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