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