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