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