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