CompilerTemplateAsm-armv5te.S revision 2e152baec01433de9c63633ebc6f4adf1cea3a87
1/*
2 * This file was generated automatically by gen-template.py for 'armv5te'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24#if defined(WITH_JIT)
25
26/*
27 * ARMv5 definitions and declarations.
28 */
29
30/*
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/platform.S */
105/*
106 * ===========================================================================
107 *  CPU-version-specific defines and utility
108 * ===========================================================================
109 */
110
111
112    .global dvmCompilerTemplateStart
113    .type   dvmCompilerTemplateStart, %function
114    .text
115
116dvmCompilerTemplateStart:
117
118/* ------------------------------ */
119    .balign 4
120    .global dvmCompiler_TEMPLATE_CMP_LONG
121dvmCompiler_TEMPLATE_CMP_LONG:
122/* File: armv5te/TEMPLATE_CMP_LONG.S */
123    /*
124     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
125     * register based on the results of the comparison.
126     *
127     * We load the full values with LDM, but in practice many values could
128     * be resolved by only looking at the high word.  This could be made
129     * faster or slower by splitting the LDM into a pair of LDRs.
130     *
131     * If we just wanted to set condition flags, we could do this:
132     *  subs    ip, r0, r2
133     *  sbcs    ip, r1, r3
134     *  subeqs  ip, r0, r2
135     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
136     * integer value, which we can do with 2 conditional mov/mvn instructions
137     * (set 1, set -1; if they're equal we already have 0 in ip), giving
138     * us a constant 5-cycle path plus a branch at the end to the
139     * instruction epilogue code.  The multi-compare approach below needs
140     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
141     * in the worst case (the 64-bit values are equal).
142     */
143    /* cmp-long vAA, vBB, vCC */
144    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
145    blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
146    bgt     .LTEMPLATE_CMP_LONG_greater
147    subs    r0, r0, r2                  @ r0<- r0 - r2
148    bxeq     lr
149    bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
150.LTEMPLATE_CMP_LONG_less:
151    mvn     r0, #0                      @ r0<- -1
152    bx      lr
153.LTEMPLATE_CMP_LONG_greater:
154    mov     r0, #1                      @ r0<- 1
155    bx      lr
156
157/* ------------------------------ */
158    .balign 4
159    .global dvmCompiler_TEMPLATE_RETURN
160dvmCompiler_TEMPLATE_RETURN:
161/* File: armv5te/TEMPLATE_RETURN.S */
162    /*
163     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
164     * If the stored value in returnAddr
165     * is non-zero, the caller is compiled by the JIT thus return to the
166     * address in the code cache following the invoke instruction. Otherwise
167     * return to the special dvmJitToInterpNoChain entry point.
168     */
169#if defined(WITH_INLINE_PROFILING)
170    stmfd   sp!, {r0-r2,lr}             @ preserve live registers
171    mov     r0, r6
172    @ r0=rGlue
173    mov     lr, pc
174    ldr     pc, .LdvmFastJavaMethodTraceExit
175    ldmfd   sp!, {r0-r2,lr}             @ restore live registers
176#endif
177    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
178    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
179    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
180    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
181#if !defined(WITH_SELF_VERIFICATION)
182    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
183#else
184    mov     r9, #0                      @ disable chaining
185#endif
186    ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
187                                        @ r2<- method we're returning to
188    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
189    cmp     r2, #0                      @ break frame?
190#if !defined(WITH_SELF_VERIFICATION)
191    beq     1f                          @ bail to interpreter
192#else
193    blxeq   lr                          @ punt to interpreter and compare state
194#endif
195    ldr     r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
196    mov     rFP, r10                    @ publish new FP
197    ldr     r10, [r2, #offMethod_clazz] @ r10<- method->clazz
198    ldr     r8, [r8]                    @ r8<- suspendCount
199
200    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
201    ldr     r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
202    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
203    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
204    str     r0, [rGLUE, #offGlue_methodClassDex]
205    cmp     r8, #0                      @ check the suspendCount
206    movne   r9, #0                      @ clear the chaining cell address
207    str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
208    cmp     r9, #0                      @ chaining cell exists?
209    blxne   r9                          @ jump to the chaining cell
210#if defined(WITH_JIT_TUNING)
211    mov     r0, #kCallsiteInterpreted
212#endif
213    mov     pc, r1                      @ callsite is interpreted
2141:
215    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
216    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
217    mov     r1, #0                      @ changeInterp = false
218    mov     r0, rGLUE                   @ Expecting rGLUE in r0
219    blx     r2                          @ exit the interpreter
220
221/* ------------------------------ */
222    .balign 4
223    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
224dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
225/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
226    /*
227     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
228     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
229     * runtime-resolved callee.
230     */
231    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
232    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
233    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
234    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
235    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
236    add     r3, r1, #1  @ Thumb addr is odd
237    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
238    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
239    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
240    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
241    ldr     r8, [r8]                    @ r8<- suspendCount (int)
242    cmp     r10, r9                     @ bottom < interpStackEnd?
243    bxlo    lr                          @ return to raise stack overflow excep.
244    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
245    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
246    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
247    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
248    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
249    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
250
251
252    @ set up newSaveArea
253    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
254    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
255    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
256    cmp     r8, #0                      @ suspendCount != 0
257    bxne    lr                          @ bail to the interpreter
258    tst     r10, #ACC_NATIVE
259#if !defined(WITH_SELF_VERIFICATION)
260    bne     .LinvokeNative
261#else
262    bxne    lr                          @ bail to the interpreter
263#endif
264
265    ldr     r10, .LdvmJitToInterpTraceSelectNoChain
266    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
267    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
268
269    @ Update "glue" values for the new method
270    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
271    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
272    mov     rFP, r1                         @ fp = newFp
273    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
274#if defined(WITH_INLINE_PROFILING)
275    stmfd   sp!, {r0-r3}                    @ preserve r0-r3
276    mov     r1, r6
277    @ r0=methodToCall, r1=rGlue
278    mov     lr, pc
279    ldr     pc, .LdvmFastMethodTraceEnter
280    ldmfd   sp!, {r0-r3}                    @ restore r0-r3
281#endif
282
283    @ Start executing the callee
284#if defined(WITH_JIT_TUNING)
285    mov     r0, #kInlineCacheMiss
286#endif
287    mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
288
289/* ------------------------------ */
290    .balign 4
291    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
292dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
293/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
294    /*
295     * For monomorphic callsite, setup the Dalvik frame and return to the
296     * Thumb code through the link register to transfer control to the callee
297     * method through a dedicated chaining cell.
298     */
299    @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
300    @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
301    @ methodToCall is guaranteed to be non-native
302.LinvokeChain:
303    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
304    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
305    add     r3, r1, #1  @ Thumb addr is odd
306    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
307    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
308    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
309    add     r12, lr, #2                 @ setup the punt-to-interp address
310    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
311    ldr     r8, [r8]                    @ r8<- suspendCount (int)
312    cmp     r10, r9                     @ bottom < interpStackEnd?
313    bxlo    r12                         @ return to raise stack overflow excep.
314    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
315    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
316    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
317    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
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#if defined(WITH_INLINE_PROFILING)
335    stmfd   sp!, {r0-r2,lr}             @ preserve clobbered live registers
336    mov     r1, r6
337    @ r0=methodToCall, r1=rGlue
338    mov     lr, pc
339    ldr     pc, .LdvmFastMethodTraceEnter
340    ldmfd   sp!, {r0-r2,lr}             @ restore registers
341#endif
342
343    bx      lr                              @ return to the callee-chaining cell
344
345/* ------------------------------ */
346    .balign 4
347    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
348dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
349/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
350    /*
351     * For polymorphic callsite, check whether the cached class pointer matches
352     * the current one. If so setup the Dalvik frame and return to the
353     * Thumb code through the link register to transfer control to the callee
354     * method through a dedicated chaining cell.
355     *
356     * The predicted chaining cell is declared in ArmLIR.h with the
357     * following layout:
358     *
359     *  typedef struct PredictedChainingCell {
360     *      u4 branch;
361     *      const ClassObject *clazz;
362     *      const Method *method;
363     *      u4 counter;
364     *  } PredictedChainingCell;
365     *
366     * Upon returning to the callsite:
367     *    - lr  : to branch to the chaining cell
368     *    - lr+2: to punt to the interpreter
369     *    - lr+4: to fully resolve the callee and may rechain.
370     *            r3 <- class
371     *            r9 <- counter
372     */
373    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
374    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
375    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
376    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
377    ldr     r9, [rGLUE, #offGlue_icRechainCount]   @ r1 <- shared rechainCount
378    cmp     r3, r8          @ predicted class == actual class?
379#if defined(WITH_JIT_TUNING)
380    ldr     r7, .LdvmICHitCount
381#if defined(WORKAROUND_CORTEX_A9_745320)
382    /* Don't use conditional loads if the HW defect exists */
383    bne     101f
384    ldr     r10, [r7, #0]
385101:
386#else
387    ldreq   r10, [r7, #0]
388#endif
389    add     r10, r10, #1
390    streq   r10, [r7, #0]
391#endif
392    ldreqh  r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
393    ldreqh  r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
394    beq     .LinvokeChain   @ predicted chain is valid
395    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
396    cmp     r8, #0          @ initialized class or not
397    moveq   r1, #0
398    subne   r1, r9, #1      @ count--
399    strne   r1, [rGLUE, #offGlue_icRechainCount]   @ write back to InterpState
400    add     lr, lr, #4      @ return to fully-resolve landing pad
401    /*
402     * r1 <- count
403     * r2 <- &predictedChainCell
404     * r3 <- this->class
405     * r4 <- dPC
406     * r7 <- this->class->vtable
407     */
408    bx      lr
409
410/* ------------------------------ */
411    .balign 4
412    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
413dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
414/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
415    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
416    @ r7 = methodToCall->registersSize
417    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
418    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
419    add     r3, r1, #1  @ Thumb addr is odd
420    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
421    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
422    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
423    ldr     r8, [r8]                    @ r3<- suspendCount (int)
424    cmp     r10, r9                     @ bottom < interpStackEnd?
425    bxlo    lr                          @ return to raise stack overflow excep.
426    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
427    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
428    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
429
430    @ set up newSaveArea
431    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
432    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
433    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
434    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
435    cmp     r8, #0                      @ suspendCount != 0
436    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
437#if !defined(WITH_SELF_VERIFICATION)
438    bxne    lr                          @ bail to the interpreter
439#else
440    bx      lr                          @ bail to interpreter unconditionally
441#endif
442
443    @ go ahead and transfer control to the native code
444    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
445    mov     r2, #0
446    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
447    str     r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
448    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
449                                        @ newFp->localRefCookie=top
450    mov     r9, r3                      @ r9<- glue->self (preserve)
451    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
452
453    mov     r2, r0                      @ r2<- methodToCall
454    mov     r0, r1                      @ r0<- newFP
455    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
456#if defined(WITH_INLINE_PROFILING)
457    @ r2=methodToCall, r6=rGLUE
458    stmfd   sp!, {r2,r6}                @ to be consumed after JNI return
459    stmfd   sp!, {r0-r3}                @ preserve r0-r3
460    mov     r0, r2
461    mov     r1, r6
462    @ r0=JNIMethod, r1=rGlue
463    mov     lr, pc
464    ldr     pc, .LdvmFastMethodTraceEnter
465    ldmfd   sp!, {r0-r3}                @ restore r0-r3
466#endif
467
468    blx     r8                          @ off to the native code
469
470#if defined(WITH_INLINE_PROFILING)
471    ldmfd   sp!, {r0-r1}                @ restore r2 and r6
472    @ r0=JNIMethod, r1=rGlue
473    mov     lr, pc
474    ldr     pc, .LdvmFastNativeMethodTraceExit
475#endif
476    @ native return; r9=self, r10=newSaveArea
477    @ equivalent to dvmPopJniLocals
478    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
479    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
480    ldr     r1, [r9, #offThread_exception] @ check for exception
481    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
482    cmp     r1, #0                      @ null?
483    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
484    ldr     r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
485
486    @ r0 = dalvikCallsitePC
487    bne     .LhandleException           @ no, handle exception
488
489    str     r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
490    cmp     r2, #0                      @ return chaining cell still exists?
491    bxne    r2                          @ yes - go ahead
492
493    @ continue executing the next instruction through the interpreter
494    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
495    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
496#if defined(WITH_JIT_TUNING)
497    mov     r0, #kCallsiteInterpreted
498#endif
499    mov     pc, r1
500
501/* ------------------------------ */
502    .balign 4
503    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
504dvmCompiler_TEMPLATE_CMPG_DOUBLE:
505/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
506/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
507    /*
508     * For the JIT: incoming arguments in r0-r1, r2-r3
509     *              result in r0
510     *
511     * Compare two floating-point values.  Puts 0, 1, or -1 into the
512     * destination register based on the results of the comparison.
513     *
514     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
515     * on what value we'd like to return when one of the operands is NaN.
516     *
517     * See OP_CMPL_FLOAT for an explanation.
518     *
519     * For: cmpl-double, cmpg-double
520     */
521    /* op vAA, vBB, vCC */
522    push    {r0-r3}                     @ save operands
523    mov     r11, lr                     @ save return address
524    mov     lr, pc
525    ldr     pc, .L__aeabi_cdcmple       @ PIC way of "bl __aeabi_cdcmple"
526    bhi     .LTEMPLATE_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
527    mvncc   r0, #0                      @ (less than) r1<- -1
528    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
529    add     sp, #16                     @ drop unused operands
530    bx      r11
531
532    @ Test for NaN with a second comparison.  EABI forbids testing bit
533    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
534    @ make the library call.
535.LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
536    pop     {r2-r3}                     @ restore operands in reverse order
537    pop     {r0-r1}                     @ restore operands in reverse order
538    mov     lr, pc
539    ldr     pc, .L__aeabi_cdcmple       @ r0<- Z set if eq, C clear if <
540    movcc   r0, #1                      @ (greater than) r1<- 1
541    bxcc    r11
542    mov     r0, #1                            @ r1<- 1 or -1 for NaN
543    bx      r11
544
545
546/* ------------------------------ */
547    .balign 4
548    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
549dvmCompiler_TEMPLATE_CMPL_DOUBLE:
550/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
551    /*
552     * For the JIT: incoming arguments in r0-r1, r2-r3
553     *              result in r0
554     *
555     * Compare two floating-point values.  Puts 0, 1, or -1 into the
556     * destination register based on the results of the comparison.
557     *
558     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
559     * on what value we'd like to return when one of the operands is NaN.
560     *
561     * See OP_CMPL_FLOAT for an explanation.
562     *
563     * For: cmpl-double, cmpg-double
564     */
565    /* op vAA, vBB, vCC */
566    push    {r0-r3}                     @ save operands
567    mov     r11, lr                     @ save return address
568    mov     lr, pc
569    ldr     pc, .L__aeabi_cdcmple       @ PIC way of "bl __aeabi_cdcmple"
570    bhi     .LTEMPLATE_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
571    mvncc   r0, #0                      @ (less than) r1<- -1
572    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
573    add     sp, #16                     @ drop unused operands
574    bx      r11
575
576    @ Test for NaN with a second comparison.  EABI forbids testing bit
577    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
578    @ make the library call.
579.LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
580    pop     {r2-r3}                     @ restore operands in reverse order
581    pop     {r0-r1}                     @ restore operands in reverse order
582    mov     lr, pc
583    ldr     pc, .L__aeabi_cdcmple       @ r0<- Z set if eq, C clear if <
584    movcc   r0, #1                      @ (greater than) r1<- 1
585    bxcc    r11
586    mvn     r0, #0                            @ r1<- 1 or -1 for NaN
587    bx      r11
588
589/* ------------------------------ */
590    .balign 4
591    .global dvmCompiler_TEMPLATE_CMPG_FLOAT
592dvmCompiler_TEMPLATE_CMPG_FLOAT:
593/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
594/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
595    /*
596     * For the JIT: incoming arguments in r0-r1, r2-r3
597     *              result in r0
598     *
599     * Compare two floating-point values.  Puts 0, 1, or -1 into the
600     * destination register based on the results of the comparison.
601     *
602     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
603     * on what value we'd like to return when one of the operands is NaN.
604     *
605     * The operation we're implementing is:
606     *   if (x == y)
607     *     return 0;
608     *   else if (x < y)
609     *     return -1;
610     *   else if (x > y)
611     *     return 1;
612     *   else
613     *     return {-1,1};  // one or both operands was NaN
614     *
615     * The straightforward implementation requires 3 calls to functions
616     * that return a result in r0.  We can do it with two calls if our
617     * EABI library supports __aeabi_cfcmple (only one if we want to check
618     * for NaN directly):
619     *   check x <= y
620     *     if <, return -1
621     *     if ==, return 0
622     *   check y <= x
623     *     if <, return 1
624     *   return {-1,1}
625     *
626     * for: cmpl-float, cmpg-float
627     */
628    /* op vAA, vBB, vCC */
629    mov     r9, r0                      @ Save copies - we may need to redo
630    mov     r10, r1
631    mov     r11, lr                     @ save return address
632    mov     lr, pc
633    ldr     pc, .L__aeabi_cfcmple       @ cmp <=: C clear if <, Z set if eq
634    bhi     .LTEMPLATE_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
635    mvncc   r0, #0                      @ (less than) r0<- -1
636    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
637    bx      r11
638    @ Test for NaN with a second comparison.  EABI forbids testing bit
639    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
640    @ make the library call.
641.LTEMPLATE_CMPG_FLOAT_gt_or_nan:
642    mov     r0, r10                     @ restore in reverse order
643    mov     r1, r9
644    mov     lr, pc
645    ldr     pc, .L__aeabi_cfcmple       @ r0<- Z set if eq, C clear if <
646    movcc   r0, #1                      @ (greater than) r1<- 1
647    bxcc    r11
648    mov     r0, #1                            @ r1<- 1 or -1 for NaN
649    bx      r11
650
651
652/* ------------------------------ */
653    .balign 4
654    .global dvmCompiler_TEMPLATE_CMPL_FLOAT
655dvmCompiler_TEMPLATE_CMPL_FLOAT:
656/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
657    /*
658     * For the JIT: incoming arguments in r0-r1, r2-r3
659     *              result in r0
660     *
661     * Compare two floating-point values.  Puts 0, 1, or -1 into the
662     * destination register based on the results of the comparison.
663     *
664     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
665     * on what value we'd like to return when one of the operands is NaN.
666     *
667     * The operation we're implementing is:
668     *   if (x == y)
669     *     return 0;
670     *   else if (x < y)
671     *     return -1;
672     *   else if (x > y)
673     *     return 1;
674     *   else
675     *     return {-1,1};  // one or both operands was NaN
676     *
677     * The straightforward implementation requires 3 calls to functions
678     * that return a result in r0.  We can do it with two calls if our
679     * EABI library supports __aeabi_cfcmple (only one if we want to check
680     * for NaN directly):
681     *   check x <= y
682     *     if <, return -1
683     *     if ==, return 0
684     *   check y <= x
685     *     if <, return 1
686     *   return {-1,1}
687     *
688     * for: cmpl-float, cmpg-float
689     */
690    /* op vAA, vBB, vCC */
691    mov     r9, r0                      @ Save copies - we may need to redo
692    mov     r10, r1
693    mov     r11, lr                     @ save return address
694    mov     lr, pc
695    ldr     pc, .L__aeabi_cfcmple       @ cmp <=: C clear if <, Z set if eq
696    bhi     .LTEMPLATE_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
697    mvncc   r0, #0                      @ (less than) r0<- -1
698    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
699    bx      r11
700    @ Test for NaN with a second comparison.  EABI forbids testing bit
701    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
702    @ make the library call.
703.LTEMPLATE_CMPL_FLOAT_gt_or_nan:
704    mov     r0, r10                     @ restore in reverse order
705    mov     r1, r9
706    mov     lr, pc
707    ldr     pc, .L__aeabi_cfcmple       @ r0<- Z set if eq, C clear if <
708    movcc   r0, #1                      @ (greater than) r1<- 1
709    bxcc    r11
710    mvn     r0, #0                            @ r1<- 1 or -1 for NaN
711    bx      r11
712
713/* ------------------------------ */
714    .balign 4
715    .global dvmCompiler_TEMPLATE_MUL_LONG
716dvmCompiler_TEMPLATE_MUL_LONG:
717/* File: armv5te/TEMPLATE_MUL_LONG.S */
718    /*
719     * Signed 64-bit integer multiply.
720     *
721     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
722     *
723     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
724     *        WX
725     *      x YZ
726     *  --------
727     *     ZW ZX
728     *  YW YX
729     *
730     * The low word of the result holds ZX, the high word holds
731     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
732     * it doesn't fit in the low 64 bits.
733     *
734     * Unlike most ARM math operations, multiply instructions have
735     * restrictions on using the same register more than once (Rd and Rm
736     * cannot be the same).
737     */
738    /* mul-long vAA, vBB, vCC */
739    mul     ip, r2, r1                  @  ip<- ZxW
740    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
741    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
742    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
743    mov     r0,r9
744    mov     r1,r10
745    bx      lr
746
747/* ------------------------------ */
748    .balign 4
749    .global dvmCompiler_TEMPLATE_SHL_LONG
750dvmCompiler_TEMPLATE_SHL_LONG:
751/* File: armv5te/TEMPLATE_SHL_LONG.S */
752    /*
753     * Long integer shift.  This is different from the generic 32/64-bit
754     * binary operations because vAA/vBB are 64-bit but vCC (the shift
755     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
756     * 6 bits.
757     */
758    /* shl-long vAA, vBB, vCC */
759    and     r2, r2, #63                 @ r2<- r2 & 0x3f
760    mov     r1, r1, asl r2              @  r1<- r1 << r2
761    rsb     r3, r2, #32                 @  r3<- 32 - r2
762    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
763    subs    ip, r2, #32                 @  ip<- r2 - 32
764    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
765    mov     r0, r0, asl r2              @  r0<- r0 << r2
766    bx      lr
767
768/* ------------------------------ */
769    .balign 4
770    .global dvmCompiler_TEMPLATE_SHR_LONG
771dvmCompiler_TEMPLATE_SHR_LONG:
772/* File: armv5te/TEMPLATE_SHR_LONG.S */
773    /*
774     * Long integer shift.  This is different from the generic 32/64-bit
775     * binary operations because vAA/vBB are 64-bit but vCC (the shift
776     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
777     * 6 bits.
778     */
779    /* shr-long vAA, vBB, vCC */
780    and     r2, r2, #63                 @ r0<- r0 & 0x3f
781    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
782    rsb     r3, r2, #32                 @  r3<- 32 - r2
783    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
784    subs    ip, r2, #32                 @  ip<- r2 - 32
785    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
786    mov     r1, r1, asr r2              @  r1<- r1 >> r2
787    bx      lr
788
789/* ------------------------------ */
790    .balign 4
791    .global dvmCompiler_TEMPLATE_USHR_LONG
792dvmCompiler_TEMPLATE_USHR_LONG:
793/* File: armv5te/TEMPLATE_USHR_LONG.S */
794    /*
795     * Long integer shift.  This is different from the generic 32/64-bit
796     * binary operations because vAA/vBB are 64-bit but vCC (the shift
797     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
798     * 6 bits.
799     */
800    /* ushr-long vAA, vBB, vCC */
801    and     r2, r2, #63                 @ r0<- r0 & 0x3f
802    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
803    rsb     r3, r2, #32                 @  r3<- 32 - r2
804    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
805    subs    ip, r2, #32                 @  ip<- r2 - 32
806    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
807    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
808    bx      lr
809
810/* ------------------------------ */
811    .balign 4
812    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
813dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
814/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
815    /*
816     * Throw an exception from JIT'ed code.
817     * On entry:
818     *    r0    Dalvik PC that raises the exception
819     */
820    b       .LhandleException
821
822/* ------------------------------ */
823    .balign 4
824    .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
825dvmCompiler_TEMPLATE_MEM_OP_DECODE:
826/* File: armv5te/TEMPLATE_MEM_OP_DECODE.S */
827#if defined(WITH_SELF_VERIFICATION)
828    /*
829     * This handler encapsulates heap memory ops for selfVerification mode.
830     *
831     * The call to the handler is inserted prior to a heap memory operation.
832     * This handler then calls a function to decode the memory op, and process
833     * it accordingly. Afterwards, the handler changes the return address to
834     * skip the memory op so it never gets executed.
835     */
836    push    {r0-r12,lr}                 @ save out all registers
837    mov     r0, lr                      @ arg0 <- link register
838    mov     r1, sp                      @ arg1 <- stack pointer
839    ldr     r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
840    blx     r2                          @ decode and handle the mem op
841    pop     {r0-r12,lr}                 @ restore all registers
842    bx      lr                          @ return to compiled code
843#endif
844
845/* ------------------------------ */
846    .balign 4
847    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
848dvmCompiler_TEMPLATE_STRING_COMPARETO:
849/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
850    /*
851     * String's compareTo.
852     *
853     * Requires r0/r1 to have been previously checked for null.  Will
854     * return negative if this's string is < comp, 0 if they are the
855     * same and positive if >.
856     *
857     * IMPORTANT NOTE:
858     *
859     * This code relies on hard-coded offsets for string objects, and must be
860     * kept in sync with definitions in UtfString.h.  See asm-constants.h
861     *
862     * On entry:
863     *    r0:   this object pointer
864     *    r1:   comp object pointer
865     *
866     */
867
868    mov    r2, r0         @ this to r2, opening up r0 for return value
869    subs   r0, r2, r1     @ Same?
870    bxeq   lr
871
872    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
873    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
874    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
875    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
876    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
877    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
878
879    /*
880     * At this point, we have:
881     *    value:  r2/r1
882     *    offset: r4/r9
883     *    count:  r7/r10
884     * We're going to compute
885     *    r11 <- countDiff
886     *    r10 <- minCount
887     */
888     subs  r11, r7, r10
889     movls r10, r7
890
891     /* Now, build pointers to the string data */
892     add   r2, r2, r4, lsl #1
893     add   r1, r1, r9, lsl #1
894     /*
895      * Note: data pointers point to previous element so we can use pre-index
896      * mode with base writeback.
897      */
898     add   r2, #16-2   @ offset to contents[-1]
899     add   r1, #16-2   @ offset to contents[-1]
900
901     /*
902      * At this point we have:
903      *   r2: *this string data
904      *   r1: *comp string data
905      *   r10: iteration count for comparison
906      *   r11: value to return if the first part of the string is equal
907      *   r0: reserved for result
908      *   r3, r4, r7, r8, r9, r12 available for loading string data
909      */
910
911    subs  r10, #2
912    blt   do_remainder2
913
914      /*
915       * Unroll the first two checks so we can quickly catch early mismatch
916       * on long strings (but preserve incoming alignment)
917       */
918
919    ldrh  r3, [r2, #2]!
920    ldrh  r4, [r1, #2]!
921    ldrh  r7, [r2, #2]!
922    ldrh  r8, [r1, #2]!
923    subs  r0, r3, r4
924    subeqs  r0, r7, r8
925    bxne  lr
926    cmp   r10, #28
927    bgt   do_memcmp16
928    subs  r10, #3
929    blt   do_remainder
930
931loopback_triple:
932    ldrh  r3, [r2, #2]!
933    ldrh  r4, [r1, #2]!
934    ldrh  r7, [r2, #2]!
935    ldrh  r8, [r1, #2]!
936    ldrh  r9, [r2, #2]!
937    ldrh  r12,[r1, #2]!
938    subs  r0, r3, r4
939    subeqs  r0, r7, r8
940    subeqs  r0, r9, r12
941    bxne  lr
942    subs  r10, #3
943    bge   loopback_triple
944
945do_remainder:
946    adds  r10, #3
947    beq   returnDiff
948
949loopback_single:
950    ldrh  r3, [r2, #2]!
951    ldrh  r4, [r1, #2]!
952    subs  r0, r3, r4
953    bxne  lr
954    subs  r10, #1
955    bne     loopback_single
956
957returnDiff:
958    mov   r0, r11
959    bx    lr
960
961do_remainder2:
962    adds  r10, #2
963    bne   loopback_single
964    mov   r0, r11
965    bx    lr
966
967    /* Long string case */
968do_memcmp16:
969    mov   r4, lr
970    ldr   lr, .Lmemcmp16
971    mov   r7, r11
972    add   r0, r2, #2
973    add   r1, r1, #2
974    mov   r2, r10
975    blx   lr
976    cmp   r0, #0
977    bxne  r4
978    mov   r0, r7
979    bx    r4
980
981.Lmemcmp16:
982    .word __memcmp16
983
984/* ------------------------------ */
985    .balign 4
986    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
987dvmCompiler_TEMPLATE_STRING_INDEXOF:
988/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
989    /*
990     * String's indexOf.
991     *
992     * Requires r0 to have been previously checked for null.  Will
993     * return index of match of r1 in r0.
994     *
995     * IMPORTANT NOTE:
996     *
997     * This code relies on hard-coded offsets for string objects, and must be
998     * kept in sync wth definitions in UtfString.h  See asm-constants.h
999     *
1000     * On entry:
1001     *    r0:   string object pointer
1002     *    r1:   char to match
1003     *    r2:   Starting offset in string data
1004     */
1005
1006    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
1007    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
1008    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
1009
1010    /*
1011     * At this point, we have:
1012     *    r0: object pointer
1013     *    r1: char to match
1014     *    r2: starting offset
1015     *    r7: offset
1016     *    r8: string length
1017     */
1018
1019     /* Build pointer to start of string data */
1020     add   r0, #16
1021     add   r0, r0, r7, lsl #1
1022
1023     /* Save a copy of starting data in r7 */
1024     mov   r7, r0
1025
1026     /* Clamp start to [0..count] */
1027     cmp   r2, #0
1028     movlt r2, #0
1029     cmp   r2, r8
1030     movgt r2, r8
1031
1032     /* Build pointer to start of data to compare and pre-bias */
1033     add   r0, r0, r2, lsl #1
1034     sub   r0, #2
1035
1036     /* Compute iteration count */
1037     sub   r8, r2
1038
1039     /*
1040      * At this point we have:
1041      *   r0: start of data to test
1042      *   r1: chat to compare
1043      *   r8: iteration count
1044      *   r7: original start of string
1045      *   r3, r4, r9, r10, r11, r12 available for loading string data
1046      */
1047
1048    subs  r8, #4
1049    blt   indexof_remainder
1050
1051indexof_loop4:
1052    ldrh  r3, [r0, #2]!
1053    ldrh  r4, [r0, #2]!
1054    ldrh  r10, [r0, #2]!
1055    ldrh  r11, [r0, #2]!
1056    cmp   r3, r1
1057    beq   match_0
1058    cmp   r4, r1
1059    beq   match_1
1060    cmp   r10, r1
1061    beq   match_2
1062    cmp   r11, r1
1063    beq   match_3
1064    subs  r8, #4
1065    bge   indexof_loop4
1066
1067indexof_remainder:
1068    adds    r8, #4
1069    beq     indexof_nomatch
1070
1071indexof_loop1:
1072    ldrh  r3, [r0, #2]!
1073    cmp   r3, r1
1074    beq   match_3
1075    subs  r8, #1
1076    bne   indexof_loop1
1077
1078indexof_nomatch:
1079    mov   r0, #-1
1080    bx    lr
1081
1082match_0:
1083    sub   r0, #6
1084    sub   r0, r7
1085    asr   r0, r0, #1
1086    bx    lr
1087match_1:
1088    sub   r0, #4
1089    sub   r0, r7
1090    asr   r0, r0, #1
1091    bx    lr
1092match_2:
1093    sub   r0, #2
1094    sub   r0, r7
1095    asr   r0, r0, #1
1096    bx    lr
1097match_3:
1098    sub   r0, r7
1099    asr   r0, r0, #1
1100    bx    lr
1101
1102/* ------------------------------ */
1103    .balign 4
1104    .global dvmCompiler_TEMPLATE_INTERPRET
1105dvmCompiler_TEMPLATE_INTERPRET:
1106/* File: armv5te/TEMPLATE_INTERPRET.S */
1107    /*
1108     * This handler transfers control to the interpeter without performing
1109     * any lookups.  It may be called either as part of a normal chaining
1110     * operation, or from the transition code in header.S.  We distinquish
1111     * the two cases by looking at the link register.  If called from a
1112     * translation chain, it will point to the chaining Dalvik PC -3.
1113     * On entry:
1114     *    lr - if NULL:
1115     *        r1 - the Dalvik PC to begin interpretation.
1116     *    else
1117     *        [lr, #3] contains Dalvik PC to begin interpretation
1118     *    rGLUE - pointer to interpState
1119     *    rFP - Dalvik frame pointer
1120     */
1121    cmp     lr, #0
1122#if defined(WORKAROUND_CORTEX_A9_745320)
1123    /* Don't use conditional loads if the HW defect exists */
1124    beq     101f
1125    ldr     r1,[lr, #3]
1126101:
1127#else
1128    ldrne   r1,[lr, #3]
1129#endif
1130    ldr     r2, .LinterpPunt
1131    mov     r0, r1                       @ set Dalvik PC
1132    bx      r2
1133    @ doesn't return
1134
1135.LinterpPunt:
1136    .word   dvmJitToInterpPunt
1137
1138/* ------------------------------ */
1139    .balign 4
1140    .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1141dvmCompiler_TEMPLATE_MONITOR_ENTER:
1142/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1143    /*
1144     * Call out to the runtime to lock an object.  Because this thread
1145     * may have been suspended in THREAD_MONITOR state and the Jit's
1146     * translation cache subsequently cleared, we cannot return directly.
1147     * Instead, unconditionally transition to the interpreter to resume.
1148     *
1149     * On entry:
1150     *    r0 - self pointer
1151     *    r1 - the object (which has already been null-checked by the caller
1152     *    r4 - the Dalvik PC of the following instruction.
1153     */
1154    ldr     r2, .LdvmLockObject
1155    mov     r3, #0                       @ Record that we're not returning
1156    str     r3, [r0, #offThread_inJitCodeCache]
1157    blx     r2                           @ dvmLockObject(self, obj)
1158    @ refresh Jit's on/off status
1159    ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1160    ldr     r0, [r0]
1161    ldr     r2, .LdvmJitToInterpNoChain
1162    str     r0, [rGLUE, #offGlue_pJitProfTable]
1163    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1164#if defined(WITH_JIT_TUNING)
1165    mov     r0, #kHeavyweightMonitor
1166#endif
1167    bx      r2
1168
1169/* ------------------------------ */
1170    .balign 4
1171    .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1172dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1173/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1174    /*
1175     * To support deadlock prediction, this version of MONITOR_ENTER
1176     * will always call the heavyweight dvmLockObject, check for an
1177     * exception and then bail out to the interpreter.
1178     *
1179     * On entry:
1180     *    r0 - self pointer
1181     *    r1 - the object (which has already been null-checked by the caller
1182     *    r4 - the Dalvik PC of the following instruction.
1183     *
1184     */
1185    ldr     r2, .LdvmLockObject
1186    mov     r3, #0                       @ Record that we're not returning
1187    str     r3, [r0, #offThread_inJitCodeCache]
1188    blx     r2             @ dvmLockObject(self, obj)
1189    @ refresh Jit's on/off status & test for exception
1190    ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1191    ldr     r1, [rGLUE, #offGlue_self]
1192    ldr     r0, [r0]
1193    ldr     r1, [r1, #offThread_exception]
1194    str     r0, [rGLUE, #offGlue_pJitProfTable]
1195    cmp     r1, #0
1196    beq     1f
1197    ldr     r2, .LhandleException
1198    sub     r0, r4, #2     @ roll dPC back to this monitor instruction
1199    bx      r2
12001:
1201    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1202#if defined(WITH_JIT_TUNING)
1203    mov     r0, #kHeavyweightMonitor
1204#endif
1205    ldr     pc, .LdvmJitToInterpNoChain
1206
1207/* ------------------------------ */
1208    .balign 4
1209    .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
1210dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
1211/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
1212    /*
1213     * Increment profile counter for this trace, and decrement
1214     * sample counter.  If sample counter goes below zero, turn
1215     * off profiling.
1216     *
1217     * On entry
1218     * (lr-11) is address of pointer to counter.  Note: the counter
1219     *    actually exists 10 bytes before the return target, but because
1220     *    we are arriving from thumb mode, lr will have its low bit set.
1221     */
1222     ldr    r0, [lr,#-11]
1223     ldr    r1, [rGLUE, #offGlue_pProfileCountdown]
1224     ldr    r2, [r0]                    @ get counter
1225     ldr    r3, [r1]                    @ get countdown timer
1226     add    r2, #1
1227     subs   r2, #1
1228     blt    .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
1229     str    r2, [r0]
1230     str    r3, [r1]
1231     bx     lr
1232
1233.LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
1234     mov    r4, lr                     @ preserve lr
1235     ldr    r0, .LdvmJitTraceProfilingOff
1236     blx    r0
1237     bx     r4
1238
1239    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1240/* File: armv5te/footer.S */
1241/*
1242 * ===========================================================================
1243 *  Common subroutines and data
1244 * ===========================================================================
1245 */
1246
1247    .text
1248    .align  2
1249.LinvokeNative:
1250    @ Prep for the native call
1251    @ r1 = newFP, r0 = methodToCall
1252    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1253    mov     r2, #0
1254    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1255    str     r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache
1256    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1257    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1258                                        @ newFp->localRefCookie=top
1259    mov     r9, r3                      @ r9<- glue->self (preserve)
1260    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1261
1262    mov     r2, r0                      @ r2<- methodToCall
1263    mov     r0, r1                      @ r0<- newFP
1264    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1265#if defined(WITH_INLINE_PROFILING)
1266    @ r2: methodToCall, r6: rGLUE
1267    stmfd   sp!, {r2,r6}
1268    stmfd   sp!, {r0-r3}
1269    mov     r0, r2
1270    mov     r1, r6
1271    mov     lr, pc
1272    ldr     pc, .LdvmFastMethodTraceEnter
1273    ldmfd   sp!, {r0-r3}
1274#endif
1275
1276    mov     lr, pc
1277    ldr     pc, [r2, #offMethod_nativeFunc]
1278
1279#if defined(WITH_INLINE_PROFILING)
1280    ldmfd   sp!, {r0-r1}
1281    mov     lr, pc
1282    ldr     pc, .LdvmFastNativeMethodTraceExit
1283#endif
1284    @ Refresh Jit's on/off status
1285    ldr     r3, [rGLUE, #offGlue_ppJitProfTable]
1286
1287    @ native return; r9=self, r10=newSaveArea
1288    @ equivalent to dvmPopJniLocals
1289    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1290    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1291    ldr     r1, [r9, #offThread_exception] @ check for exception
1292    ldr     r3, [r3]    @ r1 <- pointer to Jit profile table
1293    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1294    cmp     r1, #0                      @ null?
1295    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1296    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1297    str     r3, [rGLUE, #offGlue_pJitProfTable]  @ cache current JitProfTable
1298
1299    @ r0 = dalvikCallsitePC
1300    bne     .LhandleException           @ no, handle exception
1301
1302    str     r2, [r9, #offThread_inJitCodeCache] @ set the new mode
1303    cmp     r2, #0                      @ return chaining cell still exists?
1304    bxne    r2                          @ yes - go ahead
1305
1306    @ continue executing the next instruction through the interpreter
1307    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1308    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1309#if defined(WITH_JIT_TUNING)
1310    mov     r0, #kCallsiteInterpreted
1311#endif
1312    mov     pc, r1
1313
1314/*
1315 * On entry:
1316 * r0  Faulting Dalvik PC
1317 */
1318.LhandleException:
1319#if defined(WITH_SELF_VERIFICATION)
1320    ldr     pc, .LdeadFood @ should not see this under self-verification mode
1321.LdeadFood:
1322    .word   0xdeadf00d
1323#endif
1324    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
1325    mov     r2, #0
1326    str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
1327    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1328    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1329    mov     rPC, r0                 @ reload the faulting Dalvik address
1330    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1331
1332    .align  2
1333.LdvmAsmInstructionStart:
1334    .word   dvmAsmInstructionStart
1335.LdvmJitToInterpNoChainNoProfile:
1336    .word   dvmJitToInterpNoChainNoProfile
1337.LdvmJitToInterpTraceSelectNoChain:
1338    .word   dvmJitToInterpTraceSelectNoChain
1339.LdvmJitToInterpNoChain:
1340    .word   dvmJitToInterpNoChain
1341.LdvmMterpStdBail:
1342    .word   dvmMterpStdBail
1343.LdvmMterpCommonExceptionThrown:
1344    .word   dvmMterpCommonExceptionThrown
1345.LdvmLockObject:
1346    .word   dvmLockObject
1347.LdvmJitTraceProfilingOff:
1348    .word   dvmJitTraceProfilingOff
1349#if defined(WITH_JIT_TUNING)
1350.LdvmICHitCount:
1351    .word   gDvmICHitCount
1352#endif
1353#if defined(WITH_SELF_VERIFICATION)
1354.LdvmSelfVerificationMemOpDecode:
1355    .word   dvmSelfVerificationMemOpDecode
1356#endif
1357#if defined(WITH_INLINE_PROFILING)
1358.LdvmFastMethodTraceEnter:
1359    .word   dvmFastMethodTraceEnter
1360.LdvmFastNativeMethodTraceExit:
1361    .word   dvmFastNativeMethodTraceExit
1362.LdvmFastJavaMethodTraceExit:
1363    .word   dvmFastJavaMethodTraceExit
1364#endif
1365.L__aeabi_cdcmple:
1366    .word   __aeabi_cdcmple
1367.L__aeabi_cfcmple:
1368    .word   __aeabi_cfcmple
1369
1370    .global dmvCompilerTemplateEnd
1371dmvCompilerTemplateEnd:
1372
1373#endif /* WITH_JIT */
1374
1375